All files / blong-gogo/src/adapter/server slack.ts

20.38% Statements 21/103
100% Branches 0/0
100% Functions 0/0
20.38% Lines 21/103

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 1041x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x                                                                                                                                                                      
import {adapter, type Errors, type IErrorMap, type IMeta} from '@feasibleone/blong/types';
import {IncomingWebhook} from '@slack/webhook';
 
export interface IConfig {
    slack: {
        webhookUrl?: string;
    };
}
 
const errorMap: IErrorMap = {
    'slack.generic': 'Slack Error',
    'slack.invalid': 'Invalid Slack Operation',
    'slack.notFound': 'Slack Not Found',
    'slack.exists': 'Slack Exists',
    'slack.unique': 'Slack Unique',
    'slack.missingKey': 'Missing key value for {key}',
};
 
let _errors: Errors<typeof errorMap>;
 
export default adapter<IConfig>(({utError}) => {
    _errors ||= utError.register(errorMap);

    return {
        activation: {
            default: {
                type: 'slack',
                slack: {},
            },
        },
        start() {
            this.config.context = {
                slack: new IncomingWebhook(this.config.slack.webhookUrl!),
            };
            super.connect();
            return super.start();
        },
        async stop(...params: unknown[]) {
            this.config.context = {};
            return await super.stop(...params);
        },
        async exec(
            params: {
                text?: string;
                blocks?: unknown[];
                attachments?: unknown[];
                channel?: string;
                username?: string;
                iconEmoji?: string;
                iconUrl?: string;
                threadTs?: string;
                unfurlLinks?: boolean;
                unfurlMedia?: boolean;
            } & Record<string, unknown>,
            $meta: IMeta,
        ) {
            const {method} = $meta;
            const [, , operation] = method!.split('.');
            switch (operation) {
                case 'send':
                case 'post':
                case 'message': {
                    // Send a message to Slack
                    const {
                        text,
                        blocks,
                        attachments,
                        channel,
                        username,
                        iconEmoji,
                        iconUrl,
                        threadTs,
                        unfurlLinks,
                        unfurlMedia,
                    } = params;

                    if (!text && !blocks && !attachments) {
                        throw this.error(_errors['slack.invalid']({message: 'Must provide text, blocks, or attachments'}), $meta);
                    }

                    const payload: Record<string, unknown> = {};
                    if (text) payload.text = text;
                    if (blocks) payload.blocks = blocks;
                    if (attachments) payload.attachments = attachments;
                    if (channel) payload.channel = channel;
                    if (username) payload.username = username;
                    if (iconEmoji) payload.icon_emoji = iconEmoji;
                    if (iconUrl) payload.icon_url = iconUrl;
                    if (threadTs) payload.thread_ts = threadTs;
                    if (unfurlLinks !== undefined) payload.unfurl_links = unfurlLinks;
                    if (unfurlMedia !== undefined) payload.unfurl_media = unfurlMedia;

                    try {
                        return await this.config.context.slack!.send(payload);
                    } catch (error) {
                        throw this.error(_errors['slack.generic'](error), $meta);
                    }
                }
            }
            throw this.error(_errors['slack.invalid']({operation}), $meta);
        },
    };
});