hubot-stackstorm
Version:
A hubot plugin for integrating with StackStorm event-driven infrastructure automation platform.
246 lines (219 loc) • 8.29 kB
JavaScript
// Copyright 2019 Extreme Networks, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
;
var env = process.env;
var util = require('util');
var utils = require('./../utils');
var messages = require('./../slack-messages');
var SlackLikeAdapter = require('./slack-like');
// NOTE: Be careful about making changes to this adapter, because the adapters
// for Mattermost, Cisco Spark, and Rocketchat all inherit from this one
function SlackAdapter(robot) {
var self = this;
SlackLikeAdapter.call(self, robot);
// We monkey patch sendMessage function to send "parse" argument with the message so the text is not
// formatted and parsed on the server side.
// NOTE / TODO: We can get rid of this nasty patch once our node-slack-client and hubot-slack pull
// requests are merged.
// This code was refactored in https://github.com/StackStorm/hubot-stackstorm/pull/6
// which was opened and merged by Kami on 2015-06-04.
// As of 2019-05-22, these were the PRs I could find for the node-slack-client
// hubot-slack repositories:
// * https://github.com/slackapi/node-slack-sdk/pull/42
// - which was closed during a refactor and converted into an issue:
// https://github.com/slackapi/node-slack-sdk/issues/138
// * https://github.com/slackapi/hubot-slack/pull/544
// - which was opened on 2018-11-14, which seems to be too late to actually
// apply to the original code in lib/slack_monkey_patch.js (see the Git history)
// So...I'm not entirely sure this monkey patch is still necessary.
// End-to-end testing is required to figure out for sure.
var sendMessageRaw = function(message) {
/*jshint validthis:true */
message['channel'] = this.id;
message['parse'] = 'none';
this._client._send(message);
}
if (robot.adapter && robot.adapter.constructor && robot.adapter.constructor.name === 'SlackBot') {
for (var channel in robot.adapter.client.channels) {
robot.adapter.client.channels[channel].sendMessage = sendMessageRaw.bind(robot.adapter.client.channels[channel]);
}
}
};
util.inherits(SlackAdapter, SlackLikeAdapter);
SlackAdapter.prototype.postData = function(data) {
var self = this;
var recipient, attachment_color, split_message,
attachment, pretext = "";
var envelope,
// We capture robot here so the `sendMessage` closure captures the
// correct `this`
robot = self.robot;
if (data.whisper && data.user) {
recipient = data.user;
envelope = {
"user": data.user
};
} else {
recipient = data.channel;
pretext = (data.user && !data.whisper) ? util.format('<@%s>: ', data.user) : "";
envelope = {
"room": data.channel,
"id": data.channel,
"user": data.user,
};
}
//If extra.slack.thread_response is set, we will send the response in a thread (SLACK ONLY)
var message = {};
if (data.extra && data.extra.slack && data.extra.slack.thread_response) {
message.thread_ts = data.context.id;
}
// Allow packs to specify arbitrary keys
if (data.extra && data.extra.slack && data.extra.slack.attachments) {
// Action:
//
// result:
// format: ...
// extra:
// slack:
// icon_emoji: ":jira:"
// username: Jira Bot
// attachments:
// -
// fallback: "Info about Jira ticket {{ execution.result.result.key }}"
// color: "#042A60"
// title: "{{ execution.result.result.key }}"
// title_link: "{{ execution.result.result.url }}"
// fields:
// -
// title: Summary
// value: "{{ execution.result.result.summary }}"
// short: false
//
// becomes:
//
// {
// "icon_emoji": ":jira:",
// "username": "Jira Bot",
// "attachments": [
// {
// "fallback": "Info about Jira ticket {{ execution.result.result.key }}",
// "color": "#042A60",
// "title": "{{ execution.result.result.key }}",
// "title_link": "{{ execution.result.result.url }}",
// "fields": [
// {
// "title": "Summary",
// "value": "{{ execution.result.result.summary }}",
// "short": false
// }
// ],
// }
// ]
// }
var messages_to_send = messages.buildMessages(data.extra.slack);
var sendMessage = function (i) {
robot.adapter.client.send(envelope, messages_to_send[i]);
if (messages_to_send.length > ++i) {
setTimeout(function(){sendMessage(i);}, 300);
}
};
sendMessage(0);
return;
}
if (data.extra && data.extra.color) {
attachment_color = data.extra.color;
} else {
attachment_color = env.ST2_SLACK_SUCCESS_COLOR;
if (data.message.indexOf("status : failed") > -1) {
attachment_color = env.ST2_SLACK_FAIL_COLOR;
}
}
split_message = utils.splitMessage(self.formatData(data.message));
if (split_message.text) {
var content = {
color: attachment_color,
"mrkdwn_in": ["text", "pretext"],
};
if (data.extra && data.extra.slack) {
// Backwards compatibility
// Action:
//
// result:
// format: ...
// extra:
// slack:
// author_name: Jira_Bot
// author_link: "https://stackstorm.com"
// author_icon: "https://stackstorm.com/favicon.ico"
// color: "#042A60"
// fallback: "Info about Jira ticket {{ execution.result.result.key }}"
// title: "{{ execution.result.result.key }}"
// title_link: "{{ execution.result.result.url }}"
// fields:
// -
// title: Summary
// value: "{{ execution.result.result.summary }}"
// short: false
//
// becomes:
//
// {
// "attachments": [
// {
// "author_name": "Jira Bot",
// "author_link": "https://stackstorm.com",
// "author_icon": "https://stackstorm.com/favicon.ico",
// "color": "#042A60",
// "fallback": "Info about Jira ticket {{ execution.result.result.key }}",
// "title": "{{ execution.result.result.key }}",
// "title_link": "{{ execution.result.result.url }}",
// "fields": [
// {
// "title": "Summary",
// "value": "{{ execution.result.result.summary }}",
// "short": false
// }
// ]
// }
// ]
// }
for (var attrname in data.extra.slack) { content[attrname] = data.extra.slack[attrname]; }
}
var chunks = split_message.text.match(/[\s\S]{1,7900}/g);
var sendChunk = function (i) {
content.pretext = i === 0 ? pretext + split_message.pretext : null;
content.text = chunks[i];
content.fallback = chunks[i];
message.attachments = [content];
robot.adapter.client.send(envelope, message);
if (chunks.length > ++i) {
setTimeout(function(){ sendChunk(i); }, 300);
}
};
sendChunk(0);
} else {
self.robot.adapter.client.send(envelope, pretext + split_message.pretext);
}
};
SlackAdapter.prototype.normalizeCommand = function(command) {
var self = this;
command = SlackLikeAdapter.prototype.normalizeCommand.call(self, command);
// replace non-breaking space with regular space
// first the unicode variant, so we don't cut it in half,
// then the latin1 variant (thanks to slack)
command = command.replace(/\u00A0/g, ' ');
command = command.replace(/\xA0/g, ' ');
return command;
}
module.exports = SlackAdapter;