UNPKG

@urban-bot/slack

Version:

Create Slack chatbot with urban-bot

367 lines 15 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.UrbanBotSlack = void 0; /* eslint-disable @typescript-eslint/camelcase */ const events_api_1 = require("@slack/events-api"); const interactive_messages_1 = require("@slack/interactive-messages"); const web_api_1 = require("@slack/web-api"); const body_parser_1 = __importDefault(require("body-parser")); const format_1 = require("./format"); const utils_1 = require("./utils"); class UrbanBotSlack { constructor(options) { this.options = options; this.type = UrbanBotSlack.TYPE; this.defaultParseMode = 'markdown'; this.commandPrefix = '/'; this.handleAction = (ctx) => { if (ctx.actions.length > 0 && ctx.actions[0].type === 'button') { if (ctx.actions[0].value === undefined) { return; } const adaptedCtx = { type: 'action', chat: { id: ctx.channel.id, }, from: { id: ctx.user.id, username: ctx.user.username, }, payload: { actionId: ctx.actions[0].value, }, nativeEvent: { type: UrbanBotSlack.TYPE, payload: ctx, }, }; this.processUpdate(adaptedCtx); } }; this.handleMessage = (ctx) => { if (ctx.bot_id !== undefined) { return; } const common = { chat: { id: ctx.channel, type: ctx.channel_type, }, from: { id: ctx.user, }, nativeEvent: { type: UrbanBotSlack.TYPE, payload: ctx, }, }; if (ctx.files !== undefined) { const files = ctx.files.map((file) => { return { mimeType: file.mimetype, width: file.original_w, height: file.original_h, id: file.id, size: file.size, name: file.name, }; }); const fileEvent = { ...common, payload: { messageId: ctx.client_msg_id, text: ctx.text, files, }, }; const isAllImages = files.every(({ mimeType }) => (0, utils_1.getTypeByMimeType)(mimeType) === 'image'); const isAllVideo = files.every(({ mimeType }) => (0, utils_1.getTypeByMimeType)(mimeType) === 'video'); const isAllAudio = files.every(({ mimeType }) => (0, utils_1.getTypeByMimeType)(mimeType) === 'audio'); if (isAllImages) { this.processUpdate({ type: 'image', ...fileEvent, }); } else if (isAllVideo) { this.processUpdate({ type: 'video', ...fileEvent, }); } else if (isAllAudio) { this.processUpdate({ type: 'audio', ...fileEvent, }); } else { this.processUpdate({ ...fileEvent, type: 'file', }); } return; } if (ctx.subtype) { return; } const textEvent = { ...common, type: 'text', payload: { messageId: ctx.client_msg_id, text: ctx.text, }, }; return this.processUpdate(textEvent); }; this.handleCommand = (req, res) => { const { channel_id, command, text, user_id, user_name, channel_name } = req.body; const ctx = { type: 'command', chat: { id: channel_id, title: channel_name, username: user_name, }, payload: { command, // command has no message_id messageId: command, argument: text, }, from: { id: user_id, username: user_name, }, nativeEvent: { type: UrbanBotSlack.TYPE, payload: req.body, }, }; this.processUpdate(ctx); res.sendStatus(200); }; this.client = new web_api_1.WebClient(options.token); this.events = (0, events_api_1.createEventAdapter)(options.signingSecret); this.interactions = (0, interactive_messages_1.createMessageAdapter)(options.signingSecret); // eslint-disable-next-line @typescript-eslint/ban-ts-ignore // @ts-ignore this.events extends EventEmitter this.events.on('error', console.error); // eslint-disable-next-line @typescript-eslint/ban-ts-ignore // @ts-ignore this.events extends EventEmitter this.events.on('message', this.handleMessage); this.interactions.action(/.*/, this.handleAction); } initializeServer(expressApp) { var _a; const pathnamePrefix = (_a = this.options.pathnamePrefix) !== null && _a !== void 0 ? _a : ''; expressApp.use(`${pathnamePrefix}/slack/events`, this.events.expressMiddleware()); expressApp.use(`${pathnamePrefix}/slack/actions`, this.interactions.expressMiddleware()); expressApp.post(`${pathnamePrefix}/slack/commands`, body_parser_1.default.urlencoded({ extended: false }), this.handleCommand); } processUpdate(_event) { throw new Error('this method must be overridden'); } async sendMessage(message) { var _a, _b, _c; switch (message.nodeName) { case 'urban-text': { return this.client.chat.postMessage({ channel: message.chat.id, text: message.data.text, }); } case 'urban-img': { if (typeof message.data.file !== 'string') { if (message.data.buttons !== undefined) { console.error("@urban-bot/slack doesn't support buttons prop with file from file system. Change file to url or send buttons separately."); } return this.client.files.upload({ file: message.data.file, channels: message.chat.id, filename: message.data.name, title: message.data.title, }); } const blocks = [ { type: 'image', title: { type: 'plain_text', text: (_a = message.data.title) !== null && _a !== void 0 ? _a : '', emoji: true, }, image_url: message.data.file, alt_text: (_b = message.data.alt) !== null && _b !== void 0 ? _b : 'image', }, ]; if (message.data.buttons !== undefined) { blocks.push({ type: 'actions', elements: (0, format_1.formatButtons)(message.data.buttons), }); } return this.client.chat.postMessage({ channel: message.chat.id, blocks, text: (_c = message.data.title) !== null && _c !== void 0 ? _c : '', }); } case 'urban-audio': { if (typeof message.data.file === 'string') { throw new Error("@urban-bot/slack doesn't support audio file as string"); } return this.client.files.upload({ file: message.data.file, channels: message.chat.id, filename: message.data.name, title: message.data.title, }); } case 'urban-video': { if (typeof message.data.file === 'string') { throw new Error("@urban-bot/slack doesn't support video file as string"); } return this.client.files.upload({ file: message.data.file, channels: message.chat.id, filename: message.data.name, title: message.data.title, }); } case 'urban-file': { if (typeof message.data.file === 'string') { throw new Error("@urban-bot/slack doesn't support file as string"); } return this.client.files.upload({ file: message.data.file, filename: message.data.name, channels: message.chat.id, title: message.data.title, }); } case 'urban-animation': { if (typeof message.data.file === 'string') { throw new Error("@urban-bot/slack doesn't support animation file as string"); } return this.client.files.upload({ file: message.data.file, filename: message.data.name, channels: message.chat.id, title: message.data.title, }); } case 'urban-buttons': { const elements = (0, format_1.formatButtons)(message.data.buttons); const blocks = []; if (message.data.title !== undefined) { blocks.push((0, format_1.formatTitle)(message.data.title)); } blocks.push({ type: 'actions', elements, }); return this.client.chat.postMessage({ channel: message.chat.id, blocks, text: message.data.title, }); } case 'urban-contact': { const { firstName, lastName, username, phoneNumber } = message.data; return this.client.chat.postMessage({ channel: message.chat.id, text: (0, format_1.withRightSpaceIfExist)(firstName) + (0, format_1.withRightSpaceIfExist)(lastName) + '\n' + (0, format_1.withRightSpaceIfExist)(username) + '\n' + (0, format_1.withRightSpaceIfExist)(String(phoneNumber)), }); } default: { throw new Error(`Tag '${ // eslint-disable-next-line @typescript-eslint/no-explicit-any message.nodeName}' is not supported. Please don't use it with slack bot or add this logic to @urban-bot/slack.`); } } } async updateMessage(message) { var _a, _b, _c; switch (message.nodeName) { case 'urban-text': { this.client.chat.update({ channel: message.meta.channel, ts: message.meta.ts, text: message.data.text, }); break; } case 'urban-img': { if (typeof message.data.file !== 'string') { throw new Error('Provide urban-img file as string if you want to edit the image message. @urban-bot/slack'); } const blocks = [ { type: 'image', title: { type: 'plain_text', text: (_a = message.data.title) !== null && _a !== void 0 ? _a : '', emoji: true, }, image_url: message.data.file, alt_text: (_b = message.data.alt) !== null && _b !== void 0 ? _b : '', }, ]; if (message.data.buttons !== undefined) { blocks.push({ type: 'actions', elements: (0, format_1.formatButtons)(message.data.buttons), }); } this.client.chat.update({ channel: message.meta.channel, ts: message.meta.ts, blocks, text: (_c = message.data.title) !== null && _c !== void 0 ? _c : '', // TODO: investigate me }); break; } case 'urban-buttons': { const elements = (0, format_1.formatButtons)(message.data.buttons); const blocks = []; if (message.data.title !== undefined) { blocks.push((0, format_1.formatTitle)(message.data.title)); } blocks.push({ type: 'actions', elements, }); this.client.chat.update({ channel: message.meta.channel, ts: message.meta.ts, blocks, text: message.data.title, }); break; } default: { throw new Error(`Tag '${ // eslint-disable-next-line @typescript-eslint/no-explicit-any message.nodeName}' is not supported to update the message for @urban-bot/slack. You could send a new message every time for this tag.`); } } } deleteMessage(message) { this.client.chat.delete({ channel: message.meta.channel, ts: message.meta.ts }); } } exports.UrbanBotSlack = UrbanBotSlack; UrbanBotSlack.TYPE = 'SLACK'; //# sourceMappingURL=UrbanBotSlack.js.map