Configurar la Integration Function
Ahora configuraremos la Integration Function y le agregaremos código.
El directorio de la Integration Function functions/GithubExtension contiene:
- El archivo principal de la función MainClass.java
- Los archivos de handlers en la carpeta com/handlers
- El archivo de configuración catalyst-config.json
- Los archivos de biblioteca Java en la carpeta lib
- Los archivos de dependencias .classpath y .project
Codificaremos BotHandler.java, CommandHandler.java y FunctionHandler.java en la carpeta handlers. También crearemos un nuevo archivo de clase GithubConstants.java en este directorio y le agregaremos código.
Copia el código a continuación y pégalo en los archivos correspondientes ubicados en el directorio functions/GithubExtension/com/handlers de tu proyecto usando un IDE y guarda los archivos.
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"); // ** INGRESA EL NOMBRE DE TU BUTTON FUNCTION AQUÍ **
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");
// Usar Map en lugar de JSONObject
Map<String, Object> data = new HashMap<>();
data.put("headers", headers);
// Usar List en lugar de 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);
/// mensaje
Message msg = Message.getInstance("A commit has been pushed !");
msg.setBot(BotDetails.getInstance(GithubConstants.BOT_NAME));
/// mensaje del commit
Slide commitMsg = Slide.getInstance();
commitMsg.setType(SLIDE_TYPE.TEXT);
commitMsg.setTitle("Commit message");
commitMsg.setData(commitJson.optString("message"));
msg.addSlide(commitMsg);
// diapositiva
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");
// Usar Map en lugar de JSONObject
Map<String, Object> data = new HashMap<>();
data.put("headers", headers);
// Usar List en lugar de 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");
// Usar Map en lugar de JSONObject
Map<String, Object> data = new HashMap<>();
data.put("headers", headers);
// Usar List en lugar de 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;
}
}
A continuación, crea un nuevo archivo de clase Java en el directorio handlers/ y nómbralo GithubConstants.java. Agrega el código proporcionado a continuación en el archivo.
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”;
}
El directorio de funciones está ahora configurado.
Repasemos rápidamente el código de las clases de handlers. Analizaremos los componentes especificados aquí en detalle al configurar la extensión.
-
La clase BotHandler.java contiene la lógica de negocio del componente del bot de GitHub que configuraremos en la extensión de Cliq. Después de habilitar el bot de chat, podrás generar un token de webhook para autenticar la conexión con GitHub, listar los detalles de tus repositorios de Git y obtener los detalles de los últimos commits e issues en un repositorio. Estas acciones se definen en esta clase.
-
La clase CommandHandler.java maneja las acciones que se deben realizar para los comandos de issues y commits. También define el handler de sugerencias que lista los repositorios de la cuenta de Git. El usuario debe seleccionar un repositorio de la sugerencia después de ingresar el comando, para ejecutar el comando en ese repositorio. CommandHandler.java también define las APIs para obtener otra información de la cuenta de Git.
-
La clase FunctionHandler.java contiene la lógica de negocio de la button function que autentica el token de webhook para GitHub.
-
El archivo de clase GitHubConstants.java almacena los valores constantes de la función, como el token de acceso personal y el nombre del bot.
Última actualización 2026-03-30 13:40:30 +0530 IST