const matrix = require('matrix-js-sdk') const CommandSource = require('../util/command/command_source') const htmlStringify = require('../util/chat/stringify/html') function inject (bot, options) { if (!options.matrix?.enabled) return bot.matrix = { client: options.matrix.client ?? matrix.createClient(options.matrix), roomId: options.matrix.roomId, commandPrefix: options.matrix.commandPrefix, inviteUrl: String(options.matrix.inviteUrl) } const startTime = Date.now() bot.on('chat_html', (html, message) => { if (!bot.chat.shouldLog(message)) return sendMessage(html) }) const matrixPrefix = { text: 'ChipmunkBot Matrix', hoverEvent: { action: 'show_text', contents: 'Click to copy the invite link for the Matrix space to your clipboard!' }, clickEvent: { action: 'copy_to_clipboard', // * Minecraft, and Java's URI class in general, seem to hate `#`, so open_url does not work. value: bot.matrix.inviteUrl } } bot.matrix.client.on('Room.timeline', (event, room, toStartOfTimeline) => { if (event.getRoomId() !== bot.matrix.roomId || event.getType() !== 'm.room.message' || event.getTs() < startTime || event.sender.userId === bot.matrix.client.getUserId() || !bot.loggedIn) return const content = event.getContent() const permissionLevel = event.sender.powerLevelNorm let message = content.body const senderText = { text: String(event.sender.rawDisplayName || event.sender.name || event.sender.userId), hoverEvent: { action: 'show_text', contents: [String(event.sender.userId), '\nPermission Level: ', String(permissionLevel), '\n\nClick to copy the User ID'] }, clickEvent: { action: 'copy_to_clipboard', value: String(event.sender.userId) } } if (content.url) { message = { text: '[Attachment]', ...bot.styles.primary, clickEvent: { action: 'open_url', value: bot.matrix.client.mxcUrlToHttp(content.url) } } } else if (message.startsWith(bot.matrix.commandPrefix)) { const source = new CommandSource({ bot, permissionLevel, sendFeedback, displayName: senderText }) bot.commands.execute(message.substring(bot.matrix.commandPrefix.length), source) return } bot.fancyMsg(matrixPrefix, senderText, message) }) let dequeuingMessages = false let queue = [] async function sendMessage (html) { queue.push(html) if (dequeuingMessages) return dequeuingMessages = true while (queue.length !== 0) { const html = queue.join('
') queue = [] await _sendMessage(html) } dequeuingMessages = false } async function _sendMessage (html) { const content = { msgtype: 'm.text', format: 'org.matrix.custom.html', body: html, formatted_body: html, 'm.mentions': {} } try { await bot.matrix.client.sendEvent(bot.matrix.roomId, 'm.room.message', content, '') } catch (error) { console.error('Unable to send Matrix message:', error) } } function sendFeedback (text, sendFeedback) { const html = htmlStringify(text, { lang: bot.registry.language }) sendMessage(html) } } module.exports = inject