Aviso:

Para brindarle información de soporte completa de manera más rápida, el contenido de esta página ha sido traducido al español mediante traducción automática. Para consultar la información de soporte más precisa, consulte la versión en inglés de este contenido.

Configurar la Integration Function

Ahora configuraremos la Integration Function y le agregaremos código.

Nota: Necesitaremos codificar y desplegar la función en la consola remota de Catalyst antes de configurar la extensión en Cliq, porque debemos asociar la extensión con una función existente en la consola de Catalyst.

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.

Nota: Revisa el código en esta sección para asegurarte de comprenderlo completamente. Analizaremos el código al final de esta sección.

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.

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.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;
}

}

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.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;
}

}

View more

FunctionHandler.java
copy
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;
}

}

View more

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.

GithubConstants.java
copy
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”; }

View more

Nota: Después de copiar y pegar este código, pega el token de acceso personal que obtuviste de GitHub en el paso 2, en la línea 6 de este código.

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

ENLACES RELACIONADOS

Integration Functions