--- title: "Integration Functionの設定" url: https://docs.catalyst.zoho.com/ja/tutorials/githubbot/java/configure-integration-function/ description: "Catalyst Integration Functionsを使用してZoho Cliq上にエクステンションを構築し、Cliqボットを通じてGitHubリポジトリにアクセスして操作できるようにします" last_updated: 2026-02-23T12:39:41Z service: All Services type: tutorial related_links: - name: "Integration Functions" url: /ja/serverless/help/functions/integration-functions --- # Integration Functionの設定 Integration Functionを設定し、コードを追加します。 > **Note:** Cliq上でエクステンションを設定する前に、ファンクションをコーディングしてCatalystリモートコンソールにデプロイする必要があります。エクステンションをCatalystコンソールの既存のファンクションに関連付ける必要があるためです。 [Integration Functionのディレクトリ](https://docs.catalyst.zoho.com/ja/serverless/help/functions/integration-functions)`functions/GithubExtension`には以下が含まれます。 * `MainClass.java`メインファンクションファイル * `com/handlers`フォルダ内のハンドラーファイル * `catalyst-config.json`設定ファイル * libフォルダ内のJavaライブラリファイル * `.classpath`と`.project`の依存関係ファイル `handlers`フォルダ内の`BotHandler.java`、`CommandHandler.java`、`FunctionHandler.java`をコーディングします。また、このディレクトリに新しいクラスファイル`GithubConstants.java`を作成し、コードを追加します。 > **Note:** このセクションのコードを十分に理解するために、必ず目を通してください。コードの説明はこのセクションの最後で行います。 以下のコードをコピーして、IDEを使用してプロジェクトの`functions/GithubExtension/com/handlers`ディレクトリにある各ファイルに貼り付けて保存してください。 **BotHandler.java** ```java 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"); // ** ボタンファンクション名をここに入力 ** 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 headers = new ArrayList<>(); headers.add("Name"); headers.add("Private"); headers.add("Open Issues"); headers.add("Link"); // JSONObjectの代わりにMapを使用 Map data = new HashMap<>(); data.put("headers", headers); // JSONArrayの代わりにListを使用 List> rows = new ArrayList<>(); for (int i = 0; i < reposArray.length(); i++) { JSONObject repo = reposArray.optJSONObject(i); Map 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 msg = Message.getInstance("A commit has been pushed !"); msg.setBot(BotDetails.getInstance(GithubConstants.BOT_NAME)); /// コミットメッセージ Slide commitMsg = Slide.getInstance(); commitMsg.setType(SLIDE_TYPE.TEXT); commitMsg.setTitle("Commit message"); commitMsg.setData(commitJson.optString("message")); msg.addSlide(commitMsg); // スライド 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 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; } } ``` **CommandHandler.java** ```java 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 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の代わりにMapを使用 Map data = new HashMap<>(); data.put("headers", headers); // JSONArrayの代わりにListを使用 List> 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 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 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の代わりにMapを使用 Map data = new HashMap<>(); data.put("headers", headers); // JSONArrayの代わりにListを使用 List> rows = new ArrayList<>(); for (int i = 0; i < issuesArray.length(); i++) { JSONObject issueObj = issuesArray.optJSONObject(i); Map 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 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; } } ``` **FunctionHandler.java** ```java 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; } } ``` 次に、`handlers/directory`に新しいJavaクラスファイルを作成し、` GithubConstants.java`という名前を付けます。以下のコードをファイルに追加してください。 **GithubConstants.java** ```java 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"; } ``` > **Note:** このコードをコピー&ペーストした後、ステップ2でGitHubから取得したパーソナルアクセストークンをこのコードの6行目に**貼り付けてください**。 ファンクションディレクトリの設定が完了しました。 ハンドラークラスのコードを簡単に確認しましょう。ここで指定したコンポーネントの詳細については、[エクステンションの設定](https://docs.catalyst.zoho.com/ja/tutorials/githubbot/java/create-extension-on-cliq)で説明します。 * `BotHandler.java`クラスには、Cliqエクステンションで設定するGitHub Botコンポーネントのビジネスロジックが含まれています。チャットボットを有効にすると、GitHubへの接続を認証するためのwebhookトークンの生成、Gitリポジトリの詳細の一覧表示、リポジトリの最新コミットやIssueの詳細取得が可能になります。これらのアクションはこのクラスで定義されています。 * `CommandHandler.java`クラスは、issuesコマンドとcommitsコマンドで実行されるアクションを処理します。また、Gitアカウントのリポジトリを一覧表示するサジェスションハンドラーも定義しています。ユーザーはコマンドを入力した後、サジェスションからリポジトリを選択してコマンドを実行する必要があります。`CommandHandler.java`は、Gitアカウントから他の情報を取得するためのAPIも定義しています。 * `FunctionHandler.java`クラスには、GitHubのwebhookトークンを認証するボタンファンクションのビジネスロジックが含まれています。 * `GitHubConstants.java`クラスファイルは、パーソナルアクセストークンやボット名など、ファンクションの定数値を格納しています。