-
Notifications
You must be signed in to change notification settings - Fork 229
/
index.js
186 lines (163 loc) · 6.28 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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
'use strict'
const Adapter = require.main.require('hubot/src/adapter')
const Response = require.main.require('hubot/src/response')
const { TextMessage, EnterMessage, LeaveMessage } = require.main.require('hubot/src/message')
const { driver, api, methodCache, settings } = require('@rocket.chat/sdk')
/** Extend default response with custom adapter methods */
class RocketChatResponse extends Response {
sendDirect (...strings) {
this.robot.adapter.sendDirect(this.envelope, ...strings)
}
sendPrivate (...strings) {
this.robot.adapter.sendDirect(this.envelope, ...strings)
}
}
/** Define new message type for handling attachments */
class AttachmentMessage extends TextMessage {
constructor (user, attachment, text, id) {
super(user, text, id)
this.user = user
this.attachment = attachment
this.text = text
this.id = id
}
toString () {
return this.attachment
}
}
/** Main API for Hubot on Rocket.Chat */
class RocketChatBotAdapter extends Adapter {
run () {
this.robot.logger.info(`[startup] Rocket.Chat adapter in use`)
// Make SDK modules available to scripts, via `adapter.`
this.driver = driver
this.methodCache = methodCache
this.api = api
this.settings = settings
// Print logs with current configs
this.robot.logger.info(`[startup] Respond to name: ${this.robot.name}`)
this.robot.alias = (this.robot.name === settings.username || this.robot.alias)
? this.robot.alias
: settings.username
if (this.robot.alias) {
this.robot.logger.info(`[startup] Respond to alias: ${this.robot.alias}`)
}
// Overwrite Robot's response class with Rocket.Chat custom one
this.robot.Response = RocketChatResponse
// Use RocketChat Bot Driver to connect, login and setup subscriptions
// Joins single or array of rooms by name from room setting (comma separated)
// Reactive message subscription uses callback to process every stream update
driver.useLog(this.robot.logger)
driver.connect()
.catch((err) => {
this.robot.logger.error(this.robot.logger.error(`Unable to connect: ${JSON.stringify(err)}`))
throw err
})
.then(() => {
return driver.login()
})
.catch((err) => {
this.robot.logger.error(this.robot.logger.error(`Unable to login: ${JSON.stringify(err)}`))
throw err
})
.then(() => {
return driver.subscribeToMessages()
})
.catch((err) => {
this.robot.logger.error(`Unable to subscribe ${JSON.stringify(err)}`)
throw err
})
.then(() => {
driver.respondToMessages(this.process.bind(this)) // reactive callback
this.emit('connected') // tells hubot to load scripts
})
}
/** Process every incoming message in subscription */
process (err, message, meta) {
if (err) throw err
// Prepare message type for Hubot to receive...
this.robot.logger.info('Filters passed, will receive message')
// Collect required attributes from message meta
const isDM = (meta.roomType === 'd')
const isLC = (meta.roomType === 'l')
const user = this.robot.brain.userForId(message.u._id, {
name: message.u.username,
alias: message.alias
})
user.roomID = message.rid
user.roomType = meta.roomType
user.room = meta.roomName || message.rid
// Room joins, receive without further detail
if (message.t === 'uj') {
this.robot.logger.debug('Message type EnterMessage')
return this.robot.receive(new EnterMessage(user, null, message._id))
}
// Room exit, receive without further detail
if (message.t === 'ul') {
this.robot.logger.debug('Message type LeaveMessage')
return this.robot.receive(new LeaveMessage(user, null, message._id))
}
// Direct messages prepend bot's name so Hubot can `.respond`
const startOfText = (message.msg.indexOf('@') === 0) ? 1 : 0
const robotIsNamed = message.msg.indexOf(this.robot.name) === startOfText || message.msg.indexOf(this.robot.alias) === startOfText
if ((isDM || isLC) && !robotIsNamed) message.msg = `${this.robot.name} ${message.msg}`
// Attachments, format properties for Hubot
if (Array.isArray(message.attachments) && message.attachments.length) {
let attachment = message.attachments[0]
if (attachment.image_url) {
attachment.link = `${settings.host}${attachment.image_url}`
attachment.type = 'image'
} else if (attachment.audio_url) {
attachment.link = `${settings.host}${attachment.audio_url}`
attachment.type = 'audio'
} else if (attachment.video_url) {
attachment.link = `${settings.host}${attachment.video_url}`
attachment.type = 'video'
}
this.robot.logger.debug('Message type AttachmentMessage')
return this.robot.receive(new AttachmentMessage(user, attachment, message.msg, message._id))
}
// Standard text messages, receive as is
let textMessage = new TextMessage(user, message.msg, message._id)
this.robot.logger.debug(`TextMessage: ${textMessage.toString()}`)
return this.robot.receive(textMessage)
}
/** Send messages to user addressed in envelope */
send (envelope, ...strings) {
return strings.map((text) => {
if (envelope.user && envelope.user.roomID) driver.sendToRoomId(text, envelope.user.roomID)
else driver.sendToRoom(text, envelope.room)
})
}
/**
* Emote message to user
* @todo Improve this legacy method
*/
emote (envelope, ...strings) {
return strings.map((text) => this.send(envelope, `_${text}_`))
}
/** Send custom message to user */
customMessage (data) {
return driver.sendMessage(data)
}
/** Send DM to user */
sendDirect (envelope, ...strings) {
return strings.map((text) => driver.sendDirectToUser(text, envelope.user.name))
}
/** Reply to a user's message (mention them if not a DM) */
reply (envelope, ...strings) {
if (envelope.room.indexOf(envelope.user.id) === -1) {
strings = strings.map((s) => `@${envelope.user.name} ${s}`)
}
return this.send(envelope, ...strings)
}
/** Get a room ID via driver */
getRoomId (room) {
return driver.getRoomId(room)
}
/** Call a server message via driver */
callMethod (method, ...args) {
return driver.callMethod(method, args)
}
}
exports.use = (robot) => new RocketChatBotAdapter(robot)