From 265bdef5a56397b71b8785b72adc7d22386db31a Mon Sep 17 00:00:00 2001 From: Evert Prants Date: Fri, 1 Oct 2021 20:31:10 +0300 Subject: [PATCH] implement new sendTo method --- discord/plugin.json | 2 +- discord/plugin.ts | 103 +++++++++++++++++++++++++++++++++++++------- squeebot.repo.json | 2 +- 3 files changed, 90 insertions(+), 17 deletions(-) diff --git a/discord/plugin.json b/discord/plugin.json index a23cf03..41998e9 100644 --- a/discord/plugin.json +++ b/discord/plugin.json @@ -2,7 +2,7 @@ "main": "plugin.js", "name": "discord", "description": "Discord Service for Squeebot 3", - "version": "1.2.1", + "version": "1.2.2", "tags": ["service", "discord"], "dependencies": ["control?"], "npmDependencies": ["discord.js@^13.1.0"] diff --git a/discord/plugin.ts b/discord/plugin.ts index 13ca148..f34aae3 100644 --- a/discord/plugin.ts +++ b/discord/plugin.ts @@ -7,7 +7,7 @@ import { import util from 'util'; -import Discord, { Intents } from 'discord.js'; +import Discord, { ClientUser, Intents, Permissions, TextChannel, User } from 'discord.js'; import { logger } from '@squeebot/core/lib/core'; import { thousandsSeparator, timeSince, toHHMMSS } from '@squeebot/core/lib/common'; @@ -156,6 +156,7 @@ class DiscordProtocol extends Protocol { Intents.FLAGS.DIRECT_MESSAGE_REACTIONS, Intents.FLAGS.DIRECT_MESSAGE_TYPING, ], + partials: ['CHANNEL', 'GUILD_MEMBER', 'MESSAGE', 'USER'], }); private eventsAttached = false; @@ -167,19 +168,21 @@ class DiscordProtocol extends Protocol { this.me.id = this.client.user.id; this.me.name = this.client.user.username; } - this.emit('running'); }); this.attachEvents(); - try { - this.client.login(this.config.token); - } catch (e: any) { - this.client.on('error', (e: Error) => { - this.emit('error', e.message); + this.client.on('error', (e: Error) => { + this.emit('error', e.message); + }); + this.client.on('disconnect', () => this.stop(true)); + + this.client.login(this.config.token) + .then(() => this.emit('running'), + (reason) => { + this.emit('error', reason); + this.stop(true); }); - this.client.on('disconnect', () => this.stop(true)); - } } public stop(force = false): void { @@ -221,7 +224,7 @@ class DiscordProtocol extends Protocol { message, this, { name: message.author.username, id: message.author.id }, - { name: chanName, id: message.channel.id, server: message.guild ? message.guild.id : undefined }); + { name: chanName, id: message.channel.id, server: message.guildId || undefined }); this.plugin.stream.emitTo('channel', 'message', msg); }); @@ -256,9 +259,81 @@ class DiscordProtocol extends Protocol { } public resolve(msg: DiscordMessageAdapter, ...data: any[]): void { + const toDiscord = this.fromSend(...data); + + if (!toDiscord) { + return; + } + + // Check send permission + if (msg.data.guildId) { + const perms = msg.data.channel.permissionsFor(this.client.user as ClientUser); + if (perms && !perms.has(Permissions.FLAGS.SEND_MESSAGES, true)) { + return; + } + } + + msg.data.channel.send(toDiscord).catch((e: Error) => { + logger.error(e); + }); + } + + public async sendTo(target: string, ...data: any[]): Promise { + const rxSplit = target.split('/'); + if (rxSplit[0] !== 'discord' || rxSplit[1] !== this.name) { + // Invalid protocol, we do not want this!; + return false; + } + + const toDiscord = this.fromSend(...data); + if (!toDiscord) { + return false; + } + + let channel: TextChannel | User | null = null; + // Message to guild + if (rxSplit.length === 4) { + // Fetch the guild and ensure it's available + const guildId = rxSplit[2].substring(2); + const guild = await this.client.guilds.fetch(guildId); + if (!guild || !guild.available || !guild.channels) { + return false; + } + + // Fetch the channel and ensure we can send to it + const channelId = rxSplit[3]; + channel = await guild.channels.fetch(channelId) as TextChannel; + if (!channel || !(channel.isText || channel.isThread) || !channel.viewable) { + return false; + } + + // Check send permission + const perms = channel.permissionsFor(this.client.user as ClientUser); + if (perms) { + if (!perms.has(Permissions.FLAGS.SEND_MESSAGES, true)) { + return false; + } + } + + // Message to user + } else if (rxSplit.length === 3) { + const userId = rxSplit[2]; + channel = await this.client.users.fetch(userId); + if (!channel) { + return false; + } + } else { + return false; + } + + await channel!.send(toDiscord); + return true; + } + + private fromSend(...data: any[]): { embeds?: object[]; content?: string } | null { let response = util.format(data[0], ...data.slice(1)); if (!response) { - return; + return null; } if (Array.isArray(data[0])) { @@ -266,7 +341,7 @@ class DiscordProtocol extends Protocol { response = this.format.compose(data[0]); } catch (e: any) { logger.error('[%s] Failed to compose message:', this.fullName, e.message); - return; + return null; } } // Discord supports sending objects to the channel for things like embeds @@ -281,9 +356,7 @@ class DiscordProtocol extends Protocol { toDiscord.content = response; } - msg.data.channel.send(toDiscord).catch((e: Error) => { - logger.error(e); - }); + return toDiscord; } } diff --git a/squeebot.repo.json b/squeebot.repo.json index 5c4fd29..67a7fb8 100644 --- a/squeebot.repo.json +++ b/squeebot.repo.json @@ -3,7 +3,7 @@ "plugins": [ { "name": "discord", - "version": "1.2.1" + "version": "1.2.2" } ], "typescript": true