forked from ohbarye/kpt-bot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
152 lines (120 loc) · 3.77 KB
/
index.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
150
151
152
'use strict';
const Botkit = require('botkit');
const moment = require('moment-timezone');
const slackBotToken = process.env.SLACK_BOT_TOKEN;
if (!slackBotToken) {
console.log('Error: Specify token in environment');
process.exit(1);
}
const commonParams = {
token: slackBotToken,
};
const controller = Botkit.slackbot({
debug: !!process.env.DEBUG
});
const bot = controller.spawn({
token: slackBotToken
})
bot.startRTM(function(err, bot, payload) {
if (err) {
throw new Error('Could not connect to Slack');
}
});
/*
This KPI bot waits for you to call him. Here is sample usage.
Format:
@bot-name summary $from_date $to_date
- from_date: Required. Start of time range of messages.
- to_date: Optional. End of time range of messages.
Sample:
@bot-name 2016-11-01 2016-11-30
The bot gathers KPTs you posted 2016-11-01 00:00:00 to 2016-11-30 23:59:59 in your timezone
from history of a channel you called the bot.
```
K
- Started daily meeting
- Find a release blocker earlier
P
- Cannot help each other... :cry:
T
- How about going lunch? :smile:
```
*/
controller.hears("^summary (.+)",["direct_message","direct_mention","mention"], (bot, message) => {
let users;
const fetchUserListDone = (err, res) => {
checkError(err);
users = res.members;
// https://api.slack.com/methods/channels.history
bot.api.callAPI('channels.history', paramsToFetchChannelHistory(message, users), postSummary);
};
const postSummary = (err, res) => {
checkError(err);
let result = { K: [], P: [], T: [] };
for (const message of res.messages) {
if (!message.text) {
continue;
}
const matched = message.text.match(/^([KkPpTt])\s+(.+)/);
if (matched) {
result[matched[1].toUpperCase()].push({
content: matched[2],
userId: message.user,
reactions: (message.reactions || []),
});
}
}
bot.reply(message, createSummary(result, users));
};
// https://api.slack.com/methods/users.list
bot.api.callAPI('users.list', commonParams, fetchUserListDone)
});
/*
If no command matched, show usage.
*/
controller.hears("^((?!summary).)*$",["direct_message","direct_mention","mention"], (bot, message) => {
const reply = `
Sorry, I can't understand the order. :cry: Can you try again?
Format:
@bot-name summary $from_date $to_date
- from_date: Required. Start of time range of messages.
- to_date: Optional. End of time range of messages.
Sample:
@bot-name summary 2016-11-01 2016-11-30
@bot-name summary 2016-11-01
`;
bot.reply(message, reply);
});
const checkError = (err) => {
if (err) {
throw new Error(`Slack API returns an error. error code: ${err}`);
}
};
const createSummary = (result, users) => {
return ['K', 'P', 'T'].map((section) => {
return `## ${section}\n\n${createSectionSummary(result[section], users)}\n`
}).join('\n')
};
const createSectionSummary = (elements, users) => {
return elements.map(e => {
const username = users.find(u => u.id == e.userId).name;
const reactions = e.reactions.map(r => ` :${r.name}: `.repeat(r.count)).join('');
return `- ${e.content} by ${username} ${reactions}`;
}).reverse().join('\n')
};
const paramsToFetchChannelHistory = (message, users) => {
const [from_date, to_date] = message.match[1].split(' ');
const userTimezone = users.find(u => u.id == message.user).tz;
let params = Object.assign(commonParams, {
channel: message.channel,
oldest: moment.tz(from_date, userTimezone).unix(),
count: 1000,
});
// `latest` is optional parameter, and its default value is `now`.
if (to_date) {
params = Object.assign(params, {
latest: moment.tz(to_date, userTimezone).endOf('day').unix(),
});
}
return params;
};