UNPKG

@atomist/automation-client

Version:

Atomist API for software low-level client

303 lines • 10.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const flat_1 = require("flat"); const _ = require("lodash"); const metadataReading_1 = require("../../internal/metadata/metadataReading"); const MessageClientSupport_1 = require("./MessageClientSupport"); /** * Message Destination for the Web App. */ class WebDestination { constructor() { this.userAgent = WebDestination.WEB_USER_AGENT; } } exports.WebDestination = WebDestination; WebDestination.WEB_USER_AGENT = "web"; /** * Message Destination for the Web App. */ class SourceDestination { constructor(source, system) { this.source = source; this.system = system; this.userAgent = SourceDestination.SOURCE_USER_AGENT; } } exports.SourceDestination = SourceDestination; SourceDestination.SOURCE_USER_AGENT = "source"; function addressWeb() { return new WebDestination(); } exports.addressWeb = addressWeb; /** * Message Destination for Slack. */ class SlackDestination { /** * Create a Destination suitable for sending messages to a Slack * workspace. * * @param team Slack workspace ID, which typically starts with the * letter "T", consists of numbers and upper-case letters, * and is nine characters long. It can be obtained by * sending the Atomist Slack bot the message "team". * @return {SlackDestination} A MessageClient suitable for sending messages. */ constructor(team) { this.team = team; this.userAgent = SlackDestination.SLACK_USER_AGENT; /** Slack user names to send message to. */ this.users = []; /** Slack channel names to send message to. */ this.channels = []; } /** * Address user by Slack user name. This method appends the * provided user to a list of users that will be sent the message * via this Destination. In other words, calling repeatedly with * differing Slack user names results in the message being sent to * all such users. * * @param {string} user Slack user name. * @returns {SlackDestination} MessageClient Destination that results * in message being send to user. */ addressUser(user) { this.users.push(user); return this; } /** * Address channel by Slack channel name. This method appends the * provided channel to a list of channels that will be sent the * message via this Destination. In other words, calling * repeatedly with differing Slack channel names results in the * message being sent to all such channels. * * @param {string} channel Slack channel name. * @returns {SlackDestination} MessageClient Destination that results * in message being send to channel. */ addressChannel(channel) { this.channels.push(channel); return this; } } exports.SlackDestination = SlackDestination; SlackDestination.SLACK_USER_AGENT = "slack"; /** * Shortcut for creating a SlackDestination which addresses the given * users. * * @param {string} team Slack workspace ID to create Destination for. * @param {string} users Slack user names to send message to. * @returns {SlackDestination} MessageClient Destination to pass to `send`. */ function addressSlackUsers(team, ...users) { const sd = new SlackDestination(team); users.forEach(u => sd.addressUser(u)); return sd; } exports.addressSlackUsers = addressSlackUsers; /** * Shortcut for creating a SlackDestination which addresses the given * users in all Slack teams connected to the context. * * @param {HandlerContext} ctx Handler context as passed to the Handler handle method. * @param {string} users Slack user names to send message to. * @returns {Promise<SlackDestination>} MessageClient Destination to pass to `send`. */ function addressSlackUsersFromContext(ctx, ...users) { return MessageClientSupport_1.lookupChatTeam(ctx.graphClient) .then(chatTeamId => { return addressSlackUsers(chatTeamId, ...users); }); } exports.addressSlackUsersFromContext = addressSlackUsersFromContext; /** * Shortcut for creating a SlackDestination which addresses the given * channels. * * @param {string} team Slack workspace ID to create Destination for. * @param {string} channels Slack channel names to send messages to. * @returns {SlackDestination} MessageClient Destination to pass to `send`. */ function addressSlackChannels(team, ...channels) { const sd = new SlackDestination(team); channels.forEach(c => sd.addressChannel(c)); return sd; } exports.addressSlackChannels = addressSlackChannels; /** * Shortcut for creating a SlackDestination which addresses the given * channels in all Slack teams connected to the context. * * @param {HandlerContext} ctx Handler context as passed to the Handler handle method. * @param {string} channels Slack channel names to send messages to. * @returns {Promise<SlackDestination>} MessageClient Destination to pass to `send`. */ function addressSlackChannelsFromContext(ctx, ...channels) { return MessageClientSupport_1.lookupChatTeam(ctx.graphClient) .then(chatTeamId => { return addressSlackChannels(chatTeamId, ...channels); }); } exports.addressSlackChannelsFromContext = addressSlackChannelsFromContext; /** * Message Destination for Custom Event types. */ class CustomEventDestination { /** * Constructur returning a Destination for creating an instance of * the Custom Event type `rootType`. */ constructor(rootType) { this.rootType = rootType; this.userAgent = CustomEventDestination.INGESTER_USER_AGENT; } } exports.CustomEventDestination = CustomEventDestination; CustomEventDestination.INGESTER_USER_AGENT = "ingester"; /** * Helper wrapping the constructor for CustomEventDestination. */ function addressEvent(rootType) { return new CustomEventDestination(rootType); } exports.addressEvent = addressEvent; /** Valid MessageClient types. */ exports.MessageMimeTypes = { SLACK_JSON: "application/x-atomist-slack+json", SLACK_FILE_JSON: "application/x-atomist-slack-file+json", PLAIN_TEXT: "text/plain", APPLICATION_JSON: "application/json", }; /** * Create a slack button that invokes a command handler. */ function buttonForCommand(buttonSpec, command, parameters = {}) { const cmd = commandName(command); const params = mergeParameters(command, parameters); const id = cmd.toLocaleLowerCase(); const action = chatButtonFrom(buttonSpec, { id }); action.command = { id, name: cmd, parameters: params, }; return action; } exports.buttonForCommand = buttonForCommand; /** * Create a Slack menu that invokes a command handler. */ function menuForCommand(selectSpec, command, parameterName, parameters = {}) { const cmd = commandName(command); const params = mergeParameters(command, parameters); const id = cmd.toLocaleLowerCase(); const action = chatMenuFrom(selectSpec, { id, parameterName }); action.command = { id, name: cmd, parameters: params, parameterName, }; return action; } exports.menuForCommand = menuForCommand; /** * Check if the object is a valid Slack message. */ function isSlackMessage(object) { return !!object && (object.text || object.attachments) && !object.content; } exports.isSlackMessage = isSlackMessage; /** * Check if the object is a valid Slack file message, i.e., a snippet. */ function isFileMessage(object) { return !!object && !object.length && object.content; } exports.isFileMessage = isFileMessage; /** * Extract command name from the argument. */ function commandName(command) { try { if (typeof command === "string") { return command; } else if (typeof command === "function") { return command.prototype.constructor.name; } else { return metadataReading_1.metadataFromInstance(command).name; } } catch (e) { throw new Error("Unable to determine the name of this command. " + "Please pass the name as a string or an instance of the command"); } } exports.commandName = commandName; /** * Merge the provided parameters into any parameters provided as * command object instance variables. */ function mergeParameters(command, parameters) { // Reuse parameters defined on the instance if (typeof command !== "string" && typeof command !== "function") { const newParameters = _.merge(command, parameters); return flat_1.flatten(newParameters); } return flat_1.flatten(parameters); } exports.mergeParameters = mergeParameters; function chatButtonFrom(action, command) { if (!command.id) { throw new Error(`Please provide a valid non-empty command id`); } const button = { text: action.text, type: "button", name: `automation-command::${command.id}`, }; _.forOwn(action, (v, k) => { button[k] = v; }); return button; } function chatMenuFrom(action, command) { if (!command.id) { throw new Error("SelectableIdentifiableInstruction must have id set"); } if (!command.parameterName) { throw new Error("SelectableIdentifiableInstruction must have parameterName set"); } const select = { text: action.text, type: "select", name: `automation-command::${command.id}`, }; if (typeof action.options === "string") { select.data_source = action.options; } else if (action.options.length > 0) { const first = action.options[0]; if (first.value) { // then it's normal options select.options = action.options; } else { // then it's option groups select.option_groups = action.options; } } _.forOwn(action, (v, k) => { if (k !== "options") { select[k] = v; } }); return select; } //# sourceMappingURL=MessageClient.js.map