Skip to content

Commit a421bb3

Browse files
committed
Rolling back to node 16 due to incompatibilities with FormData and the MM client. Fixes yGuy#47
1 parent 473b827 commit a421bb3

File tree

4 files changed

+52
-34
lines changed

4 files changed

+52
-34
lines changed

Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# NPM builder image
2-
FROM node:18-alpine as npm_builder
2+
FROM node:16-alpine as npm_builder
33

44
WORKDIR /app
55
COPY [ "package.json", "package-lock.json", "tsconfig.json", "./"]
@@ -9,7 +9,7 @@ RUN npm ci --omit dev
99
RUN npm run build
1010

1111
# NPM runtime image
12-
FROM node:18-alpine as npm_runtime
12+
FROM node:16-alpine as npm_runtime
1313

1414
WORKDIR /app
1515

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@
2121
"devDependencies": {
2222
"@types/ws": "^8.5.5"
2323
},
24+
"engineStrict": true,
2425
"engines": {
2526
"npm": ">=8.0.0",
26-
"node": ">=16.0.0"
27+
"node": ">=16.0.0 <18"
2728
}
2829
}

src/botservice.ts

Lines changed: 43 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {continueThread, registerChatPlugin} from "./openai-wrapper";
2-
import { Log } from "debug-level"
3-
import { mmClient, wsClient } from "./mm-client";
2+
import {Log} from "debug-level"
3+
import {mmClient, wsClient} from "./mm-client";
44
import 'babel-polyfill'
55
import 'isomorphic-fetch'
66
import {WebSocketMessage} from "@mattermost/client";
@@ -13,7 +13,7 @@ import {JSONMessageData, MessageData} from "./types";
1313
import {ExitPlugin} from "./plugins/ExitPlugin";
1414
import {MessageCollectPlugin} from "./plugins/MessageCollectPlugin";
1515

16-
if(!global.FormData) {
16+
if (!global.FormData) {
1717
global.FormData = require('form-data')
1818
}
1919

@@ -36,15 +36,15 @@ const botInstructions = "Your name is " + name + " and you are a helpful assista
3636
"meta data of his messages."
3737

3838
async function onClientMessage(msg: WebSocketMessage<JSONMessageData>, meId: string, log: Log) {
39-
if(msg.event !== 'posted' || !meId) {
39+
if (msg.event !== 'posted' || !meId) {
4040
log.debug({msg: msg})
4141
return
4242
}
4343

4444
const msgData = parseMessageData(msg.data)
45-
const posts = await getOlderPosts(msgData.post, { lookBackTime: 1000 * 60 * 60 * 24 })
45+
const posts = await getOlderPosts(msgData.post, {lookBackTime: 1000 * 60 * 60 * 24})
4646

47-
if(isMessageIgnored(msgData, meId, posts)) {
47+
if (isMessageIgnored(msgData, meId, posts)) {
4848
return
4949
}
5050

@@ -56,7 +56,7 @@ async function onClientMessage(msg: WebSocketMessage<JSONMessageData>, meId: str
5656
]
5757

5858
// create the context
59-
for(const threadPost of posts.slice(-contextMsgCount)) {
59+
for (const threadPost of posts.slice(-contextMsgCount)) {
6060
log.trace({msg: threadPost})
6161
if (threadPost.user_id === meId) {
6262
chatmessages.push({
@@ -79,7 +79,7 @@ async function onClientMessage(msg: WebSocketMessage<JSONMessageData>, meId: str
7979

8080
try {
8181
log.trace({chatmessages})
82-
const { message, fileId, props } = await continueThread(chatmessages, msgData)
82+
const {message, fileId, props} = await continueThread(chatmessages, msgData)
8383
log.trace({message})
8484

8585
// create answer response
@@ -91,7 +91,7 @@ async function onClientMessage(msg: WebSocketMessage<JSONMessageData>, meId: str
9191
file_ids: fileId ? [fileId] : undefined
9292
})
9393
log.trace({msg: newPost})
94-
} catch(e) {
94+
} catch (e) {
9595
log.error(e)
9696
await mmClient.createPost({
9797
message: "Sorry, but I encountered an internal error when trying to process your message",
@@ -114,16 +114,22 @@ async function onClientMessage(msg: WebSocketMessage<JSONMessageData>, meId: str
114114
*/
115115
function isMessageIgnored(msgData: MessageData, meId: string, previousPosts: Post[]): boolean {
116116
// we are not in a thread and not mentioned
117-
if(msgData.post.root_id === '' && !msgData.mentions.includes(meId)) { return true }
117+
if (msgData.post.root_id === '' && !msgData.mentions.includes(meId)) {
118+
return true
119+
}
118120

119121
// it is our own message
120-
if(msgData.post.user_id === meId) { return true }
122+
if (msgData.post.user_id === meId) {
123+
return true
124+
}
121125

122-
for(let i = previousPosts.length - 1; i > 0; i--) {
126+
for (let i = previousPosts.length - 1; i > 0; i--) {
123127
// we were asked to stop participating in the conversation
124-
if(previousPosts[i].props.bot_status === 'stopped') { return true }
128+
if (previousPosts[i].props.bot_status === 'stopped') {
129+
return true
130+
}
125131

126-
if(previousPosts[i].user_id === meId || previousPosts[i].message.includes(name)) {
132+
if (previousPosts[i].user_id === meId || previousPosts[i].message.includes(name)) {
127133
// we are in a thread were we are actively participating, or we were mentioned in the thread => respond
128134
return false
129135
}
@@ -155,23 +161,24 @@ function parseMessageData(msg: JSONMessageData): MessageData {
155161
* <li><b>postCount</b>: Determines how many of the previous posts should be collected. If this parameter is omitted all posts are returned.</li>
156162
* </ul>
157163
*/
158-
async function getOlderPosts(refPost: Post, options: {lookBackTime?: number, postCount?: number }) {
164+
async function getOlderPosts(refPost: Post, options: { lookBackTime?: number, postCount?: number }) {
159165
const thread = await mmClient.getPostThread(refPost.id, true, false, true)
160166

161167
let posts: Post[] = [...new Set(thread.order)].map(id => thread.posts[id])
162168
.sort((a, b) => a.create_at - b.create_at)
163169

164-
if(options.lookBackTime && options.lookBackTime > 0) {
170+
if (options.lookBackTime && options.lookBackTime > 0) {
165171
posts = posts.filter(a => a.create_at > refPost.create_at - options.lookBackTime!)
166172
}
167-
if(options.postCount && options.postCount > 0) {
173+
if (options.postCount && options.postCount > 0) {
168174
posts = posts.slice(-options.postCount)
169175
}
170176

171177
return posts
172178
}
173179

174-
const usernameCache: Record<string, {username: string, expireTime: number}> = {}
180+
const usernameCache: Record<string, { username: string, expireTime: number }> = {}
181+
175182
/**
176183
* Looks up the mattermost username for the given userId. Every username which is looked up will be cached for 5 minutes.
177184
* @param userId
@@ -180,17 +187,17 @@ async function userIdToName(userId: string): Promise<string> {
180187
let username: string
181188

182189
// check if userId is in cache and not outdated
183-
if(usernameCache[userId] && Date.now() < usernameCache[userId].expireTime ) {
190+
if (usernameCache[userId] && Date.now() < usernameCache[userId].expireTime) {
184191
username = usernameCache[userId].username
185192
} else {
186193
// username not in cache our outdated
187194
username = (await mmClient.getUser(userId)).username
188195

189-
if(!/^[a-zA-Z0-9_-]{1,64}$/.test(username)) {
190-
username = username.replace(/[.@!?]/g,'_').slice(0, 64)
196+
if (!/^[a-zA-Z0-9_-]{1,64}$/.test(username)) {
197+
username = username.replace(/[.@!?]/g, '_').slice(0, 64)
191198
}
192199

193-
if(!/^[a-zA-Z0-9_-]{1,64}$/.test(username)) {
200+
if (!/^[a-zA-Z0-9_-]{1,64}$/.test(username)) {
194201
username = [...username.matchAll(/[a-zA-Z0-9_-]/g)].join('').slice(0, 64)
195202
}
196203

@@ -203,20 +210,28 @@ async function userIdToName(userId: string): Promise<string> {
203210
return username
204211
}
205212

213+
Log.options({json: true, colors: true})
214+
Log.wrapConsole('bot-ws', {level4log: 'INFO'})
215+
const log = new Log('bot')
216+
206217
/* Entry point */
207218
async function main(): Promise<void> {
208-
Log.options({json: true, colors: true})
209-
Log.wrapConsole('bot-ws', { level4log: 'INFO'})
210-
const log = new Log('bot')
211219
const meId = (await mmClient.getMe()).id
212220

213-
for(const plugin of plugins) {
214-
if(plugin.setup()) {
221+
log.log("Connected to Mattermost.")
222+
223+
for (const plugin of plugins) {
224+
if (plugin.setup()) {
215225
registerChatPlugin(plugin)
226+
log.trace("Registered plugin " + plugin.key)
216227
}
217228
}
218229

219230
wsClient.addMessageListener((e) => onClientMessage(e, meId, log))
231+
log.trace("Listening to MM messages...")
220232
}
221233

222-
main().catch(console.error)
234+
main().catch(reason => {
235+
log.error(reason);
236+
process.exit(-1)
237+
})

src/mm-client.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,19 @@ const log = new Log('bot')
1010
const mattermostToken = process.env['MATTERMOST_TOKEN']!
1111
const matterMostURLString = process.env['MATTERMOST_URL']!
1212

13+
log.trace("Configuring Mattermost URL to " + matterMostURLString)
14+
1315
export const mmClient = new Client4()
1416
mmClient.setUrl(matterMostURLString)
1517
mmClient.setToken(mattermostToken)
1618

1719
export const wsClient = new WebSocketClient()
18-
const wsUrl = new URL(exports.mmClient.getWebSocketUrl())
20+
const wsUrl = new URL(mmClient.getWebSocketUrl())
1921
wsUrl.protocol = wsUrl.protocol === 'https:' ? 'wss' : 'ws'
2022

2123
new Promise((resolve, reject) => {
22-
exports.wsClient.addCloseListener(() => reject())
23-
exports.wsClient.addErrorListener((e: Event) => {
24+
wsClient.addCloseListener(() => reject())
25+
wsClient.addErrorListener((e: Event) => {
2426
reject(e)
2527
})
2628
})

0 commit comments

Comments
 (0)