forked from johnagan/triagebot-example
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtriage.js
149 lines (124 loc) · 5.09 KB
/
triage.js
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
const DEFAULTS = require('./settings.json'),
i18n = require('i18n');
/**
* Create a triage report
*
* @param {Object} payload - The Slack slash command payload
* @param {Object[]} message - The Slack message history
* @param {Object} options - (optional) settings overrides
* @returns {Object} The Slack triage report message
*/
function create(payload, messages, options) {
console.log("Messages \n");
console.log(messages);
console.log("Options \n");
console.log(options);
console.log("Payload \n");
console.log(payload);
let settings = Object.assign({}, DEFAULTS, options);
console.log("Settings \n");
console.log(settings);
let map = getRequest.bind(null, settings);
console.log("Map \n");
console.log(map);
let sort = (a, b) => a.priority - b.priority;
let filter = m => m.emoji
console.log("Sort \n");
console.log(sort);
console.log("Filter \n");
console.log(filter);
let requests = messages.map(map).filter(filter).sort(sort);
console.log("Requests \n");
console.log(requests);
let message = buildMessage(payload, requests, settings);
console.log("Message \n");
console.log(message);
return message;
}
/**
* Get triage request details from a Slack message
*
* @param {Object} settings - The triage report settings
* @param {Object} message - A Slack message
* @returns {Object} A triage object
*/
function getRequest(settings, message) {
// the emoji that was matched
let test = new RegExp(settings.pending.emojis.join('|'));
let match = message.text.match(test);
let emoji = match ? match[0] : null;
// flags based on reactions
let reactions = (message.reactions || []).map(r => r.name);
let addressed = settings.addressed.emojis.some(e => reactions.includes(e.replace(/:/g, '')));
let review = settings.review.emojis.some(e => reactions.includes(e.replace(/:/g, ''))) && !addressed;
let pending = emoji && !review && !addressed;
let id = message.ts.replace('.', ''); // deep link id
let bot = message.subtype === 'bot_message'; // bot posts
let priority = settings.pending.emojis.indexOf(emoji); // display order
return { bot, priority, emoji, review, addressed, pending, id, message };
}
/**
* Build a Slack triage response
*
* @param {Object} settings - The triage report settings
* @param {Object} payload - The Slack slash command payload
* @param {Object[]} requests - The triage request details
* @returns {Object} The Slack triage report message
*/
function buildMessage(payload, requests, settings) {
let {channel_id, channel_name} = payload;
let message = { unfurl_links: settings.unfurl_links };
let publish_test = new RegExp(settings.publish_text, 'i');
// build display text
let map = buildSection.bind(null, settings, requests, payload);
message.text = settings.display.map(map).join('\n\n\n');
// attach instructions if not publish else make public
let pending_emojis = settings.pending.emojis.join(', ');
let review_emojis = settings.review.emojis.join(', ');
let addressed_emojis = settings.addressed.emojis.join(', ');
let help_text = [
"I look at the last 1000 messages posted in this channel.",
"I'll only review messages that have one of these reacji - {{pending_emojis}}.",
"If a message has one of these reacji - {{review_emojis}} - it's in progress.",
"If it has one of these reacji - {{addressed_emojis}} - it's done. Otherwise it's still pending."
]
let attachment = [
{
color: "#fff",
text: "\n"
},
{
mrkdwn_in: ["text", "pretext"],
pretext: i18n.__("Here's how the *Triage Bot* works:"),
text: i18n.__(help_text.join("\n"), { pending_emojis: pending_emojis, review_emojis: review_emojis, addressed_emojis: addressed_emojis})
},
{
mrkdwn_in: ["pretext"],
pretext: i18n.__("To publish this to the channel type `/triage publish`.")
}
];
if (publish_test.test(payload.text)) message.response_type = 'in_channel';
else message.attachments = attachment;
return message;
}
/**
* Build a triage section's text
*
* @param {String} name - The section name
* @param {Object} settings - The triage report settings
* @param {Object[]} requests - The triage request details
* @param {Object} payload - The Slack slash command payload
* @returns {String} The section text
*/
function buildSection(settings, requests, payload, name) {
let {channel_id, channel_name, team_domain} = payload;
let baseUrl = `https://${team_domain}.slack.com/archives/${channel_name}/p`;
let filtered = requests.filter(r => r[name]); // filtered list of requests
let title = i18n.__(settings[name].title, {count: filtered.length, channel: '<#'+channel_id+'|'+channel_name+'>' }); // section title
title = title.replace(/</g, `<`); // Lightweight encoding of HTML Entities
title = title.replace(/>/g, `>`); // Lightweight encoding of HTML Entities
let items = filtered.map(r => `${r.emoji} ${baseUrl + r.id}`); // section line item
let text = [title].concat(items).join('\n'); // combined text
return text;
}
module.exports = create;