# Java -------------------------------------------------------------------------------- title: "Introduction" description: "Build an extension on Zoho Cliq using Catalyst Integration Functions, that enables you to access and work with your GitHub repositories using a Cliq bot." last_updated: "2026-03-18T07:41:08.678Z" source: "https://docs.catalyst.zoho.com/en/tutorials/githubbot/java/introduction/" service: "All Services" related: - Project Directory Structure (/en/cli/v1/project-directory-structure/introduction/) - Java SDK (/en/sdk/java/v1/overview/) - Zoho Cliq (https://www.zoho.com/in/cliq/) - GitHub (https://github.com/) -------------------------------------------------------------------------------- # GitHub Bot on Cliq ### Introduction This tutorial will help you build an extension on {{%link href="https://www.zoho.com/in/cliq/" %}}Zoho Cliq{{%/link%}} that will enable you to view the details of your {{%link href="https://github.com/" %}}GitHub{{%/link%}} repositories using a Cliq bot. The Cliq extension will bundle the following internal components: Commands, Function, and Bot. You can learn about these components from the {{%link href="https://www.zoho.com/cliq/help/platform/getting-started-with-cliq-platform.html" %}}Cliq help documentation{{%/link%}}. The Cliq chat bot will provide the following information along with appropriate links when you enter the right command in the chat: * List of all the repositories in the GitHub account * Details of the last ten commits made in a specific repository * Details of the last ten issues raised in a specific repository For example, when you enter the command to display the latest issues raised in the Git repository, the chat bot will display details as shown below. The bot will also send you an alert in the chat immediately after a commit is pushed to the Git repository, along with the commit details. This setup includes the following Catalyst component: 1. {{%link href="/en/serverless/getting-started/introduction/" %}}**Catalyst Serverless**{{%/link%}}: - {{%bold%}}{{%link href="/en/serverless/help/functions/integration-functions" %}}Integration Function{{%/link%}}:{{%/bold%}} The backend of this Cliq extension will be built using an Integration function in the {{%bold%}}Java{{%/bold%}} platform. This function will enable you to build and maintain the backend of the Cliq extension. We will associate this function with the extension while creating the extension on Cliq. After this integration is configured, the integration function will be invoked each time the Cliq bot is accessed. {{%note%}}{{%bold%}}Note:{{%/bold%}} Integration Functions is currently not available to Catalyst users accessing from the EU, AU, IN, or CA data centers. Users accessing from these DCs will not be able to avail this tutorial to build the GitHub bot.{{%/note%}} This setup will not include a Catalyst client component. We will code a few {{%link href="/en/serverless/help/functions/integration-functions/#cliq-integration-function-structure" %}}handlers{{%/link%}} in the Integration function that will handle specific events and actions. We will also use the Catalyst Command Line Interface (CLI) to build this application. You will be given the code for the files to be included in the Integration function in this tutorial. You will just have to copy the code given here and paste it into the appropriate files as directed. ### Application Workflow -------------------------------------------------------------------------------- title: "Prerequisites" description: "Build an extension on Zoho Cliq using Catalyst Integration Functions, that enables you to access and work with your GitHub repositories using a Cliq bot" last_updated: "2026-03-18T07:41:08.678Z" source: "https://docs.catalyst.zoho.com/en/tutorials/githubbot/java/prerequisites/" service: "All Services" related: - CLI Command Reference (/en/cli/v1/cli-command-reference/) - Install CLI (/en/getting-started/installing-catalyst-cli/) - Login CLI (/en/cli/v1/login/login-from-cli/) -------------------------------------------------------------------------------- # Prerequisites Before you begin building the application, you must have the following prerequisites installed on your system: 1. {{%bold%}}Catalyst CLI{{%/bold%}}<br /><br /> Catalyst CLI contains a host of tools that enable you to initialize, develop, test, and deploy the components of your application from your local machine. We will be working with Catalyst CLI in this tutorial. You must perform these actions: 1. {{%bold%}}Install Catalyst CLI:{{%/bold%}} Catalyst CLI is installed through NPM. You must therefore have NPM and Node.js installed on your system before you install the CLI. Refer to the {{%link href="/en/getting-started/installing-catalyst-cli" %}}**Install Catalyst CLI help page**{{%/link%}} for details on the pre-requisites and the steps to install it. 2. {{%bold%}}Login Catalyst CLI:{{%/bold%}} After you install Catalyst CLI, you must authenticate the CLI with your Catalyst account before using it. Refer to the {{%link href="/en/cli/v1/login/login-from-cli/" %}}**CLI Login help page**{{%/link%}} for the steps to login from Catalyst CLI and the various options available for it. 2. {{%bold%}}GitHub Account with Repositories{{%/bold%}}<br /><br /> You must have an account on {{%link href="https://github.com/" %}}GitHub{{%/link%}} that contains one or more repositories. Ensure that the repositories contain valid files. This will enable you to test the execution of the commands in the Cliq bot, and also verify if the bot sends you an alert when you push a commit to a repository. We will access GitHub to generate an access token and to configure a webhook with Cliq. 3. {{%bold%}}Zoho Cliq Account{{%/bold%}}<br /><br /> You must have a Zoho Cliq account set up. We will access the developer console of Zoho Cliq to create and configure the extension and associate it with the Catalyst Integration function. 4. {{%bold%}}Any IDE tool for Java code development{{%/bold%}}<br /><br /> You can use any IDE to work with the Integration function code. Some popular choices include Visual Studio Code, IntelliJ IDEA, Eclipse, and Sublime Text. Download and install an IDE of your choice in your system. {{%info image="/images/tutorials/todo-list/vscode.png"%}}If you are a Visual Studio Code IDE user, you can install the {{%bold%}}Catalyst Tools{{%/bold%}} extension, and use your IDE itself in place of the CLI. You can find more details about the Catalyst VS Code extension from this {{%link href="/en/catalyst-extensions/vs-code-extension/introduction/" %}}help section{{%/link%}}.{{%/info%}} -------------------------------------------------------------------------------- title: "Create a project" description: "Build an extension on Zoho Cliq using Catalyst Integration Functions, that enables you to access and work with your GitHub repositories using a Cliq bot" last_updated: "2026-03-18T07:41:08.678Z" source: "https://docs.catalyst.zoho.com/en/tutorials/githubbot/java/create-project/" service: "All Services" related: - Catalyst Projects (/en/getting-started/catalyst-projects) - Project Directory Structure (/en/cli/v1/project-directory-structure/introduction) -------------------------------------------------------------------------------- # Create a Project Let's {{%link href="/en/getting-started/catalyst-projects" %}}create a Catalyst project{{%/link%}} from the Catalyst console. 1. Log in to the {{%link href="https://console.catalyst.zoho.com/baas/index" %}}Catalyst console{{%/link%}} and click {{%bold%}}Create new Project{{%/bold%}}. 2. Enter the project's name as "{{%bold%}}GitHubBot{{%/bold%}}" in the pop-up window. 3. Click {{%bold%}}Create{{%/bold%}}. Your project will be created and opened. -------------------------------------------------------------------------------- title: "Generate a personal access token on GitHub" description: "Build an extension on Zoho Cliq using Catalyst Integration Functions, that enables you to access and work with your GitHub repositories using a Cliq bot" last_updated: "2026-03-18T07:41:08.679Z" source: "https://docs.catalyst.zoho.com/en/tutorials/githubbot/java/generate-personal-access-token/" service: "All Services" related: - GitHub Integration (/en/devops/help/github-integration/introduction) -------------------------------------------------------------------------------- # Generate a Personal Access Token on GitHub Let us now generate a personal access token for the repositories in the Git account. A personal access token on GitHub functions like an OAuth access token and authenticates the access to the GitHub API. You can generate a personal access token on GitHub in the following way: 1. Navigate to your {{%bold%}}Git account settings{{%/bold%}}, then {{%bold%}}Developer Settings{{%/bold%}}. Click the {{%bold%}}Personal access tokens{{%/bold%}} menu, then click {{%bold%}}Tokens (classic){{%/bold%}} → {{%bold%}}Generate new token{{%/bold%}}. <br /> 2. Select {{%bold%}}repo{{%/bold%}} as the scope. The token will be applicable for all the specified actions in your repositories. <br /> 3. Click {{%bold%}}Generate Token{{%/bold%}}. GitHub will display the personal access token only once. Ensure that you copy the token and store it in a safe space. <br /> We will use this token in the Integration function's code, which will enable Catalyst to fetch necessary information about the repositories from GitHub. -------------------------------------------------------------------------------- title: "Initialize the project" description: "Build an extension on Zoho Cliq using Catalyst Integration Functions, that enables you to access and work with your GitHub repositories using a Cliq bot" last_updated: "2026-03-18T07:41:08.679Z" source: "https://docs.catalyst.zoho.com/en/tutorials/githubbot/java/initialize-project/" service: "All Services" related: - Initialize CLI Resources (/en/cli/v1/initialize-resources/introduction) - Project Directory Structure (/en/cli/v1/project-directory-structure/introduction) -------------------------------------------------------------------------------- # Initialize the Project from the CLI You can now begin working on your Catalyst project from the CLI. The first step is to initialize the project in an empty directory. This will be the home directory of your project and all of the project files will be saved in it. You can learn more about this from the {{%link href="/en/cli/v1/project-directory-structure/introduction" %}}Project Directory Structure help page{{%/link%}}. You can learn about initializing a project in detail from the {{%link href="/en/cli/v1/cli-command-reference/" %}}CLI help documentation{{%/link%}}. 1. Create a folder for the project on your local machine and navigate to it from the terminal. 2. Initialize a project by executing the following command from that directory: {{%cli%}}catalyst init{{%/cli%}} 3. Select the preferred portal (or organization) by navigating using the arrow keys and press **Enter** to confirm. If you have no other organizations associated with the account, then the default one will be selected automatically. <br /> 4. Now, CLI will ask you to associate a Catalyst project with the directory. Associate it with the project that we created earlier from the console. Select **GitHubBot** from the list and press **Enter**. <br /> 5. Select **Functions** using the space bar. Press the **Enter** key to initialize. <br /> 6. The CLI will initiate the function setup. Select Integration as the function type. <br /> 7. Select {{%bold%}}Cliq{{%/bold%}} as the service and press Enter. <br /> 8. All Cliq handlers classes will be selected by default. Press {{%bold%}}Enter{{%/bold%}}. <br /> 9. Select the latest supported runtime of Java as the function stack, and press {{%bold%}}Enter{{%/bold%}}. <br /> 10. Enter "{{%bold%}}GithubExtension{{%/bold%}}" as the folder name and "{{%bold%}}MainClass{{%/bold%}}" as the class name. Press {{%bold%}}Enter{{%/bold%}} each time. <br /> The CLI will download and install the latest {{%link href="/en/sdk/java/v1/overview" %}}Catalyst Java SDK{{%/link%}} package. {{%note%}}{{%bold%}} Note:{{%/bold%}} Ensure that you enter the class name and folder name exactly as instructed, because the application's code contains the same names.{{%/note%}} The functions directory is now created in the standard structure. Catalyst initialization is complete. Your project directory is now set up with the {{%link href="/en/cli/v1/project-directory-structure/functions-directory" %}}functions directory{{%/link%}} (CATALYST\_FUNCTIONS\_HOME) along with configuration files and dependencies. The project directory also contains the {{%badge%}}{{%link href="/en/cli/v1/project-directory-structure/catalyst-json" %}}catalyst.json{{%/link%}}{{%/badge%}} configuration file and a hidden {{%badge%}}.catalystrc{{%/badge%}} file. This will be the final structure of your project directory. {{%note%}}{{%bold%}}Note:{{%/bold%}} This image includes an additional file {{%badge%}}GithubConstants.java{{%/badge%}}. We will create this file while configuring the functions directory in the next step.{{%/note%}} -------------------------------------------------------------------------------- title: "Configure the Integration function" description: "Build an extension on Zoho Cliq using Catalyst Integration Functions, that enables you to access and work with your GitHub repositories using a Cliq bot" last_updated: "2026-03-18T07:41:08.679Z" source: "https://docs.catalyst.zoho.com/en/tutorials/githubbot/java/configure-integration-function/" service: "All Services" related: - Integration Functions (/en/serverless/help/functions/integration-functions) -------------------------------------------------------------------------------- # Configure the Integration Function We will now configure the Integration function and add code to it. {{%note%}}{{%bold%}}Note:{{%/bold%}} 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.{{%/note%}} The {{%link href="/en/serverless/help/functions/integration-functions" %}}Integration function's directory{{%/link%}}{{%badge%}}functions/GithubExtension{{%/badge%}} contains: * The {{%badge%}}MainClass.java{{%/badge%}} main function file * Handler files in the {{%badge%}}com/handlers{{%/badge%}} folder * The {{%badge%}}catalyst-config.json{{%/badge%}} configuration file * Java library files in the lib folder * {{%badge%}}.classpath{{%/badge%}} and {{%badge%}}.project{{%/badge%}} dependency files We will be coding {{%badge%}}BotHandler.java{{%/badge%}}, {{%badge%}}CommandHandler.java{{%/badge%}} and {{%badge%}}FunctionHandler.java{{%/badge%}} in the {{%badge%}}handlers{{%/badge%}} folder. We will also create a new class file {{%badge%}}GithubConstants.java{{%/badge%}} in this directory and add code in it. {{%note%}}{{%bold%}}Note:{{%/bold%}} 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.{{%/note%}} Copy the code below and paste it into the respective files located in the {{%badge%}}functions/GithubExtension/com/handlers{{%/badge%}} directory of your project using an IDE and save the files. {{% panel_with_adjustment header="BotHandler.java" footer="button" class="language-java line-numbers" scroll="set-scroll" %}}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; } } {{% /panel_with_adjustment %}} {{% panel_with_adjustment header="CommandHandler.java" footer="button" class="language-java line-numbers" scroll="set-scroll" %}}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; } } {{% /panel_with_adjustment %}} {{% panel_with_adjustment header="FunctionHandler.java" footer="button" class="language-java line-numbers" scroll="set-scroll" %}}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; } } {{% /panel_with_adjustment %}} Next,create a new Java class file in the {{%badge%}}handlers/directory{{%/badge%}} and name it {{%badge%}} GithubConstants.java{{%/badge%}}.Add the code given below to the file. {{% panel_with_adjustment header="GithubConstants.java" footer="button" class="language-java line-numbers" scroll="set-scroll" %}}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"; } {{% /panel_with_adjustment %}} {{%note%}}{{%bold%}}Note:{{%/bold%}} After you copy and paste this code,{{%bold%}}paste the personal access token that you obtained from GitHub{{%/bold%}} in Step 2 on line 6 in this code. {{%/note%}} 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 {{%link href="/en/tutorials/githubbot/java/create-extension-on-cliq" %}}configuring the extension{{%/link%}}. * The {{%badge%}}{{%bold%}}BotHandler.java{{%/bold%}}{{%/badge%}} 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 {{%badge%}}{{%bold%}}CommandHandler.java{{%/bold%}}{{%/badge%}} 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. {{%badge%}}CommandHandler.java{{%/badge%}} also defines the APIs for fetching other information from the Git account. * The {{%badge%}}{{%bold%}}FunctionHandler.java{{%/bold%}}{{%/badge%}} class contains the business logic of the button function that authenticates the webhook token for GitHub. * The {{%badge%}}{{%bold%}}GitHubConstants.java{{%/bold%}}{{%/badge%}} class file stores the constant values of the function, such as the personal access token and the bot name. -------------------------------------------------------------------------------- title: "Deploy the function" description: "Build an extension on Zoho Cliq using Catalyst Integration Functions, that enables you to access and work with your GitHub repositories using a Cliq bot" last_updated: "2026-03-18T07:41:08.681Z" source: "https://docs.catalyst.zoho.com/en/tutorials/githubbot/java/deploy-function/" service: "All Services" related: - Deploy Resources (/en/cli/v1/deploy-resources/introduction) - Integration Functions (/en/serverless/help/functions/integration-functions) -------------------------------------------------------------------------------- # Deploy the Function Let's deploy the function to make it available in the Catalyst remote console. We will need to select it while creating the extension on Cliq. To {{%link href="/en/cli/v1/deploy-resources/introduction" %}}deploy your Catalyst project from the CLI{{%/link%}}, run the following command in your terminal from your project directory: {{%cli%}} catalyst deploy{{%/cli%}} Each handler class in the Java function will be compiled and deployed to the Catalyst project in the console. -------------------------------------------------------------------------------- title: "Create an extension on Cliq" description: "Build an extension on Zoho Cliq using Catalyst Integration Functions, that enables you to access and work with your GitHub repositories using a Cliq bot" last_updated: "2026-03-18T07:41:08.681Z" source: "https://docs.catalyst.zoho.com/en/tutorials/githubbot/java/create-extension-on-cliq/" service: "All Services" related: - Integration Functions (/en/serverless/help/functions/integration-functions) -------------------------------------------------------------------------------- # Create an Extension on Cliq You can now configure the extension in Cliq. As mentioned in the introduction, this Cliq extension will bundle all the development components that we will require for this setup. You can learn about Cliq extensions in detail from the {{%link href="https://www.zoho.com/cliq/help/platform/build-cliq-extensions.html" %}}Cliq help documentation{{%/link%}}. We will add the following Cliq components to be bundled in the extension: * {{%bold%}}Command for issues:{{%/bold%}} A command handled by the {{%badge%}}CommandHandler.java{{%/badge%}} class that fetches the last ten issues raised in a specific repository. * {{%bold%}}Command for commits:{{%/bold%}} A command handled by the {{%badge%}}CommandHandler.java{{%/badge%}} class that fetches the last ten commits made in a specific repository. * {{%bold%}}Button function to authenticate the webhook token:{{%/bold%}} A function handled by the {{%badge%}}FunctionHandler.java{{%/badge%}} class that is executed when a button is clicked in the chat bot. This function authenticates the webhook token for GitHub. * {{%bold%}}GitHub bot:{{%/bold%}} A chat bot handled by the {{%badge%}}BotHandler.java{{%/badge%}} class that enables you to execute these commands. The bot also includes a menu action that lists your existing repositories, and enables you to select a repo to execute a command for. You can configure the Cliq extension in the following way: 1. Log in to your Cliq account and open the {{%link href="https://cliq.zoho.com/developer" %}}Cliq developer console{{%/link%}}. 2. The index page contains all the extensions you develop in your Cliq account. Click {{%bold%}}Create Extension{{%/bold%}}.<br /> <br /> 3. Enter the name of the extension as "{{%bold%}}GitHubExt{{%/bold%}}" and enter a description for it.<br /> <br /> 4. Select the execution type as {{%bold%}}Catalyst Function{{%/bold%}}. Select the Catalyst project {{%bold%}}GitHubBot{{%/bold%}} that we created for this tutorial and the {{%bold%}}GithubExtension{{%/bold%}} function from the dropdown lists.<br /><br /> This lets the extension invoke the function whenever any of the components in the extension are accessed.<br /><br /> We can now add the components that we will require for this extension. 5. Click {{%bold%}}Add components{{%/bold%}}, then click {{%bold%}}Command{{%/bold%}}.<br /> <br /> 6. Enter the command's name as "issues". Configure it as shown in the image below. Click {{%bold%}}Add{{%/bold%}}.<br /> <br /> 7. Similarly, click the {{%bold%}}Add components{{%/bold%}} button in the extension configuration again, then click {{%bold%}}Command{{%/bold%}}. Configure the command "commits" as shown below. Click {{%bold%}}Add{{%/bold%}}.<br /> <br /> 8. Next, add a {{%bold%}}function component{{%/bold%}} and configure the "authenticate" function as shown below. <br /> <br /> 9. Finally, add a {{%bold%}}bot component{{%/bold%}} and configure the "GitHub Bot" as shown below.<br /> <br /> Enable the {{%bold%}}Message Handler{{%/bold%}} and {{%bold%}}Incoming Webhook Handler{{%/bold%}}, and select all the checkboxes. This will enable the bot to acknowledge messages in the chat and the webhook requests received from GitHub.<br /><br /> You must also add a bot menu action "Repos" that lists and select all the checkboxes.<br /><br /> <br /> All the required components have been added.<br /><br /> {{%note%}}{{%bold%}}Note:{{%/bold%}} Ensure that you have given the same component names as specified, because we have configured the same names in the function code.{{%/note%}} 10. After you add all the components, click {{%bold%}}Create Extension{{%/bold%}} in the extension configuration page.<br /> <br /> The extension will be created and listed in your developer console. {{%note%}}{{%bold%}}Note:{{%/bold%}} Since we have hardcoded the Personal Access token to access the GitHub API in the {{%badge%}}GithubConstants.java{{%/badge%}} class, it is not advisable to publish this extension, as the code contains a confidential token.{{%/note%}} The Cliq bot will now be available in your Cliq account. The {{%badge%}}issues{{%/badge%}} and {{%badge%}}commits{{%/badge%}} commands, along with the {{%badge%}}Repos{{%/badge%}} menu action will work in the bot. Before you test these commands, you must also enable alerts to be received automatically whenever a commit is pushed to one of the repositories in the GitHub account using a webhook. -------------------------------------------------------------------------------- title: "Configure a bot" description: "Build an extension on Zoho Cliq using Catalyst Integration Functions, that enables you to access and work with your GitHub repositories using a Cliq bot" last_updated: "2026-03-18T07:41:08.681Z" source: "https://docs.catalyst.zoho.com/en/tutorials/githubbot/java/configure-bot/" service: "All Services" related: - Integration Functions (/en/serverless/help/functions/integration-functions) -------------------------------------------------------------------------------- # Configure the Bot as an Incoming Webhook Notifier Next, let's configure the bot as an incoming webhook notifier, that performs actions when the webhook URL is invoked on GitHub. You can do this in the following way: 1. Generate a webhook token on the Cliq bot 2. Obtain the App Key of your extension 3. Obtain the webhook handler URL of your extension 4. Create a webhook on GitHub and configure these values We will discuss these actions in detail one after the other. This webhook gets triggered whenever a commit is pushed to one of the repositories on your Git account. When that event occurs, GitHub makes an HTTP request to the URL webhook handler URL with the credentials that we configure. It will pass the details of that push event to Cliq, and the Cliq bot will notify you of it and display the details. ### Generate a WebHook Token You can generate a webhook token on Cliq as described below. The webhook token is authenticated by the authenticate button function that we configured in the previous step. 1. Search for the GitHub bot in your Cliq account. Select the bot and click {{%bold%}}Continue{{%/bold%}}. 2. Provide permission for the bot to access your account details. <br /> The chat will be activated. 3. Type "webhooktoken" in the chat and press {{%bold%}}Enter{{%/bold%}}. 4. Click the {{%bold%}}Create Webhook{{%/bold%}} button. 5. Allow the extension to access your authorization token. 6. The bot will now generate and display the webhook token. Copy this token. This webhook token will be the value of the {{%badge%}}{{%bold%}}zapikey{{%/bold%}}{{%/badge%}} parameter in the URL that we will configure on GitHub. ### Obtain the App Key You can obtain the App Key of the extension in the following way: 1. Click on the {{%bold%}}GitHubExt{{%/bold%}} extension from the extensions page in the {{%link href="https://cliq.zoho.com/developer" %}}Cliq developer console{{%/link%}}, then navigate to the {{%bold%}}Connectors{{%/bold%}} section. 2. Copy the Sandbox App Key of your extension.<br /> <br /> This key will be the value of the {{%badge%}}{{%bold%}}appkey{{%/bold%}}{{%/badge%}} parameter in the URL that we will configure on GitHub. ### Obtain the Webhook Handler URL You can obtain the Webhook Handler URL of the extension in the following way: 1. Navigate back to your Cliq account and click on your profile picture. Click on {{%bold%}}Bots & Tools{{%/bold%}} in the menu section.<br /> 2. Click on the {{%bold%}}GitHub Bot{{%/bold%}} from your bots list. This will open a side panel. Copy the URL displayed under _Incoming WebHook Endpoint_.<br /> <br /> This will be the base URL that we will configure on GitHub. ### Create a Webhook on GitHub The complete URL to configure on GitHub is: {{%bold%}}_baseURL_?{{%badge%}}appkey{{%/badge%}}\={{_appkey_}}&{{%badge%}}zapikey{{%/badge%}}\={{_zapikey_}}{{%/bold%}} where _baseURL_ is the webhook handler URL, {{%badge%}}appkey{{%/badge%}} is the sandbox App Key of your extension, and {{%badge%}}zapikey{{%/badge%}} is the webhook token generated on Cliq. For example: {{%bold%}}https:<span></span>//cliq.zoho.com/company/org_id/api/v2/githubbot/incoming?appkey={{_appkey_}}&zapikey={{_zapikey_}}{{%/bold%}} Let's now add this URL on GitHub in the following way: 1. Open your {{%link href="https://github.com/" %}}GitHub{{%/link%}} account and navigate to any one of your repositories. 2. Open your {{%bold%}}repository's settings{{%/bold%}}, then click {{%bold%}}Webhooks -> Add webhook{{%/bold%}}. 3. Enter the URL in the format specified above, substituting the values of {{%badge%}}appkey{{%/badge%}} and {{%badge%}}zapikey{{%/badge%}}. Configure the webhook as shown below. You can select the events that you would like to be notified about. 4. Click {{%bold%}}Add webhook{{%/bold%}}. This webhook will now enable alerts for the configured events in your repository. -------------------------------------------------------------------------------- title: "Test the GitHub bot" description: "Build an extension on Zoho Cliq using Catalyst Integration Functions, that enables you to access and work with your GitHub repositories using a Cliq bot." last_updated: "2026-03-18T07:41:08.682Z" source: "https://docs.catalyst.zoho.com/en/tutorials/githubbot/java/test-github-bot/" service: "All Services" related: - Integration Functions (/en/serverless/help/functions/integration-functions) -------------------------------------------------------------------------------- # Test the GitHub Bot We can now test the commands and functioning of the GitHub bot. Open your Cliq account and open {{%bold%}}GitHub Bot{{%/bold%}}. Let's first test the _issues_ command. All Cliq commands must be entered with a preceding '/' backslash. Type "/issues" in the bot's chat. This will trigger the Integration function and enable the command handler to fetch the repositories in your Git account. Your repositories will be displayed in the chat. <br /> Select a repository using the arrow buttons, then press {{%bold%}}Enter{{%/bold%}}. This will display the details of the last ten issues raised to that repository, if any. You can view any of these issues on GitHub by clicking on its link. <br /> You can click {{%bold%}}Post here{{%/bold%}} to post the details as a message by the bot, and {{%bold%}}Close{{%/bold%}} to remove the embedded view. Next, type "/commits" in the chat and select one of the repositories from the list. This will display the details of the last ten commits pushed to that repository, if any. <br /> You can also test the bot menu action that you configured for the GitHub bot. Type "Repos" in the chat and press {{%bold%}}Enter{{%/bold%}}. This will list the details of all the repositories in the GitHub account. <br /> You can verify if the Cliq bot alerts you whenever a commit is pushed in the repository that you configured the webhook for. Make a commit in that repository. The Cliq bot will send you an alert with the commit details and a link to access that repository. <br /> If all actions work fine, the GitHub bot is configured properly.