Configure the Integration Function
We will now configure the Integration function and add code to it.
The Integration function’s directoryfunctions/GithubExtension contains:
- The MainClass.java main function file
- Handler files in the com/handlers folder
- The catalyst-config.json configuration file
- Java library files in the lib folder
- .classpath and .project dependency files
We will be coding BotHandler.java, CommandHandler.java and FunctionHandler.java in the handlers folder. We will also create a new class file GithubConstants.java in this directory and add code in it.
Copy the code below and paste it into the respective files located in the functions/GithubExtension/com/handlers directory of your project using an IDE and save the files.
package com.handlers;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import java.util.logging.Level;
import org.json.JSONObject;
import org.json.JSONArray;
import org.json.JSONException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zc.cliq.enums.ACTION_TYPE;
import com.zc.cliq.enums.BANNER_STATUS;
import com.zc.cliq.enums.BUTTON_TYPE;
import com.zc.cliq.enums.CHANNEL_OPERATION;
import com.zc.cliq.enums.SLIDE_TYPE;
import com.zc.cliq.objects.Action;
import com.zc.cliq.objects.ActionData;
import com.zc.cliq.objects.BotDetails;
import com.zc.cliq.objects.ButtonObject;
import com.zc.cliq.objects.Confirm;
import com.zc.cliq.objects.Message;
import com.zc.cliq.objects.Slide;
import com.zc.cliq.requests.BotCallHandlerRequest;
import com.zc.cliq.requests.BotContextHandlerRequest;
import com.zc.cliq.requests.BotMentionHandlerRequest;
import com.zc.cliq.requests.BotMenuActionHandlerRequest;
import com.zc.cliq.requests.BotMessageHandlerRequest;
import com.zc.cliq.requests.BotParticipationHandlerRequest;
import com.zc.cliq.requests.BotWebhookHandlerRequest;
import com.zc.cliq.requests.BotWelcomeHandlerRequest;
import com.zc.cliq.responses.BannerResponse;
import com.zc.cliq.responses.CoreResponse;
import com.zc.cliq.responses.WebhookHandlerResponse;
// import com.zc.cliq.util.ZCCliqUtil;
public class BotHandler implements com.zc.cliq.interfaces.BotHandler, CoreResponse {
Logger LOGGER = Logger.getLogger(BotHandler.class.getName());
@Override
public CoreResponse messageHandler(BotMessageHandlerRequest req) throws JSONException {
LOGGER.log(Level.SEVERE, "class BotHandler method messageHandler");
String message = req.getMessage();
String text;
if (message == null) {
text = "Hello! How can I help you?";
} else if (message.equalsIgnoreCase("hello")) {
text = "Hello! How can I help you?";
} else if (message.equalsIgnoreCase("webhooktoken")) {
Message msg = Message.getInstance("Click on the token generation button below!");
ButtonObject btnObj = new ButtonObject();
btnObj.setType(BUTTON_TYPE.GREEN_OUTLINE);
btnObj.setLabel("Create Webhook");
Action action = new Action();
action.setType(ACTION_TYPE.INVOKE_FUNCTION);
ActionData actionData = new ActionData();
actionData.setName("authenticate"); // ** ENTER YOUR BUTTON FUNCTION NAME HERE **
action.setData(actionData);
Confirm confirm = new Confirm();
confirm.setTitle("Generate Webhooks for a GitLab Project");
confirm.setDescription("Connect to GitLab Projects from within Cliq");
confirm.setInput("user_webhook_token");
action.setConfirm(confirm);
btnObj.setAction(action);
msg.addButton(btnObj);
return (CoreResponse) msg;
} else {
text = "Sorry, I'm not programmed yet to do this :sad:";
}
Message resp = Message.getInstance(text);
return (CoreResponse) resp;
}
@Override
public CoreResponse menuActionHandler(BotMenuActionHandlerRequest req) throws Exception {
LOGGER.log(Level.SEVERE, "class BotHandler method menuActionHandler");
Message msg = Message.getInstance();
BotDetails bot = BotDetails.getInstance(GithubConstants.BOT_NAME);
msg.setBot(bot);
if (req.getActionName().equals("Repos")) {
JSONArray reposArray = CommandHandler.getRepos();
if (reposArray.length() == 0) {
msg.setText("There aren't are repos created yet.");
} else {
Slide slide = Slide.getInstance();
msg.setText("Here's a list of the *repositories*");
slide.setType(SLIDE_TYPE.TABLE);
slide.setTitle("Repo details");
List<String> headers = new ArrayList<>();
headers.add("Name");
headers.add("Private");
headers.add("Open Issues");
headers.add("Link");
// Use Map instead of JSONObject
Map<String, Object> data = new HashMap<>();
data.put("headers", headers);
// Use List instead of JSONArray
List<Map<String, Object>> rows = new ArrayList<>();
for (int i = 0; i < reposArray.length(); i++) {
JSONObject repo = reposArray.optJSONObject(i);
Map<String, Object> row = new HashMap<>();
row.put("Name", repo.optString("name"));
row.put("Private", repo.optBoolean("private") ? "Yes" : "No");
row.put("Open Issues", repo.optString("open_issues_count"));
row.put("Link", "[Click here](" + repo.optString("html_url") + ")");
rows.add(row);
}
data.put("rows", rows);
slide.setData(data);
msg.addSlide(slide);
}
} else {
msg.setText("Menu action triggered :fist:");
}
return (CoreResponse) msg;
}
@Override
public WebhookHandlerResponse webhookHandler(BotWebhookHandlerRequest req) throws Exception {
LOGGER.log(Level.SEVERE, "class BotHandler method webhookHandler");
JSONObject reqBody = req.getBody();
LOGGER.info(reqBody.toString());
JSONObject commitJson = reqBody.optJSONArray("commits").optJSONObject(0);
/// message
Message msg = Message.getInstance("A commit has been pushed !");
msg.setBot(BotDetails.getInstance(GithubConstants.BOT_NAME));
/// commit msg
Slide commitMsg = Slide.getInstance();
commitMsg.setType(SLIDE_TYPE.TEXT);
commitMsg.setTitle("Commit message");
commitMsg.setData(commitJson.optString("message"));
msg.addSlide(commitMsg);
// slide
Slide details = Slide.getInstance();
details.setType(SLIDE_TYPE.LABEL);
details.setTitle("Details");
JSONArray dataArray = new JSONArray();
JSONObject committer = new JSONObject();
committer.put("Committer", commitJson.optJSONObject("author").optString("username"));
dataArray.put(committer);
JSONObject repoName = new JSONObject();
repoName.put("Repo Name", reqBody.optJSONObject("repository").optString("name"));
dataArray.put(repoName);
JSONObject timestamp = new JSONObject();
timestamp.put("Timestamp", commitJson.optString("timestamp"));
dataArray.put(timestamp);
JSONObject compare = new JSONObject();
compare.put("Compare", "[Click here](" + reqBody.optString("compare") + ")");
dataArray.put(compare);
details.setData(dataArray);
LOGGER.log(Level.SEVERE, "printing array");
ObjectMapper mapper = new ObjectMapper();
LOGGER.log(Level.SEVERE, mapper.writeValueAsString(dataArray));
msg.addSlide(details);
return (WebhookHandlerResponse) msg;
}
@Override
public CoreResponse participationHandler(BotParticipationHandlerRequest req) throws Exception {
LOGGER.log(Level.SEVERE, "class BotHandler method participationHandler");
String text;
if (req.getOperation().equals(CHANNEL_OPERATION.ADDED)) {
text = "Hi. Thanks for adding me to the channel :smile:";
} else if (req.getOperation().equals(CHANNEL_OPERATION.REMOVED)) {
text = "Bye-Bye :bye-bye:";
} else {
text = "I'm too a participant of this chat :wink:";
}
Message msg = Message.getInstance(text);
return (CoreResponse) msg;
}
@Override
public Message welcomeHandler(BotWelcomeHandlerRequest req) {
LOGGER.log(Level.SEVERE, "class BotHandler method welcomeHandler");
String uName = req.getUser() != null ? req.getUser().getFirstName() : "user";
String text = "Hello " + uName + ". Thank you for subscribing :smile:";
Message msg = Message.getInstance(text);
return msg;
}
@Override
public CoreResponse contextHandler(BotContextHandlerRequest req) {
LOGGER.log(Level.SEVERE, "class BotHandler method contextHandler");
BannerResponse resp = new BannerResponse("", BANNER_STATUS.SUCCESS);
if (req.getContextId().equals("personal_details")) {
Map<String, String> answers = req.getAnswers();
StringBuilder str = new StringBuilder();
str.append("Name: ").append(answers.get("name")).append("\n");
str.append("Department: ").append(answers.get("dept")).append("\n");
resp = new BannerResponse("Nice ! I have collected your info: \n" + str.toString(), BANNER_STATUS.SUCCESS);
}
return (CoreResponse) resp;
}
@Override
public CoreResponse mentionHandler(BotMentionHandlerRequest req) {
LOGGER.log(Level.SEVERE, "class BotHandler method mentionHandler");
String text = "Hey *" + req.getUser().getFirstName()
+ "*, thanks for mentioning me here. I'm from Catalyst city";
BannerResponse resp = new BannerResponse(text, BANNER_STATUS.SUCCESS);
return (CoreResponse) resp;
}
@Override
public void callHandler(BotCallHandlerRequest req) throws Exception {
LOGGER.log(Level.SEVERE, "class BotHandler method callHandler");
return;
}
}
package com.handlers;
import java.util.logging.Logger;
import java.util.logging.Level;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.json.JSONArray;
import org.json.JSONObject;
import com.zc.api.APIConstants.RequestMethod;
import com.zc.api.APIRequest;
import com.zc.cliq.enums.SLIDE_TYPE;
import com.zc.cliq.objects.BotDetails;
import com.zc.cliq.objects.CommandSuggestion;
import com.zc.cliq.objects.Message;
import com.zc.cliq.objects.Slide;
import com.zc.cliq.requests.CommandHandlerRequest;
import com.zc.cliq.responses.CoreResponse;
import okhttp3.Response;
public class CommandHandler implements com.zc.cliq.interfaces.CommandHandler {
Logger LOGGER = Logger.getLogger(CommandHandler.class.getName());
@Override
public CoreResponse executionHandler(CommandHandlerRequest req) throws Exception {
LOGGER.log(Level.SEVERE, "class CommandHandler method executionHandler");
Message msg = Message.getInstance();
BotDetails bot = BotDetails.getInstance(GithubConstants.BOT_NAME);
msg.setBot(bot);
String commandName = req.getName();
if (commandName.equals("commits")) {
List<CommandSuggestion> repoSuggestions = req.getSelections();
if (repoSuggestions == null || repoSuggestions.isEmpty()) {
msg.setText("Please select a repo from the suggestions.");
} else {
String repoName = repoSuggestions.get(0).getTitle();
JSONArray commitsArray = getCommits(repoName);
if (commitsArray.length() == 0) {
msg.setText("There aren't are commits made yet.");
} else {
Slide slide = Slide.getInstance();
msg.setText("Here's a list of the latest " + GithubConstants.PER_PAGE
+ " commits made to the repository *" + repoName + "*.");
slide.setType(SLIDE_TYPE.TABLE);
slide.setTitle("Commit details");
List<String> headers = new ArrayList<>();
headers.add("Date");
headers.add("Commit message");
headers.add("Committed by");
headers.add("Link");
// Use Map instead of JSONObject
Map<String, Object> data = new HashMap<>();
data.put("headers", headers);
// Use List instead of JSONArray
List<Map<String, Object>> rows = new ArrayList<>();
for (int i = 0; i < commitsArray.length(); i++) {
JSONObject obj = commitsArray.optJSONObject(i);
JSONObject commit = obj.optJSONObject("commit");
JSONObject author = commit.optJSONObject("author");
Map<String, Object> row = new HashMap<>();
row.put("Date", author.optString("date"));
row.put("Commit message", commit.optString("message"));
row.put("Committed by", author.optString("name"));
row.put("Link", "[Click here](" + obj.optString("html_url") + ")");
rows.add(row);
}
data.put("rows", rows);
slide.setData(data);
msg.addSlide(slide);
}
}
} else if (commandName.equals("issues")) {
List<CommandSuggestion> repoSuggestions = req.getSelections();
if (repoSuggestions == null || repoSuggestions.isEmpty()) {
msg.setText("Please select a repo from the suggestions.");
} else {
String repoName = repoSuggestions.get(0).getTitle();
JSONArray issuesArray = getIssues(repoName);
if (issuesArray.length() == 0) {
msg.setText("There aren't are issues raised yet.");
} else {
Slide slide = Slide.getInstance();
msg.setText("Here's a list of the latest " + GithubConstants.PER_PAGE
+ " issues raised to the repository *" + repoName + "*");
slide.setType(SLIDE_TYPE.TABLE);
slide.setTitle("Issue details");
List<String> headers = new ArrayList<>();
headers.add("Created At");
headers.add("Title");
headers.add("Created By");
headers.add("Link");
// Use Map instead of JSONObject
Map<String, Object> data = new HashMap<>();
data.put("headers", headers);
// Use List instead of JSONArray
List<Map<String, Object>> rows = new ArrayList<>();
for (int i = 0; i < issuesArray.length(); i++) {
JSONObject issueObj = issuesArray.optJSONObject(i);
Map<String, Object> row = new HashMap<>();
row.put("Created At", issueObj.optString("created_at"));
row.put("Title", issueObj.optString("title"));
row.put("Created By", issueObj.optJSONObject("user").optString("login"));
row.put("Link", "[Click here](" + issueObj.optString("html_url") + ")");
rows.add(row);
}
data.put("rows", rows);
slide.setData(data);
msg.addSlide(slide);
}
}
} else {
msg.setText("Slash command executed");
}
return (CoreResponse) msg;
}
@Override
public List<CommandSuggestion> suggestionHandler(CommandHandlerRequest req) throws Exception {
LOGGER.log(Level.SEVERE, "class CommandHandler method suggestionHandler");
List<CommandSuggestion> suggestionList = new ArrayList<CommandSuggestion>();
JSONArray reposArray = getRepos();
List<String> repoNames = new ArrayList<>();
for (int i = 0; i < reposArray.length(); i++) {
JSONObject repo = reposArray.optJSONObject(i);
repoNames.add(repo.optString("name"));
}
if (req.getName().equals("commits") || req.getName().equals("issues")) {
repoNames.forEach((name) -> {
CommandSuggestion sugg = CommandSuggestion.getInstance();
sugg.setTitle(name);
suggestionList.add(sugg);
});
}
return suggestionList;
}
public static JSONArray getRepos() throws Exception {
APIRequest req = getRequestObj("https://api.github.com/user/repos");
req.executeRequest();
Response resp = req.getHttpResponse();
JSONArray reposArray = new JSONArray(resp.body().string());
return reposArray;
}
private String getUsername() throws Exception {
LOGGER.log(Level.SEVERE, "class CommandHandler method getUsername");
APIRequest req = getRequestObj("https://api.github.com/user");
JSONObject respJson = new JSONObject(req.getResponse().getResponseJSON().get(0).toString());
return respJson.get("login").toString();
}
private JSONArray getCommits(String repoName) throws Exception {
LOGGER.log(Level.SEVERE, "class CommandHandler method getCommits");
APIRequest req = getRequestObj("https://api.github.com/repos/" + getUsername() + "/" + repoName
+ "/commits?per_page=" + GithubConstants.PER_PAGE);
req.executeRequest();
Response resp = req.getHttpResponse();
JSONArray commitsArray = new JSONArray(resp.body().string());
return commitsArray;
}
private JSONArray getIssues(String repoName) throws Exception {
LOGGER.log(Level.SEVERE, "class CommandHandler method getIssues");
APIRequest req = getRequestObj("https://api.github.com/repos/" + getUsername() + "/" + repoName
+ "/issues?per_page=" + GithubConstants.PER_PAGE);
req.executeRequest();
Response resp = req.getHttpResponse();
JSONArray issuesArray = new JSONArray(resp.body().string());
return issuesArray;
}
private static APIRequest getRequestObj(String url) {
APIRequest req = new APIRequest();
req.setUrl(url);
req.setRequestMethod(RequestMethod.GET);
req.setAuthNeeded(false);
HashMap<String, String> headers = new HashMap<>();
headers.put("Authorization", "Token " + GithubConstants.PERSONAL_ACCESS_TOKEN);
req.setHeaders(headers);
return req;
}
}
package com.handlers;
import java.util.HashMap;
import java.util.Map;
import com.zc.cliq.objects.Form;
import com.zc.cliq.objects.FormChangeResponse;
import com.zc.cliq.objects.FormDynamicFieldResponse;
import com.zc.cliq.objects.Message;
import com.zc.cliq.objects.WidgetSection;
import com.zc.cliq.requests.ButtonFunctionRequest;
import com.zc.cliq.requests.FormFunctionRequest;
import com.zc.cliq.requests.WidgetFunctionRequest;
public class FunctionHandler implements com.zc.cliq.interfaces.FunctionHandler {
@SuppressWarnings(“unchecked”)
@Override
public Message buttonFunctionHandler(ButtonFunctionRequest req) throws Exception {
String text;
if (req.getName().equals(“authenticate”)) {
System.out.println(“Arguments: " + req.getArguments());
text = req.getArguments().get(“input”).toString();
} else {
text = “Button function executed”;
}
Message msg = Message.getInstance(text);
return msg;
}
@Override
public Message formSubmitHandler(FormFunctionRequest req) throws Exception {
return Message.getInstance("Form submitted successfully");
}
@Override
public FormChangeResponse formChangeHandler(FormFunctionRequest req) throws Exception {
FormChangeResponse resp = FormChangeResponse.getInstance();
return resp;
}
@Override
public FormDynamicFieldResponse formDynamicFieldHandler(FormFunctionRequest req) throws Exception {
FormDynamicFieldResponse resp = FormDynamicFieldResponse.getInstance();
return resp;
}
@Override
public Form formViewHandler(FormFunctionRequest req) throws Exception {
return Form.getInstance();
}
@Override
public WidgetSection widgetButtonHandler(WidgetFunctionRequest req) throws Exception {
return getButtonsSection();
}
private WidgetSection getButtonsSection() {
WidgetSection buttonSection = WidgetSection.getInstance();
return buttonSection;
}
}
Next,create a new Java class file in the handlers/directory and name it GithubConstants.java.Add the code given below to the file.
package com.handlers;
public class GithubConstants {
public static final String PERSONAL_ACCESS_TOKEN = “XXXXx”;
public static final Integer PER_PAGE = 10;
public static final String BOT_NAME = “github-bot”;
}
The functions directory is now configured.
Let’s quickly go over the code of the handler classes.We will discuss the components specified here in detail while configuring the extension.
-
The BotHandler.java class contains the business logic of the GitHub bot component that we will configure in the Cliq extension. After you enable the chat bot, you can generate a webhook token to authenticate the connection to GitHub, list the details of your Git repositories, and obtain the details of the latest commits and issues in a repository. These actions are defined in this class.
-
The CommandHandler.java class handles the actions to be performed for the issues and commits commands. It also defines the suggestion handler that lists the repos of the Git account. The user must select a repo from the suggestion after entering the command, to execute the command for. CommandHandler.java also defines the APIs for fetching other information from the Git account.
-
The FunctionHandler.java class contains the business logic of the button function that authenticates the webhook token for GitHub.
-
The GitHubConstants.java class file stores the constant values of the function, such as the personal access token and the bot name.
Last Updated 2025-11-19 20:37:41 +0530 IST