@naturalcycles/nodejs-lib
Version:
Standard library for Node.js
107 lines • 3.41 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const js_lib_1 = require("@naturalcycles/js-lib");
const time_lib_1 = require("@naturalcycles/time-lib");
const got_1 = require("got");
const __1 = require("..");
const GAE = !!process.env.GAE_INSTANCE;
const DEFAULTS = () => ({
username: 'bot',
channel: '#log',
icon_emoji: ':spider_web:',
text: 'no text',
});
const log = __1.Debug('nc:nodejs-lib:slack');
class SlackSharedService {
constructor(slackServiceCfg) {
this.slackServiceCfg = slackServiceCfg;
}
// Convenience method
async send(text, ctx) {
await this.sendMsg({
text,
}, ctx);
}
// todo: log method that allows many input objects, like console.log()
/**
* Send error.
*/
async error(_err, opts = {}, ctx) {
const err = js_lib_1._anyToErrorObject(_err);
const text = err.stack || err.message;
await this.sendMsg({
level: __1.DebugLogLevel.error,
...opts,
text,
}, ctx);
}
async sendMsg(msg, ctx) {
var _a;
const { webhookUrl } = this.slackServiceCfg;
if (!msg.noLog) {
log[msg.level || __1.DebugLogLevel.info](...[msg.text, msg.kv, msg.attachments, msg.mentions].filter(Boolean));
}
if (!webhookUrl)
return;
this.processKV(msg);
let text = __1.inspectAny(msg.text, {
colors: false,
});
// Wrap in markdown-text-block if it's anything but plain String
if (typeof msg.text !== 'string') {
text = '```' + text + '```';
}
if ((_a = msg.mentions) === null || _a === void 0 ? void 0 : _a.length) {
text += '\n' + msg.mentions.map(s => `<@${s}>`).join(' ');
}
const body = {
...DEFAULTS(),
...this.slackServiceCfg.defaults,
...msg,
text,
};
body.channel = (this.slackServiceCfg.channelByLevel || {})[msg.level] || body.channel;
await this.decorateMsg(body, ctx);
await got_1.default
.post(webhookUrl, {
json: body,
})
.catch(err => {
// ignore (unless throwOnError is set), cause slack is weirdly returning non-json text "ok" response
if (msg.throwOnError)
throw err;
});
}
/**
* Mutates msg.
* To be overridden.
*/
async decorateMsg(msg, ctx) {
const tokens = [time_lib_1.dayjs().toPretty()];
// AppEngine-specific decoration
if (GAE && ctx && typeof ctx === 'object' && typeof ctx.header === 'function') {
tokens.push(ctx.header('x-appengine-country'), ctx.header('x-appengine-city'));
}
msg.text = [tokens.filter(Boolean).join(': '), msg.text].join('\n');
}
kvToFields(kv) {
return Object.entries(kv).map(([k, v]) => ({
title: k,
value: String(v),
short: String(v).length < 80,
}));
}
/**
* mutates
*/
processKV(msg) {
if (!msg.kv)
return;
msg.attachments = (msg.attachments || []).concat({
fields: this.kvToFields(msg.kv),
});
delete msg.kv;
}
}
exports.SlackSharedService = SlackSharedService;
//# sourceMappingURL=slack.shared.service.js.map