This repository has been archived by the owner on Jan 11, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.js
158 lines (140 loc) · 7.1 KB
/
app.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
153
154
155
156
157
158
var changeCase = require('change-case');
var config = require('./config.json');
var format = require('string-template');
var RtmClient = require('@slack/client').RtmClient;
var MemoryDataStore = require('@slack/client').MemoryDataStore;
var CLIENT_EVENTS = require('@slack/client').CLIENT_EVENTS;
var RTM_EVENTS = require('@slack/client').RTM_EVENTS;
if (typeof config.ignoreSelf === 'undefined') {
config.ignoreSelf = false;
}
var jira = false;
if (typeof config.jira !== 'undefined') {
var Jira = require('jira').JiraApi;
jira = new Jira(config.jira.protocol, config.jira.host, config.jira.port, config.jira.user, config.jira.password, '2');
}
var rtm = new RtmClient(config.token, {
logLevel: 'error',
dataStore: new MemoryDataStore(),
autoReconnect: true,
autoMark: true
});
rtm.start();
rtm.on(CLIENT_EVENTS.RTM.AUTHENTICATED, function (rtmStartData) {
console.log(`Logged in as ${rtmStartData.self.name} of team ${rtmStartData.team.name}.`);
});
rtm.on(RTM_EVENTS.MESSAGE, function handleRtmMessage (message) {
var channel = rtm.dataStore.getChannelGroupOrDMById(message.channel);
var user = rtm.dataStore.getUserById(message.user);
var response = config.response;
var subtype = message.subtype;
var type = message.type;
var ts = message.ts;
var text = message.text;
var userName = (user != null ? user.real_name : message.username);
var team = rtm.dataStore.getTeamById(rtm.activeTeamId);
var announceChannel = rtm.dataStore.getChannelByName(config.announceChannel);
var selfUser = rtm.dataStore.getUserById(rtm.activeUserId);
var channelName = (channel != null ? channel.is_channel : void 0) ? '#' : '';
channelName = channelName + (channel ? channel.name : 'UNKNOWN_CHANNEL');
// By trial and error this seems to be the archive URL of Slack messages. When included in a message Slack formats
// it nicely.
var archiveUrl = 'https://' + team.domain + '.slack.com/archives/' + channel.name + '/p' +
ts.split('.').join('');
if (message.hidden) {
return;
}
if (config.ignoreBots && user && (user.is_bot || (user.id && user.id === 'USLACKBOT'))) {
return;
}
if (
type === 'message' && text != null && channel != null &&
subtype !== 'channel_join' && subtype !== 'channel_leave' && channel.id !== announceChannel.id
) {
if (jira) {
// http://stackoverflow.com/a/6969486
// https:\/\/lyytidev\.atlassian\.net\/browse\/([A-Za-z0-9-]+)
var re = new RegExp(config.jira.protocol + ":\/\/" + config.jira.host.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&") + "\/browse\/([A-Za-z0-9-]+)", "g");
var match = re.exec(text);
var matches = [];
while (match != null) {
if (matches.indexOf(match[1]) === -1) {
matches.push(match[1]);
}
match = re.exec(text);
}
matches.forEach(function (value) {
jira.findIssue(value, function (error, issue) {
if (!error) {
// Need to use send instead of sendMessage to include the thread_ts value, that uses a message
// object instead of just the message text
// The ID is always 1, but it doesn't seem to matter as we don't use it anywhere at the moment
var reply = {
id: 1,
type: 'message',
channel: message.channel,
text: '[' + issue.key + '] ' + issue.fields.summary
};
if (message.thread_ts) {
// if already in a thread
reply.thread_ts = message.thread_ts;
} else if (message.ts) {
// if not in a thread
reply.thread_ts = message.ts;
}
rtm.send(reply);
}
});
});
}
if (channel.id !== announceChannel.id) {
var keyword;
// Using for instead of forEach() so that we can break the loop by returning. Prevents multiple announcements if
// there are more than one keyword in a message.
for (i = 0; i < config.keywords.length; i++) {
keyword = config.keywords[i];
if (changeCase.lowerCase(text).indexOf(changeCase.lowerCase(keyword)) > -1) {
// Check if the bot name contains the keyword and if the message contains the bot name. If both of these
// conditions are true it seems like the bot triggered on the bot name, which is a behavior that is mostly
// unwanted.
if (
config.ignoreSelf &&
changeCase.lowerCase(selfUser.name).indexOf(changeCase.lowerCase(keyword)) > -1 &&
changeCase.lowerCase(text).indexOf(changeCase.lowerCase(selfUser.name)) > -1
) {
console.log('Received ' + type + ' in ' + channelName + ' from ' + userName + ' at ' + ts +
' on keyword "' + keyword + '", triggered on bot name, didn\'t respond: "' + text + '"');
} else {
// Could include a bunch more of these, but currently only the ones I personally need or have needed are
// listed. Might be a good idea to add some validation for some of these. Pull requests welcome!
response = format(response, {
archiveUrl: archiveUrl,
channelId: channel.id,
channelName: channelName,
keyword: keyword,
keywordUcfirst: changeCase.upperCaseFirst(keyword),
messageText: text,
realName: userName
});
rtm.sendMessage(response, announceChannel.id);
return console.log('Received ' + type + ' in ' + channelName + ' from ' + userName + ' at ' + ts +
' on keyword "' + keyword + '": "' + text + '"');
}
}
}
}
} else {
var typeError = type !== 'message' ? 'unexpected type ' + type + '.' : null;
var textError = text == null ? 'text was undefined.' : null;
var channelError = channel == null ? 'channel was undefined.' : null;
var joinError = subtype === 'channel_join' ? 'channel join message.' : null;
var leaveError = subtype === 'channel_leave' ? 'channel leave message.' : null;
var errors = [typeError, textError, channelError, joinError, leaveError].filter(function (element) {
return element !== null;
}).join(' ');
if (errors) {
return console.log('@' + selfUser.name + ' could not respond. ' + errors);
}
return;
}
});