Configure the Integration Function

We will now configure the Integration function and add code to it.

Note: We will need to code and deploy the function to the Catalyst remote console before configuring the extension on Cliq, because we have to associate the extension with an existing function from the Catalyst console.

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.

Note: Please go through the code in this section to make sure you fully understand it. We will discuss the code at the end of this section.

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.

    
BotHandler.java
copy
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.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.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.util.ZCCliqUtil; public class BotHandler implements com.zc.cliq.interfaces.BotHandler { Logger LOGGER = Logger.getLogger(BotHandler.class.getName()); @Override public Map messageHandler(BotMessageHandlerRequest req) throws JSONException { LOGGER.log(Level.SEVERE, "class BotHandler method messageHandler"); String message = req.getMessage(); Map resp = new HashMap(); String text; if(message == null){ text = "Please enable 'Message' in bot settings"; } 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"); JSONObject input = new JSONObject(); input.put("type", "user_webhook_token"); confirm.setInput(input); action.setConfirm(confirm); btnObj.setAction(action); msg.addButton(btnObj); return ZCCliqUtil.toMap(msg); } else{ text = "Sorry, I'm not programmed yet to do this :sad:"; } resp.put("text", text); return resp; } @Override public Map 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 headers = new ArrayList(); headers.add("Name"); headers.add("Private"); headers.add("Open Issues"); headers.add("Link"); JSONObject data = new JSONObject(); data.put("headers", headers); JSONArray rows = new JSONArray(); for(int i=0; i< reposArray.length(); i++){ JSONObject repo = reposArray.optJSONObject(i); JSONObject row = new JSONObject(); 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.put(row); } data.put("rows", rows); slide.setData(data); msg.addSlide(slide); } } else{ msg.setText("Menu action triggered :fist:"); } return ZCCliqUtil.toMap(msg); } @Override public Map 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 ZCCliqUtil.toMap(msg); } @Override public Map 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 ZCCliqUtil.toMap(msg); } @Override public Map 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 ZCCliqUtil.toMap(msg); } @Override public Map contextHandler(BotContextHandlerRequest req) { LOGGER.log(Level.SEVERE, "class BotHandler method contextHandler"); Map resp = new HashMap(); if(req.getContextId().equals("personal_details")){ Map 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.put("text", "Nice ! I have collected your info: \n" + str.toString()); } return resp; } @Override public Map 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"; Map resp = new HashMap(); resp.put("text", text); return resp; } }
View more
    
CommandHandler.java
copy
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.util.ZCCliqUtil; import okhttp3.Response; public class CommandHandler implements com.zc.cliq.interfaces.CommandHandler { Logger LOGGER = Logger.getLogger(CommandHandler.class.getName()); @Override public Map 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 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 headers = new ArrayList(); headers.add("Date"); headers.add("Commit message"); headers.add("Committed by"); headers.add("Link"); JSONObject data = new JSONObject(); data.put("headers", headers); JSONArray rows = new JSONArray(); for(int i=0; i 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 headers = new ArrayList(); headers.add("Created At"); headers.add("Title"); headers.add("Created By"); headers.add("Link"); JSONObject data = new JSONObject(); data.put("headers", headers); JSONArray rows = new JSONArray(); for(int i=0; i suggestionHandler(CommandHandlerRequest req) throws Exception { LOGGER.log(Level.SEVERE, "class CommandHandler method suggestionHandler"); List suggestionList = new ArrayList(); JSONArray reposArray = getRepos(); List 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 headers = new HashMap<>(); headers.put("Authorization", "Token " + GithubConstants.PERSONAL_ACCESS_TOKEN); req.setHeaders(headers); return req; } }
View more
    
FunctionHandler.java
copy
package com.handlers; import java.util.HashMap; import java.util.Map; 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; import com.zc.cliq.util.ZCCliqUtil; public class FunctionHandler implements com.zc.cliq.interfaces.FunctionHandler { @SuppressWarnings("unchecked") @Override public Map buttonFunctionHandler(ButtonFunctionRequest req) throws Exception { String text; if(req.getName().equals("authenticate")){ text = ((HashMap)req.getArguments().get("input")).get("token").toString(); } else{ text = "Button function executed"; } Message msg = Message.getInstance(text); return ZCCliqUtil.toMap(msg); } @Override public Map formSubmitHandler(FormFunctionRequest req) throws Exception { return new HashMap<>(); } @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 Map widgetButtonHandler(WidgetFunctionRequest req) throws Exception { return new HashMap<>(); } private WidgetSection getButtonsSection() { WidgetSection buttonSection = WidgetSection.getInstance(); return buttonSection; } }
View more

Next,create a new Java class file in the handlers/directory and name it GithubConstants.java.Add the code given below to the file.

    
GithubConstants.java
copy
package com.handlers; public class GithubConstants { public static final String PERSONAL_ACCESS_TOKEN = "xxxxxxxxxxxxxxxxxxxxx"; public static final Integer PER_PAGE = 10; public static final String BOT_NAME = "github-bot"; }
View more
Note: After you copy and paste this code,paste the personal access token that you obtained from GitHub in Step 2 on line 6 in this code.

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 2024-06-11 19:21:32 +0530 +0530

RELATED LINKS

Integration Functions