|
1 | | -import { Robot, Adapter, TextMessage, User } from 'hubot'; |
| 1 | +import { Robot, Adapter, TextMessage, User } from 'hubot' |
2 | 2 |
|
3 | | -import sdk from "matrix-js-sdk"; |
| 3 | +import sdk from 'matrix-js-sdk' |
4 | 4 |
|
5 | | -import request from 'request'; |
6 | | -import sizeOf from 'image-size'; |
7 | | -import MatrixSession from './session.mjs'; |
| 5 | +import request from 'request' |
| 6 | +import sizeOf from 'image-size' |
| 7 | +import MatrixSession from './session.mjs' |
8 | 8 |
|
9 | | -import {LocalStorage} from 'node-localstorage'; |
| 9 | +import { LocalStorage } from 'node-localstorage' |
10 | 10 |
|
11 | | -let localStorage; |
| 11 | +let localStorage |
12 | 12 | if (localStorage == null) { |
13 | | - localStorage = new LocalStorage('./hubot-matrix.localStorage'); |
| 13 | + localStorage = new LocalStorage('./hubot-matrix.localStorage') |
14 | 14 | } |
15 | 15 |
|
16 | 16 | export default { |
17 | | - use(robot) { |
18 | | - |
19 | | - let that; |
20 | | - |
21 | | - class Matrix extends Adapter { |
22 | | - constructor() { |
23 | | - super(...arguments); |
24 | | - this.robot.logger.info("Constructor"); |
25 | | - } |
26 | | - |
27 | | - handleUnknownDevices(err) { |
28 | | - let that = this; |
29 | | - return (() => { |
30 | | - let result = []; |
31 | | - for (const stranger in err.devices) { |
32 | | - const devices = err.devices[stranger]; |
33 | | - result.push((() => { |
34 | | - let result1 = []; |
35 | | - for (let device in devices) { |
36 | | - that.robot.logger.info(`Acknowledging ${stranger}'s device ${device}`); |
37 | | - result1.push(that.robot.matrixClient.setDeviceKnown(stranger, device)); |
38 | | - } |
39 | | - return result1; |
40 | | - })()); |
41 | | - } |
42 | | - return result; |
43 | | - })(); |
| 17 | + use (robot) { |
| 18 | + let that |
| 19 | + |
| 20 | + class Matrix extends Adapter { |
| 21 | + constructor () { |
| 22 | + super(...arguments) |
| 23 | + this.robot.logger.info('Constructor') |
| 24 | + } |
| 25 | + |
| 26 | + handleUnknownDevices (err) { |
| 27 | + const that = this |
| 28 | + return (() => { |
| 29 | + const result = [] |
| 30 | + for (const stranger in err.devices) { |
| 31 | + const devices = err.devices[stranger] |
| 32 | + result.push((() => { |
| 33 | + const result1 = [] |
| 34 | + for (const device in devices) { |
| 35 | + that.robot.logger.info(`Acknowledging ${stranger}'s device ${device}`) |
| 36 | + result1.push(that.robot.matrixClient.setDeviceKnown(stranger, device)) |
| 37 | + } |
| 38 | + return result1 |
| 39 | + })()) |
| 40 | + } |
| 41 | + return result |
| 42 | + })() |
| 43 | + } |
| 44 | + |
| 45 | + send (envelope, ...strings) { |
| 46 | + return (() => { |
| 47 | + const result = [] |
| 48 | + for (const str of Array.from(strings)) { |
| 49 | + that.robot.logger.info(`Sending to ${envelope.room}: ${str}`) |
| 50 | + if (/^(f|ht)tps?:\/\//i.test(str)) { |
| 51 | + result.push(that.sendURL(envelope, str)) |
| 52 | + } else { |
| 53 | + result.push(that.robot.matrixClient.sendNotice(envelope.room, str).catch(err => { |
| 54 | + if (err.name === 'UnknownDeviceError') { |
| 55 | + that.handleUnknownDevices(err) |
| 56 | + return that.robot.matrixClient.sendNotice(envelope.room, str) |
| 57 | + } |
| 58 | + })) |
44 | 59 | } |
45 | | - |
46 | | - send(envelope, ...strings) { |
47 | | - return (() => { |
48 | | - let result = []; |
49 | | - for (const str of Array.from(strings)) { |
50 | | - that.robot.logger.info(`Sending to ${envelope.room}: ${str}`); |
51 | | - if (/^(f|ht)tps?:\/\//i.test(str)) { |
52 | | - result.push(that.sendURL(envelope, str)); |
53 | | - } else { |
54 | | - result.push(that.robot.matrixClient.sendNotice(envelope.room, str).catch(err => { |
55 | | - if (err.name === 'UnknownDeviceError') { |
56 | | - that.handleUnknownDevices(err); |
57 | | - return that.robot.matrixClient.sendNotice(envelope.room, str); |
58 | | - } |
59 | | - })); |
60 | | - } |
61 | | - } |
62 | | - return result; |
63 | | - })(); |
64 | | - } |
65 | | - |
66 | | - emote(envelope, ...strings) { |
67 | | - return Array.from(strings).map((str) => |
68 | | - that.robot.matrixClient.sendEmoteMessage(envelope.room, str).catch(err => { |
69 | | - if (err.name === 'UnknownDeviceError') { |
70 | | - that.handleUnknownDevices(err); |
71 | | - return that.robot.matrixClient.sendEmoteMessage(envelope.room, str); |
72 | | - } |
73 | | - })); |
| 60 | + } |
| 61 | + return result |
| 62 | + })() |
| 63 | + } |
| 64 | + |
| 65 | + emote (envelope, ...strings) { |
| 66 | + return Array.from(strings).map((str) => |
| 67 | + that.robot.matrixClient.sendEmoteMessage(envelope.room, str).catch(err => { |
| 68 | + if (err.name === 'UnknownDeviceError') { |
| 69 | + that.handleUnknownDevices(err) |
| 70 | + return that.robot.matrixClient.sendEmoteMessage(envelope.room, str) |
74 | 71 | } |
75 | | - |
76 | | - reply(envelope, ...strings) { |
77 | | - return Array.from(strings).map((str) => |
78 | | - that.send(envelope, `${envelope.user.name}: ${str}`)); |
| 72 | + })) |
| 73 | + } |
| 74 | + |
| 75 | + reply (envelope, ...strings) { |
| 76 | + return Array.from(strings).map((str) => |
| 77 | + that.send(envelope, `${envelope.user.name}: ${str}`)) |
| 78 | + } |
| 79 | + |
| 80 | + topic (envelope, ...strings) { |
| 81 | + return Array.from(strings).map((str) => |
| 82 | + that.robot.matrixClient.sendStateEvent(envelope.room, 'm.room.topic', { |
| 83 | + topic: str |
| 84 | + }, '')) |
| 85 | + } |
| 86 | + |
| 87 | + sendURL (envelope, url) { |
| 88 | + that.robot.logger.info(`Downloading ${url}`) |
| 89 | + return request({ url, encoding: null }, (error, response, body) => { |
| 90 | + if (error) { |
| 91 | + return that.robot.logger.info(`Request error: ${JSON.stringify(error)}`) |
| 92 | + } else if (response.statusCode === 200) { |
| 93 | + let info |
| 94 | + try { |
| 95 | + const dims = sizeOf(body) |
| 96 | + that.robot.logger.info(`Image has dimensions ${JSON.stringify(dims)}, size ${body.length}`) |
| 97 | + if (dims.type === 'jpg') { |
| 98 | + dims.type = 'jpeg' |
| 99 | + } |
| 100 | + info = { mimetype: `image/${dims.type}`, h: dims.height, w: dims.width, size: body.length } |
| 101 | + return that.robot.matrixClient.uploadContent(body, { |
| 102 | + name: url, |
| 103 | + type: info.mimetype |
| 104 | + }).then(response => { |
| 105 | + return that.robot.matrixClient.sendImageMessage(envelope.room, response.content_uri, info, url).catch(err => { |
| 106 | + if (err.name === 'UnknownDeviceError') { |
| 107 | + that.handleUnknownDevices(err) |
| 108 | + return that.robot.matrixClient.sendImageMessage(envelope.room, response.content_uri, info, url) |
| 109 | + } |
| 110 | + }) |
| 111 | + }) |
| 112 | + } catch (error1) { |
| 113 | + error = error1 |
| 114 | + that.robot.logger.info(error.message) |
| 115 | + return that.send(envelope, ` ${url}`) |
79 | 116 | } |
80 | | - |
81 | | - topic(envelope, ...strings) { |
82 | | - return Array.from(strings).map((str) => |
83 | | - that.robot.matrixClient.sendStateEvent(envelope.room, "m.room.topic", { |
84 | | - topic: str |
85 | | - }, "")); |
| 117 | + } |
| 118 | + }) |
| 119 | + } |
| 120 | + |
| 121 | + run () { |
| 122 | + this.robot.logger.info(`Run ${this.robot.name}`) |
| 123 | + |
| 124 | + const matrixServer = process.env.HUBOT_MATRIX_HOST_SERVER |
| 125 | + const matrixUser = process.env.HUBOT_MATRIX_USER |
| 126 | + const matrixPassword = process.env.HUBOT_MATRIX_PASSWORD |
| 127 | + const botName = this.robot.name |
| 128 | + |
| 129 | + const that = this |
| 130 | + const matrixSession = new MatrixSession(botName, matrixServer, matrixUser, matrixPassword, this.robot.logger, localStorage) |
| 131 | + matrixSession.createClient(async (err, client) => { |
| 132 | + if (err) { |
| 133 | + this.robot.logger.error(err) |
| 134 | + return |
| 135 | + } |
| 136 | + that.robot.matrixClient = client |
| 137 | + that.robot.matrixClient.on('sync', (state, prevState, data) => { |
| 138 | + switch (state) { |
| 139 | + case 'PREPARED': |
| 140 | + that.robot.logger.info(`Synced ${that.robot.matrixClient.getRooms().length} rooms`) |
| 141 | + // We really don't want to let people set the display name to something other than the bot |
| 142 | + // name because the bot only reacts to it's own name. |
| 143 | + const userId = that.robot.matrixClient.getUserId() |
| 144 | + const currentDisplayName = that.robot.matrixClient.getUser(userId).displayName |
| 145 | + if (that.robot.name !== currentDisplayName) { |
| 146 | + that.robot.logger.info(`Setting display name to ${that.robot.name}`) |
| 147 | + that.robot.matrixClient.setDisplayName(that.robot.name) |
| 148 | + } |
| 149 | + return that.emit('connected') |
86 | 150 | } |
87 | | - |
88 | | - sendURL(envelope, url) { |
89 | | - that.robot.logger.info(`Downloading ${url}`); |
90 | | - return request({url, encoding: null}, (error, response, body) => { |
91 | | - if (error) { |
92 | | - return that.robot.logger.info(`Request error: ${JSON.stringify(error)}`); |
93 | | - } else if (response.statusCode === 200) { |
94 | | - let info; |
95 | | - try { |
96 | | - let dims = sizeOf(body); |
97 | | - that.robot.logger.info(`Image has dimensions ${JSON.stringify(dims)}, size ${body.length}`); |
98 | | - if (dims.type === 'jpg') { |
99 | | - dims.type = 'jpeg'; |
100 | | - } |
101 | | - info = {mimetype: `image/${dims.type}`, h: dims.height, w: dims.width, size: body.length}; |
102 | | - return that.robot.matrixClient.uploadContent(body, { |
103 | | - name: url, |
104 | | - type: info.mimetype |
105 | | - }).then(response => { |
106 | | - return that.robot.matrixClient.sendImageMessage(envelope.room, response.content_uri, info, url).catch(err => { |
107 | | - if (err.name === 'UnknownDeviceError') { |
108 | | - that.handleUnknownDevices(err); |
109 | | - return that.robot.matrixClient.sendImageMessage(envelope.room, response.content_uri, info, url); |
110 | | - } |
111 | | - }); |
112 | | - }); |
113 | | - } catch (error1) { |
114 | | - error = error1; |
115 | | - that.robot.logger.info(error.message); |
116 | | - return that.send(envelope, ` ${url}`); |
117 | | - } |
118 | | - } |
119 | | - }); |
| 151 | + }) |
| 152 | + that.robot.matrixClient.on('Room.timeline', (event, room, toStartOfTimeline) => { |
| 153 | + if ((event.getType() === 'm.room.message') && (toStartOfTimeline === false)) { |
| 154 | + that.robot.matrixClient.setPresence({ presence: 'online' }) |
| 155 | + const message = event.getContent() |
| 156 | + const name = event.getSender() |
| 157 | + const user = that.robot.brain.userForId(name) |
| 158 | + user.room = room.roomId |
| 159 | + const userId = that.robot.matrixClient.getUserId() |
| 160 | + if (name !== userId) { |
| 161 | + that.robot.logger.info(`Received message: ${JSON.stringify(message)} in room: ${user.room}, from: ${user.name} (${user.id}).`) |
| 162 | + if (message.msgtype === 'm.text') { |
| 163 | + that.receive(new TextMessage(user, message.body)) |
| 164 | + } |
| 165 | + if ((message.msgtype !== 'm.text') || (message.body.indexOf(that.robot.name) !== -1)) { |
| 166 | + return that.robot.matrixClient.sendReadReceipt(event) |
| 167 | + } |
| 168 | + } |
120 | 169 | } |
121 | | - |
122 | | - run() { |
123 | | - this.robot.logger.info(`Run ${this.robot.name}`); |
124 | | - |
125 | | - let matrixServer = process.env.HUBOT_MATRIX_HOST_SERVER; |
126 | | - let matrixUser = process.env.HUBOT_MATRIX_USER; |
127 | | - let matrixPassword = process.env.HUBOT_MATRIX_PASSWORD; |
128 | | - let botName = this.robot.name; |
129 | | - |
130 | | - let that = this; |
131 | | - let matrixSession = new MatrixSession(botName, matrixServer, matrixUser, matrixPassword, this.robot.logger, localStorage); |
132 | | - matrixSession.createClient(async (err, client) => { |
133 | | - if (err) { |
134 | | - this.robot.logger.error(err); |
135 | | - return; |
136 | | - } |
137 | | - that.robot.matrixClient = client; |
138 | | - that.robot.matrixClient.on('sync', (state, prevState, data) => { |
139 | | - switch (state) { |
140 | | - case "PREPARED": |
141 | | - that.robot.logger.info(`Synced ${that.robot.matrixClient.getRooms().length} rooms`); |
142 | | - // We really don't want to let people set the display name to something other than the bot |
143 | | - // name because the bot only reacts to it's own name. |
144 | | - let userId = that.robot.matrixClient.getUserId(); |
145 | | - const currentDisplayName = that.robot.matrixClient.getUser(userId).displayName; |
146 | | - if (that.robot.name !== currentDisplayName) { |
147 | | - that.robot.logger.info(`Setting display name to ${that.robot.name}`); |
148 | | - that.robot.matrixClient.setDisplayName(that.robot.name); |
149 | | - } |
150 | | - return that.emit('connected'); |
151 | | - } |
152 | | - }); |
153 | | - that.robot.matrixClient.on('Room.timeline', (event, room, toStartOfTimeline) => { |
154 | | - if ((event.getType() === 'm.room.message') && (toStartOfTimeline === false)) { |
155 | | - that.robot.matrixClient.setPresence({presence: "online"}); |
156 | | - let message = event.getContent(); |
157 | | - let name = event.getSender(); |
158 | | - let user = that.robot.brain.userForId(name); |
159 | | - user.room = room.roomId; |
160 | | - let userId = that.robot.matrixClient.getUserId(); |
161 | | - if (name !== userId) { |
162 | | - that.robot.logger.info(`Received message: ${JSON.stringify(message)} in room: ${user.room}, from: ${user.name} (${user.id}).`); |
163 | | - if (message.msgtype === "m.text") { |
164 | | - that.receive(new TextMessage(user, message.body)); |
165 | | - } |
166 | | - if ((message.msgtype !== "m.text") || (message.body.indexOf(that.robot.name) !== -1)) { |
167 | | - return that.robot.matrixClient.sendReadReceipt(event); |
168 | | - } |
169 | | - } |
170 | | - } |
171 | | - }); |
172 | | - that.robot.matrixClient.on('RoomMember.membership', (event, member) => { |
173 | | - let userId = that.robot.matrixClient.getUserId(); |
174 | | - if ((member.membership === 'invite') && (member.userId === userId)) { |
175 | | - return that.robot.matrixClient.joinRoom(member.roomId).then(() => { |
176 | | - return that.robot.logger.info(`Auto-joined ${member.roomId}`); |
177 | | - }); |
178 | | - } |
179 | | - }); |
180 | | - return that.robot.matrixClient.startClient(0); |
181 | | - }); |
182 | | - |
| 170 | + }) |
| 171 | + that.robot.matrixClient.on('RoomMember.membership', (event, member) => { |
| 172 | + const userId = that.robot.matrixClient.getUserId() |
| 173 | + if ((member.membership === 'invite') && (member.userId === userId)) { |
| 174 | + return that.robot.matrixClient.joinRoom(member.roomId).then(() => { |
| 175 | + return that.robot.logger.info(`Auto-joined ${member.roomId}`) |
| 176 | + }) |
183 | 177 | } |
184 | | - } |
185 | | - |
186 | | - that = new Matrix(robot); |
187 | | - return that; |
| 178 | + }) |
| 179 | + return that.robot.matrixClient.startClient(0) |
| 180 | + }) |
| 181 | + } |
188 | 182 | } |
| 183 | + |
| 184 | + that = new Matrix(robot) |
| 185 | + return that |
| 186 | + } |
189 | 187 | } |
0 commit comments