diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..afcf2ce --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "revolt.js"] + path = revolt.js + url = https://github.com/revoltchat/revolt.js + branch = insert/feat/store-rewrite diff --git a/bot/package.json b/bot/package.json index 4df27b9..be29a04 100644 --- a/bot/package.json +++ b/bot/package.json @@ -13,7 +13,6 @@ "author": "", "license": "ISC", "dependencies": { - "@janderedev/revolt.js": "latest", "@types/monk": "^6.0.0", "automod": "^0.1.0", "axios": "^0.22.0", @@ -24,7 +23,8 @@ "log75": "^2.2.0", "monk": "^7.3.4", "prom-client": "^14.0.1", - "revolt-api": "^0.5.16", + "revolt-api": "latest", + "revolt.js": "^7.0.0", "ulid": "^2.3.0", "xlsx": "^0.17.3" }, @@ -33,6 +33,7 @@ }, "packageManager": "yarn@3.2.1", "resolutions": { - "automod": "portal:../lib" + "automod": "portal:../lib", + "revolt.js": "portal:../revolt.js" } } diff --git a/bot/src/bot/commands/admin/botadm.ts b/bot/src/bot/commands/admin/botadm.ts index 6186cc7..23c8ee1 100644 --- a/bot/src/bot/commands/admin/botadm.ts +++ b/bot/src/bot/commands/admin/botadm.ts @@ -5,7 +5,7 @@ import { commands, DEFAULT_PREFIX, ownerIDs } from "../../modules/command_handle import child_process from 'child_process'; import fs from 'fs'; import path from 'path'; -import { User } from "@janderedev/revolt.js/dist/maps/Users"; +import { User } from "revolt.js"; import { adminBotLog } from "../../logging"; import CommandCategory from "../../../struct/commands/CommandCategory"; import { getMutualServers, parseUserOrId } from "../../util"; @@ -17,11 +17,11 @@ const BLACKLIST_MESSAGE = (username: string) => `\`@${username}\` has been banne const sudoOverrides: { [key: string]: number|null } = {} const isSudo = (user: User): boolean => { - return !!(sudoOverrides[user._id] && sudoOverrides[user._id]! > Date.now()); + return !!(sudoOverrides[user.id] && sudoOverrides[user.id]! > Date.now()); } const updateSudoTimeout = (user: User) => { - sudoOverrides[user._id] = Date.now() + (1000 * 60 * 5); + sudoOverrides[user.id] = Date.now() + (1000 * 60 * 5); } const getCommitHash = (): Promise => new Promise((resolve) => { @@ -57,23 +57,22 @@ export default { const pjson = JSON.parse((await fs.promises.readFile(path.join(process.cwd(), 'package.json'))).toString()); let msg = `# AutoMod stats\n` + `### Cache\n` - + `Servers: \`${client.servers.size}\`\n` - + `Channels: \`${client.channels.size}\`\n` - + `Users: \`${client.users.size}\`\n` + + `Servers: \`${client.servers.size()}\`\n` + + `Channels: \`${client.channels.size()}\`\n` + + `Users: \`${client.users.size()}\`\n` + `### Misc\n` + `Command count: \`${commands.length}\`\n` + `Environment: \`${process.env.NODE_ENV || 'testing'}\`\n` + `Commit hash: \`${await getCommitHash() || 'Unknown'}\`\n` + `### Packages\n` - + `revolt.js: \`${pjson.dependencies['@janderedev/revolt.js']}\`\n` + + `revolt.js: \`${pjson.dependencies['revolt.js']}\`\n` + `discord.js: \`${pjson.dependencies['discord.js']}\`\n` + `axios: \`${pjson.dependencies['axios']}\`\n` + `log75: \`${pjson.dependencies['log75']}\`\n` + `typescript: \`${pjson.devDependencies['typescript']}\`\n` + `### Connection\n` - + `API Endpoint: \`${client.apiURL}\`\n` - + `Heartbeat: \`${client.heartbeat}\`\n` - + `Ping: \`${client.websocket.ping ?? 'Unknown'}\`\n` + + `API Endpoint: \`${client.options.baseURL}\`\n` + + `Ping: \`${client.events.ping() ?? 'Unknown'}\`\n` + `### Bot configuration\n` + `Owners: \`${ownerIDs.length}\` (${ownerIDs.join(', ')})\n`; @@ -87,7 +86,7 @@ export default { case 'on': { if (isSudo(message.author!)) return message.reply('You are already in sudo mode!'); - sudoOverrides[message.author_id] = Date.now() + (1000 * 60 * 5); + sudoOverrides[message.authorId!] = Date.now() + (1000 * 60 * 5); let msg = `# %emoji% Sudo mode enabled\n` + `In sudo mode, you will be able to run any command regardless of your server permissions.\n` @@ -106,7 +105,7 @@ export default { case 'off': { if (!isSudo(message.author!)) return message.reply('You currently not in sudo mode.'); - sudoOverrides[message.author_id] = null; + sudoOverrides[message.authorId!] = null; let msg = `# %emoji% Sudo mode disabled.`; const sentMsg = await message.reply(msg.replace('%emoji%', ':unlock:'), false); @@ -138,7 +137,7 @@ export default { const target = await parseUserOrId(args.shift() || ''); if (!target) return message.reply('Specified user could not be found.'); - const res = await dbs.USERS.findOne({ id: target._id }); + const res = await dbs.USERS.findOne({ id: target.id }); if (!res) await message.reply(`Nothing stored about this user.`); else await message.reply(`\`\`\`json\n${JSON.stringify(res, null, 4)}\n\`\`\``); @@ -149,12 +148,12 @@ export default { case 'blacklist': { const target = await parseUserOrId(args.shift() || ''); if (!target) return message.reply('Specified user could not be found.'); - if (target._id == message.author_id) return message.reply(`no`); + if (target.id == message.authorId) return message.reply(`no`); await dbs.USERS.update({ - id: target._id, + id: target.id, }, { - $setOnInsert: { id: target._id }, + $setOnInsert: { id: target.id }, $set: { globalBlacklist: true } }, { upsert: true }); @@ -167,23 +166,23 @@ export default { const mutuals = getMutualServers(target); for (const server of mutuals) { if (server.havePermission('BanMembers')) { - const config = await dbs.SERVERS.findOne({ id: server._id }); + const config = await dbs.SERVERS.findOne({ id: server.id }); if (config?.allowBlacklistedUsers) continue; try { - await server.banUser(target._id, { + await server.banUser(target.id, { reason: BLACKLIST_BAN_REASON, }); bannedServers++; - if (server.system_messages?.user_banned) { - const channel = server.channels.find(c => c!._id == server.system_messages!.user_banned); + if (server.systemMessages?.user_banned) { + const channel = server.channels.find(c => c!.id == server.systemMessages!.user_banned); if (channel && channel.havePermission('SendMessage')) { await channel.sendMessage(BLACKLIST_MESSAGE(target.username)); } } } catch(e) { - console.error(`Failed to ban in ${server._id}: ${e}`); + console.error(`Failed to ban in ${server.id}: ${e}`); } } } @@ -205,9 +204,9 @@ export default { if (!target) return message.reply('Specified user could not be found.'); await dbs.USERS.update({ - id: target._id, + id: target.id, }, { - $setOnInsert: { id: target._id }, + $setOnInsert: { id: target.id }, $set: { globalBlacklist: false } }, { upsert: true }); @@ -221,9 +220,9 @@ export default { if (!target) return message.reply('Specified user could not be found.'); await dbs.USERS.update({ - id: target._id, + id: target.id, }, { - $setOnInsert: { id: target._id }, + $setOnInsert: { id: target.id }, $set: { blacklistReason: args.join(' ') || undefined } }, { upsert: true }); @@ -235,12 +234,12 @@ export default { case 'ignore': { const target = await parseUserOrId(args.shift() || ''); if (!target) return message.reply('Specified user could not be found.'); - if (target._id == message.author_id) return message.reply(`no`); + if (target.id == message.authorId) return message.reply(`no`); await dbs.USERS.update( - { id: target._id }, + { id: target.id }, { - $setOnInsert: { id: target._id }, + $setOnInsert: { id: target.id }, $set: { ignore: true }, }, { upsert: true } @@ -254,12 +253,12 @@ export default { case 'unignore': { const target = await parseUserOrId(args.shift() || ''); if (!target) return message.reply('Specified user could not be found.'); - if (target._id == message.author_id) return message.reply(`no`); + if (target.id == message.authorId) return message.reply(`no`); await dbs.USERS.update( - { id: target._id }, + { id: target.id }, { - $setOnInsert: { id: target._id }, + $setOnInsert: { id: target.id }, $set: { ignore: false }, }, { upsert: true } diff --git a/bot/src/bot/commands/configuration/bot_managers.ts b/bot/src/bot/commands/configuration/bot_managers.ts index 2bf6e7f..c9a40d8 100644 --- a/bot/src/bot/commands/configuration/bot_managers.ts +++ b/bot/src/bot/commands/configuration/bot_managers.ts @@ -1,7 +1,7 @@ import SimpleCommand from "../../../struct/commands/SimpleCommand"; -import { hasPerm, parseUser } from "../../util"; +import { parseUser } from "../../util"; import { client, dbs } from "../../.."; -import { User } from "@janderedev/revolt.js/dist/maps/Users"; +import { User } from "revolt.js"; import MessageCommandContext from "../../../struct/MessageCommandContext"; import CommandCategory from "../../../struct/commands/CommandCategory"; @@ -14,10 +14,10 @@ export default { syntax: SYNTAX, category: CommandCategory.Config, run: async (message: MessageCommandContext, args: string[]) => { - if (!hasPerm(message.member!, 'ManageServer')) + if (!message.member?.hasPermission(message.member.server!, 'ManageServer')) return message.reply('You need **ManageServer** permission to use this command.'); - let config = await dbs.SERVERS.findOne({ id: message.serverContext._id }); + let config = await dbs.SERVERS.findOne({ id: message.serverContext.id }); let admins = config?.botManagers ?? []; let user: User|null; @@ -28,12 +28,12 @@ export default { user = await parseUser(args[1]); if (!user) return message.reply('I can\'t find that user.'); - if (admins.indexOf(user._id) > -1) return message.reply('This user is already added as bot admin.'); + if (admins.indexOf(user.id) > -1) return message.reply('This user is already added as bot admin.'); - admins.push(user._id); - await dbs.SERVERS.update({ id: message.serverContext._id }, { $set: { botManagers: admins } }); + admins.push(user.id); + await dbs.SERVERS.update({ id: message.serverContext.id }, { $set: { botManagers: admins } }); - message.reply(`✅ Added [@${user.username}](/@${user._id}) to bot admins.`); + message.reply(`✅ Added [@${user.username}](/@${user.id}) to bot admins.`); break; case 'remove': case 'delete': @@ -43,12 +43,12 @@ export default { user = await parseUser(args[1]); if (!user) return message.reply('I can\'t find that user.'); - if (admins.indexOf(user._id) == -1) return message.reply('This user is not added as bot admin.'); + if (admins.indexOf(user.id) == -1) return message.reply('This user is not added as bot admin.'); - admins = admins.filter(a => a != user?._id); - await dbs.SERVERS.update({ id: message.serverContext._id }, { $set: { botManagers: admins } }); + admins = admins.filter(a => a != user?.id); + await dbs.SERVERS.update({ id: message.serverContext.id }, { $set: { botManagers: admins } }); - message.reply(`✅ Removed [@${user.username}](/@${user._id}) from bot admins.`); + message.reply(`✅ Removed [@${user.username}](/@${user.id}) from bot admins.`); break; case 'list': case 'ls': diff --git a/bot/src/bot/commands/configuration/botctl.ts b/bot/src/bot/commands/configuration/botctl.ts index 2ab11aa..e88b111 100644 --- a/bot/src/bot/commands/configuration/botctl.ts +++ b/bot/src/bot/commands/configuration/botctl.ts @@ -7,7 +7,7 @@ import SimpleCommand from "../../../struct/commands/SimpleCommand"; import MessageCommandContext from "../../../struct/MessageCommandContext"; import { checkMessageForFilteredWords } from "../../modules/antispam"; import { DEFAULT_PREFIX } from "../../modules/command_handler"; -import { embed, EmbedColor, getAutumnURL, getDmChannel, isBotManager, NO_MANAGER_MSG, sanitizeMessageContent } from "../../util"; +import { embed, EmbedColor, getDmChannel, isBotManager, NO_MANAGER_MSG, sanitizeMessageContent } from "../../util"; const WORDLIST_DEFAULT_MESSAGE = '<@{{user_id}}>, the message you sent contained a blocked word.'; @@ -28,10 +28,10 @@ export default { return message.reply('Your server is currently listed in server discovery. As part of Revolt\'s [Discover Guidelines](), all servers on Discover are enrolled to AutoMod\'s antispam features.'); } - await dbs.SERVERS.update({ id: message.serverContext._id }, { $set: { allowBlacklistedUsers: true } }); + await dbs.SERVERS.update({ id: message.serverContext.id }, { $set: { allowBlacklistedUsers: true } }); await message.reply('Globally blacklisted users will no longer get banned in this server. Previously banned users will need to be unbanned manually.'); } else if (args[0] == 'no') { - await dbs.SERVERS.update({ id: message.serverContext._id }, { $set: { allowBlacklistedUsers: false } }); + await dbs.SERVERS.update({ id: message.serverContext.id }, { $set: { allowBlacklistedUsers: false } }); await message.reply('Globally blacklisted users will now get banned in this server.'); } else { await message.reply(`Please specify either 'yes' or 'no' to toggle this setting.`); @@ -41,7 +41,7 @@ export default { case 'spam_detection': { if (args[0] == 'on') { - await dbs.SERVERS.update({ id: message.serverContext._id }, { $set: { antispamEnabled: true } }); + await dbs.SERVERS.update({ id: message.serverContext.id }, { $set: { antispamEnabled: true } }); await message.reply('Spam detection is now enabled in this server.\nIf a user is wrongfully kicked ' + 'or banned, please report it here: https://rvlt.gg/jan\n\n' + 'Please make sure to grant AutoMod permission to **Kick**, **Ban** and **Manage Messages**!'); @@ -50,11 +50,11 @@ export default { return message.reply('Your server is currently listed in server discovery. As part of Revolt\'s [Discover Guidelines](), all servers on Discover are enrolled to AutoMod\'s antispam features.'); } - await dbs.SERVERS.update({ id: message.serverContext._id }, { $set: { antispamEnabled: false } }); + await dbs.SERVERS.update({ id: message.serverContext.id }, { $set: { antispamEnabled: false } }); await message.reply('Spam detection is now disabled in this server.'); } else { - const cfg = await dbs.SERVERS.findOne({ id: message.serverContext._id }); + const cfg = await dbs.SERVERS.findOne({ id: message.serverContext.id }); await message.reply(`Spam detection is currently **${cfg?.antispamEnabled ? 'enabled' : 'disabled'}**. ` + `Please specify either 'on' or 'off' to toggle this setting.`); } @@ -80,48 +80,48 @@ export default { const channel = client.channels.get(channelInput); if (!channel) return message.reply('I can\'t find that channel.'); - if (channel.server_id != message.channel?.server_id) return message.reply('That channel is not part of this server!'); + if (channel.serverId != message.channel?.serverId) return message.reply('That channel is not part of this server!'); if (!channel.havePermission('SendMessage')) return message.reply('I don\'t have permission to **send messages** in that channel.'); if (!channel.havePermission('SendEmbeds')) return message.reply('I don\'t have permission to **send embeds** in that channel.'); switch(args[0]?.toLowerCase()) { case 'messageupdate': { await dbs.SERVERS.update( - { id: message.channel!.server_id! }, + { id: message.channel!.serverId! }, { $set: { 'logs.messageUpdate.revolt': { - channel: channel._id, + channel: channel.id, type: 'EMBED', }, }, $setOnInsert: { - id: message.channel!.server_id!, + id: message.channel!.serverId!, } }, { upsert: true }, ); - await message.reply(`Bound message update logs to <#${channel._id}>!`); + await message.reply(`Bound message update logs to <#${channel.id}>!`); break; } case 'modaction': { await dbs.SERVERS.update( - { id: message.channel!.server_id! }, + { id: message.channel!.serverId! }, { $set: { 'logs.modAction.revolt': { - channel: channel._id, + channel: channel.id, type: 'EMBED', }, }, $setOnInsert: { - id: message.channel!.server_id!, + id: message.channel!.serverId!, } }, { upsert: true }, ); - await message.reply(`Bound moderation logs to <#${channel._id}>!`); + await message.reply(`Bound moderation logs to <#${channel.id}>!`); break; } @@ -133,11 +133,11 @@ export default { } case 'filter': { - const config = await dbs.SERVERS.findOne({ id: message.channel!.server_id! }); + const config = await dbs.SERVERS.findOne({ id: message.channel!.serverId! }); switch(args.shift()?.toLowerCase()) { case 'enable': { await dbs.SERVERS.update( - { id: message.channel!.server_id! }, + { id: message.channel!.serverId! }, { $set: { wordlistEnabled: true } }, { upsert: true }, ); @@ -152,7 +152,7 @@ export default { } case 'disable': { await dbs.SERVERS.update( - { id: message.channel!.server_id! }, + { id: message.channel!.serverId! }, { $set: { wordlistEnabled: false } }, { upsert: true }, ); @@ -172,7 +172,7 @@ export default { if (config?.wordlist?.find(w => w.word == word)) return await message.reply('That word is already on the list!'); await dbs.SERVERS.update( - { id: message.channel!.server_id! }, + { id: message.channel!.serverId! }, { $push: { wordlist: { strictness, word } } }, { upsert: true }, ); @@ -187,7 +187,7 @@ export default { if (!config?.wordlist?.find(w => w.word == word)) return await message.reply('That word is not on the list.'); await dbs.SERVERS.update( - { id: message.channel!.server_id! }, + { id: message.channel!.serverId! }, { $pull: { wordlist: { word } } }, { upsert: true }, ); @@ -199,15 +199,15 @@ export default { case 'show': { const formData = new FormData(); formData.append( - `wordlist_${message.channel?.server_id}`, + `wordlist_${message.channel?.serverId}`, config?.wordlist?.map(w => `${w.strictness}\t${w.word}`).join('\n') ?? '', - `wordlist_${message.channel?.server_id}.txt` + `wordlist_${message.channel?.serverId}.txt` ); try { - const channel = await getDmChannel(message.author_id); + const channel = await getDmChannel(message.authorId!); const res = await axios.post( - `${await getAutumnURL()}/attachments`, + `${client.configuration?.features.autumn.url}/attachments`, formData, { headers: formData.getHeaders(), responseType: 'json' } ); @@ -244,7 +244,7 @@ export default { } await dbs.SERVERS.update( - { id: message.channel!.server_id! }, + { id: message.channel!.serverId! }, { $set: { wordlistAction: { action: config?.wordlistAction?.action ?? 'LOG', message: msg } } }, { upsert: true }, ); @@ -281,7 +281,7 @@ export default { } await dbs.SERVERS.update( - { id: message.channel!.server_id! }, + { id: message.channel!.serverId! }, { $set: { wordlistAction: { action: action as any, message: config?.wordlistAction?.message ?? WORDLIST_DEFAULT_MESSAGE diff --git a/bot/src/bot/commands/configuration/bridge.ts b/bot/src/bot/commands/configuration/bridge.ts index f2b0871..69eff98 100644 --- a/bot/src/bot/commands/configuration/bridge.ts +++ b/bot/src/bot/commands/configuration/bridge.ts @@ -1,4 +1,4 @@ -import { Message } from "@janderedev/revolt.js"; +import { Message } from "revolt.js"; import { ulid } from "ulid"; import { SendableEmbed } from "revolt-api"; import { CONFIG_KEYS } from "automod/dist/misc/bridge_config_keys"; @@ -30,20 +30,20 @@ export default { return message.reply(NO_MANAGER_MSG); const count = await dbs.BRIDGE_CONFIG.count({ - revolt: message.channel_id, + revolt: message.channelId, }); if (count) return message.reply(`This channel is already bridged.`); // Invalidate previous bridge request await dbs.BRIDGE_REQUESTS.remove({ - revolt: message.channel_id, + revolt: message.channelId, }); const reqId = ulid(); await dbs.BRIDGE_REQUESTS.insert({ id: reqId, - revolt: message.channel_id, + revolt: message.channelId, expires: Date.now() + 1000 * 60 * 15, }); @@ -74,7 +74,7 @@ export default { return message.reply(NO_MANAGER_MSG); const res = await dbs.BRIDGE_CONFIG.remove({ - revolt: message.channel_id, + revolt: message.channelId, }); if (res.deletedCount) await message.reply(`Channel unlinked!`); else @@ -86,7 +86,7 @@ export default { return message.reply(NO_MANAGER_MSG); const query = { - revolt: { $in: message.channel?.server?.channel_ids || [] }, + revolt: { $in: Array.from(message.channel?.server?.channelIds.values() ?? []) }, }; if (args[1] == "CONFIRM") { const res = await dbs.BRIDGE_CONFIG.remove(query); @@ -119,7 +119,7 @@ export default { return message.reply(NO_MANAGER_MSG); const links = await dbs.BRIDGE_CONFIG.find({ - revolt: { $in: message.channel?.server?.channel_ids || [] }, + revolt: { $in: Array.from(message.channel?.server?.channelIds.values() ?? []) }, }); await message.reply({ @@ -142,14 +142,14 @@ export default { } case "info": { try { - if (!message.reply_ids) { + if (!message.replyIds) { return await message.reply( "Please run this command again while replying to a message." ); } if ( - message.reply_ids.length > 1 && + message.replyIds.length > 1 && !(await isModerator(message, false)) ) { return await message.reply( @@ -159,7 +159,7 @@ export default { const messages = ( await Promise.allSettled( - message.reply_ids?.map((m) => + message.replyIds.map((m) => message.channel!.fetchMessage(m) ) || [] ) @@ -179,7 +179,7 @@ export default { messages.map(async (msg) => { const bridgeData = await dbs.BRIDGED_MESSAGES.findOne({ - "revolt.messageId": msg._id, + "revolt.messageId": msg.id, }); const embed: SendableEmbed = bridgeData @@ -237,7 +237,7 @@ export default { } case "status": { const link = await dbs.BRIDGE_CONFIG.findOne({ - revolt: message.channel_id, + revolt: message.channelId, }); if (!link) @@ -291,7 +291,7 @@ export default { if (!newVal) { const bridgeConfig = await dbs.BRIDGE_CONFIG.findOne({ - revolt: message.channel_id, + revolt: message.channelId, }); return await message.reply({ embeds: [ @@ -316,10 +316,10 @@ export default { } await dbs.BRIDGE_CONFIG.update( - { revolt: message.channel_id }, + { revolt: message.channelId }, { $set: { [`config.${configKey}`]: newVal == "true" }, - $setOnInsert: { revolt: message.channel_id }, + $setOnInsert: { revolt: message.channelId }, }, { upsert: true } ); diff --git a/bot/src/bot/commands/configuration/login.ts b/bot/src/bot/commands/configuration/login.ts index 32d823d..9ad5fbe 100644 --- a/bot/src/bot/commands/configuration/login.ts +++ b/bot/src/bot/commands/configuration/login.ts @@ -23,7 +23,7 @@ export default { const login: FindOneResult = await dbs.PENDING_LOGINS.findOne({ code, - user: message.author_id, + user: message.authorId, confirmed: false, exchanged: false, invalid: false, @@ -35,7 +35,7 @@ export default { if (!login) return message.reply(`Unknown code. Make sure you're logged into the correct account.`); if (login.requirePhishingConfirmation) { - logger.info(`Showing phishing warning to ${message.author_id}`); + logger.info(`Showing phishing warning to ${message.authorId}`); await Promise.all([ message.reply( `# If someone told you to run this, stop!\n` + diff --git a/bot/src/bot/commands/configuration/logout.ts b/bot/src/bot/commands/configuration/logout.ts index 7341bfc..349490d 100644 --- a/bot/src/bot/commands/configuration/logout.ts +++ b/bot/src/bot/commands/configuration/logout.ts @@ -20,8 +20,8 @@ export default { if (code.toLowerCase() == 'all') { const [resA, resB] = await Promise.all([ - dbs.PENDING_LOGINS.update({ user: message.author_id, invalid: false }, { $set: { invalid: true } }), - dbs.SESSIONS.update({ user: message.author_id, invalid: false }, { $set: { invalid: true } }), + dbs.PENDING_LOGINS.update({ user: message.authorId, invalid: false }, { $set: { invalid: true } }), + dbs.SESSIONS.update({ user: message.authorId, invalid: false }, { $set: { invalid: true } }), ]); if (resA.nModified == 0 && resB.nModified == 0) return message.reply('There are no sessions to invalidate.'); @@ -30,7 +30,7 @@ export default { } else { const loginAttempt = await dbs.PENDING_LOGINS.findOne({ code: code.toUpperCase(), - user: message.author_id, + user: message.authorId, }); if (!loginAttempt || loginAttempt.invalid) { diff --git a/bot/src/bot/commands/configuration/moderator.ts b/bot/src/bot/commands/configuration/moderator.ts index f92bf4d..5f0df58 100644 --- a/bot/src/bot/commands/configuration/moderator.ts +++ b/bot/src/bot/commands/configuration/moderator.ts @@ -1,7 +1,7 @@ import SimpleCommand from "../../../struct/commands/SimpleCommand"; import { isBotManager, NO_MANAGER_MSG, parseUser } from "../../util"; import { client, dbs } from "../../.."; -import { User } from "@janderedev/revolt.js/dist/maps/Users"; +import { User } from "revolt.js"; import MessageCommandContext from "../../../struct/MessageCommandContext"; import CommandCategory from "../../../struct/commands/CommandCategory"; @@ -18,7 +18,7 @@ export default { run: async (message: MessageCommandContext, args: string[]) => { if (!await isBotManager(message)) return message.reply(NO_MANAGER_MSG); - let config = await dbs.SERVERS.findOne({ id: message.serverContext._id }); + let config = await dbs.SERVERS.findOne({ id: message.serverContext.id }); let mods = config?.moderators ?? []; let user: User|null; @@ -29,12 +29,12 @@ export default { user = await parseUser(args[1]); if (!user) return message.reply('I can\'t find that user.'); - if (mods.indexOf(user._id) > -1) return message.reply('This user is already added as moderator.'); + if (mods.indexOf(user.id) > -1) return message.reply('This user is already added as moderator.'); - mods.push(user._id); - await dbs.SERVERS.update({ id: message.serverContext._id }, { $set: { moderators: mods } }); + mods.push(user.id); + await dbs.SERVERS.update({ id: message.serverContext.id }, { $set: { moderators: mods } }); - message.reply(`✅ Added [@${user.username}](/@${user._id}) to moderators.`); + message.reply(`✅ Added [@${user.username}](/@${user.id}) to moderators.`); break; case 'remove': case 'delete': @@ -44,12 +44,12 @@ export default { user = await parseUser(args[1]); if (!user) return message.reply('I can\'t find that user.'); - if (mods.indexOf(user._id) == -1) return message.reply('This user is not added as moderator.'); + if (mods.indexOf(user.id) == -1) return message.reply('This user is not added as moderator.'); - mods = mods.filter(a => a != user?._id); - await dbs.SERVERS.update({ id: message.serverContext._id }, { $set: { moderators: mods } }); + mods = mods.filter(a => a != user?.id); + await dbs.SERVERS.update({ id: message.serverContext.id }, { $set: { moderators: mods } }); - message.reply(`✅ Removed [@${user.username}](/@${user._id}) from moderators.`); + message.reply(`✅ Removed [@${user.username}](/@${user.id}) from moderators.`); break; case 'list': case 'ls': diff --git a/bot/src/bot/commands/configuration/prefix.ts b/bot/src/bot/commands/configuration/prefix.ts index a088413..58fe313 100644 --- a/bot/src/bot/commands/configuration/prefix.ts +++ b/bot/src/bot/commands/configuration/prefix.ts @@ -15,7 +15,7 @@ export default { syntax: SYNTAX, category: CommandCategory.Config, run: async (message: MessageCommandContext, args: string[]) => { - let config = await dbs.SERVERS.findOne({ id: message.channel!.server_id! }); + let config = await dbs.SERVERS.findOne({ id: message.channel!.serverId! }); switch(args[0]?.toLowerCase()) { case 'set': @@ -31,7 +31,7 @@ export default { return message.reply(val); } - await dbs.SERVERS.update({ id: message.channel!.server_id! }, { $set: { 'prefix': newPrefix } }); + await dbs.SERVERS.update({ id: message.channel!.serverId! }, { $set: { 'prefix': newPrefix } }); message.reply(`✅ Prefix has been changed from \`${oldPrefix}\` to \`${newPrefix}\`.\n${MENTION_TEXT}`); break; @@ -45,7 +45,7 @@ export default { if (!await isBotManager(message)) return message.reply(NO_MANAGER_MSG); if (config?.prefix != null) { - await dbs.SERVERS.update({ id: message.channel!.server_id! }, { $set: { prefix: undefined } }); + await dbs.SERVERS.update({ id: message.channel!.serverId! }, { $set: { prefix: undefined } }); } message.reply(`✅ Prefix has been reset to the default: \`${DEFAULT_PREFIX}\`.`); diff --git a/bot/src/bot/commands/configuration/whitelist.ts b/bot/src/bot/commands/configuration/whitelist.ts index 4faaba1..20add32 100644 --- a/bot/src/bot/commands/configuration/whitelist.ts +++ b/bot/src/bot/commands/configuration/whitelist.ts @@ -1,4 +1,4 @@ -import { User } from "@janderedev/revolt.js/dist/maps/Users"; +import { User } from "revolt.js"; import { client, dbs } from "../../.."; import CommandCategory from "../../../struct/commands/CommandCategory"; import SimpleCommand from "../../../struct/commands/SimpleCommand"; @@ -15,8 +15,8 @@ export default { syntax: SYNTAX, category: CommandCategory.Config, run: async (message: MessageCommandContext, args: string[]) => { - let config: ServerConfig|null = await dbs.SERVERS.findOne({ id: message.serverContext._id }) - if (!config) config = { id: message.channel!.server_id! }; + let config: ServerConfig|null = await dbs.SERVERS.findOne({ id: message.serverContext.id }) + if (!config) config = { id: message.channel!.serverId! }; if (!config.whitelist) config.whitelist = { users: [], roles: [], managers: true } if (!isBotManager(message)) return message.reply(NO_MANAGER_MSG); @@ -37,18 +37,18 @@ export default { return message.reply('That role is already whitelisted.'); config.whitelist!.roles = [role, ...(config.whitelist!.roles ?? [])]; - await dbs.SERVERS.update({ id: message.serverContext._id }, { $set: { whitelist: config.whitelist } }); + await dbs.SERVERS.update({ id: message.serverContext.id }, { $set: { whitelist: config.whitelist } }); return message.reply(`Added role to whitelist!`); } user = await parseUser(args[1]) if (user == null) return message.reply('I can\'t find that user or role.'); if (user.bot != null) return message.reply('Bots cannot be whitelisted.'); - if (config.whitelist!.users?.includes(user._id)) + if (config.whitelist!.users?.includes(user.id)) return message.reply('That user is already whitelisted.'); - config.whitelist!.users = [user._id, ...(config.whitelist!.users ?? [])]; - await dbs.SERVERS.update({ id: message.serverContext._id }, { $set: { whitelist: config.whitelist } }); + config.whitelist!.users = [user.id, ...(config.whitelist!.users ?? [])]; + await dbs.SERVERS.update({ id: message.serverContext.id }, { $set: { whitelist: config.whitelist } }); return message.reply('Added user to whitelist!'); break; case 'rm': @@ -67,17 +67,17 @@ export default { return message.reply('That role is not whitelisted.'); config.whitelist!.roles = config.whitelist!.roles.filter(r => r != role); - await dbs.SERVERS.update({ id: message.serverContext._id }, { $set: { whitelist: config.whitelist } }); + await dbs.SERVERS.update({ id: message.serverContext.id }, { $set: { whitelist: config.whitelist } }); return message.reply(`Removed role from whitelist!`); } user = await parseUser(args[1]) if (user == null) return message.reply('I can\'t find that user or role.'); - if (!config.whitelist!.users?.includes(user._id)) + if (!config.whitelist!.users?.includes(user.id)) return message.reply('That user is not whitelisted.'); - config.whitelist!.users = config.whitelist!.users.filter(u => u != user?._id); - await dbs.SERVERS.update({ id: message.serverContext._id }, { $set: { whitelist: config.whitelist } }); + config.whitelist!.users = config.whitelist!.users.filter(u => u != user?.id); + await dbs.SERVERS.update({ id: message.serverContext.id }, { $set: { whitelist: config.whitelist } }); return message.reply('Removed user from whitelist!'); break; case 'l': @@ -98,7 +98,7 @@ export default { if (config.whitelist.roles?.length) { config.whitelist.roles - ?.map(r => message.serverContext.roles?.[r]?.name || `Unknown role (${r})`) + ?.map(r => message.serverContext.roles.get(r)?.name || `Unknown role (${r})`) .forEach((r, index) => { if (index < 15) str += `* ${r}\n`; if (index == 15) str += `**${config!.whitelist!.roles!.length - 15} more role${config?.whitelist?.roles?.length == 16 ? '' : 's'}**\n`; diff --git a/bot/src/bot/commands/misc/debug.ts b/bot/src/bot/commands/misc/debug.ts index 2c97333..d7953f9 100644 --- a/bot/src/bot/commands/misc/debug.ts +++ b/bot/src/bot/commands/misc/debug.ts @@ -31,11 +31,11 @@ export default { ); } else { await message.reply( - `Server ID: ${message.channel?.server_id || 'None'}\n` - + `Server context: ${message.serverContext._id} ` - + `(${message.serverContext._id == message.channel?.server_id ? 'This server' : message.serverContext.name})\n` - + `Channel ID: ${message.channel_id}\n` - + `User ID: ${message.author_id}`, + `Server ID: ${message.channel?.serverId || 'None'}\n` + + `Server context: ${message.serverContext.id} ` + + `(${message.serverContext.id == message.channel?.serverId ? 'This server' : message.serverContext.name})\n` + + `Channel ID: ${message.channelId}\n` + + `User ID: ${message.authorId}`, false ); } diff --git a/bot/src/bot/commands/misc/help.ts b/bot/src/bot/commands/misc/help.ts index ab1d4c6..4924cbb 100644 --- a/bot/src/bot/commands/misc/help.ts +++ b/bot/src/bot/commands/misc/help.ts @@ -42,7 +42,7 @@ export default { removeEmptyArgs: true, category: CommandCategory.Misc, run: async (message: MessageCommandContext, args: string[]) => { - const isBotOwner = ownerIDs.includes(message.author_id); + const isBotOwner = ownerIDs.includes(message.authorId!); const prefix = DEFAULT_PREFIX; // TODO: fetch prefix from server config let searchInput = args.shift()?.toLowerCase(); @@ -50,7 +50,7 @@ export default { let msg = `## AutoMod help\n` + `Type **${prefix}help [category]** to view see all commands or **${prefix}help [command]** to learn more about a command.\n\n` + `### [Open Server Settings]` - + `(<${process.env.WEB_UI_URL || 'https://automod.janderedev.xyz'}/dashboard/${message.channel?.server_id}>)\n\n`; + + `(<${process.env.WEB_UI_URL || 'https://automod.janderedev.xyz'}/dashboard/${message.channel?.serverId}>)\n\n`; let total = 0; diff --git a/bot/src/bot/commands/misc/ping.ts b/bot/src/bot/commands/misc/ping.ts index cf5c57b..1704258 100644 --- a/bot/src/bot/commands/misc/ping.ts +++ b/bot/src/bot/commands/misc/ping.ts @@ -14,8 +14,8 @@ export default { ?.catch(console.error) .then(msg => { if (msg) msg.edit({ content: `## Ping Pong!\n` - + `WS: \`${client.websocket.ping ?? '--'}ms\`\n` - + `Msg: \`${Math.round(Date.now() - now) / 2}ms\`` }); + + `WS: \`${client.events.ping() ?? '--'}ms\`\n` + + `Msg: \`${Math.round(Date.now() - now)}ms\`` }); }); } } as SimpleCommand; diff --git a/bot/src/bot/commands/moderation/avatar.ts b/bot/src/bot/commands/moderation/avatar.ts index 716abee..fe6a2f5 100644 --- a/bot/src/bot/commands/moderation/avatar.ts +++ b/bot/src/bot/commands/moderation/avatar.ts @@ -1,9 +1,11 @@ -import { Member } from "@janderedev/revolt.js/dist/maps/Members"; +import { ServerMember } from "revolt.js"; import axios from "axios"; import CommandCategory from "../../../struct/commands/CommandCategory"; import SimpleCommand from "../../../struct/commands/SimpleCommand"; import MessageCommandContext from "../../../struct/MessageCommandContext"; -import { hasPerm, isModerator, NO_MANAGER_MSG, parseUser } from "../../util"; +import { isModerator, NO_MANAGER_MSG, parseUser } from "../../util"; +import AutomodClient from "../../../struct/AutomodClient"; +import { client } from "../../.."; export default { name: 'avatar', @@ -23,13 +25,13 @@ export default { || args[0]?.toLowerCase() == 'clear') { // Clear server avatar if (!message.member) return; - if (!hasPerm(message.member, 'RemoveAvatars') + if (!message.member.hasPermission(message.member.server!, 'RemoveAvatars') && !await isModerator(message)) return message.reply(NO_MANAGER_MSG); if (!target.avatar) { await message.reply(`\`@${targetUser.username}\` does not currently have an avatar set for this server.`); } else { - await clearAvatar(target); + await target.edit({ remove: ['Avatar'] }); await message.reply(`\`@${targetUser.username}\`'s server avatar has been cleared.`); } } else { @@ -37,9 +39,9 @@ export default { await message.reply( `### \`@${targetUser.username}\`'s avatar\n` + - (targetUser.avatar ? `[\\[Global\\]](<${targetUser.generateAvatarURL()}>)` : '[No global avatar]') + + (targetUser.avatar ? `[\\[Global\\]](<${targetUser.avatarURL}>)` : '[No global avatar]') + ' | ' + - (target.avatar ? `[\\[Server\\]](<${target.generateAvatarURL()}>)` : '[No server avatar]') + (target.avatar ? `[\\[Server\\]](<${target.avatarURL}>)` : '[No server avatar]') ); } } catch(e) { @@ -48,17 +50,3 @@ export default { } } } as SimpleCommand; - -async function clearAvatar(member: Member) { - await axios.patch( - `${member.client.apiURL}/servers/${member.server!._id}/members/${member._id.user}`, - { - remove: [ "Avatar" ], - }, - { - headers: { - 'x-bot-token': process.env['BOT_TOKEN']! - } - } - ); -} diff --git a/bot/src/bot/commands/moderation/ban.ts b/bot/src/bot/commands/moderation/ban.ts index f6a1a76..0c4e11b 100644 --- a/bot/src/bot/commands/moderation/ban.ts +++ b/bot/src/bot/commands/moderation/ban.ts @@ -13,6 +13,7 @@ import { getDmChannel, getMembers, isModerator, + memberRanking, NO_MANAGER_MSG, parseUserOrId, sanitizeMessageContent, @@ -23,7 +24,7 @@ import Day from "dayjs"; import RelativeTime from "dayjs/plugin/relativeTime"; import CommandCategory from "../../../struct/commands/CommandCategory"; import { SendableEmbed } from "revolt-api"; -import { User } from "@janderedev/revolt.js"; +import { User } from "revolt.js"; import logger from "../../logger"; Day.extend(RelativeTime); @@ -49,10 +50,10 @@ export default { }); } - const userInput = !message.reply_ids?.length + const userInput = !message.replyIds?.length ? args.shift() || "" : undefined; - if (!userInput && !message.reply_ids?.length) + if (!userInput && !message.replyIds?.length) return message.reply({ embeds: [ embed( @@ -121,13 +122,13 @@ export default { const embeds: SendableEmbed[] = []; const handledUsers: string[] = []; - const targetUsers: User | { _id: string }[] = []; + const targetUsers: User | { id: string }[] = []; const targetInput = dedupeArray( - message.reply_ids?.length + message.replyIds?.length ? ( await Promise.allSettled( - message.reply_ids.map((msg) => + message.replyIds.map((msg) => message.channel?.fetchMessage(msg) ) ) @@ -154,10 +155,10 @@ export default { } // Silently ignore duplicates - if (handledUsers.includes(user._id)) continue; - handledUsers.push(user._id); + if (handledUsers.includes(user.id)) continue; + handledUsers.push(user.id); - if (user._id == message.author_id) { + if (user.id == message.authorId!) { embeds.push( embed( "I recommend against banning yourself :yeahokayyy:", @@ -168,7 +169,7 @@ export default { continue; } - if (user._id == client.user!._id) { + if (user.id == client.user!.id) { embeds.push( embed( "I'm not going to ban myself :flushee:", @@ -194,21 +195,21 @@ export default { } } - if (message.reply_ids?.length && targetUsers.length) { + if (message.replyIds?.length && targetUsers.length) { let res = await yesNoMessage( message.channel!, - message.author_id, + message.authorId!, `This will ban the author${targetUsers.length > 1 ? 's' : ''} ` - + `of the message${message.reply_ids.length > 1 ? 's' : ''} you replied to.\n` + + `of the message${message.replyIds.length > 1 ? 's' : ''} you replied to.\n` + `The following user${targetUsers.length > 1 ? 's' : ''} will be affected: ` - + `${targetUsers.map(u => `<@${u._id}>`).join(', ')}.\n` + + `${targetUsers.map(u => `<@${u.id}>`).join(', ')}.\n` + `Are you sure?`, 'Confirm action' ); if (!res) return; } - const members = getMembers(message.serverContext._id); + const members = getMembers(message.serverContext.id); for (const user of targetUsers) { try { @@ -216,18 +217,18 @@ export default { const infId = ulid(); const infraction: Infraction = { _id: infId, - createdBy: message.author_id, + createdBy: message.authorId!, date: Date.now(), reason: reason || "No reason provided", - server: message.serverContext._id, + server: message.serverContext.id, type: InfractionType.Manual, - user: user._id, + user: user.id, actionType: "ban", expires: Infinity, }; const { userWarnCount } = await storeInfraction(infraction); - const member = members.find((m) => m._id.user == user._id); + const member = members.find((m) => m.id.user == user.id); if ( member && @@ -244,11 +245,11 @@ export default { continue; } - if (member && !member.bannable) { + if (member && !memberRanking(member).bannable) { embeds.push( embed( `I don't have permission to ban \`${ - member?.user?.username || user._id + member?.user?.username || user.id }\`.`, null, EmbedColor.SoftError @@ -281,11 +282,11 @@ export default { } } - await message.serverContext.banUser(user._id, { + await message.serverContext.banUser(user.id, { reason: reason + - ` (by ${await fetchUsername(message.author_id)} ${ - message.author_id + ` (by ${await fetchUsername(message.authorId!)} ${ + message.authorId })`, }); @@ -293,7 +294,7 @@ export default { "ban", message.serverContext, message.member!, - user._id, + user.id, reason, infraction._id, `Ban duration: **Permanent**` @@ -305,7 +306,7 @@ export default { }`, icon_url: user instanceof User - ? user.generateAvatarURL() + ? user.avatarURL : undefined, colour: EmbedColor.Success, description: @@ -314,8 +315,8 @@ export default { ? "**the first infraction**" : `infraction number **${userWarnCount}**` }` + - ` for ${await fetchUsername(user._id)}.\n` + - `**User ID:** \`${user._id}\`\n` + + ` for ${await fetchUsername(user.id)}.\n` + + `**User ID:** \`${user.id}\`\n` + `**Infraction ID:** \`${infraction._id}\`\n` + `**Reason:** \`${infraction.reason}\``, }); @@ -325,14 +326,14 @@ export default { const infId = ulid(); const infraction: Infraction = { _id: infId, - createdBy: message.author_id, + createdBy: message.authorId!, date: Date.now(), reason: (reason || "No reason provided") + ` (${durationStr})`, - server: message.serverContext._id, + server: message.serverContext.id, type: InfractionType.Manual, - user: user._id, + user: user.id, actionType: "ban", expires: banUntil, }; @@ -362,26 +363,26 @@ export default { } } - await message.serverContext.banUser(user._id, { + await message.serverContext.banUser(user.id, { reason: reason + - ` (by ${await fetchUsername(message.author_id)} ${ - message.author_id + ` (by ${await fetchUsername(message.authorId!)} ${ + message.authorId }) (${durationStr})`, }); await Promise.all([ storeTempBan({ id: infId, - bannedUser: user._id, - server: message.serverContext._id, + bannedUser: user.id, + server: message.serverContext.id, until: banUntil, }), logModAction( "ban", message.serverContext, message.member!, - user._id, + user.id, reason, infraction._id, `Ban duration: **${banDurationFancy}**` @@ -392,7 +393,7 @@ export default { title: `User temporarily banned`, icon_url: user instanceof User - ? user.generateAvatarURL() + ? user.avatarURL : undefined, colour: EmbedColor.Success, description: @@ -401,9 +402,9 @@ export default { ? "**the first infraction**" : `infraction number **${userWarnCount}**` }` + - ` for ${await fetchUsername(user._id)}.\n` + + ` for ${await fetchUsername(user.id)}.\n` + `**Ban duration:** ${banDurationFancy}\n` + - `**User ID:** \`${user._id}\`\n` + + `**User ID:** \`${user.id}\`\n` + `**Infraction ID:** \`${infraction._id}\`\n` + `**Reason:** \`${infraction.reason}\``, }); @@ -413,8 +414,8 @@ export default { embeds.push( embed( `Failed to ban target \`${await fetchUsername( - user._id, - user._id + user.id, + user.id )}\`: ${e}`, "Failed to ban: An error has occurred", EmbedColor.Error diff --git a/bot/src/bot/commands/moderation/kick.ts b/bot/src/bot/commands/moderation/kick.ts index 7b754d4..8af5ee4 100644 --- a/bot/src/bot/commands/moderation/kick.ts +++ b/bot/src/bot/commands/moderation/kick.ts @@ -1,4 +1,4 @@ -import { User } from "@janderedev/revolt.js"; +import { User } from "revolt.js"; import { SendableEmbed } from "revolt-api"; import { ulid } from "ulid"; import { client } from "../../../"; @@ -39,10 +39,10 @@ export default { ); } - const userInput = !message.reply_ids?.length + const userInput = !message.replyIds?.length ? args.shift() || "" : undefined; - if (!userInput && !message.reply_ids?.length) + if (!userInput && !message.replyIds?.length) return message.reply({ embeds: [ embed( @@ -72,19 +72,19 @@ export default { const embeds: SendableEmbed[] = []; const handledUsers: string[] = []; - const targetUsers: User | { _id: string }[] = []; + const targetUsers: User | { id: string }[] = []; const targetInput = dedupeArray( - message.reply_ids?.length + message.replyIds?.length ? ( await Promise.allSettled( - message.reply_ids.map((msg) => + message.replyIds.map((msg) => message.channel?.fetchMessage(msg) ) ) ) .filter((m) => m.status == "fulfilled") - .map((m) => (m as any).value.author_id) + .map((m) => (m as any).value.authorId) : userInput!.split(",") ); @@ -105,10 +105,10 @@ export default { } // Silently ignore duplicates - if (handledUsers.includes(user._id)) continue; - handledUsers.push(user._id); + if (handledUsers.includes(user.id)) continue; + handledUsers.push(user.id); - if (user._id == message.author_id) { + if (user.id == message.authorId) { embeds.push( embed( "You might want to avoid kicking yourself...", @@ -119,7 +119,7 @@ export default { continue; } - if (user._id == client.user!._id) { + if (user.id == client.user!.id) { embeds.push( embed( "I won't allow you to get rid of me this easily :trol:", @@ -145,30 +145,30 @@ export default { } } - if (message.reply_ids?.length && targetUsers.length) { + if (message.replyIds?.length && targetUsers.length) { let res = await yesNoMessage( message.channel!, - message.author_id, + message.authorId!, `This will kick the author${targetUsers.length > 1 ? 's' : ''} ` - + `of the message${message.reply_ids.length > 1 ? 's' : ''} you replied to.\n` + + `of the message${message.replyIds.length > 1 ? 's' : ''} you replied to.\n` + `The following user${targetUsers.length > 1 ? 's' : ''} will be affected: ` - + `${targetUsers.map(u => `<@${u._id}>`).join(', ')}.\n` + + `${targetUsers.map(u => `<@${u.id}>`).join(', ')}.\n` + `Are you sure?`, 'Confirm action' ); if (!res) return; } - const members = getMembers(message.serverContext._id); + const members = getMembers(message.serverContext.id); for (const user of targetUsers) { try { - const member = members.find((m) => m._id.user == user._id); + const member = members.find((m) => m.id.user == user.id); if (!member) { embeds.push( embed( `\`${await fetchUsername( - user._id + user.id )}\` is not a member of this server.` ) ); @@ -178,12 +178,12 @@ export default { let infId = ulid(); let infraction: Infraction = { _id: infId, - createdBy: message.author_id, + createdBy: message.authorId!, date: Date.now(), reason: reason || "No reason provided", - server: message.serverContext._id, + server: message.serverContext.id, type: InfractionType.Manual, - user: user._id, + user: user.id, actionType: "kick", }; @@ -214,7 +214,7 @@ export default { "kick", message.serverContext, message.member!, - user._id, + user.id, reason, infraction._id ), @@ -225,7 +225,7 @@ export default { title: `User kicked`, icon_url: user instanceof User - ? user.generateAvatarURL() + ? user.avatarURL : undefined, colour: EmbedColor.Success, description: @@ -234,8 +234,8 @@ export default { ? "**the first infraction**" : `infraction number **${userWarnCount}**` }` + - ` for ${await fetchUsername(user._id)}.\n` + - `**User ID:** \`${user._id}\`\n` + + ` for ${await fetchUsername(user.id)}.\n` + + `**User ID:** \`${user.id}\`\n` + `**Infraction ID:** \`${infraction._id}\`\n` + `**Reason:** \`${infraction.reason}\``, }); @@ -243,7 +243,7 @@ export default { embeds.push( embed( `Failed to kick user ${await fetchUsername( - user._id + user.id )}: ${e}`, "Failed to kick user", EmbedColor.Error diff --git a/bot/src/bot/commands/moderation/nick.ts b/bot/src/bot/commands/moderation/nick.ts index e5ab1ad..9958fc2 100644 --- a/bot/src/bot/commands/moderation/nick.ts +++ b/bot/src/bot/commands/moderation/nick.ts @@ -1,9 +1,10 @@ -import { Member } from "@janderedev/revolt.js/dist/maps/Members"; +import { ServerMember } from "revolt.js"; import axios from "axios"; import CommandCategory from "../../../struct/commands/CommandCategory"; import SimpleCommand from "../../../struct/commands/SimpleCommand"; import MessageCommandContext from "../../../struct/MessageCommandContext"; -import { hasPerm, isModerator, NO_MANAGER_MSG, parseUser } from "../../util"; +import { isModerator, NO_MANAGER_MSG, parseUser } from "../../util"; +import { client } from "../../.."; export default { name: 'nick', @@ -13,7 +14,7 @@ export default { run: async (message: MessageCommandContext, args: string[]) => { try { if (!message.member) return; - if (!hasPerm(message.member, 'ManageNicknames') + if (!message.member.hasPermission(message.member.server!, 'ManageNicknames') && !await isModerator(message)) return message.reply(NO_MANAGER_MSG); const targetStr = args.shift(); @@ -42,9 +43,9 @@ export default { } } as SimpleCommand; -async function setNick(member: Member, newName: string|null) { +async function setNick(member: ServerMember, newName: string|null) { await axios.patch( - `${member.client.apiURL}/servers/${member.server!._id}/members/${member._id.user}`, + `${client.options.baseURL}/servers/${member.server!.id}/members/${member.id.user}`, { nickname: newName || undefined, remove: !newName ? [ "Nickname" ] : undefined, diff --git a/bot/src/bot/commands/moderation/purge.ts b/bot/src/bot/commands/moderation/purge.ts index 9ee57ca..5b0f2f4 100644 --- a/bot/src/bot/commands/moderation/purge.ts +++ b/bot/src/bot/commands/moderation/purge.ts @@ -1,5 +1,5 @@ import SimpleCommand from "../../../struct/commands/SimpleCommand"; -import { Message } from "@janderedev/revolt.js/dist/maps/Messages"; +import { Message } from "revolt.js"; import { decodeTime } from 'ulid'; import { isModerator, parseUserOrId } from "../../util"; import MessageCommandContext from "../../../struct/MessageCommandContext"; @@ -31,7 +31,7 @@ export default { messages = await message.channel!.fetchMessages({ limit: amount, - before: message._id, + before: message.id, }); } // delete messages between [id] and [id] @@ -49,7 +49,7 @@ export default { ]); // Make sure the msg1 and msg2 are in the correct order - if (decodeTime(msg1._id) < decodeTime(msg2._id)) { + if (decodeTime(msg1.id) < decodeTime(msg2.id)) { [msg1, msg2] = [msg2, msg1]; } @@ -60,17 +60,17 @@ export default { sort: "Latest", }); - if (!messages.find((m) => m._id == msg1._id)) + if (!messages.find((m) => m.id == msg1.id)) messages = [msg1, ...messages]; - if (!messages.find((m) => m._id == msg2._id)) + if (!messages.find((m) => m.id == msg2.id)) messages = [...messages, msg2]; // Discard messages that are not in the selected range, // because Revolt returns more messages than expected for some reason messages = messages.filter( (m) => - decodeTime(m._id) <= decodeTime(id2) && - decodeTime(m._id) >= decodeTime(id1) + decodeTime(m.id) <= decodeTime(id2) && + decodeTime(m.id) >= decodeTime(id1) ); } // allow single messages too, because why not? @@ -92,11 +92,11 @@ export default { ); messages = messages.filter((m) => - users.find((u) => u?._id == m.author_id) + users.find((u) => u?.id == m.authorId) ); } - await message.channel?.deleteMessages(messages.map((m) => m._id)); + await message.channel?.deleteMessages(messages.map((m) => m.id)); const replyMsg = await message.channel ?.sendMessage({ @@ -107,8 +107,8 @@ export default { setTimeout(async () => { try { await message.channel?.deleteMessages([ - replyMsg!._id, - message._id, + replyMsg!.id, + message.id, ]); } catch (e) { console.error(e); diff --git a/bot/src/bot/commands/moderation/timeout.ts b/bot/src/bot/commands/moderation/timeout.ts index 5ea4d2e..762170f 100644 --- a/bot/src/bot/commands/moderation/timeout.ts +++ b/bot/src/bot/commands/moderation/timeout.ts @@ -45,13 +45,13 @@ export default { const duration = parseTimeInput(args[1] ?? ''); if (!duration) { - await client.api.patch(`/servers/${message.serverContext._id}/members/${target._id}` as '/servers/{server}/members/{target}', { + await client.api.patch(`/servers/${message.serverContext.id}/members/${target.id}` as '/servers/{server}/members/{target}', { timeout: new Date(0).toISOString() } as any); await message.reply(`Timeout cleared on @${target.username}`); } else { - await client.api.patch(`/servers/${message.serverContext._id}/members/${target._id}` as '/servers/{server}/members/{target}', { + await client.api.patch(`/servers/${message.serverContext.id}/members/${target.id}` as '/servers/{server}/members/{target}', { timeout: new Date(Date.now() + duration).toISOString() } as any); await message.reply(`Successfully timed out @${target.username}`); diff --git a/bot/src/bot/commands/moderation/unban.ts b/bot/src/bot/commands/moderation/unban.ts index 605ced8..e66a296 100644 --- a/bot/src/bot/commands/moderation/unban.ts +++ b/bot/src/bot/commands/moderation/unban.ts @@ -18,7 +18,7 @@ export default { } let checkTempBans = async (id: string): Promise => { - let tempbans = await dbs.TEMPBANS.find({ bannedUser: id, server: message.serverContext._id }); + let tempbans = await dbs.TEMPBANS.find({ bannedUser: id, server: message.serverContext.id }); if (tempbans.length > 0) { for (const ban of tempbans) { await removeTempBan(ban.id); @@ -37,7 +37,7 @@ export default { let id: string|undefined = undefined; try { - id = (await parseUser(target))?._id; + id = (await parseUser(target))?.id; } catch(e) { if (USER_MENTION_REGEX.test(target)) { id = target @@ -46,8 +46,8 @@ export default { } else if (ULID_REGEX.test(target)) { id = target; } else { - let user = bans.users.find(u => u.username.toLowerCase() == target.toLowerCase()); - if (user) id = user._id; + let ban = bans.find(b => b.user?.username.toLowerCase() == target.toLowerCase()); + if (ban) id = ban.id.user; } } @@ -58,9 +58,9 @@ export default { } else return msg.edit({ content: 'The user could not be found.' }); } - let bannedUser = bans.users.find(u => u._id == id); + let ban = bans.find(b => b.id.user == id); - if (!bannedUser) { + if (!ban) { let tempnum = await checkTempBans(id); if (tempnum > 0) { return msg.edit({ content: 'This user is not banned, but leftover database entries have been cleaned up.' }); @@ -68,12 +68,12 @@ export default { } await Promise.all([ - msg.edit({ content: `User found: @${bannedUser.username}, unbanning...` }), + msg.edit({ content: `User found: @${ban.user?.username ?? ban.id.user}, unbanning...` }), message.serverContext.unbanUser(id), checkTempBans(id), ]); - await msg.edit({ content: `@${bannedUser.username} has been unbanned.` }); + await msg.edit({ content: `@${ban.user?.username ?? ban.id.user} has been unbanned.` }); } catch(e) { console.error(e) } } } as SimpleCommand; diff --git a/bot/src/bot/commands/moderation/votekick.ts b/bot/src/bot/commands/moderation/votekick.ts index 1dfee0b..ea04b78 100644 --- a/bot/src/bot/commands/moderation/votekick.ts +++ b/bot/src/bot/commands/moderation/votekick.ts @@ -24,7 +24,7 @@ export default { category: CommandCategory.Moderation, run: async (message: MessageCommandContext, args: string[]) => { try { - const serverConfig = await dbs.SERVERS.findOne({ id: message.serverContext._id }); + const serverConfig = await dbs.SERVERS.findOne({ id: message.serverContext.id }); if (!serverConfig?.votekick?.enabled) return message.reply('Vote kick is not enabled for this server.'); if (!message.member!.roles?.filter(r => serverConfig.votekick?.trustedRoles.includes(r)).length && !(await isModerator(message))) { @@ -47,23 +47,23 @@ export default { const vote: VoteEntry = { id: ulid(), - target: target._id, - user: message.author_id, - server: message.serverContext._id, + target: target.id, + user: message.authorId!, + server: message.serverContext.id, time: Date.now(), ignore: false, } const votes = await dbs.VOTEKICKS.find({ - server: message.serverContext._id, - target: target._id, + server: message.serverContext.id, + target: target.id, time: { $gt: Date.now() - 1000 * 60 * 30, // Last 30 minutes }, ignore: false, }); - if (votes.find(v => v.user == message.author_id)) return message.reply('You can\'t vote twice for this user.'); + if (votes.find(v => v.user == message.authorId)) return message.reply('You can\'t vote twice for this user.'); await dbs.VOTEKICKS.insert(vote); votes.push({ _id: '' as any, ...vote }); @@ -72,7 +72,7 @@ export default { "votekick", message.serverContext, message.member!, - target._id, + target.id, `n/a`, vote.id, `This is vote ${votes.length}/${serverConfig.votekick.votesRequired} for this user.`, @@ -82,15 +82,15 @@ export default { if (serverConfig.votekick.banDuration == -1) { targetMember.kick(); } else if (serverConfig.votekick.banDuration == 0) { - message.serverContext.banUser(target._id, { reason: 'Automatic permanent ban triggered by /votekick' }); + message.serverContext.banUser(target.id, { reason: 'Automatic permanent ban triggered by /votekick' }); } else { - message.serverContext.banUser(target._id, { reason: `Automatic temporary ban triggered by /votekick ` + message.serverContext.banUser(target.id, { reason: `Automatic temporary ban triggered by /votekick ` + `(${serverConfig.votekick.banDuration} minutes)` }); await storeTempBan({ id: ulid(), - bannedUser: target._id, - server: message.serverContext._id, + bannedUser: target.id, + server: message.serverContext.id, until: Date.now() + (1000 * 60 * serverConfig.votekick.banDuration), }); } @@ -99,8 +99,8 @@ export default { + `Banned @${target.username} for ${serverConfig.votekick.banDuration} minutes.`); // Todo: display ban duration properly (Permban, kick, etc) await dbs.VOTEKICKS.update({ - server: message.serverContext._id, - target: target._id, + server: message.serverContext.id, + target: target.id, time: { $gt: Date.now() - 1000 * 60 * 30 }, ignore: false, }, { $set: { ignore: true } }); diff --git a/bot/src/bot/commands/moderation/warn.ts b/bot/src/bot/commands/moderation/warn.ts index 2445e13..001cbe2 100644 --- a/bot/src/bot/commands/moderation/warn.ts +++ b/bot/src/bot/commands/moderation/warn.ts @@ -6,7 +6,7 @@ import InfractionType from "automod/dist/types/antispam/InfractionType"; import { fetchUsername, logModAction } from "../../modules/mod_logs"; import CommandCategory from "../../../struct/commands/CommandCategory"; import { SendableEmbed } from "revolt-api"; -import { User } from "@janderedev/revolt.js"; +import { User } from "revolt.js"; import logger from "../../logger"; export default { @@ -19,7 +19,7 @@ export default { if (!await isModerator(message)) return message.reply(NO_MANAGER_MSG); const userInput = args.shift() || ''; - if (!userInput && !message.reply_ids?.length) return message.reply({ embeds: [ + if (!userInput && !message.replyIds?.length) return message.reply({ embeds: [ embed( `Please specify one or more users by replying to their message while running this command or ` + `by specifying a comma-separated list of usernames.`, @@ -38,12 +38,12 @@ export default { const embeds: SendableEmbed[] = []; const handledUsers: string[] = []; - const targetUsers: User|{ _id: string }[] = []; + const targetUsers: User|{ id: string }[] = []; const targetInput = dedupeArray( // Replied messages (await Promise.allSettled( - (message.reply_ids ?? []).map(msg => message.channel?.fetchMessage(msg)) + (message.replyIds ?? []).map(msg => message.channel?.fetchMessage(msg)) )) .filter(m => m.status == 'fulfilled').map(m => (m as any).value.author_id), // Provided users @@ -54,7 +54,7 @@ export default { try { let user = await parseUserOrId(userStr); if (!user) { - if (message.reply_ids?.length && userStr == userInput) { + if (message.replyIds?.length && userStr == userInput) { reason = reason ? `${userInput} ${reason}` : userInput; } else { @@ -64,8 +64,8 @@ export default { } // Silently ignore duplicates - if (handledUsers.includes(user._id)) continue; - handledUsers.push(user._id); + if (handledUsers.includes(user.id)) continue; + handledUsers.push(user.id); if ((user as any)?.bot != null) return await message.reply({ embeds: [ embed('You cannot warn bots.', null, EmbedColor.SoftError) @@ -85,10 +85,10 @@ export default { for (const user of targetUsers) { let infraction = { _id: ulid(), - createdBy: message.author_id, - user: user._id, + createdBy: message.authorId, + user: user.id, reason: reason || 'No reason provided', - server: message.serverContext._id, + server: message.serverContext.id, type: InfractionType.Manual, date: Date.now(), } as Infraction; @@ -99,7 +99,7 @@ export default { 'warn', message.serverContext, message.member!, - user._id, + user.id, reason || 'No reason provided', infraction._id, `This is warn number ${userWarnCount} for this user.` @@ -123,10 +123,10 @@ export default { embeds.push({ title: `User warned`, - icon_url: user instanceof User ? user.generateAvatarURL() : undefined, + icon_url: user instanceof User ? user.avatarURL : undefined, colour: EmbedColor.Success, description: `This is ${userWarnCount == 1 ? '**the first warn**' : `warn number **${userWarnCount}**`}` + - ` for ${await fetchUsername(user._id)}.\n` + + ` for ${await fetchUsername(user.id)}.\n` + `**Infraction ID:** \`${infraction._id}\`\n` + `**Reason:** \`${infraction.reason}\`` }); diff --git a/bot/src/bot/commands/moderation/warns.ts b/bot/src/bot/commands/moderation/warns.ts index fb380b6..41227d7 100644 --- a/bot/src/bot/commands/moderation/warns.ts +++ b/bot/src/bot/commands/moderation/warns.ts @@ -23,7 +23,7 @@ export default { category: CommandCategory.Moderation, run: async (message: MessageCommandContext, args: string[]) => { let infractions: Array = await dbs.INFRACTIONS.find({ - server: message.serverContext._id, + server: message.serverContext.id, }); let userInfractions: Map = new Map(); infractions.forEach(i => { @@ -56,7 +56,7 @@ export default { if (!id) return message.reply('No infraction ID provided.'); let inf = await dbs.INFRACTIONS.findOneAndDelete({ _id: { $eq: id.toUpperCase() }, - server: message.serverContext._id + server: message.serverContext.id }); if (!inf) return message.reply('I can\'t find that ID.'); @@ -69,18 +69,18 @@ export default { break; default: let user = await parseUserOrId(args[0]); - if (!user?._id) return message.reply('I can\'t find this user.'); + if (!user?.id) return message.reply('I can\'t find this user.'); - if (user._id != message.author_id && !await isModerator(message)) return message.reply(NO_MANAGER_MSG); + if (user.id != message.authorId && !await isModerator(message)) return message.reply(NO_MANAGER_MSG); - const infs = userInfractions.get(user._id); - const userConfig = await dbs.USERS.findOne({ id: user._id }); + const infs = userInfractions.get(user.id); + const userConfig = await dbs.USERS.findOne({ id: user.id }); - if (!infs) return message.reply(`There are no infractions stored for \`${await fetchUsername(user._id)}\`.` + if (!infs) return message.reply(`There are no infractions stored for \`${await fetchUsername(user.id)}\`.` + (userConfig?.globalBlacklist ? '\n' + GLOBAL_BLACKLIST_TEXT(userConfig.blacklistReason) : ''), false); else { - let msg = `## ${infs.length} infractions stored for ${await fetchUsername(user._id)}\n`; + let msg = `## ${infs.length} infractions stored for ${await fetchUsername(user.id)}\n`; if (userConfig?.globalBlacklist) { msg += GLOBAL_BLACKLIST_TEXT(userConfig.blacklistReason); @@ -108,7 +108,7 @@ export default { if (attachSpreadsheet) { try { let csv_data = [ - [`Warns for ${await fetchUsername(user._id)} (${user._id}) - ${Day().toString()}`], + [`Warns for ${await fetchUsername(user.id)} (${user.id}) - ${Day().toString()}`], [], ['Date', 'Reason', 'Created By', 'Type', 'Action Type', 'ID'], ]; @@ -127,7 +127,7 @@ export default { let sheet = Xlsx.utils.aoa_to_sheet(csv_data); let csv = Xlsx.utils.sheet_to_csv(sheet); - message.reply({ content: msg, attachments: [ await uploadFile(csv, `${user._id}.csv`) ] }, false); + message.reply({ content: msg, attachments: [ await uploadFile(csv, `${user.id}.csv`) ] }, false); } catch(e) { console.error(e); message.reply(msg, false); diff --git a/bot/src/bot/logging.ts b/bot/src/bot/logging.ts index 6c4767a..01897dd 100644 --- a/bot/src/bot/logging.ts +++ b/bot/src/bot/logging.ts @@ -29,7 +29,7 @@ async function adminBotLog(data: { message: string, type: 'INFO'|'WARN'|'ERROR' await client?.send({ embeds: [ embed ], username: bot.user?.username, - avatarURL: bot.user?.generateAvatarURL({ size: 128 }) + avatarURL: bot.user?.avatarURL, }); } catch(e) { logger.error(`Failed to log: ${e}`); diff --git a/bot/src/bot/modules/antispam.ts b/bot/src/bot/modules/antispam.ts index aaaf0ec..e859b76 100644 --- a/bot/src/bot/modules/antispam.ts +++ b/bot/src/bot/modules/antispam.ts @@ -1,4 +1,4 @@ -import { Message } from "@janderedev/revolt.js/dist/maps/Messages"; +import { Message } from "revolt.js"; import { ulid } from "ulid"; import { client, dbs } from "../.."; import AntispamRule from "automod/dist/types/antispam/AntispamRule"; @@ -23,7 +23,7 @@ const SENT_FILTER_MESSAGE: string[] = []; */ async function antispam(message: Message): Promise { try { - let serverRules = await dbs.SERVERS.findOne({ id: message.channel!.server_id! }); + let serverRules = await dbs.SERVERS.findOne({ id: message.channel!.serverId! }); if (!serverRules?.automodSettings) return true; let ruleTriggered = false; @@ -34,14 +34,14 @@ async function antispam(message: Message): Promise { } if (message.author?.bot != null) break; - if (serverRules.whitelist?.users?.includes(message.author_id)) break; + if (serverRules.whitelist?.users?.includes(message.authorId!)) break; if (message.member?.roles?.filter(r => serverRules!.whitelist?.roles?.includes(r)).length) break; if (serverRules.whitelist?.managers !== false && await isModerator(message, false)) break; - if (rule.channels?.length && rule.channels.indexOf(message.channel_id) == -1) break; + if (rule.channels?.length && rule.channels.indexOf(message.channelId) == -1) break; let store = msgCountStore.get(rule.id)!; - if (!store.users[message.channel_id]) store.users[message.channel_id] = {} - let userStore = store.users[message.channel_id]; + if (!store.users[message.channelId]) store.users[message.channelId] = {} + let userStore = store.users[message.channelId]; if (!userStore.count) userStore.count = 1; else userStore.count++; @@ -75,9 +75,9 @@ async function antispam(message: Message): Promise { createdBy: null, date: Date.now(), reason: `Automatic moderation rule triggered: More than ${rule.max_msg} messages per ${rule.timeframe} seconds.`, - server: message.channel?.server_id, + server: message.channel?.serverId, type: InfractionType.Automatic, - user: message.author_id, + user: message.authorId, } as Infraction; message.channel?.sendMessage('## User has been warned.\n\u200b\n' + getWarnMsg(rule, message)) @@ -107,8 +107,8 @@ async function antispam(message: Message): Promise { function getWarnMsg(rule: AntispamRule, message: Message) { if (rule.message != null) { return rule.message - .replace(new RegExp('{{userid}}', 'gi'), message.author_id); - } else return `<@${message.author_id}>, please stop spamming.`; + .replace(new RegExp('{{userid}}', 'gi'), message.authorId!); + } else return `<@${message.authorId}>, please stop spamming.`; } /** @@ -133,9 +133,9 @@ async function wordFilterCheck(message: Message, config: ServerConfig) { createdBy: null, date: Date.now(), reason: 'Word filter triggered', - server: message.channel!.server_id!, + server: message.channel!.serverId!, type: InfractionType.Automatic, - user: message.author_id, + user: message.authorId!, } await storeInfraction(infraction); @@ -155,14 +155,14 @@ async function wordFilterCheck(message: Message, config: ServerConfig) { } case 'DELETE': { if (message.channel?.havePermission('ManageMessages')) { - const key = `${message.author_id}:${message.channel_id}`; + const key = `${message.authorId}:${message.channelId}`; await message.delete(); if (!SENT_FILTER_MESSAGE.includes(key)) { SENT_FILTER_MESSAGE.push(key); setTimeout(() => SENT_FILTER_MESSAGE.splice(SENT_FILTER_MESSAGE.indexOf(key), 1), 30000); await message.channel.sendMessage((config.wordlistAction.message || WORDLIST_DEFAULT_MESSAGE) - .replaceAll('{{user_id}}', message.author_id)); + .replaceAll('{{user_id}}', message.authorId!)); } } } @@ -171,7 +171,7 @@ async function wordFilterCheck(message: Message, config: ServerConfig) { if (!config.logs?.modAction) break; await sendLogMessage(config.logs.modAction, { title: 'Message triggered word filter', - description: `**Author:** @${message.author?.username} (${message.author_id})\n` + + description: `**Author:** @${message.author?.username} (${message.authorId})\n` + `**Action:** ${config.wordlistAction?.action || 'LOG'}\n` + `#### Content\n` + `>${sanitizeMessageContent(message.content.substring(0, 1000)).trim().replace(/\n/g, '\n>')}`, @@ -259,7 +259,7 @@ const notifyPublicServers = async () => { .filter(server => server.discoverable); const res = await dbs.SERVERS.find({ - id: { $in: servers.map(s => s._id) }, + id: { $in: servers.map(s => s.id) }, discoverAutospamNotify: { $in: [ undefined, false ] }, }); @@ -273,7 +273,7 @@ const notifyPublicServers = async () => { ); const server = client.servers.get(serverConfig.id); - const channel = await getDmChannel(server!.owner); + const channel = await getDmChannel(server!.ownerId); await channel.sendMessage(`Hi there, It looks like your server, **${sanitizeMessageContent(server!.name).trim()}**, has been added to server discovery. Congratulations! diff --git a/bot/src/bot/modules/api/server_details.ts b/bot/src/bot/modules/api/server_details.ts index 4238bd1..564cb8c 100644 --- a/bot/src/bot/modules/api/server_details.ts +++ b/bot/src/bot/modules/api/server_details.ts @@ -1,5 +1,5 @@ -import { Member } from "@janderedev/revolt.js/dist/maps/Members"; -import { User } from "@janderedev/revolt.js/dist/maps/Users"; +import { ServerMember } from "revolt.js"; +import { User } from "revolt.js"; import { client, dbs } from "../../.."; import ServerConfig from "automod/dist/types/ServerConfig"; import { getPermissionLevel } from "../../util"; @@ -37,7 +37,7 @@ wsEvents.on('req:getUserServerDetails', async (data: ReqData, cb: (data: WSRespo return; } - let member: Member; + let member: ServerMember; try { member = await server.fetchMember(user); } catch(e) { @@ -45,7 +45,7 @@ wsEvents.on('req:getUserServerDetails', async (data: ReqData, cb: (data: WSRespo return; } - const serverConfig = await dbs.SERVERS.findOne({ id: server._id }); + const serverConfig = await dbs.SERVERS.findOne({ id: server.id }); // todo: remove unwanted keys from server config @@ -60,28 +60,28 @@ wsEvents.on('req:getUserServerDetails', async (data: ReqData, cb: (data: WSRespo const users = await Promise.allSettled([ ...(serverConfig?.botManagers?.map(u => fetchUser(u)) ?? []), ...(serverConfig?.moderators?.map(u => fetchUser(u)) ?? []), - fetchUser(user._id), + fetchUser(user.id), ]); const response: ServerDetails = { - id: server._id, + id: server.id, name: server.name, perms: await getPermissionLevel(member, server), description: server.description ?? undefined, - bannerURL: server.generateBannerURL(), - iconURL: server.generateIconURL(), + bannerURL: server.bannerURL, + iconURL: server.iconURL, serverConfig: (serverConfig as ServerConfig|undefined), users: users.map( u => u.status == 'fulfilled' - ? { id: u.value._id, avatarURL: u.value.generateAvatarURL(), username: u.value.username } + ? { id: u.value.id, avatarURL: u.value.avatarURL, username: u.value.username } : { id: u.reason } ), channels: server.channels.filter(c => c != undefined).map(c => ({ - id: c!._id, + id: c!.id, name: c!.name ?? '', - nsfw: c!.nsfw ?? false, - type: c!.channel_type == 'VoiceChannel' ? 'VOICE' : 'TEXT', - icon: c!.generateIconURL(), + nsfw: false, // todo? + type: c!.type == 'VoiceChannel' ? 'VOICE' : 'TEXT', + icon: c!.iconURL, })), dmOnKick: serverConfig?.dmOnKick, dmOnWarn: serverConfig?.dmOnWarn, diff --git a/bot/src/bot/modules/api/servers.ts b/bot/src/bot/modules/api/servers.ts index e771a89..07fbd9e 100644 --- a/bot/src/bot/modules/api/servers.ts +++ b/bot/src/bot/modules/api/servers.ts @@ -1,4 +1,4 @@ -import { User } from '@janderedev/revolt.js/dist/maps/Users'; +import { User } from 'revolt.js'; import { client } from '../../..'; import { getMutualServers, getPermissionLevel } from '../../util'; import { wsEvents, WSResponse } from '../api_communication'; @@ -27,11 +27,11 @@ wsEvents.on('req:getUserServers', async (data: ReqData, cb: (data: WSResponse) = if (!server) return reject('Server not found'); const perms = await getPermissionLevel(user, server); resolve({ - id: server._id, + id: server.id, perms, name: server.name, - bannerURL: server.generateBannerURL(), - iconURL: server.generateIconURL({}), + bannerURL: server.bannerURL, + iconURL: server.iconURL, }); } catch(e) { console.error(e); diff --git a/bot/src/bot/modules/api/users.ts b/bot/src/bot/modules/api/users.ts index 0a4ced6..ff96228 100644 --- a/bot/src/bot/modules/api/users.ts +++ b/bot/src/bot/modules/api/users.ts @@ -1,4 +1,4 @@ -import { User } from "@janderedev/revolt.js/dist/maps/Users"; +import { User } from "revolt.js"; import { client } from "../../.."; import { getPermissionLevel, parseUser } from "../../util"; import { wsEvents, WSResponse } from "../api_communication"; @@ -30,7 +30,7 @@ wsEvents.on('req:getUser', async (data: { user: string }, cb: (data: WSResponse) if (!user) cb({ success: false, statusCode: 404, error: 'User could not be found' }); else - cb({ success: true, user: { id: user._id, username: user.username, avatarURL: user.generateAvatarURL() } as APIUser }); + cb({ success: true, user: { id: user.id, username: user.username, avatarURL: user.avatarURL } as APIUser }); } catch(e) { console.error(e); cb({ success: false, error: `${e}` }); diff --git a/bot/src/bot/modules/api_communication.ts b/bot/src/bot/modules/api_communication.ts index ee50ab1..4c3588d 100644 --- a/bot/src/bot/modules/api_communication.ts +++ b/bot/src/bot/modules/api_communication.ts @@ -102,18 +102,18 @@ wsEvents.on('req:requestLogin', async (data: any, cb: (data: WSResponse) => void let code: string|null = null; while (!code) { const c = crypto.randomBytes(8).toString('hex'); - const found = await dbs.PENDING_LOGINS.find({ code: c, user: user._id, confirmed: false }); + const found = await dbs.PENDING_LOGINS.find({ code: c, user: user.id, confirmed: false }); if (found.length > 0) continue; code = c.substring(0, 8).toUpperCase(); } - logger.info(`Attempted login for user ${user._id} with code ${code}`); + logger.info(`Attempted login for user ${user.id} with code ${code}`); const nonce = ulid(); const [previousLogins, currentValidLogins] = await Promise.all([ - dbs.PENDING_LOGINS.find({ user: user._id, confirmed: true }), - dbs.PENDING_LOGINS.find({ user: user._id, confirmed: false, expires: { $gt: Date.now() } }), + dbs.PENDING_LOGINS.find({ user: user.id, confirmed: true }), + dbs.PENDING_LOGINS.find({ user: user.id, confirmed: false, expires: { $gt: Date.now() } }), ]); if (currentValidLogins.length >= 5) return cb({ success: false, statusCode: 403, error: 'Too many pending logins. Try again later.' }); @@ -121,7 +121,7 @@ wsEvents.on('req:requestLogin', async (data: any, cb: (data: WSResponse) => void await dbs.PENDING_LOGINS.insert({ code, expires: Date.now() + (1000 * 60 * 15), // Expires in 15 minutes - user: user._id, + user: user.id, nonce: nonce, confirmed: false, requirePhishingConfirmation: previousLogins.length == 0, @@ -129,7 +129,7 @@ wsEvents.on('req:requestLogin', async (data: any, cb: (data: WSResponse) => void invalid: false, } as PendingLogin); - cb({ success: true, uid: user._id, nonce, code }); + cb({ success: true, uid: user.id, nonce, code }); } catch(e) { console.error(e); cb({ success: false, error: `${e}` }); @@ -137,7 +137,7 @@ wsEvents.on('req:requestLogin', async (data: any, cb: (data: WSResponse) => void }); wsEvents.on('req:stats', async (_data: any, cb: (data: { servers: number }) => void) => { - const servers = bot.servers.size; + const servers = bot.servers.size(); cb({ servers }); }); diff --git a/bot/src/bot/modules/bot_status.ts b/bot/src/bot/modules/bot_status.ts index 1f4cf1c..b19454c 100644 --- a/bot/src/bot/modules/bot_status.ts +++ b/bot/src/bot/modules/bot_status.ts @@ -15,10 +15,10 @@ import logger from "../logger"; const update = async () => { try { const statusText = statuses[i] - .replace('{{servers}}', `${client.servers.size}`) - .replace('{{users}}', `${client.users.size}`) + .replace('{{servers}}', `${client.servers.size()}`) + .replace('{{users}}', `${client.users.size()}`) .replace('{{infractions_total}}', `${await dbs.INFRACTIONS.count({})}`) - .replace('{{ping_ms}}', `${client.websocket.ping ?? -1}`); + .replace('{{ping_ms}}', `${client.events.ping() ?? -1}`); await setStatus(statusText, 'Online'); logger.debug(`Bot status updated`); @@ -37,7 +37,7 @@ import logger from "../logger"; async function setStatus(text: string, presence: 'Online'|'Idle'|'Busy'|'Invisible') { await axios.patch( - `${client.apiURL}/users/@me`, + `${client.options.baseURL}/users/@me`, { status: { text, presence } }, diff --git a/bot/src/bot/modules/command_handler.ts b/bot/src/bot/modules/command_handler.ts index f2272f9..ed5045d 100644 --- a/bot/src/bot/modules/command_handler.ts +++ b/bot/src/bot/modules/command_handler.ts @@ -7,7 +7,7 @@ import { antispam, wordFilterCheck } from "./antispam"; import checkCustomRules from "./custom_rules/custom_rules"; import MessageCommandContext from "../../struct/MessageCommandContext"; import { fileURLToPath } from 'url'; -import { getOwnMemberInServer, hasPermForChannel } from "../util"; +import { getOwnMemberInServer } from "../util"; import { isSudo, updateSudoTimeout } from "../commands/admin/botadm"; import { metrics } from "./metrics"; @@ -30,20 +30,20 @@ let commands: SimpleCommand[]; .map(async file => await import(file) as SimpleCommand) )).map(c => (c as any).default) - client.on('message/update', async msg => { + client.on('messageUpdate', async msg => { checkCustomRules(msg, true); }); - client.on('message', async msg => { + client.on('messageCreate', async msg => { logger.debug(`Message -> ${msg.content}`); if (typeof msg.content != 'string' || - msg.author_id == client.user?._id || + msg.authorId == client.user?.id || !msg.channel?.server) return; try { - if (!msg.member) await msg.channel.server.fetchMember(msg.author_id); - if (!msg.author) await client.users.fetch(msg.author_id); + if (!msg.member) await msg.channel.server.fetchMember(msg.authorId!); + if (!msg.author) await client.users.fetch(msg.authorId!); } catch(e) { return msg.reply('⚠ Failed to fetch message author'); } @@ -51,7 +51,8 @@ let commands: SimpleCommand[]; if (msg.author!.bot) return; // If we can't reply to the message, return - if (!hasPermForChannel(await getOwnMemberInServer(msg.channel.server), msg.channel, 'SendMessage')) { + const member = await getOwnMemberInServer(msg.channel.server); + if (!member.hasPermission(msg.channel, 'SendMessage')) { logger.debug('Cannot reply to message; returning'); return; } @@ -61,8 +62,8 @@ let commands: SimpleCommand[]; checkCustomRules(msg); let [ config, userConfig ] = await Promise.all([ - dbs.SERVERS.findOne({ id: msg.channel!.server_id! }), - dbs.USERS.findOne({ id: msg.author_id }), + dbs.SERVERS.findOne({ id: msg.channel!.serverId! }), + dbs.USERS.findOne({ id: msg.authorId }), ]); if (config) { @@ -75,8 +76,8 @@ let commands: SimpleCommand[]; let cmdName = args.shift() ?? ''; let guildPrefix = config?.prefix ?? DEFAULT_PREFIX; - if (cmdName.startsWith(`<@${client.user?._id}>`)) { - cmdName = cmdName.substring(`<@${client.user?._id}>`.length); + if (cmdName.startsWith(`<@${client.user?.id}>`)) { + cmdName = cmdName.substring(`<@${client.user?.id}>`.length); if (!cmdName) cmdName = args.shift() ?? ''; // Space between mention and command name } else if (cmdName.startsWith(guildPrefix)) { cmdName = cmdName.substring(guildPrefix.length); @@ -108,7 +109,7 @@ let commands: SimpleCommand[]; if (isSudo(msg.author!)) updateSudoTimeout(msg.author!); - if (cmd.restrict == 'BOTOWNER' && ownerIDs.indexOf(msg.author_id) == -1) { + if (cmd.restrict == 'BOTOWNER' && ownerIDs.indexOf(msg.authorId!) == -1) { logger.warn(`User ${msg.author?.username} tried to run owner-only command: ${cmdName}`); msg.reply('🔒 Access denied'); return; @@ -130,10 +131,10 @@ let commands: SimpleCommand[]; let message: MessageCommandContext = msg as MessageCommandContext; message.serverContext = serverCtx; - logger.info(`Command: ${message.author?.username} (${message.author?._id}) in ${message.channel?.server?.name} (${message.channel?.server?._id}): ${message.content}`); + logger.info(`Command: ${message.author?.username} (${message.author?.id}) in ${message.channel?.server?.name} (${message.channel?.serverId}): ${message.content}`); // Create document for server in DB, if not already present - if (JSON.stringify(config) == '{}' || !config) await dbs.SERVERS.insert({ id: message.channel!.server_id! }); + if (JSON.stringify(config) == '{}' || !config) await dbs.SERVERS.insert({ id: message.channel!.serverId! }); if (cmd.removeEmptyArgs !== false) { args = args.filter(a => a.length > 0); diff --git a/bot/src/bot/modules/custom_rules/actions/delete.ts b/bot/src/bot/modules/custom_rules/actions/delete.ts index 197de97..105da30 100644 --- a/bot/src/bot/modules/custom_rules/actions/delete.ts +++ b/bot/src/bot/modules/custom_rules/actions/delete.ts @@ -1,4 +1,4 @@ -import { Message } from "@janderedev/revolt.js/dist/maps/Messages"; +import { Message } from "revolt.js"; import CustomRuleAction from "automod/dist/types/antispam/CustomRuleAction"; async function execute(message: Message, action: CustomRuleAction) { diff --git a/bot/src/bot/modules/custom_rules/actions/sendMessage.ts b/bot/src/bot/modules/custom_rules/actions/sendMessage.ts index 3a8a1c6..921f7e1 100644 --- a/bot/src/bot/modules/custom_rules/actions/sendMessage.ts +++ b/bot/src/bot/modules/custom_rules/actions/sendMessage.ts @@ -1,4 +1,4 @@ -import { Message } from "@janderedev/revolt.js/dist/maps/Messages"; +import { Message } from "revolt.js"; import { client } from "../../../.."; import CustomRuleAction from "automod/dist/types/antispam/CustomRuleAction"; @@ -8,7 +8,7 @@ async function execute(message: Message, action: CustomRuleAction) { text = text.slice(0, 1996) + ' ...'; } - if (!message.channel) await client.channels.fetch(message.channel_id); + if (!message.channel) await client.channels.fetch(message.channelId); let msg = await message.channel!.sendMessage(text); if (action.duration) { diff --git a/bot/src/bot/modules/custom_rules/actions/warn.ts b/bot/src/bot/modules/custom_rules/actions/warn.ts index 7c209fc..eb82281 100644 --- a/bot/src/bot/modules/custom_rules/actions/warn.ts +++ b/bot/src/bot/modules/custom_rules/actions/warn.ts @@ -1,4 +1,4 @@ -import { Message } from "@janderedev/revolt.js/dist/maps/Messages"; +import { Message } from "revolt.js"; import CustomRuleAction from "automod/dist/types/antispam/CustomRuleAction"; import { storeInfraction } from '../../../util'; import Infraction from "automod/dist/types/antispam/Infraction"; @@ -7,17 +7,17 @@ import InfractionType from "automod/dist/types/antispam/InfractionType"; async function execute(message: Message, action: CustomRuleAction) { let warnMsg = action.text - ? `${action.text}\n(Triggered on ${message.channel_id} / ${message._id})` - : `Moderation rule triggered on ${message.channel_id} / ${message._id}`; + ? `${action.text}\n(Triggered on ${message.channelId} / ${message.id})` + : `Moderation rule triggered on ${message.channelId} / ${message.id}`; let infraction: Infraction = { _id: ulid(), date: Date.now(), createdBy: null, reason: warnMsg, - server: message.channel?.server_id!, + server: message.channel?.serverId!, type: InfractionType.Automatic, - user: message.author_id + user: message.authorId!, } let { userWarnCount } = await storeInfraction(infraction); diff --git a/bot/src/bot/modules/custom_rules/custom_rules.ts b/bot/src/bot/modules/custom_rules/custom_rules.ts index ba9d149..da6f60d 100644 --- a/bot/src/bot/modules/custom_rules/custom_rules.ts +++ b/bot/src/bot/modules/custom_rules/custom_rules.ts @@ -1,4 +1,4 @@ -import { Message } from "@janderedev/revolt.js/dist/maps/Messages"; +import { Message } from "revolt.js"; import { dbs } from "../../.."; import logger from "../../logger"; import messageContentTrigger from "./message_content_trigger"; @@ -6,11 +6,11 @@ import messageContentTrigger from "./message_content_trigger"; import custom_sendMessage from "./actions/sendMessage"; import custom_delete from "./actions/delete"; import custom_warn from "./actions/warn"; -import { getOwnMemberInServer, hasPermForChannel } from "../../util"; +import { getOwnMemberInServer } from "../../util"; async function checkCustomRules(message: Message, isEdit: boolean = false) { try { - let serverConfig = await dbs.SERVERS.findOne({ id: message.channel!.server_id! }); + let serverConfig = await dbs.SERVERS.findOne({ id: message.channel!.serverId! }); let rules = serverConfig?.automodSettings?.custom; if (!rules) return; @@ -24,27 +24,28 @@ async function checkCustomRules(message: Message, isEdit: boolean = false) { if (await messageContentTrigger(message, rule.trigger)) { for (const action of rule.action) { + const member = await getOwnMemberInServer(message.channel!.server!); switch(action.action) { case 'sendMessage': - if (hasPermForChannel(await getOwnMemberInServer(message.channel!.server!), message.channel!, 'SendMessage')) + if (member.hasPermission(message.channel!, 'SendMessage')) await custom_sendMessage(message, action); else logger.warn(`Custom rule ${rule._id}: 'sendMessage' action lacks permission`); break; case 'delete': - if (hasPermForChannel(await getOwnMemberInServer(message.channel!.server!), message.channel!, 'ManageMessages')) + if (member.hasPermission(message.channel!, 'ManageMessages')) await custom_delete(message, action); else logger.warn(`Custom rule ${rule._id}: 'delete' action lacks permission`); break; case 'warn': - if (hasPermForChannel(await getOwnMemberInServer(message.channel!.server!), message.channel!, 'SendMessage')) + if (member.hasPermission(message.channel!, 'SendMessage')) await custom_warn(message, action); else logger.warn(`Custom rule ${rule._id}: 'warn' action lacks permission`); break; default: - logger.warn(`Unknown action ${action.action} in custom rule ${rule._id} in server ${message.channel?.server_id}`); + logger.warn(`Unknown action ${action.action} in custom rule ${rule._id} in server ${message.channel?.serverId}`); } } } diff --git a/bot/src/bot/modules/custom_rules/message_content_trigger.ts b/bot/src/bot/modules/custom_rules/message_content_trigger.ts index 5849f95..8352355 100644 --- a/bot/src/bot/modules/custom_rules/message_content_trigger.ts +++ b/bot/src/bot/modules/custom_rules/message_content_trigger.ts @@ -1,4 +1,4 @@ -import { Message } from "@janderedev/revolt.js/dist/maps/Messages"; +import { Message } from "revolt.js"; import { client } from "../../.."; import CustomRuleTrigger from "automod/dist/types/antispam/CustomRuleTrigger"; import VM from 'vm'; @@ -12,8 +12,8 @@ async function messageContentTrigger(message: Message, trigger: CustomRuleTrigge let matched = false; if (trigger.matcher) { if (trigger.channelFilter) { - if (trigger.channelFilter.mode == 'WHITELIST' && !trigger.channelFilter.channels.includes(message.channel_id)) return false; - if (trigger.channelFilter.mode == 'BLACKLIST' && trigger.channelFilter.channels.includes(message.channel_id)) return false; + if (trigger.channelFilter.mode == 'WHITELIST' && !trigger.channelFilter.channels.includes(message.channelId)) return false; + if (trigger.channelFilter.mode == 'BLACKLIST' && trigger.channelFilter.channels.includes(message.channelId)) return false; } if (trigger.matcher instanceof RegExp) { @@ -55,8 +55,8 @@ async function messageContentTrigger(message: Message, trigger: CustomRuleTrigge let timeoutKeys = { global: trigger._id, - channel: trigger._id + '/channel/' + message.channel_id, - user: trigger._id + '/user/' + message.author_id, + channel: trigger._id + '/channel/' + message.channelId, + user: trigger._id + '/user/' + message.authorId, } let timeoutPass = true; @@ -87,7 +87,7 @@ async function messageContentTrigger(message: Message, trigger: CustomRuleTrigge /* User/bot filter comes last because we want to avoid fetching users if possible */ if (trigger.userFilter && trigger.userFilter != 'any') { - let user = message.author || await client.users.fetch(message.author_id); + let user = message.author || await client.users.fetch(message.authorId!); if (trigger.userFilter == 'bot' && !user.bot) return false; if (trigger.userFilter == 'user' && user.bot) return false; } diff --git a/bot/src/bot/modules/event_handler.ts b/bot/src/bot/modules/event_handler.ts index bcf83ed..d9536f9 100644 --- a/bot/src/bot/modules/event_handler.ts +++ b/bot/src/bot/modules/event_handler.ts @@ -5,71 +5,61 @@ import Infraction from "automod/dist/types/antispam/Infraction"; import InfractionType from "automod/dist/types/antispam/InfractionType"; import { BLACKLIST_BAN_REASON, BLACKLIST_MESSAGE } from "../commands/admin/botadm"; import logger from "../logger"; -import { hasPermForChannel, storeInfraction } from "../util"; +import { storeInfraction } from "../util"; import { DEFAULT_PREFIX } from "./command_handler"; +import { SendableEmbed } from "revolt-api"; const DM_SESSION_LIFETIME = 1000 * 60 * 60 * 24 * 30; // Listen to system messages -client.on('message', async message => { - if (typeof message.content != 'object') { - // reply to 74 - if (message.author_id == '01FCXF8V6RDKHSQ3AHJ410AASX' && message.content == 'we do a little') { - try { - message.reply('shut the fuck up'); - } catch(e) { console.error(e) } - } +client.on('messageCreate', async message => { - return; - } + let sysMsg = message.systemMessage; - let sysMsg = message.asSystemMessage; - - switch(sysMsg.type) { + if (sysMsg) switch(sysMsg.type) { case 'user_kicked': case 'user_banned': try { let recentEvents = await dbs.INFRACTIONS.findOne({ date: { $gt: Date.now() - 30000 }, - user: sysMsg.user?._id, - server: message.channel!.server_id!, + user: sysMsg.id, + server: message.channel!.serverId!, actionType: sysMsg.type == 'user_kicked' ? 'kick' : 'ban', }); if (!message.channel || - !sysMsg.user || + !sysMsg.id || recentEvents) return; storeInfraction({ _id: ulid(), - createdBy: sysMsg.by?._id, + createdBy: null, reason: 'Unknown reason (caught system message)', - date: message.createdAt, - server: message.channel!.server_id, + date: message.createdAt.getTime(), + server: message.channel!.serverId, type: InfractionType.Manual, - user: sysMsg.user!._id, + user: sysMsg.id, actionType: sysMsg.type == 'user_kicked' ? 'kick' : 'ban', } as Infraction).catch(console.warn); } catch(e) { console.error(e) } break; case 'user_joined': { - if (!sysMsg.user) break; - try { const [ serverConfig, userConfig ] = await Promise.all([ - dbs.SERVERS.findOne({ id: message.channel!.server_id! }), - dbs.USERS.findOne({ id: sysMsg.user._id }), + dbs.SERVERS.findOne({ id: message.channel!.serverId }), + dbs.USERS.findOne({ id: sysMsg.id }), ]); if (userConfig?.globalBlacklist && !serverConfig?.allowBlacklistedUsers) { const server = message.channel?.server; if (server && server.havePermission('BanMembers')) { - await server.banUser(sysMsg.user._id, { reason: BLACKLIST_BAN_REASON }); + await server.banUser(sysMsg.id, { reason: BLACKLIST_BAN_REASON }); - if (server.system_messages?.user_banned) { - const channel = server.channels.find(c => c?._id == server.system_messages?.user_banned); + if (server.systemMessages?.user_banned) { + const channel = server.channels.find(c => c?.id == server.systemMessages?.user_banned); if (channel && channel.havePermission('SendMessage')) { - await channel.sendMessage(BLACKLIST_MESSAGE(sysMsg.user.username)); + const user = client.users.get(sysMsg.id); + await channel.sendMessage(BLACKLIST_MESSAGE(user?.username ?? sysMsg.id)); } } } @@ -85,10 +75,10 @@ client.on('message', async message => { }); // DM message based API session token retrieval -client.on('message', async message => { +client.on('messageCreate', async message => { try { if ( - message.channel?.channel_type == "DirectMessage" && + message.channel?.type == "DirectMessage" && message.nonce?.startsWith("REQUEST_SESSION_TOKEN-") && message.content?.toLowerCase().startsWith("requesting session token.") ) { @@ -97,17 +87,16 @@ client.on('message', async message => { const token = crypto.randomBytes(48).toString('base64').replace(/=/g, ''); await client.db.get('sessions').insert({ - user: message.author_id, + user: message.authorId, token: token, nonce: message.nonce, invalid: false, expires: Date.now() + DM_SESSION_LIFETIME, }) - // Don't need to risk exposing the user to the token, so we'll send it in the nonce await message.channel.sendMessage({ content: `Token request granted. **Do not send the content of this message to anyone!**\n$%${token}%$`, - replies: [ { id: message._id, mention: false } ], + replies: [ { id: message.id, mention: false } ], }); return; } @@ -117,26 +106,24 @@ client.on('message', async message => { }); // Send a message when added to a server -client.on('member/join', (member) => { - if (member._id.user != client.user?._id) return; - - let url = `https://rvembed.janderedev.xyz/embed` - + `?title=${encodeURIComponent('Hi there, thanks for adding me!')}` - + `&description=${encodeURIComponent(`My prefix is "${DEFAULT_PREFIX}", ` - + `but you can also @mention me instead.\nCheck out ${DEFAULT_PREFIX}help to get started!`)}` - + `&link=${encodeURIComponent(`/bot/${client.user._id}`)}` - + `&redir=${encodeURIComponent(`https://github.com/janderedev/revolt-automod`)}` - + `&color=${encodeURIComponent("#ff6e6d")}` - + `&image=${encodeURIComponent(client.user.generateAvatarURL({ size: 128 }))}` - + `&image_large=false`; +client.on('serverMemberJoin', (member) => { + if (member.id.user != client.user?.id) return; if (!member.server) return; + const embed: SendableEmbed = { + title: 'Hi there, thanks for adding me!', + description: `My prefix is "${DEFAULT_PREFIX}", but you can also @mention me instead.\nCheck out ${DEFAULT_PREFIX}help to get started!`, + icon_url: client.user.avatarURL, + colour: '#ff6e6d', + url: `/bot/${client.user.id}`, + } + let channels = member.server.channels.filter( c => c - && c.channel_type == 'TextChannel' - && hasPermForChannel(member, c, 'SendMessage') - && hasPermForChannel(member, c, 'SendEmbeds') + && c.type == 'TextChannel' + && member.hasPermission(c, 'SendMessage') + && member.hasPermission(c, 'SendEmbeds') ); // Attempt to find an appropriate channel, otherwise use the first one available @@ -147,6 +134,8 @@ client.on('member/join', (member) => { || channels[0]; if (!channel) return logger.debug('Cannot send hello message: No suitable channel found'); - channel.sendMessage(`[:wave:](${url} "Hi there!")`) - .catch(e => logger.debug('Cannot send hello message: ' + e)); + channel.sendMessage({ + content: `:wave: "Hi there!")`, + embeds: [embed], + }).catch(e => logger.debug('Cannot send hello message: ' + e)); }); diff --git a/bot/src/bot/modules/fetch_all.ts b/bot/src/bot/modules/fetch_all.ts index 56531f1..f5d9177 100644 --- a/bot/src/bot/modules/fetch_all.ts +++ b/bot/src/bot/modules/fetch_all.ts @@ -6,14 +6,14 @@ import logger from "../logger"; (async () => { if (!client.user) await new Promise(r => client.once('ready', () => r())); - logger.info(`Starting to fetch users in ${client.servers.size} servers.`); + logger.info(`Starting to fetch users in ${client.servers.size()} servers.`); const promises: Promise[] = []; - for (const server of client.servers) { + for (const server of client.servers.entries()) { promises.push(server[1].fetchMembers()); } const res = await Promise.allSettled(promises); logger.done(`Downloaded all users from ${res.filter(r => r.status == 'fulfilled').length} servers ` - + `with ${res.filter(r => r.status == 'rejected').length} errors. Cache size: ${client.users.size}`); + + `with ${res.filter(r => r.status == 'rejected').length} errors. Cache size: ${client.users.size()}`); })(); diff --git a/bot/src/bot/modules/metrics.ts b/bot/src/bot/modules/metrics.ts index e73ffa6..aa4d7b1 100644 --- a/bot/src/bot/modules/metrics.ts +++ b/bot/src/bot/modules/metrics.ts @@ -30,14 +30,14 @@ if (!isNaN(PORT)) { } }); - const setServerCount = () => metrics.servers.set(client.servers.size); + const setServerCount = () => metrics.servers.set(client.servers.size()); client.once('ready', setServerCount); - client.on('server/update', setServerCount); - client.on('server/delete', setServerCount); + client.on('serverUpdate', setServerCount); + client.on('serverDelete', setServerCount); const measureLatency = async () => { - const wsPing = client.websocket.ping; + const wsPing = -1; // currently not exported by revolt.js, todo? if (wsPing != undefined) metrics.wsPing.set(wsPing); } diff --git a/bot/src/bot/modules/mod_logs.ts b/bot/src/bot/modules/mod_logs.ts index 3794db5..fbc5fd5 100644 --- a/bot/src/bot/modules/mod_logs.ts +++ b/bot/src/bot/modules/mod_logs.ts @@ -1,146 +1,161 @@ -import { Member } from "@janderedev/revolt.js/dist/maps/Members"; -import { Server } from "@janderedev/revolt.js/dist/maps/Servers"; +import { Server, ServerMember } from "revolt.js"; import { client, dbs } from "../.."; import LogMessage from "automod/dist/types/LogMessage"; +import Xlsx from 'xlsx'; import logger from "../logger"; -import { getAutumnURL, sanitizeMessageContent, sendLogMessage } from "../util"; +import { sanitizeMessageContent, sendLogMessage } from "../util"; // the `packet` event is emitted before the client's cache // is updated, which allows us to get the old message content // if it was cached before -client.on('packet', async (packet) => { - if (packet.type == 'MessageUpdate') { - try { - if (!packet.data.content) return; +client.on('messageUpdate', async (message, oldMessage) => { + try { + if (!message.content) return; - let m = client.messages.get(packet.id); + if (message.authorId == client.user?.id) return; - if (m?.author_id == client.user?._id) return; + let oldMsgRaw = String(oldMessage.content ?? '(Unknown)'); + let newMsgRaw = String(message.content); + let oldMsg = sanitizeMessageContent(oldMsgRaw) || '(Empty)'; + let newMsg = sanitizeMessageContent(newMsgRaw) || '(Empty)'; - let oldMsgRaw = String(m?.content ?? '(Unknown)'); - let newMsgRaw = String(packet.data.content); - let oldMsg = sanitizeMessageContent(oldMsgRaw) || '(Empty)'; - let newMsg = sanitizeMessageContent(newMsgRaw) || '(Empty)'; + let channel = message.channel; + let server = channel?.server; + if (!server || !channel) return logger.warn('Received message update in unknown channel or server'); - let channel = client.channels.get(packet.channel); - let server = channel?.server; - if (!server || !channel) return logger.warn('Received message update in unknown channel or server'); - - let config = await dbs.SERVERS.findOne({ id: server._id }); - if (config?.logs?.messageUpdate) { - const attachFullMessage = oldMsg.length > 800 || newMsg.length > 800; - let embed: LogMessage = { - title: `Message edited in ${server.name}`, - description: - `[#${channel.name}](/server/${server._id}/channel/${channel._id}) | ` + - `[@${sanitizeMessageContent( - m?.author?.username ?? "Unknown User" - )}](/@${m?.author_id}) | ` + - `[Jump to message](/server/${server._id}/channel/${channel._id}/${packet.id})`, - fields: [], - color: "#829dff", - overrides: { - discord: { - description: `Author: @${ - m?.author?.username || m?.author_id || "Unknown" - } | Channel: ${channel?.name || channel?._id}`, - }, + let config = await dbs.SERVERS.findOne({ id: server.id }); + if (config?.logs?.messageUpdate) { + const attachFullMessage = oldMsg.length > 800 || newMsg.length > 800; + let embed: LogMessage = { + title: `Message edited in ${server.name}`, + description: + `[#${channel.name}](/server/${server.id}/channel/${channel.id}) | ` + + `@${sanitizeMessageContent( + message.author?.username ?? "Unknown User" + )} (${message.authorId}) | ` + + `[Jump to message](/server/${server.id}/channel/${channel.id}/${message.id})`, + fields: [], + color: "#829dff", + overrides: { + discord: { + description: `Author: @${ + message.author?.username || message.authorId || "Unknown" + } | Channel: ${channel.name || channel.id}`, }, - }; + }, + }; - if (attachFullMessage) { - embed.attachments = [ - { name: 'old_message.txt', content: Buffer.from(oldMsgRaw) }, - { name: 'new_message.txt', content: Buffer.from(newMsgRaw) }, - ]; - } else { - embed.fields!.push({ title: 'Old content', content: oldMsg }); - embed.fields!.push({ title: 'New content', content: newMsg }); - } - - await sendLogMessage(config.logs.messageUpdate, embed); + if (attachFullMessage) { + embed.attachments = [ + { name: 'old_message.txt', content: Buffer.from(oldMsgRaw) }, + { name: 'new_message.txt', content: Buffer.from(newMsgRaw) }, + ]; + } else { + embed.fields!.push({ title: 'Old content', content: oldMsg }); + embed.fields!.push({ title: 'New content', content: newMsg }); } - } catch(e) { - console.error(e); + + await sendLogMessage(config.logs.messageUpdate, embed); } + } catch(e) { + console.error(e); } - - if (packet.type == 'MessageDelete') { - try { - let channel = client.channels.get(packet.channel); - if (!channel) return; - let message = client.messages.get(packet.id); - if (!message) return; - - let msgRaw = String(message.content ?? '(Unknown)'); - let msg = sanitizeMessageContent(msgRaw); - - let config = await dbs.SERVERS.findOne({ id: message.channel?.server?._id }); - if (config?.logs?.messageUpdate) { - let embed: LogMessage = { - title: `Message deleted in ${message.channel?.server?.name}`, - description: `[\\[#${channel.name}\\]](/server/${channel.server_id}/channel/${channel._id}) | ` - + `[\\[Author\\]](/@${message.author_id}) | ` - + `[\\[Jump to context\\]](/server/${channel.server_id}/channel/${channel._id}/${packet.id})`, - fields: [], - color: '#ff6b6b', - overrides: { - discord: { - description: `Author: @${message.author?.username || message.author_id} | Channel: ${message.channel?.name || message.channel_id}` - }, - } - } - - if (msg.length > 1000) { - embed.attachments?.push({ name: 'message.txt', content: Buffer.from(msgRaw) }); - } else { - embed.fields!.push({ title: 'Content', content: msg || "(Empty)" }); - } - - if (message.attachments?.length) { - let autumnURL = await getAutumnURL(); - embed.fields!.push({ title: 'Attachments', content: message.attachments.map(a => - `[\\[${a.filename}\\]](<${autumnURL}/${a.tag}/${a._id}/${a.filename}>)`).join(' | ') }) - } - - await sendLogMessage(config.logs.messageUpdate, embed); - } - } catch(e) { - console.error(e); - } - } - - if (packet.type == 'BulkMessageDelete') { - const channel = client.channels.get(packet.channel); +}); +client.on('messageDelete', async (message) => { + try { + let channel = client.channels.get(message.channelId); + let author = message.authorId ? client.users.get(message.authorId) : null; if (!channel) return; - try { - let config = await dbs.SERVERS.findOne({ id: channel.server?._id }); - if (config?.logs?.messageUpdate) { - let embed: LogMessage = { - title: `Bulk delete in ${channel.server?.name}`, - description: `${packet.ids.length} messages deleted in ` + - `[#${channel.name}](/server/${channel.server_id}/channel/${channel._id})`, - fields: [], - color: '#ff392b', - overrides: { - discord: { - description: `${packet.ids.length} messages deleted in #${channel.name}`, - } - } - } + let msgRaw = String(message.content ?? '(Unknown)'); + let msg = sanitizeMessageContent(msgRaw); - await sendLogMessage(config.logs.messageUpdate, embed); + let config = await dbs.SERVERS.findOne({ id: channel?.server?.id }); + if (config?.logs?.messageUpdate) { + let embed: LogMessage = { + title: `Message deleted in ${channel?.server?.name}`, + description: `[#${channel.name}](/server/${channel.serverId}/channel/${channel.id}) | ` + + `@${sanitizeMessageContent( + author?.username ?? "Unknown User" + )} (${message.authorId}) | ` + + `[\\[Jump to context\\]](/server/${channel.serverId}/channel/${channel.id}/${message.id})`, + fields: [], + color: '#ff6b6b', + overrides: { + discord: { + description: `Author: @${author?.username || message.authorId} | Channel: ${channel?.name || message.channelId}` + }, + } } - } catch(e) { - console.error(e); + + if (msg.length > 1000) { + embed.attachments?.push({ name: 'message.txt', content: Buffer.from(msgRaw) }); + } else { + embed.fields!.push({ title: 'Content', content: msg || "(Empty)" }); + } + + if (message.attachments?.length) { + let autumnURL = client.configuration?.features.autumn.url; + embed.fields!.push({ title: 'Attachments', content: message.attachments.map(a => + `[\\[${a.filename}\\]](<${autumnURL}/${a.tag}/${a.id}/${a.filename}>)`).join(' | ') }) + } + + await sendLogMessage(config.logs.messageUpdate, embed); } + } catch(e) { + console.error(e); } }); -async function logModAction(type: 'warn'|'kick'|'ban'|'votekick', server: Server, mod: Member, target: string, reason: string|null, infractionID: string, extraText?: string): Promise { +client.on('messageDeleteBulk', async (messages) => { + const channel = client.channels.get(messages[0].channelId); + if (!channel) return; + try { - let config = await dbs.SERVERS.findOne({ id: server._id }); + let config = await dbs.SERVERS.findOne({ id: channel.serverId }); + if (config?.logs?.messageUpdate) { + const data: String[][] = [ + ['Message ID', 'Author ID', 'Author Name', 'Content', 'Attachment URLs'], + [], + ]; + + for (const message of messages) { + data.push([ + message.id, + message.authorId ?? '', + message.authorId ? client.users.get(message.authorId)?.username ?? '' : '', + message.content ?? '', + message.attachments?.map(a => a.id).join(', ') ?? '', + ]); + } + + const sheet = Xlsx.utils.aoa_to_sheet(data); + const csv = Xlsx.utils.sheet_to_csv(data); + + let embed: LogMessage = { + title: `Bulk delete in ${channel.server?.name}`, + description: `${messages.length} messages deleted in ` + + `[#${channel.name}](/server/${channel.serverId}/channel/${channel.id})`, + fields: [], + attachments: [{ name: 'messages.csv', content: Buffer.from(csv) }], + color: '#ff392b', + overrides: { + discord: { + description: `${messages.length} messages deleted in #${channel.name}`, + } + } + } + + await sendLogMessage(config.logs.messageUpdate, embed); + } + } catch(e) { + console.error(e); + } +}); + +async function logModAction(type: 'warn'|'kick'|'ban'|'votekick', server: Server, mod: ServerMember, target: string, reason: string|null, infractionID: string, extraText?: string): Promise { + try { + let config = await dbs.SERVERS.findOne({ id: server.id }); if (config?.logs?.modAction) { let aType = type == 'ban' ? 'banned' : type + 'ed'; diff --git a/bot/src/bot/modules/tempbans.ts b/bot/src/bot/modules/tempbans.ts index db8a101..dfd385b 100644 --- a/bot/src/bot/modules/tempbans.ts +++ b/bot/src/bot/modules/tempbans.ts @@ -29,11 +29,11 @@ async function processUnban(ban: TempBan) { if (expired.includes(ban.id)) return; let server = client.servers.get(ban.server) || await client.servers.fetch(ban.server); - if (!server.havePermission('BanMembers')) return logger.debug(`No permission to process unbans in ${server._id}, skipping`); + if (!server.havePermission('BanMembers')) return logger.debug(`No permission to process unbans in ${server.id}, skipping`); let serverBans = await server.fetchBans(); - if (serverBans.bans.find(b => b._id.user == ban.bannedUser)) { - logger.debug(`Unbanning user ${ban.bannedUser} from ${server._id}`); + if (serverBans.find(b => b.id.user == ban.bannedUser)) { + logger.debug(`Unbanning user ${ban.bannedUser} from ${server.id}`); let promises = [ server.unbanUser(ban.bannedUser), diff --git a/bot/src/bot/util.ts b/bot/src/bot/util.ts index 6cfbd76..0186eaa 100644 --- a/bot/src/bot/util.ts +++ b/bot/src/bot/util.ts @@ -1,23 +1,20 @@ -import { Member } from "@janderedev/revolt.js/dist/maps/Members"; -import { User } from "@janderedev/revolt.js/dist/maps/Users"; +import { ServerMember } from "revolt.js"; +import { User } from "revolt.js"; import { client, dbs } from ".."; import Infraction from "automod/dist/types/antispam/Infraction"; import FormData from 'form-data'; import axios from 'axios'; -import { Server } from "@janderedev/revolt.js/dist/maps/Servers"; +import { Server } from "revolt.js"; import LogConfig from "automod/dist/types/LogConfig"; import LogMessage from "automod/dist/types/LogMessage"; import { ColorResolvable, MessageEmbed } from "discord.js"; import logger from "./logger"; import { ulid } from "ulid"; -import { Channel } from "@janderedev/revolt.js/dist/maps/Channels"; -import { Permission } from "@janderedev/revolt.js/dist/permissions/definitions"; -import { Message } from "@janderedev/revolt.js/dist/maps/Messages"; +import { Channel } from "revolt.js"; +import { Message } from "revolt.js"; import { isSudo } from "./commands/admin/botadm"; import { SendableEmbed } from "revolt-api"; -import MessageCommandContext from "../struct/MessageCommandContext"; import ServerConfig from "automod/dist/types/ServerConfig"; -import { ClientboundNotification } from "@janderedev/revolt.js"; const NO_MANAGER_MSG = "🔒 Missing permission"; const ULID_REGEX = /^[0-9A-HJ-KM-NP-TV-Z]{26}$/i; @@ -26,18 +23,6 @@ const CHANNEL_MENTION_REGEX = /^<#[0-9A-HJ-KM-NP-TV-Z]{26}>$/i; const RE_HTTP_URI = /^http(s?):\/\//g; const RE_MAILTO_URI = /^mailto:/g; -let autumn_url: string | null = null; -let apiConfig: any = axios.get(client.apiURL).then((res) => { - autumn_url = (res.data as any).features.autumn.url; -}); - -async function getAutumnURL() { - return ( - autumn_url || - ((await axios.get(client.apiURL)).data as any).features.autumn.url - ); -} - /** * Parses user input and returns an user object. * Supports: `userID`, `<@userID>` (mention), `username`, `@username` (if user is cached). @@ -80,10 +65,10 @@ async function parseUser(text: string): Promise { */ async function parseUserOrId( text: string -): Promise { +): Promise { let parsed = await parseUser(text); if (parsed) return parsed; - if (ULID_REGEX.test(text)) return { _id: text.toUpperCase() }; + if (ULID_REGEX.test(text)) return { id: text.toUpperCase() }; return null; } @@ -91,17 +76,17 @@ async function isModerator(message: Message, announceSudo?: boolean) { let member = message.member!, server = message.channel!.server!; - if (hasPerm(member, "KickMembers")) return true; + if (member.hasPermission(member.server!, "KickMembers")) return true; const [isManager, mods, isSudo] = await Promise.all([ isBotManager(message), - dbs.SERVERS.findOne({ id: server._id }), + dbs.SERVERS.findOne({ id: server.id }), checkSudoPermission(message, announceSudo), ]); return ( isManager || - (mods?.moderators?.indexOf(member.user?._id!) ?? -1) > -1 || + (mods?.moderators?.indexOf(member.user?.id!) ?? -1) > -1 || isSudo ); } @@ -109,15 +94,15 @@ async function isBotManager(message: Message, announceSudo?: boolean) { let member = message.member!, server = message.channel!.server!; - if (hasPerm(member, "ManageServer")) return true; + if (member.hasPermission(member.server!, "ManageServer")) return true; const [managers, isSudo] = await Promise.all([ - dbs.SERVERS.findOne({ id: server._id }), + dbs.SERVERS.findOne({ id: server.id }), checkSudoPermission(message, announceSudo), ]); return ( - (managers?.botManagers?.indexOf(member.user?._id!) ?? -1) > -1 || isSudo + (managers?.botManagers?.indexOf(member.user?.id!) ?? -1) > -1 || isSudo ); } async function checkSudoPermission( @@ -137,68 +122,38 @@ async function checkSudoPermission( } } async function getPermissionLevel( - user: User | Member, + member: ServerMember | User, server: Server ): Promise<0 | 1 | 2 | 3> { + + if (member instanceof User) { + member = client.serverMembers.getByKey({ server: server.id, user: member.id }) || await server.fetchMember(member.id); + } + + if (isSudo(member.user!)) return 3; + + if (member.hasPermission(member.server!, "ManageServer")) return 3; + + const config = await dbs.SERVERS.findOne({ id: server.id }); + + if (config?.botManagers?.includes(member.id.user)) return 2; if ( - isSudo( - user instanceof User - ? user - : user.user || (await client.users.fetch(user._id.user)) - ) - ) - return 3; - - const member = user instanceof User ? await server.fetchMember(user) : user; - if (user instanceof Member) user = user.user!; - - if (hasPerm(member, "ManageServer")) return 3; - - const config = await dbs.SERVERS.findOne({ id: server._id }); - - if (config?.botManagers?.includes(user._id)) return 2; - if ( - config?.moderators?.includes(user._id) || - hasPerm(member, "KickMembers") + config?.moderators?.includes(member.id.user) || + member.hasPermission(member.server!, "KickMembers") ) return 1; return 0; } -function getPermissionBasedOnRole(member: Member): 0 | 1 | 2 | 3 { - if (hasPerm(member, "ManageServer")) return 3; - if (hasPerm(member, "KickMembers")) return 1; +function getPermissionBasedOnRole(member: ServerMember): 0 | 1 | 2 | 3 { + if (member.hasPermission(member.server!, "ManageServer")) return 3; + if (member.hasPermission(member.server!, "KickMembers")) return 1; return 0; } -/** - * @deprecated Unnecessary - */ -function hasPerm(member: Member, perm: keyof typeof Permission): boolean { - let p = Permission[perm]; - if (member.server?.owner == member.user?._id) return true; - - return member.hasPermission(member.server!, perm); -} - -/** - * @deprecated Unnecessary - */ -function hasPermForChannel( - member: Member, - channel: Channel, - perm: keyof typeof Permission -): boolean { - if (!member.server) throw "hasPermForChannel(): Server is undefined"; - return member.hasPermission(channel, perm); -} - -async function getOwnMemberInServer(server: Server): Promise { - return ( - client.members.getKey({ server: server._id, user: client.user!._id }) || - (await server.fetchMember(client.user!._id)) - ); +async function getOwnMemberInServer(server: Server): Promise { + return server.member || await server.fetchMember(client.user!.id); } async function storeInfraction( @@ -220,7 +175,7 @@ async function uploadFile(file: any, filename: string): Promise { let data = new FormData(); data.append("file", file, { filename: filename }); - let req = await axios.post((await getAutumnURL()) + "/attachments", data, { + let req = await axios.post(client.configuration?.features.autumn.url + "/attachments", data, { headers: data.getHeaders(), }); return (req.data as any)["id"] as string; @@ -432,8 +387,8 @@ function dedupeArray(...arrays: T[][]): T[] { function getMutualServers(user: User) { const servers: Server[] = []; - for (const member of client.members) { - if (member[1]._id.user == user._id && member[1].server) + for (const member of client.serverMembers.entries()) { + if (member[1].id.user == user.id && member[1].server) servers.push(member[1].server); } return servers; @@ -445,19 +400,21 @@ const awaitClient = () => else resolve(); }); -const getDmChannel = async (user: string | { _id: string } | User) => { - if (typeof user == "string") +const getDmChannel = async (user: string | { id: string } | User) => { + if (typeof user == "string") { user = client.users.get(user) || (await client.users.fetch(user)); - if (!(user instanceof User)) - user = - client.users.get(user._id) || (await client.users.fetch(user._id)); + } + + if (!(user instanceof User)) { + user = client.users.get(user.id) || (await client.users.fetch(user.id)); + } return ( - Array.from(client.channels).find( - (c) => - c[1].channel_type == "DirectMessage" && - c[1].recipient?._id == (user as User)._id - )?.[1] || (await (user as User).openDM()) + Array.from(client.channels.values()).find( + (c: Channel) => + c.type == "DirectMessage" && + c.recipient?.id == (user as User).id + ) || (await (user as User).openDM()) ); }; @@ -469,7 +426,7 @@ const generateInfractionDMEmbed = ( ) => { const embed: SendableEmbed = { title: server.name, - icon_url: server.generateIconURL({ max_side: 128 }), + icon_url: server.icon?.createFileURL({ max_side: 128 }), colour: "#ff9e2f", url: message.url, description: @@ -485,7 +442,7 @@ const generateInfractionDMEmbed = ( `**Reason:** ${infraction.reason}\n` + `**Moderator:** [@${sanitizeMessageContent( message.author?.username || "Unknown" - )}](/@${message.author_id})\n` + + )}](/@${message.authorId})\n` + `**Infraction ID:** \`${infraction._id}\`` + (infraction.actionType == "ban" && infraction.expires ? infraction.expires == Infinity @@ -545,14 +502,13 @@ const yesNoMessage = ( }); let destroyed = false; - const cb = async (packet: ClientboundNotification) => { - if (packet.type != "MessageReact") return; - if (packet.id != msg._id) return; - if (packet.user_id != allowedUser) return; + const cb = async (m: Message, userId: string, emoji: string) => { + if (m.id != msg.id) return; + if (userId != allowedUser) return; - switch (packet.emoji_id) { + switch (emoji) { case EMOJI_YES: - channel.client.removeListener("packet", cb); + client.removeListener("messageReactionAdd", cb); destroyed = true; resolve(true); msg.edit({ @@ -569,7 +525,7 @@ const yesNoMessage = ( break; case EMOJI_NO: - channel.client.removeListener("packet", cb); + client.removeListener("messageReactionAdd", cb); destroyed = true; resolve(false); msg.edit({ @@ -587,16 +543,16 @@ const yesNoMessage = ( default: logger.warn( - "Received unexpected reaction: " + packet.emoji_id + "Received unexpected reaction: " + emoji ); } }; - channel.client.on("packet", cb); + client.on("messageReactionAdd", cb); setTimeout(() => { if (!destroyed) { resolve(false); - channel.client.removeListener("packet", cb); + client.removeListener("messageReactionAdd", cb); msg.edit({ embeds: [ { @@ -615,14 +571,19 @@ const yesNoMessage = ( // Get all cached members of a server. Whoever put STRINGIFIED JSON as map keys is now on my hit list. const getMembers = (id: string) => - Array.from(client.members.entries()) + Array.from(client.serverMembers.entries()) .filter((item) => item[0].includes(`"${id}"`)) .map((entry) => entry[1]); +const memberRanking = (member: ServerMember) => { + const inferior = (member.server?.member?.ranking ?? Infinity) < member.ranking; + const kickable = member.server?.havePermission('KickMembers') && inferior; + const bannable = member.server?.havePermission('BanMembers') && inferior; + + return { inferior, kickable, bannable } +} + export { - getAutumnURL, - hasPerm, - hasPermForChannel, getOwnMemberInServer, isModerator, isBotManager, @@ -642,6 +603,7 @@ export { generateInfractionDMEmbed, yesNoMessage, getMembers, + memberRanking, EmbedColor, NO_MANAGER_MSG, ULID_REGEX, diff --git a/bot/src/index.ts b/bot/src/index.ts index 50fd931..17ae000 100644 --- a/bot/src/index.ts +++ b/bot/src/index.ts @@ -18,12 +18,6 @@ logger.info('Initializing client'); let db = MongoDB(); let client = new AutomodClient({ -// pongTimeout: 10, -// onPongTimeout: 'RECONNECT', - fixReplyCrash: true, - messageTimeoutFix: true, - apiURL: process.env.API_URL, - messageRateLimiter: true, autoReconnect: true, }, db); login(client); diff --git a/bot/src/struct/AutomodClient.ts b/bot/src/struct/AutomodClient.ts index 2e99604..c26e4f9 100644 --- a/bot/src/struct/AutomodClient.ts +++ b/bot/src/struct/AutomodClient.ts @@ -1,12 +1,13 @@ -import * as Revolt from "@janderedev/revolt.js"; +import * as Revolt from "revolt.js"; import { IMonkManager } from 'monk'; import logger from '../bot/logger'; import { adminBotLog } from "../bot/logging"; +import { ClientOptions } from "revolt.js/src/Client"; class AutomodClient extends Revolt.Client { db: IMonkManager; - constructor(options: Partial | undefined, monk: IMonkManager) { + constructor(options: Partial | undefined, monk: IMonkManager) { super(options); this.db = monk; @@ -29,13 +30,6 @@ let login = (client: Revolt.Client): Promise => new Promise((resolve, reje adminBotLog({ message: 'Bot logged in', type: 'INFO' }); resolve(); }); - - client.on('packet', packet => { - if (packet.type == 'InvalidSession' as any) { - logger.error('Authentication failed: ' + JSON.stringify(packet)); - process.exit(99); - } - }); }); export default AutomodClient; diff --git a/bot/src/struct/MessageCommandContext.ts b/bot/src/struct/MessageCommandContext.ts index 38baf75..7a548b2 100644 --- a/bot/src/struct/MessageCommandContext.ts +++ b/bot/src/struct/MessageCommandContext.ts @@ -1,14 +1,9 @@ -import { Message } from "@janderedev/revolt.js/dist/maps/Messages"; -import { Server } from "@janderedev/revolt.js/dist/maps/Servers"; -import logger from "../bot/logger"; +import { Message } from "revolt.js"; +import { Server } from "revolt.js"; class MessageCommandContext extends Message { // The server to which the command should be applied. serverContext: Server; - - /* Override types */ - - declare content: string; } export default MessageCommandContext; diff --git a/bot/yarn.lock b/bot/yarn.lock index ceb719f..8e6b38c 100644 --- a/bot/yarn.lock +++ b/bot/yarn.lock @@ -25,22 +25,6 @@ __metadata: languageName: node linkType: hard -"@insertish/exponential-backoff@npm:3.1.0-patch.2": - version: 3.1.0-patch.2 - resolution: "@insertish/exponential-backoff@npm:3.1.0-patch.2" - checksum: 510a531965965c8cc633a91653ca09ffa8408925eb403d07c072bed065ec8ce429b4fd42fb0639a3dbee73d300d4422c306ebaaab3292b06778a224a2b5b0bf1 - languageName: node - linkType: hard - -"@insertish/isomorphic-ws@npm:^4.0.1": - version: 4.0.1 - resolution: "@insertish/isomorphic-ws@npm:4.0.1" - peerDependencies: - ws: "*" - checksum: 64e6464b379784d0c8df31868eb8301b3e3827f91131755c38f66a007fcd791314c6ef49f3ead37bb5d62cc7fd52f2171b2e0ce04564a744905f72d3cd86f1ba - languageName: node - linkType: hard - "@insertish/oapi@npm:0.1.18": version: 0.1.18 resolution: "@insertish/oapi@npm:0.1.18" @@ -59,26 +43,6 @@ __metadata: languageName: node linkType: hard -"@janderedev/revolt.js@npm:latest": - version: 6.0.20-patch.9 - resolution: "@janderedev/revolt.js@npm:6.0.20-patch.9" - dependencies: - "@insertish/exponential-backoff": 3.1.0-patch.2 - "@insertish/isomorphic-ws": ^4.0.1 - axios: ^0.21.4 - eventemitter3: ^4.0.7 - lodash.defaultsdeep: ^4.6.1 - lodash.flatten: ^4.4.0 - lodash.isequal: ^4.5.0 - long: ^5.2.0 - mobx: ^6.3.2 - revolt-api: 0.5.16 - ulid: ^2.3.0 - ws: ^8.2.2 - checksum: 942f8cb7339f6378738d97ff788680dc63c287624e749b95b867a82c877bc6416a4a7b85264bf8797e034132d5a84843d75b820b6a1c37a760a88f13114772a0 - languageName: node - linkType: hard - "@sapphire/async-queue@npm:^1.5.0": version: 1.5.0 resolution: "@sapphire/async-queue@npm:1.5.0" @@ -96,6 +60,48 @@ __metadata: languageName: node linkType: hard +"@solid-primitives/map@npm:^0.4.3": + version: 0.4.3 + resolution: "@solid-primitives/map@npm:0.4.3" + dependencies: + "@solid-primitives/trigger": ^1.0.3 + peerDependencies: + solid-js: ^1.6.12 + checksum: e2408d7309c2bc0b93126771ad796cc3cbc2b150a03b4f3d4963dbc6df2ad26e671277fc14aafe1c117f1228c35557686e709accd6237ac511d2e05a6682006d + languageName: node + linkType: hard + +"@solid-primitives/set@npm:^0.4.3": + version: 0.4.3 + resolution: "@solid-primitives/set@npm:0.4.3" + dependencies: + "@solid-primitives/trigger": ^1.0.3 + peerDependencies: + solid-js: ^1.6.12 + checksum: fcab5679185633b887d6d9ef4c12ded12d1773969a66079ce98dc18bbb2869f9fe743a1f3cd1f5721b52dcd274ae096470daa8ab1284643b4b26eeb28b7a5698 + languageName: node + linkType: hard + +"@solid-primitives/trigger@npm:^1.0.3": + version: 1.0.5 + resolution: "@solid-primitives/trigger@npm:1.0.5" + dependencies: + "@solid-primitives/utils": ^6.0.0 + peerDependencies: + solid-js: ^1.6.12 + checksum: 5f137ec425b317c09de6b994928992201206c16be7a01f7add46e0ee987d76a947a7f4f9396a945eeb671c43307b6f5d55bd57d90738880cebdaa0907aca65dd + languageName: node + linkType: hard + +"@solid-primitives/utils@npm:^6.0.0": + version: 6.0.0 + resolution: "@solid-primitives/utils@npm:6.0.0" + peerDependencies: + solid-js: ^1.6.12 + checksum: c581b995e2d16c9ed0546baef52a9e60f54dda457a3733bac467a19f2a63227179eb0ec6faa16397af4cacc13fa281288cf967a206b0a75255412fafadc55411 + languageName: node + linkType: hard + "@types/bson@npm:*": version: 4.0.5 resolution: "@types/bson@npm:4.0.5" @@ -196,15 +202,6 @@ __metadata: languageName: node linkType: soft -"axios@npm:^0.21.4": - version: 0.21.4 - resolution: "axios@npm:0.21.4" - dependencies: - follow-redirects: ^1.14.0 - checksum: 44245f24ac971e7458f3120c92f9d66d1fc695e8b97019139de5b0cc65d9b8104647db01e5f46917728edfc0cfd88eb30fc4c55e6053eef4ace76768ce95ff3c - languageName: node - linkType: hard - "axios@npm:^0.22.0": version: 0.22.0 resolution: "axios@npm:0.22.0" @@ -298,6 +295,13 @@ __metadata: languageName: node linkType: hard +"csstype@npm:^3.1.0": + version: 3.1.2 + resolution: "csstype@npm:3.1.2" + checksum: e1a52e6c25c1314d6beef5168da704ab29c5186b877c07d822bd0806717d9a265e8493a2e35ca7e68d0f5d472d43fac1cdce70fd79fd0853dff81f3028d857b5 + languageName: node + linkType: hard + "dayjs@npm:^1.10.7": version: 1.11.7 resolution: "dayjs@npm:1.11.7" @@ -369,10 +373,10 @@ __metadata: languageName: node linkType: hard -"eventemitter3@npm:^4.0.7": - version: 4.0.7 - resolution: "eventemitter3@npm:4.0.7" - checksum: 1875311c42fcfe9c707b2712c32664a245629b42bb0a5a84439762dd0fd637fc54d078155ea83c2af9e0323c9ac13687e03cfba79b03af9f40c89b4960099374 +"eventemitter3@npm:^5.0.0": + version: 5.0.0 + resolution: "eventemitter3@npm:5.0.0" + checksum: b974bafbab860e0a5bbb21add4c4e82f9d5691c583c03f2e4c5d44a2d6c4556d79223621bdcfc6c8e14366a4af9df6b5ea9d6caf65fbffc80b66f3e1dceacbc9 languageName: node linkType: hard @@ -390,7 +394,7 @@ __metadata: languageName: node linkType: hard -"follow-redirects@npm:^1.14.0, follow-redirects@npm:^1.14.4, follow-redirects@npm:^1.14.8": +"follow-redirects@npm:^1.14.4, follow-redirects@npm:^1.14.8": version: 1.15.2 resolution: "follow-redirects@npm:1.15.2" peerDependenciesMeta: @@ -457,6 +461,15 @@ __metadata: languageName: node linkType: hard +"isomorphic-ws@npm:^5.0.0": + version: 5.0.0 + resolution: "isomorphic-ws@npm:5.0.0" + peerDependencies: + ws: "*" + checksum: e20eb2aee09ba96247465fda40c6d22c1153394c0144fa34fe6609f341af4c8c564f60ea3ba762335a7a9c306809349f9b863c8beedf2beea09b299834ad5398 + languageName: node + linkType: hard + "js-yaml@npm:^4.1.0": version: 4.1.0 resolution: "js-yaml@npm:4.1.0" @@ -475,20 +488,6 @@ __metadata: languageName: node linkType: hard -"lodash.flatten@npm:^4.4.0": - version: 4.4.0 - resolution: "lodash.flatten@npm:4.4.0" - checksum: 0ac34a393d4b795d4b7421153d27c13ae67e08786c9cbb60ff5b732210d46f833598eee3fb3844bb10070e8488efe390ea53bb567377e0cb47e9e630bf0811cb - languageName: node - linkType: hard - -"lodash.isequal@npm:^4.5.0": - version: 4.5.0 - resolution: "lodash.isequal@npm:4.5.0" - checksum: da27515dc5230eb1140ba65ff8de3613649620e8656b19a6270afe4866b7bd461d9ba2ac8a48dcc57f7adac4ee80e1de9f965d89d4d81a0ad52bb3eec2609644 - languageName: node - linkType: hard - "lodash@npm:^4.17.21": version: 4.17.21 resolution: "lodash@npm:4.17.21" @@ -505,7 +504,7 @@ __metadata: languageName: node linkType: hard -"long@npm:^5.2.0": +"long@npm:^5.2.1": version: 5.2.1 resolution: "long@npm:5.2.1" checksum: 9264da12d1b7df67e5aa6da4498144293caf1ad12e7f092efe4e9a2d32c53f0bbf7334f7cef997080a2a3af061142558ab366efa71698d98b1cdb883477445a7 @@ -544,13 +543,6 @@ __metadata: languageName: node linkType: hard -"mobx@npm:^6.3.2": - version: 6.8.0 - resolution: "mobx@npm:6.8.0" - checksum: f09bb079292ea59023a7e35a9c73ed577e3de9a0175ec3d5a2adc8192e2e3a352b29ec0981ee06d1d63f701f81bb7fc6cc19fd9089edf84a754a8a75ef00ef7f - languageName: node - linkType: hard - "mongodb@npm:^3.2.3": version: 3.7.3 resolution: "mongodb@npm:3.7.3" @@ -750,14 +742,14 @@ __metadata: languageName: node linkType: hard -"revolt-api@npm:0.5.16, revolt-api@npm:^0.5.16": - version: 0.5.16 - resolution: "revolt-api@npm:0.5.16" +"revolt-api@npm:^0.5.17, revolt-api@npm:latest": + version: 0.5.17 + resolution: "revolt-api@npm:0.5.17" dependencies: "@insertish/oapi": 0.1.18 axios: ^0.26.1 lodash.defaultsdeep: ^4.6.1 - checksum: ce39f61e371c1b7da0704191317bccf88b6630f1d8ffcef6bc9c699ebdc8cfbb3fcc5e054f96f9751c2f4a048398d4b349670cd067bcaad2e099d0c30efd9cfe + checksum: aa722f4739c09bea46f738a1b9aef61af126e06aa924a61fcf33caa53561c5de4e7e2ddde26b496cdd0546e113cf324821fead0035973e2ebdb2633df482091b languageName: node linkType: hard @@ -765,7 +757,6 @@ __metadata: version: 0.0.0-use.local resolution: "revolt-automod@workspace:." dependencies: - "@janderedev/revolt.js": latest "@types/monk": ^6.0.0 automod: ^0.1.0 axios: ^0.22.0 @@ -776,13 +767,30 @@ __metadata: log75: ^2.2.0 monk: ^7.3.4 prom-client: ^14.0.1 - revolt-api: ^0.5.16 + revolt-api: latest + revolt.js: ^7.0.0 typescript: ^4.4.3 ulid: ^2.3.0 xlsx: ^0.17.3 languageName: unknown linkType: soft +"revolt.js@portal:../revolt.js::locator=revolt-automod%40workspace%3A.": + version: 0.0.0-use.local + resolution: "revolt.js@portal:../revolt.js::locator=revolt-automod%40workspace%3A." + dependencies: + "@solid-primitives/map": ^0.4.3 + "@solid-primitives/set": ^0.4.3 + eventemitter3: ^5.0.0 + isomorphic-ws: ^5.0.0 + long: ^5.2.1 + revolt-api: ^0.5.17 + solid-js: ^1.7.2 + ulid: ^2.3.0 + ws: ^8.13.0 + languageName: node + linkType: soft + "safe-buffer@npm:^5.1.1, safe-buffer@npm:^5.1.2": version: 5.2.1 resolution: "safe-buffer@npm:5.2.1" @@ -806,6 +814,23 @@ __metadata: languageName: node linkType: hard +"seroval@npm:^0.5.0": + version: 0.5.1 + resolution: "seroval@npm:0.5.1" + checksum: a4c1e42d6a65ed12de3c1f1b6a5b6b996e575c5bc838e1998e92daed7bc05421f3f6c82096387082dba33c475d64a31d0d932ac9b693352549259216e38dc091 + languageName: node + linkType: hard + +"solid-js@npm:^1.7.2": + version: 1.7.3 + resolution: "solid-js@npm:1.7.3" + dependencies: + csstype: ^3.1.0 + seroval: ^0.5.0 + checksum: 052a3148b6d0960312793781435005c16a7a80c2271e2bf2370ec22ec57ffd77e3e4a41335c1bd785ab36500adef86da79536445983efbed404db860e11593d4 + languageName: node + linkType: hard + "sparse-bitfield@npm:^3.0.3": version: 3.0.3 resolution: "sparse-bitfield@npm:3.0.3" @@ -956,7 +981,7 @@ __metadata: languageName: node linkType: hard -"ws@npm:^8.2.2, ws@npm:^8.9.0": +"ws@npm:^8.13.0, ws@npm:^8.9.0": version: 8.13.0 resolution: "ws@npm:8.13.0" peerDependencies: diff --git a/bridge/package.json b/bridge/package.json index 93368e9..9bbd005 100644 --- a/bridge/package.json +++ b/bridge/package.json @@ -14,7 +14,6 @@ "license": "ISC", "dependencies": { "@discordjs/rest": "^0.4.1", - "@janderedev/revolt.js": "latest", "automod": "^0.1.0", "axios": "^0.26.1", "discord-api-types": "^0.31.2", @@ -25,7 +24,8 @@ "log75": "^2.2.0", "monk": "^7.3.4", "prom-client": "^14.0.1", - "revolt-api": "^0.5.3-rc.8", + "revolt-api": "latest", + "revolt.js": "^7.0.0", "smart-replace": "^1.0.2", "ulid": "^2.3.0" }, @@ -34,6 +34,7 @@ "typescript": "^4.7.4" }, "resolutions": { - "automod": "portal:../lib" + "automod": "portal:../lib", + "revolt.js": "portal:../revolt.js" } } diff --git a/bridge/src/discord/commands.ts b/bridge/src/discord/commands.ts index d9c23c8..42aef17 100644 --- a/bridge/src/discord/commands.ts +++ b/bridge/src/discord/commands.ts @@ -303,7 +303,7 @@ client.on("interactionCreate", async (interaction) => { embed.addField( "Adding AutoMod to your server", `You can add the Revolt bot to your server ` + - `[here](https://app.revolt.chat/bot/${revoltClient.user?._id} "Open Revolt"). To add the Discord counterpart, ` + + `[here](https://app.revolt.chat/bot/${revoltClient.user?.id} "Open Revolt"). To add the Discord counterpart, ` + `click [here](${INVITE_URL} "Add Discord bot").` ); @@ -480,11 +480,11 @@ client.on("interactionCreate", async (interaction) => { if (revoltMsg) { const author = await revoltFetchUser( - revoltMsg.author_id + revoltMsg.authorId ); embed.addField( "Message Author", - `**@${author?.username}** (${revoltMsg.author_id})` + `**@${author?.username}** (${revoltMsg.authorId})` ); } } diff --git a/bridge/src/discord/events.ts b/bridge/src/discord/events.ts index fb67b02..1623a13 100644 --- a/bridge/src/discord/events.ts +++ b/bridge/src/discord/events.ts @@ -1,6 +1,6 @@ import { BRIDGED_MESSAGES, BRIDGE_CONFIG, BRIDGE_USER_CONFIG, logger } from ".."; import { client } from "./client"; -import { AUTUMN_URL, client as revoltClient } from "../revolt/client"; +import { client as revoltClient } from "../revolt/client"; import axios from 'axios'; import { ulid } from "ulid"; import GenericEmbed from "../types/GenericEmbed"; @@ -196,7 +196,7 @@ client.on("messageCreate", async (message) => { await BRIDGED_MESSAGES.update( { "discord.messageId": message.id }, { - $set: { "revolt.messageId": msg._id }, + $set: { "revolt.messageId": msg.id }, } ); @@ -233,7 +233,7 @@ client.on("messageCreate", async (message) => { }); const res = await axios.post( - `${AUTUMN_URL}/attachments`, + `${revoltClient.configuration?.features.autumn.url}/attachments`, formData, { headers: formData.getHeaders() } ); @@ -280,7 +280,7 @@ client.on("messageCreate", async (message) => { }); const res = await axios.post( - `${AUTUMN_URL}/attachments`, + `${revoltClient.configuration?.features.autumn.url}/attachments`, formData, { headers: formData.getHeaders() } ); @@ -338,7 +338,7 @@ client.on("messageCreate", async (message) => { await axios .post( - `${revoltClient.apiURL}/channels/${channel._id}/messages`, + `${revoltClient.options.baseURL}/channels/${channel.id}/messages`, payload, { headers: { @@ -474,7 +474,7 @@ async function renderMessageBody(message: string): Promise { : undefined; return revoltChannel - ? `<#${revoltChannel._id}>` + ? `<#${revoltChannel.id}>` : `#${(channel as TextChannel)?.name || id}`; }, { cacheMatchResults: true, maxMatches: 10 } diff --git a/bridge/src/revolt/client.ts b/bridge/src/revolt/client.ts index a075098..7331c2e 100644 --- a/bridge/src/revolt/client.ts +++ b/bridge/src/revolt/client.ts @@ -1,21 +1,18 @@ -import { Client } from '@janderedev/revolt.js'; -import axios from 'axios'; +import { Client } from 'revolt.js'; import { logger } from '..'; -let AUTUMN_URL = `http://autumnUrl`; +let AUTUMN_URL: string = ''; const client = new Client({ - apiURL: process.env.REVOLT_API_URL, + baseURL: process.env.REVOLT_API_URL || 'https://api.revolt.chat', autoReconnect: true, }); const login = () => new Promise((resolve: (value: Client) => void) => { client.loginBot(process.env['REVOLT_TOKEN']!); client.once('ready', async () => { - logger.info(`Revolt: ${client.user?.username} ready - ${client.servers.size} servers`); - - const apiConfig = await axios.get(client.apiURL); - AUTUMN_URL = apiConfig.data?.features?.autumn?.url; + logger.info(`Revolt: ${client.user?.username} ready - ${client.servers.size()} servers`); + AUTUMN_URL = client.configuration?.features.autumn.url ?? ''; resolve(client); }); diff --git a/bridge/src/revolt/events.ts b/bridge/src/revolt/events.ts index 757df43..55859da 100644 --- a/bridge/src/revolt/events.ts +++ b/bridge/src/revolt/events.ts @@ -26,7 +26,7 @@ fetchEmojiList() ) .catch((e) => console.error(e)); -client.on("message/delete", async (id) => { +client.on("messageDelete", async (id) => { try { logger.debug(`[D] Revolt: ${id}`); @@ -83,15 +83,15 @@ client.on("message/delete", async (id) => { } }); -client.on("message/update", async (message) => { +client.on("messageUpdate", async (message) => { if (!message.content || typeof message.content != "string") return; - if (message.author_id == client.user?._id) return; + if (message.authorId == client.user?.id) return; try { logger.debug(`[E] Revolt: ${message.content}`); const [bridgeCfg, bridgedMsg] = await Promise.all([ - BRIDGE_CONFIG.findOne({ revolt: message.channel_id }), + BRIDGE_CONFIG.findOne({ revolt: message.channelId }), BRIDGED_MESSAGES.findOne({ "revolt.nonce": message.nonce }), ]); @@ -127,18 +127,18 @@ client.on("message/update", async (message) => { } }); -client.on("message", async (message) => { +client.on("messageCreate", async (message) => { try { - logger.debug(`[M] Revolt: ${message._id} ${message.content}`); + logger.debug(`[M] Revolt: ${message.id} ${message.content}`); const [bridgeCfg, bridgedMsg, ...repliedMessages] = await Promise.all([ - BRIDGE_CONFIG.findOne({ revolt: message.channel_id }), + BRIDGE_CONFIG.findOne({ revolt: message.channelId }), BRIDGED_MESSAGES.findOne( message.nonce ? { "revolt.nonce": message.nonce } - : { "revolt.messageId": message._id } + : { "revolt.messageId": message.id } ), - ...(message.reply_ids?.map((id) => + ...(message.replyIds?.map((id) => BRIDGED_MESSAGES.findOne({ "revolt.messageId": id }) ) ?? []), ]); @@ -147,7 +147,7 @@ client.on("message", async (message) => { return logger.debug( `Revolt: Message has already been bridged; ignoring` ); - if (message.system && bridgeCfg?.config?.disable_system_messages) + if (message.systemMessage && bridgeCfg?.config?.disable_system_messages) return logger.debug( `Revolt: System message bridging disabled; ignoring` ); @@ -182,7 +182,7 @@ client.on("message", async (message) => { token: hook.token || "", }; await BRIDGE_CONFIG.update( - { revolt: message.channel_id }, + { revolt: message.channelId }, { $set: { discordWebhook: bridgeCfg.discordWebhook, @@ -193,7 +193,7 @@ client.on("message", async (message) => { logger.warn( `Unable to create new webhook for channel ${bridgeCfg.discord}; Deleting link\n${e}` ); - await BRIDGE_CONFIG.remove({ revolt: message.channel_id }); + await BRIDGE_CONFIG.remove({ revolt: message.channelId }); await message.channel ?.sendMessage( ":warning: I was unable to create a webhook in the bridged Discord channel. " + @@ -206,15 +206,15 @@ client.on("message", async (message) => { } await BRIDGED_MESSAGES.update( - { "revolt.messageId": message._id }, + { "revolt.messageId": message.id }, { $set: { revolt: { - messageId: message._id, + messageId: message.id, nonce: message.nonce, }, channels: { - revolt: message.channel_id, + revolt: message.channelId, discord: bridgeCfg.discord, }, }, @@ -238,23 +238,23 @@ client.on("message", async (message) => { content: message.content ? await renderMessageBody(message.content) - : message.system - ? await renderSystemMessage(message.system) + : message.systemMessage + ? await renderSystemMessage(message.systemMessage) : undefined, - username: message.system + username: message.systemMessage ? "Revolt" : (bridgeCfg.config?.bridge_nicknames ? message.masquerade?.name ?? message.member?.nickname ?? message.author?.username : message.author?.username) ?? "Unknown user", - avatarURL: message.system + avatarURL: message.systemMessage ? "https://app.revolt.chat/assets/logo_round.png" : bridgeCfg.config?.bridge_nicknames ? message.masquerade?.avatar ?? - message.member?.generateAvatarURL({ max_side: 128 }) ?? - message.author?.generateAvatarURL({ max_side: 128 }) - : message.author?.generateAvatarURL({ max_side: 128 }), + message.member?.avatarURL ?? + message.author?.avatarURL + : message.author?.avatarURL, embeds: message.embeds?.length ? message.embeds .filter((e) => e.type == "Text") @@ -293,15 +293,15 @@ client.on("message", async (message) => { ); } else { const msg = await revoltFetchMessage( - message.reply_ids?.[0], + message.replyIds?.[0], message.channel ); const brMsg = repliedMessages.find( - (m) => m?.revolt.messageId == msg?._id + (m) => m?.revolt.messageId == msg?.id ); embed.setAuthor({ name: `@${msg?.author?.username ?? "Unknown"}`, - iconURL: msg?.author?.generateAvatarURL({ size: 64 }), + iconURL: msg?.author?.avatarURL, url: brMsg ? `https://discord.com/channels/${ channel.guildId @@ -338,7 +338,7 @@ client.on("message", async (message) => { msgUrl = msg.url; } else { const brMsg = repliedMessages.find( - (m) => m?.revolt.messageId == msg?._id + (m) => m?.revolt.messageId == msg?.id ); if (brMsg) msgUrl = `https://discord.com/channels/${ @@ -367,7 +367,7 @@ client.on("message", async (message) => { for (const attachment of message.attachments) { payload.files.push({ - attachment: `${AUTUMN_URL}/attachments/${attachment._id}/${attachment.filename}`, + attachment: `${AUTUMN_URL}/attachments/${attachment.id}/${attachment.filename}`, name: attachment.filename, }); } @@ -378,7 +378,7 @@ client.on("message", async (message) => { .then(async (res) => { await BRIDGED_MESSAGES.update( { - "revolt.messageId": message._id, + "revolt.messageId": message.id, }, { $set: { @@ -400,7 +400,7 @@ client.on("message", async (message) => { "Revolt: Got Unknown Webhook error, deleting webhook config" ); await BRIDGE_CONFIG.update( - { revolt: message.channel_id }, + { revolt: message.channelId }, { $set: { discordWebhook: undefined } } ); } catch (e) { @@ -436,7 +436,7 @@ async function renderMessageBody(message: string): Promise { const channel = client.channels.get(id); const bridgeCfg = channel - ? await BRIDGE_CONFIG.findOne({ revolt: channel._id }) + ? await BRIDGE_CONFIG.findOne({ revolt: channel.id }) : undefined; const discordChannel = bridgeCfg?.discord ? discordClient.channels.cache.get(bridgeCfg.discord) diff --git a/bridge/src/util.ts b/bridge/src/util.ts index 9863364..f92fade 100644 --- a/bridge/src/util.ts +++ b/bridge/src/util.ts @@ -1,6 +1,6 @@ -import { Channel } from "@janderedev/revolt.js/dist/maps/Channels"; -import { Message } from "@janderedev/revolt.js/dist/maps/Messages"; -import { User } from "@janderedev/revolt.js/dist/maps/Users"; +import { Channel } from "revolt.js"; +import { Message } from "revolt.js"; +import { User } from "revolt.js"; import { Message as DiscordMessage, TextChannel, User as DiscordUser } from "discord.js"; import { client as discordClient } from "./discord/client"; import { client as revoltClient } from "./revolt/client" diff --git a/bridge/yarn.lock b/bridge/yarn.lock index dc3c41d..e89d5d2 100644 --- a/bridge/yarn.lock +++ b/bridge/yarn.lock @@ -41,22 +41,6 @@ __metadata: languageName: node linkType: hard -"@insertish/exponential-backoff@npm:3.1.0-patch.2": - version: 3.1.0-patch.2 - resolution: "@insertish/exponential-backoff@npm:3.1.0-patch.2" - checksum: 510a531965965c8cc633a91653ca09ffa8408925eb403d07c072bed065ec8ce429b4fd42fb0639a3dbee73d300d4422c306ebaaab3292b06778a224a2b5b0bf1 - languageName: node - linkType: hard - -"@insertish/isomorphic-ws@npm:^4.0.1": - version: 4.0.1 - resolution: "@insertish/isomorphic-ws@npm:4.0.1" - peerDependencies: - ws: "*" - checksum: 64e6464b379784d0c8df31868eb8301b3e3827f91131755c38f66a007fcd791314c6ef49f3ead37bb5d62cc7fd52f2171b2e0ce04564a744905f72d3cd86f1ba - languageName: node - linkType: hard - "@insertish/oapi@npm:0.1.18": version: 0.1.18 resolution: "@insertish/oapi@npm:0.1.18" @@ -75,26 +59,6 @@ __metadata: languageName: node linkType: hard -"@janderedev/revolt.js@npm:latest": - version: 6.0.20-patch.9 - resolution: "@janderedev/revolt.js@npm:6.0.20-patch.9" - dependencies: - "@insertish/exponential-backoff": 3.1.0-patch.2 - "@insertish/isomorphic-ws": ^4.0.1 - axios: ^0.21.4 - eventemitter3: ^4.0.7 - lodash.defaultsdeep: ^4.6.1 - lodash.flatten: ^4.4.0 - lodash.isequal: ^4.5.0 - long: ^5.2.0 - mobx: ^6.3.2 - revolt-api: 0.5.16 - ulid: ^2.3.0 - ws: ^8.2.2 - checksum: 942f8cb7339f6378738d97ff788680dc63c287624e749b95b867a82c877bc6416a4a7b85264bf8797e034132d5a84843d75b820b6a1c37a760a88f13114772a0 - languageName: node - linkType: hard - "@sapphire/async-queue@npm:^1.3.1, @sapphire/async-queue@npm:^1.5.0": version: 1.5.0 resolution: "@sapphire/async-queue@npm:1.5.0" @@ -119,6 +83,48 @@ __metadata: languageName: node linkType: hard +"@solid-primitives/map@npm:^0.4.3": + version: 0.4.3 + resolution: "@solid-primitives/map@npm:0.4.3" + dependencies: + "@solid-primitives/trigger": ^1.0.3 + peerDependencies: + solid-js: ^1.6.12 + checksum: e2408d7309c2bc0b93126771ad796cc3cbc2b150a03b4f3d4963dbc6df2ad26e671277fc14aafe1c117f1228c35557686e709accd6237ac511d2e05a6682006d + languageName: node + linkType: hard + +"@solid-primitives/set@npm:^0.4.3": + version: 0.4.3 + resolution: "@solid-primitives/set@npm:0.4.3" + dependencies: + "@solid-primitives/trigger": ^1.0.3 + peerDependencies: + solid-js: ^1.6.12 + checksum: fcab5679185633b887d6d9ef4c12ded12d1773969a66079ce98dc18bbb2869f9fe743a1f3cd1f5721b52dcd274ae096470daa8ab1284643b4b26eeb28b7a5698 + languageName: node + linkType: hard + +"@solid-primitives/trigger@npm:^1.0.3": + version: 1.0.5 + resolution: "@solid-primitives/trigger@npm:1.0.5" + dependencies: + "@solid-primitives/utils": ^6.0.0 + peerDependencies: + solid-js: ^1.6.12 + checksum: 5f137ec425b317c09de6b994928992201206c16be7a01f7add46e0ee987d76a947a7f4f9396a945eeb671c43307b6f5d55bd57d90738880cebdaa0907aca65dd + languageName: node + linkType: hard + +"@solid-primitives/utils@npm:^6.0.0": + version: 6.0.0 + resolution: "@solid-primitives/utils@npm:6.0.0" + peerDependencies: + solid-js: ^1.6.12 + checksum: c581b995e2d16c9ed0546baef52a9e60f54dda457a3733bac467a19f2a63227179eb0ec6faa16397af4cacc13fa281288cf967a206b0a75255412fafadc55411 + languageName: node + linkType: hard + "@types/bson@npm:*": version: 4.0.5 resolution: "@types/bson@npm:4.0.5" @@ -191,15 +197,6 @@ __metadata: languageName: node linkType: soft -"axios@npm:^0.21.4": - version: 0.21.4 - resolution: "axios@npm:0.21.4" - dependencies: - follow-redirects: ^1.14.0 - checksum: 44245f24ac971e7458f3120c92f9d66d1fc695e8b97019139de5b0cc65d9b8104647db01e5f46917728edfc0cfd88eb30fc4c55e6053eef4ace76768ce95ff3c - languageName: node - linkType: hard - "axios@npm:^0.26.1": version: 0.26.1 resolution: "axios@npm:0.26.1" @@ -231,7 +228,6 @@ __metadata: resolution: "bridge@workspace:." dependencies: "@discordjs/rest": ^0.4.1 - "@janderedev/revolt.js": latest automod: ^0.1.0 axios: ^0.26.1 discord-api-types: ^0.31.2 @@ -242,7 +238,8 @@ __metadata: log75: ^2.2.0 monk: ^7.3.4 prom-client: ^14.0.1 - revolt-api: ^0.5.3-rc.8 + revolt-api: latest + revolt.js: ^7.0.0 smart-replace: ^1.0.2 typescript: ^4.7.4 ulid: ^2.3.0 @@ -281,6 +278,13 @@ __metadata: languageName: node linkType: hard +"csstype@npm:^3.1.0": + version: 3.1.2 + resolution: "csstype@npm:3.1.2" + checksum: e1a52e6c25c1314d6beef5168da704ab29c5186b877c07d822bd0806717d9a265e8493a2e35ca7e68d0f5d472d43fac1cdce70fd79fd0853dff81f3028d857b5 + languageName: node + linkType: hard + "debug@npm:*": version: 4.3.4 resolution: "debug@npm:4.3.4" @@ -359,10 +363,10 @@ __metadata: languageName: node linkType: hard -"eventemitter3@npm:^4.0.7": - version: 4.0.7 - resolution: "eventemitter3@npm:4.0.7" - checksum: 1875311c42fcfe9c707b2712c32664a245629b42bb0a5a84439762dd0fd637fc54d078155ea83c2af9e0323c9ac13687e03cfba79b03af9f40c89b4960099374 +"eventemitter3@npm:^5.0.0": + version: 5.0.0 + resolution: "eventemitter3@npm:5.0.0" + checksum: b974bafbab860e0a5bbb21add4c4e82f9d5691c583c03f2e4c5d44a2d6c4556d79223621bdcfc6c8e14366a4af9df6b5ea9d6caf65fbffc80b66f3e1dceacbc9 languageName: node linkType: hard @@ -373,7 +377,7 @@ __metadata: languageName: node linkType: hard -"follow-redirects@npm:^1.14.0, follow-redirects@npm:^1.14.8": +"follow-redirects@npm:^1.14.8": version: 1.15.2 resolution: "follow-redirects@npm:1.15.2" peerDependenciesMeta: @@ -433,6 +437,15 @@ __metadata: languageName: node linkType: hard +"isomorphic-ws@npm:^5.0.0": + version: 5.0.0 + resolution: "isomorphic-ws@npm:5.0.0" + peerDependencies: + ws: "*" + checksum: e20eb2aee09ba96247465fda40c6d22c1153394c0144fa34fe6609f341af4c8c564f60ea3ba762335a7a9c306809349f9b863c8beedf2beea09b299834ad5398 + languageName: node + linkType: hard + "js-yaml@npm:^4.1.0": version: 4.1.0 resolution: "js-yaml@npm:4.1.0" @@ -460,20 +473,6 @@ __metadata: languageName: node linkType: hard -"lodash.flatten@npm:^4.4.0": - version: 4.4.0 - resolution: "lodash.flatten@npm:4.4.0" - checksum: 0ac34a393d4b795d4b7421153d27c13ae67e08786c9cbb60ff5b732210d46f833598eee3fb3844bb10070e8488efe390ea53bb567377e0cb47e9e630bf0811cb - languageName: node - linkType: hard - -"lodash.isequal@npm:^4.5.0": - version: 4.5.0 - resolution: "lodash.isequal@npm:4.5.0" - checksum: da27515dc5230eb1140ba65ff8de3613649620e8656b19a6270afe4866b7bd461d9ba2ac8a48dcc57f7adac4ee80e1de9f965d89d4d81a0ad52bb3eec2609644 - languageName: node - linkType: hard - "lodash@npm:^4.17.21": version: 4.17.21 resolution: "lodash@npm:4.17.21" @@ -490,7 +489,7 @@ __metadata: languageName: node linkType: hard -"long@npm:^5.2.0": +"long@npm:^5.2.1": version: 5.2.1 resolution: "long@npm:5.2.1" checksum: 9264da12d1b7df67e5aa6da4498144293caf1ad12e7f092efe4e9a2d32c53f0bbf7334f7cef997080a2a3af061142558ab366efa71698d98b1cdb883477445a7 @@ -529,13 +528,6 @@ __metadata: languageName: node linkType: hard -"mobx@npm:^6.3.2": - version: 6.8.0 - resolution: "mobx@npm:6.8.0" - checksum: f09bb079292ea59023a7e35a9c73ed577e3de9a0175ec3d5a2adc8192e2e3a352b29ec0981ee06d1d63f701f81bb7fc6cc19fd9089edf84a754a8a75ef00ef7f - languageName: node - linkType: hard - "mongodb@npm:^3.2.3": version: 3.7.3 resolution: "mongodb@npm:3.7.3" @@ -726,17 +718,33 @@ __metadata: languageName: node linkType: hard -"revolt-api@npm:0.5.16, revolt-api@npm:^0.5.3-rc.8": - version: 0.5.16 - resolution: "revolt-api@npm:0.5.16" +"revolt-api@npm:^0.5.17, revolt-api@npm:latest": + version: 0.5.17 + resolution: "revolt-api@npm:0.5.17" dependencies: "@insertish/oapi": 0.1.18 axios: ^0.26.1 lodash.defaultsdeep: ^4.6.1 - checksum: ce39f61e371c1b7da0704191317bccf88b6630f1d8ffcef6bc9c699ebdc8cfbb3fcc5e054f96f9751c2f4a048398d4b349670cd067bcaad2e099d0c30efd9cfe + checksum: aa722f4739c09bea46f738a1b9aef61af126e06aa924a61fcf33caa53561c5de4e7e2ddde26b496cdd0546e113cf324821fead0035973e2ebdb2633df482091b languageName: node linkType: hard +"revolt.js@portal:../revolt.js::locator=bridge%40workspace%3A.": + version: 0.0.0-use.local + resolution: "revolt.js@portal:../revolt.js::locator=bridge%40workspace%3A." + dependencies: + "@solid-primitives/map": ^0.4.3 + "@solid-primitives/set": ^0.4.3 + eventemitter3: ^5.0.0 + isomorphic-ws: ^5.0.0 + long: ^5.2.1 + revolt-api: ^0.5.17 + solid-js: ^1.7.2 + ulid: ^2.3.0 + ws: ^8.13.0 + languageName: node + linkType: soft + "safe-buffer@npm:^5.1.1, safe-buffer@npm:^5.1.2": version: 5.2.1 resolution: "safe-buffer@npm:5.2.1" @@ -760,6 +768,13 @@ __metadata: languageName: node linkType: hard +"seroval@npm:^0.5.0": + version: 0.5.1 + resolution: "seroval@npm:0.5.1" + checksum: a4c1e42d6a65ed12de3c1f1b6a5b6b996e575c5bc838e1998e92daed7bc05421f3f6c82096387082dba33c475d64a31d0d932ac9b693352549259216e38dc091 + languageName: node + linkType: hard + "smart-replace@npm:^1.0.2": version: 1.0.2 resolution: "smart-replace@npm:1.0.2" @@ -767,6 +782,16 @@ __metadata: languageName: node linkType: hard +"solid-js@npm:^1.7.2": + version: 1.7.3 + resolution: "solid-js@npm:1.7.3" + dependencies: + csstype: ^3.1.0 + seroval: ^0.5.0 + checksum: 052a3148b6d0960312793781435005c16a7a80c2271e2bf2370ec22ec57ffd77e3e4a41335c1bd785ab36500adef86da79536445983efbed404db860e11593d4 + languageName: node + linkType: hard + "sparse-bitfield@npm:^3.0.3": version: 3.0.3 resolution: "sparse-bitfield@npm:3.0.3" @@ -894,7 +919,7 @@ __metadata: languageName: node linkType: hard -"ws@npm:^8.2.2, ws@npm:^8.9.0": +"ws@npm:^8.13.0, ws@npm:^8.9.0": version: 8.13.0 resolution: "ws@npm:8.13.0" peerDependencies: diff --git a/revolt.js b/revolt.js new file mode 160000 index 0000000..d452295 --- /dev/null +++ b/revolt.js @@ -0,0 +1 @@ +Subproject commit d452295c85c0d700ea536ebed2061c5daf960612