Merge branch 'master' of https://github.com/janderedev/automod
This commit is contained in:
commit
5d20b0ca12
23 changed files with 486 additions and 121 deletions
|
@ -10,6 +10,10 @@
|
||||||
# after initializing the database.
|
# after initializing the database.
|
||||||
DB_PASS=
|
DB_PASS=
|
||||||
|
|
||||||
|
# Base URL of the Revolt API to connect to.
|
||||||
|
# Defaults to https://api.revolt.chat
|
||||||
|
API_URL=
|
||||||
|
|
||||||
# Your bot account's token.
|
# Your bot account's token.
|
||||||
BOT_TOKEN=
|
BOT_TOKEN=
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@janderedev/revolt.js": "^5.2.8-patch.2",
|
"@janderedev/revolt.js": "^6.0.0-rc.21",
|
||||||
"@types/monk": "^6.0.0",
|
"@types/monk": "^6.0.0",
|
||||||
"axios": "^0.22.0",
|
"axios": "^0.22.0",
|
||||||
"dayjs": "^1.10.7",
|
"dayjs": "^1.10.7",
|
||||||
|
@ -23,6 +23,7 @@
|
||||||
"log75": "^2.2.0",
|
"log75": "^2.2.0",
|
||||||
"monk": "^7.3.4",
|
"monk": "^7.3.4",
|
||||||
"prom-client": "^14.0.1",
|
"prom-client": "^14.0.1",
|
||||||
|
"revolt-api": "^0.5.3-rc.15",
|
||||||
"ulid": "^2.3.0",
|
"ulid": "^2.3.0",
|
||||||
"xlsx": "^0.17.3"
|
"xlsx": "^0.17.3"
|
||||||
},
|
},
|
||||||
|
|
|
@ -24,6 +24,9 @@ export default {
|
||||||
run: async (message: MessageCommandContext, args: string[]) => {
|
run: async (message: MessageCommandContext, args: string[]) => {
|
||||||
if (!await isModerator(message))
|
if (!await isModerator(message))
|
||||||
return message.reply(NO_MANAGER_MSG);
|
return message.reply(NO_MANAGER_MSG);
|
||||||
|
if (!message.serverContext.havePermission('BanMembers')) {
|
||||||
|
return await message.reply(`Sorry, I do not have \`BanMembers\` permission.`);
|
||||||
|
}
|
||||||
|
|
||||||
if (args.length == 0)
|
if (args.length == 0)
|
||||||
return message.reply(`You need to provide a target user!`);
|
return message.reply(`You need to provide a target user!`);
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { User } from "@janderedev/revolt.js/dist/maps/Users";
|
||||||
import { adminBotLog } from "../logging";
|
import { adminBotLog } from "../logging";
|
||||||
import CommandCategory from "../../struct/commands/CommandCategory";
|
import CommandCategory from "../../struct/commands/CommandCategory";
|
||||||
import { parseUserOrId } from "../util";
|
import { parseUserOrId } from "../util";
|
||||||
import { ChannelPermission, ServerPermission } from "@janderedev/revolt.js";
|
import { Permission } from "@janderedev/revolt.js/dist/permissions/definitions";
|
||||||
|
|
||||||
const BLACKLIST_BAN_REASON = `This user is globally blacklisted and has been banned automatically. If you wish to opt out of the global blacklist, run '/botctl ignore_blacklist yes'.`;
|
const BLACKLIST_BAN_REASON = `This user is globally blacklisted and has been banned automatically. If you wish to opt out of the global blacklist, run '/botctl ignore_blacklist yes'.`;
|
||||||
const BLACKLIST_MESSAGE = (username: string) => `\`@${username}\` has been banned automatically. Check the ban reason for more info.`;
|
const BLACKLIST_MESSAGE = (username: string) => `\`@${username}\` has been banned automatically. Check the ban reason for more info.`;
|
||||||
|
@ -172,7 +172,7 @@ export default {
|
||||||
const server = client.servers.get(serverid);
|
const server = client.servers.get(serverid);
|
||||||
if (!server) continue;
|
if (!server) continue;
|
||||||
|
|
||||||
if (server.permission & ServerPermission.BanMembers) {
|
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;
|
if (config?.allowBlacklistedUsers) continue;
|
||||||
|
|
||||||
|
@ -184,7 +184,7 @@ export default {
|
||||||
|
|
||||||
if (server.system_messages?.user_banned) {
|
if (server.system_messages?.user_banned) {
|
||||||
const channel = server.channels.find(c => c!._id == server.system_messages!.user_banned);
|
const channel = server.channels.find(c => c!._id == server.system_messages!.user_banned);
|
||||||
if (channel && channel.permission & ChannelPermission.SendMessage) {
|
if (channel && channel.havePermission('SendMessage')) {
|
||||||
await channel.sendMessage(BLACKLIST_MESSAGE(target.username));
|
await channel.sendMessage(BLACKLIST_MESSAGE(target.username));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
|
import { Message } from "@janderedev/revolt.js";
|
||||||
import { ulid } from "ulid";
|
import { ulid } from "ulid";
|
||||||
|
import { SendableEmbed } from "revolt-api";
|
||||||
import { dbs } from "../..";
|
import { dbs } from "../..";
|
||||||
import CommandCategory from "../../struct/commands/CommandCategory";
|
import CommandCategory from "../../struct/commands/CommandCategory";
|
||||||
import SimpleCommand from "../../struct/commands/SimpleCommand";
|
import SimpleCommand from "../../struct/commands/SimpleCommand";
|
||||||
import MessageCommandContext from "../../struct/MessageCommandContext";
|
import MessageCommandContext from "../../struct/MessageCommandContext";
|
||||||
import { DEFAULT_PREFIX } from "../modules/command_handler";
|
import { DEFAULT_PREFIX } from "../modules/command_handler";
|
||||||
import { isBotManager, NO_MANAGER_MSG } from "../util";
|
import { isBotManager, isModerator, NO_MANAGER_MSG } from "../util";
|
||||||
|
|
||||||
const DISCORD_INVITE_URL = 'https://discord.com/api/oauth2/authorize?client_id=965692929643524136&permissions=536996864&scope=bot%20applications.commands'; // todo: read this from env or smth
|
const DISCORD_INVITE_URL = 'https://discord.com/api/oauth2/authorize?client_id=965692929643524136&permissions=536996864&scope=bot%20applications.commands'; // todo: read this from env or smth
|
||||||
|
|
||||||
|
@ -14,10 +16,10 @@ export default {
|
||||||
description: 'Bridge a channel with Discord',
|
description: 'Bridge a channel with Discord',
|
||||||
category: CommandCategory.Misc,
|
category: CommandCategory.Misc,
|
||||||
run: async (message: MessageCommandContext, args: string[]) => {
|
run: async (message: MessageCommandContext, args: string[]) => {
|
||||||
if (!await isBotManager(message)) return message.reply(NO_MANAGER_MSG);
|
|
||||||
|
|
||||||
switch(args[0]?.toLowerCase()) {
|
switch(args[0]?.toLowerCase()) {
|
||||||
case 'link': {
|
case 'link': {
|
||||||
|
if (!await isBotManager(message)) return message.reply(NO_MANAGER_MSG);
|
||||||
|
|
||||||
const count = await dbs.BRIDGE_CONFIG.count({ revolt: message.channel_id });
|
const count = await dbs.BRIDGE_CONFIG.count({ revolt: message.channel_id });
|
||||||
if (count) return message.reply(`This channel is already bridged.`);
|
if (count) return message.reply(`This channel is already bridged.`);
|
||||||
|
|
||||||
|
@ -31,21 +33,35 @@ export default {
|
||||||
expires: Date.now() + (1000 * 60 * 15),
|
expires: Date.now() + (1000 * 60 * 15),
|
||||||
});
|
});
|
||||||
|
|
||||||
await message.reply(`### Link request created.\n`
|
let text = `### Link request created.\n` +
|
||||||
+ `Request ID: \`${reqId}\`\n\n`
|
`Request ID: \`${reqId}\`\n\n` +
|
||||||
+ `[Invite the bridge bot to your Discord server](<${DISCORD_INVITE_URL}>) `
|
`[Invite the bridge bot to your Discord server](<${DISCORD_INVITE_URL}>) ` +
|
||||||
+ `and run \`/bridge confirm ${reqId}\` in the channel you wish to link.\n`
|
`and run \`/bridge confirm ${reqId}\` in the channel you wish to link.\n` +
|
||||||
+ `This request expires in 15 minutes.`);
|
`This request expires in 15 minutes.`;
|
||||||
|
|
||||||
|
if (!message.channel!.havePermission('Masquerade')
|
||||||
|
|| !message.channel!.havePermission('SendEmbeds')
|
||||||
|
|| !message.channel!.havePermission('UploadFiles')) {
|
||||||
|
text += '\n\n> :warning: I currently don\'t have all required permissions in this ' +
|
||||||
|
'channel for the bridge to work. Please make sure to grant the "Masquerade", ' +
|
||||||
|
'"Upload Files" and "Send Embeds" permission.'
|
||||||
|
}
|
||||||
|
|
||||||
|
await message.reply(text, false);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'unlink': {
|
case 'unlink': {
|
||||||
|
if (!await isBotManager(message)) return message.reply(NO_MANAGER_MSG);
|
||||||
|
|
||||||
const res = await dbs.BRIDGE_CONFIG.remove({ revolt: message.channel_id });
|
const res = await dbs.BRIDGE_CONFIG.remove({ revolt: message.channel_id });
|
||||||
if (res.deletedCount) await message.reply(`Channel unlinked!`);
|
if (res.deletedCount) await message.reply(`Channel unlinked!`);
|
||||||
else await message.reply(`Unable to unlink; no channel linked.`);
|
else await message.reply(`Unable to unlink; no channel linked.`);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'unlink_all': {
|
case 'unlink_all': {
|
||||||
|
if (!await isBotManager(message)) return message.reply(NO_MANAGER_MSG);
|
||||||
|
|
||||||
const query = { revolt: { $in: message.channel?.server?.channel_ids || [] } };
|
const query = { revolt: { $in: message.channel?.server?.channel_ids || [] } };
|
||||||
if (args[1] == 'CONFIRM') {
|
if (args[1] == 'CONFIRM') {
|
||||||
const res = await dbs.BRIDGE_CONFIG.remove(query);
|
const res = await dbs.BRIDGE_CONFIG.remove(query);
|
||||||
|
@ -65,13 +81,14 @@ export default {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'list': {
|
case 'list': {
|
||||||
|
if (!await isBotManager(message)) return message.reply(NO_MANAGER_MSG);
|
||||||
|
|
||||||
const links = await dbs.BRIDGE_CONFIG.find({ revolt: { $in: message.channel?.server?.channel_ids || [] } });
|
const links = await dbs.BRIDGE_CONFIG.find({ revolt: { $in: message.channel?.server?.channel_ids || [] } });
|
||||||
|
|
||||||
await message.reply({
|
await message.reply({
|
||||||
content: '#',
|
content: '#',
|
||||||
embeds: [
|
embeds: [
|
||||||
{
|
{
|
||||||
type: 'Text',
|
|
||||||
title: `Bridges in ${message.channel?.server?.name}`,
|
title: `Bridges in ${message.channel?.server?.name}`,
|
||||||
description: `**${links.length}** bridged channels found.\n\n`
|
description: `**${links.length}** bridged channels found.\n\n`
|
||||||
+ links.map(l => `<#${l.revolt}> **->** ${l.discord}`).join('\n'),
|
+ links.map(l => `<#${l.revolt}> **->** ${l.discord}`).join('\n'),
|
||||||
|
@ -80,12 +97,72 @@ export default {
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'info': {
|
||||||
|
try {
|
||||||
|
if (!message.reply_ids) {
|
||||||
|
return await message.reply('Please run this command again while replying to a message.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message.reply_ids.length > 1 && !await isModerator(message, false)) {
|
||||||
|
return await message.reply(
|
||||||
|
'To avoid spam, only moderators are allowed to query bridge info for more than one message at a time.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const messages = (await Promise.allSettled(
|
||||||
|
message.reply_ids?.map(m => message.channel!.fetchMessage(m)) || []
|
||||||
|
))
|
||||||
|
.filter(m => m.status == 'fulfilled')
|
||||||
|
.map(m => (m as PromiseFulfilledResult<Message>).value);
|
||||||
|
|
||||||
|
if (!messages.length) {
|
||||||
|
return await message.reply('Something went wrong; could not fetch the target message(s).');
|
||||||
|
}
|
||||||
|
|
||||||
|
const embeds: SendableEmbed[] = await Promise.all(messages.map(async msg => {
|
||||||
|
const bridgeData = await dbs.BRIDGED_MESSAGES.findOne({
|
||||||
|
'revolt.messageId': msg._id,
|
||||||
|
});
|
||||||
|
|
||||||
|
const embed: SendableEmbed = bridgeData ? {
|
||||||
|
url: msg.url,
|
||||||
|
title: `Message ${bridgeData?.origin == 'revolt' ? `by ${msg.author?.username}` : 'from Discord'}`,
|
||||||
|
colour: '#7e96ff',
|
||||||
|
description: `**Origin:** ${bridgeData.origin == 'revolt' ? 'Revolt' : 'Discord'}\n` +
|
||||||
|
`**Bridge Status:** ${
|
||||||
|
bridgeData.origin == 'revolt'
|
||||||
|
? (bridgeData.discord.messageId ? 'Bridged' : 'Unbridged')
|
||||||
|
: (bridgeData.revolt.messageId ? 'Bridged' : (bridgeData.revolt.nonce ? 'ID unknown' : 'Unbridged'))
|
||||||
|
}\n` +
|
||||||
|
`### Bridge Data\n` +
|
||||||
|
`Origin: \`${bridgeData.origin}\`\n` +
|
||||||
|
`Discord ID: \`${bridgeData.discord.messageId}\`\n` +
|
||||||
|
`Revolt ID: \`${bridgeData.revolt.messageId}\`\n` +
|
||||||
|
`Revolt Nonce: \`${bridgeData.revolt.nonce}\`\n` +
|
||||||
|
`Discord Channel: \`${bridgeData.channels?.discord}\`\n` +
|
||||||
|
`Revolt Channel: \`${bridgeData.channels?.revolt}\``,
|
||||||
|
} : {
|
||||||
|
url: msg.url,
|
||||||
|
title: `Message by ${msg.author?.username}`,
|
||||||
|
description: 'This message has not been bridged.',
|
||||||
|
colour: '#7e96ff',
|
||||||
|
}
|
||||||
|
|
||||||
|
return embed;
|
||||||
|
}));
|
||||||
|
|
||||||
|
await message.reply({ embeds }, false);
|
||||||
|
} catch(e) {
|
||||||
|
console.error(e);
|
||||||
|
message.reply(''+e)?.catch(() => {});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'help': {
|
case 'help': {
|
||||||
await message.reply({
|
await message.reply({
|
||||||
content: '#',
|
content: '#',
|
||||||
embeds: [
|
embeds: [
|
||||||
{
|
{
|
||||||
type: 'Text',
|
|
||||||
title: 'Discord Bridge',
|
title: 'Discord Bridge',
|
||||||
description: `Bridges allow you to link your Revolt server to a Discord server `
|
description: `Bridges allow you to link your Revolt server to a Discord server `
|
||||||
+ `by relaying all messages.\n\n`
|
+ `by relaying all messages.\n\n`
|
||||||
|
@ -95,7 +172,9 @@ export default {
|
||||||
+ `then run the command: \`/bridge confirm [ID]\`.\n\n`
|
+ `then run the command: \`/bridge confirm [ID]\`.\n\n`
|
||||||
+ `You can list all bridges in a Revolt server by running \`${DEFAULT_PREFIX}bridge list\`\n\n`
|
+ `You can list all bridges in a Revolt server by running \`${DEFAULT_PREFIX}bridge list\`\n\n`
|
||||||
+ `To unlink a channel, run \`/bridge unlink\` from either Discord or Revolt. If you wish to `
|
+ `To unlink a channel, run \`/bridge unlink\` from either Discord or Revolt. If you wish to `
|
||||||
+ `unbridge all channels in a Revolt server, run \`${DEFAULT_PREFIX}bridge unlink_all\`.`
|
+ `unbridge all channels in a Revolt server, run \`${DEFAULT_PREFIX}bridge unlink_all\`.\n`
|
||||||
|
+ `To view bridge info about a particular message, run \`${DEFAULT_PREFIX}bridge info\` `
|
||||||
|
+ `while replying to the message.`
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
|
@ -19,6 +19,9 @@ export default {
|
||||||
run: async (message: MessageCommandContext, args: string[]) => {
|
run: async (message: MessageCommandContext, args: string[]) => {
|
||||||
if (!await isModerator(message))
|
if (!await isModerator(message))
|
||||||
return message.reply(NO_MANAGER_MSG);
|
return message.reply(NO_MANAGER_MSG);
|
||||||
|
if (!message.serverContext.havePermission('KickMembers')) {
|
||||||
|
return await message.reply(`Sorry, I do not have \`KickMembers\` permission.`);
|
||||||
|
}
|
||||||
|
|
||||||
if (args.length == 0)
|
if (args.length == 0)
|
||||||
return message.reply(`You need to provide a target user!`);
|
return message.reply(`You need to provide a target user!`);
|
||||||
|
|
|
@ -12,7 +12,6 @@ export default {
|
||||||
content: 'Beep boop.',
|
content: 'Beep boop.',
|
||||||
embeds: [
|
embeds: [
|
||||||
{
|
{
|
||||||
type: "Text",
|
|
||||||
colour: "#ff0000",
|
colour: "#ff0000",
|
||||||
description: "embed description",
|
description: "embed description",
|
||||||
title: "embed title",
|
title: "embed title",
|
||||||
|
|
|
@ -15,6 +15,9 @@ export default {
|
||||||
category: CommandCategory.Moderation,
|
category: CommandCategory.Moderation,
|
||||||
run: async (message: MessageCommandContext, args: string[]) => {
|
run: async (message: MessageCommandContext, args: string[]) => {
|
||||||
if (!await isModerator(message)) return message.reply(NO_MANAGER_MSG);
|
if (!await isModerator(message)) return message.reply(NO_MANAGER_MSG);
|
||||||
|
if (!message.serverContext.havePermission('BanMembers')) {
|
||||||
|
return await message.reply(`Sorry, I do not have \`BanMembers\` permission.`);
|
||||||
|
}
|
||||||
|
|
||||||
let checkTempBans = async (id: string): Promise<number> => {
|
let checkTempBans = async (id: string): Promise<number> => {
|
||||||
let tempbans = await dbs.TEMPBANS.find({ bannedUser: id, server: message.serverContext._id });
|
let tempbans = await dbs.TEMPBANS.find({ bannedUser: id, server: message.serverContext._id });
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ChannelPermission, ServerPermission } from "@janderedev/revolt.js";
|
import { Permission } from "@janderedev/revolt.js/dist/permissions/definitions";
|
||||||
import { ulid } from "ulid";
|
import { ulid } from "ulid";
|
||||||
import { client, dbs } from "../..";
|
import { client, dbs } from "../..";
|
||||||
import Infraction from "../../struct/antispam/Infraction";
|
import Infraction from "../../struct/antispam/Infraction";
|
||||||
|
@ -61,12 +61,12 @@ client.on('message', async message => {
|
||||||
|
|
||||||
if (userConfig?.globalBlacklist && !serverConfig?.allowBlacklistedUsers) {
|
if (userConfig?.globalBlacklist && !serverConfig?.allowBlacklistedUsers) {
|
||||||
const server = message.channel?.server;
|
const server = message.channel?.server;
|
||||||
if (server && (server?.permission ?? 0) & ServerPermission.BanMembers) {
|
if (server && server.havePermission('BanMembers')) {
|
||||||
await server.banUser(sysMsg.user._id, { reason: BLACKLIST_BAN_REASON });
|
await server.banUser(sysMsg.user._id, { reason: BLACKLIST_BAN_REASON });
|
||||||
|
|
||||||
if (server.system_messages?.user_banned) {
|
if (server.system_messages?.user_banned) {
|
||||||
const channel = server.channels.find(c => c?._id == server.system_messages?.user_banned);
|
const channel = server.channels.find(c => c?._id == server.system_messages?.user_banned);
|
||||||
if (channel && channel.permission & ChannelPermission.SendMessage) {
|
if (channel && channel.havePermission('SendMessage')) {
|
||||||
await channel.sendMessage(BLACKLIST_MESSAGE(sysMsg.user.username));
|
await channel.sendMessage(BLACKLIST_MESSAGE(sysMsg.user.username));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,7 +102,7 @@ client.on('member/join', (member) => {
|
||||||
c => c
|
c => c
|
||||||
&& c.channel_type == 'TextChannel'
|
&& c.channel_type == 'TextChannel'
|
||||||
&& hasPermForChannel(member, c, 'SendMessage')
|
&& hasPermForChannel(member, c, 'SendMessage')
|
||||||
&& hasPermForChannel(member, c, 'EmbedLinks')
|
&& hasPermForChannel(member, c, 'SendEmbeds')
|
||||||
);
|
);
|
||||||
|
|
||||||
// Attempt to find an appropriate channel, otherwise use the first one available
|
// Attempt to find an appropriate channel, otherwise use the first one available
|
||||||
|
|
|
@ -29,6 +29,7 @@ async function processUnban(ban: TempBan) {
|
||||||
if (expired.includes(ban.id)) return;
|
if (expired.includes(ban.id)) return;
|
||||||
|
|
||||||
let server = client.servers.get(ban.server) || await client.servers.fetch(ban.server);
|
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`);
|
||||||
let serverBans = await server.fetchBans();
|
let serverBans = await server.fetchBans();
|
||||||
|
|
||||||
if (serverBans.bans.find(b => b._id.user == ban.bannedUser)) {
|
if (serverBans.bans.find(b => b._id.user == ban.bannedUser)) {
|
||||||
|
|
|
@ -73,8 +73,8 @@ async function scanUser(member: Member) {
|
||||||
lastLoggedProfile: {
|
lastLoggedProfile: {
|
||||||
username: user.username,
|
username: user.username,
|
||||||
nickname: member.nickname || undefined,
|
nickname: member.nickname || undefined,
|
||||||
profile: profile.content,
|
profile: profile.content || undefined,
|
||||||
status: user.status?.text,
|
status: user.status?.text || undefined,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,11 +11,10 @@ import { ColorResolvable, MessageEmbed } from "discord.js";
|
||||||
import logger from "./logger";
|
import logger from "./logger";
|
||||||
import { ulid } from "ulid";
|
import { ulid } from "ulid";
|
||||||
import { Channel } from "@janderedev/revolt.js/dist/maps/Channels";
|
import { Channel } from "@janderedev/revolt.js/dist/maps/Channels";
|
||||||
import { ChannelPermission, ServerPermission } from "@janderedev/revolt.js";
|
import { Permission } from "@janderedev/revolt.js/dist/permissions/definitions";
|
||||||
import { Message } from "@janderedev/revolt.js/dist/maps/Messages";
|
import { Message } from "@janderedev/revolt.js/dist/maps/Messages";
|
||||||
import { isSudo } from "./commands/botadm";
|
import { isSudo } from "./commands/botadm";
|
||||||
|
|
||||||
|
|
||||||
const NO_MANAGER_MSG = '🔒 Missing permission';
|
const NO_MANAGER_MSG = '🔒 Missing permission';
|
||||||
const ULID_REGEX = /^[0-9A-HJ-KM-NP-TV-Z]{26}$/i;
|
const ULID_REGEX = /^[0-9A-HJ-KM-NP-TV-Z]{26}$/i;
|
||||||
const USER_MENTION_REGEX = /^<@[0-9A-HJ-KM-NP-TV-Z]{26}>$/i;
|
const USER_MENTION_REGEX = /^<@[0-9A-HJ-KM-NP-TV-Z]{26}>$/i;
|
||||||
|
@ -135,20 +134,22 @@ function getPermissionBasedOnRole(member: Member): 0|1|2|3 {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function hasPerm(member: Member, perm: keyof typeof ServerPermission): boolean {
|
/**
|
||||||
let p = ServerPermission[perm];
|
* @deprecated Unnecessary
|
||||||
|
*/
|
||||||
|
function hasPerm(member: Member, perm: keyof typeof Permission): boolean {
|
||||||
|
let p = Permission[perm];
|
||||||
if (member.server?.owner == member.user?._id) return true;
|
if (member.server?.owner == member.user?._id) return true;
|
||||||
|
|
||||||
// this should work but im not 100% certain
|
return member.hasPermission(member.server!, perm);
|
||||||
let userPerm = member.roles?.map(id => member.server?.roles?.[id]?.permissions?.[0])
|
|
||||||
.reduce((sum?: number, cur?: number) => sum! | cur!, member.server?.default_permissions[0]) ?? 0;
|
|
||||||
|
|
||||||
return !!(userPerm & p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function hasPermForChannel(member: Member, channel: Channel, perm: keyof typeof ChannelPermission): boolean {
|
/**
|
||||||
|
* @deprecated Unnecessary
|
||||||
|
*/
|
||||||
|
function hasPermForChannel(member: Member, channel: Channel, perm: keyof typeof Permission): boolean {
|
||||||
if (!member.server) throw 'hasPermForChannel(): Server is undefined';
|
if (!member.server) throw 'hasPermForChannel(): Server is undefined';
|
||||||
return !!(channel.permission & ChannelPermission[perm]);
|
return member.hasPermission(channel, perm);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getOwnMemberInServer(server: Server): Promise<Member> {
|
async function getOwnMemberInServer(server: Server): Promise<Member> {
|
||||||
|
|
|
@ -13,6 +13,7 @@ import { VoteEntry } from './bot/commands/votekick';
|
||||||
import ScannedUser from './struct/ScannedUser';
|
import ScannedUser from './struct/ScannedUser';
|
||||||
import BridgeRequest from './struct/BridgeRequest';
|
import BridgeRequest from './struct/BridgeRequest';
|
||||||
import BridgeConfig from './struct/BridgeConfig';
|
import BridgeConfig from './struct/BridgeConfig';
|
||||||
|
import BridgedMessage from './struct/BridgedMessage';
|
||||||
|
|
||||||
logger.info('Initializing client');
|
logger.info('Initializing client');
|
||||||
|
|
||||||
|
@ -21,7 +22,8 @@ let client = new AutomodClient({
|
||||||
// pongTimeout: 10,
|
// pongTimeout: 10,
|
||||||
// onPongTimeout: 'RECONNECT',
|
// onPongTimeout: 'RECONNECT',
|
||||||
fixReplyCrash: true,
|
fixReplyCrash: true,
|
||||||
messageTimeoutFix: true
|
messageTimeoutFix: true,
|
||||||
|
apiURL: process.env.API_URL,
|
||||||
}, db);
|
}, db);
|
||||||
login(client);
|
login(client);
|
||||||
|
|
||||||
|
@ -35,6 +37,7 @@ const dbs = {
|
||||||
VOTEKICKS: db.get<VoteEntry>('votekicks'),
|
VOTEKICKS: db.get<VoteEntry>('votekicks'),
|
||||||
SCANNED_USERS: db.get<ScannedUser>('scanned_users'),
|
SCANNED_USERS: db.get<ScannedUser>('scanned_users'),
|
||||||
BRIDGE_CONFIG: db.get<BridgeConfig>('bridge_config'),
|
BRIDGE_CONFIG: db.get<BridgeConfig>('bridge_config'),
|
||||||
|
BRIDGED_MESSAGES: db.get<BridgedMessage>('bridged_messages'),
|
||||||
BRIDGE_REQUESTS: db.get<BridgeRequest>('bridge_requests'),
|
BRIDGE_REQUESTS: db.get<BridgeRequest>('bridge_requests'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,13 @@ let login = (client: Revolt.Client): Promise<void> => new Promise((resolve, reje
|
||||||
adminBotLog({ message: 'Bot logged in', type: 'INFO' });
|
adminBotLog({ message: 'Bot logged in', type: 'INFO' });
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
client.on('packet', packet => {
|
||||||
|
if (packet.type == 'InvalidSession' as any) {
|
||||||
|
logger.error('Authentication failed: ' + JSON.stringify(packet));
|
||||||
|
process.exit(99);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
export default AutomodClient;
|
export default AutomodClient;
|
||||||
|
|
18
bot/src/struct/BridgedMessage.ts
Normal file
18
bot/src/struct/BridgedMessage.ts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
export default class {
|
||||||
|
origin: 'discord'|'revolt';
|
||||||
|
|
||||||
|
discord: {
|
||||||
|
messageId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
revolt: {
|
||||||
|
messageId?: string;
|
||||||
|
nonce?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Required to sync message deletions
|
||||||
|
channels?: {
|
||||||
|
discord: string;
|
||||||
|
revolt: string;
|
||||||
|
}
|
||||||
|
}
|
127
bot/yarn.lock
127
bot/yarn.lock
|
@ -27,30 +27,41 @@
|
||||||
combined-stream "^1.0.8"
|
combined-stream "^1.0.8"
|
||||||
mime-types "^2.1.12"
|
mime-types "^2.1.12"
|
||||||
|
|
||||||
"@insertish/exponential-backoff@3.1.0-patch.0":
|
"@insertish/exponential-backoff@3.1.0-patch.2":
|
||||||
version "3.1.0-patch.0"
|
version "3.1.0-patch.2"
|
||||||
resolved "https://registry.yarnpkg.com/@insertish/exponential-backoff/-/exponential-backoff-3.1.0-patch.0.tgz#1fff134f70fc0906d11d09069d51183b542e42cf"
|
resolved "https://registry.yarnpkg.com/@insertish/exponential-backoff/-/exponential-backoff-3.1.0-patch.2.tgz#08310c856b795c783a832f3f608c0feaff262c0d"
|
||||||
integrity sha512-1qhW81s3GDbssyaxRWdpBAn1cIw5s393HnrdYFjfa2i6rq3SEjQDK6U80g6dq/K0or6JRr2eCn75Wfc1IrGM0g==
|
integrity sha512-0lsMVexkZ7dHpQlPrTZDRsm42hZ4/CzKxP1hbAEJH8IaEwrIEhhTKJuFxPuLOi2TwPImuocncjYHpGpwVNOemQ==
|
||||||
|
|
||||||
"@insertish/isomorphic-ws@^4.0.1":
|
"@insertish/isomorphic-ws@^4.0.1":
|
||||||
version "4.0.1"
|
version "4.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/@insertish/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#5bcd6f73b93efa9ccdb6abf887ae808d40827169"
|
resolved "https://registry.yarnpkg.com/@insertish/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#5bcd6f73b93efa9ccdb6abf887ae808d40827169"
|
||||||
integrity sha512-kFD/p8T4Hkqr992QrdkbW/cQ/W/q2d9MPCobwzBv2PwTKLkCD9RaYDy6m17qRnSLQQ5PU0kHCG8kaOwAqzj1vQ==
|
integrity sha512-kFD/p8T4Hkqr992QrdkbW/cQ/W/q2d9MPCobwzBv2PwTKLkCD9RaYDy6m17qRnSLQQ5PU0kHCG8kaOwAqzj1vQ==
|
||||||
|
|
||||||
"@janderedev/revolt.js@^5.2.8-patch.2":
|
"@insertish/oapi@0.1.15":
|
||||||
version "5.2.8-patch.2"
|
version "0.1.15"
|
||||||
resolved "https://registry.yarnpkg.com/@janderedev/revolt.js/-/revolt.js-5.2.8-patch.2.tgz#d74a6500e217a4cb94d139027dec2acb71f73a0f"
|
resolved "https://registry.yarnpkg.com/@insertish/oapi/-/oapi-0.1.15.tgz#ee58b82d879ed5af54db846699941b8ad0262e7b"
|
||||||
integrity sha512-2nucMuToKC5F4jsajmTauBaV9Q7oyl1KWKF0ysYYPzEKxK9LfPL560v9bQR/ff1g8GkEv4biAN/A17MCcddAuw==
|
integrity sha512-2G8eFxrojF651tBoRutQ8CJOw0u8UjYSlw/LQU+xycw5KpXslhWp/KSR86uIFyDIPddwfMCNA91vwHGCFRA63w==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@insertish/exponential-backoff" "3.1.0-patch.0"
|
typescript "^4.6.2"
|
||||||
|
optionalDependencies:
|
||||||
|
axios "^0.26.1"
|
||||||
|
openapi-typescript "^5.2.0"
|
||||||
|
|
||||||
|
"@janderedev/revolt.js@^6.0.0-rc.21":
|
||||||
|
version "6.0.0-rc.21"
|
||||||
|
resolved "https://registry.yarnpkg.com/@janderedev/revolt.js/-/revolt.js-6.0.0-rc.21.tgz#0629700cd78d0f7db5f4707dc7a8f5ba67482e1a"
|
||||||
|
integrity sha512-uLFXrv6ZjLJ+e9keevv0sUeZY8gDw3RfSg07LNYVUfqi1T64WwmZypz3zc2kTacbfthIgI368K2e6f3q4toc4Q==
|
||||||
|
dependencies:
|
||||||
|
"@insertish/exponential-backoff" "3.1.0-patch.2"
|
||||||
"@insertish/isomorphic-ws" "^4.0.1"
|
"@insertish/isomorphic-ws" "^4.0.1"
|
||||||
axios "^0.21.4"
|
axios "^0.21.4"
|
||||||
eventemitter3 "^4.0.7"
|
eventemitter3 "^4.0.7"
|
||||||
lodash.defaultsdeep "^4.6.1"
|
lodash.defaultsdeep "^4.6.1"
|
||||||
lodash.flatten "^4.4.0"
|
lodash.flatten "^4.4.0"
|
||||||
lodash.isequal "^4.5.0"
|
lodash.isequal "^4.5.0"
|
||||||
|
long "^5.2.0"
|
||||||
mobx "^6.3.2"
|
mobx "^6.3.2"
|
||||||
revolt-api "0.5.3-alpha.12"
|
revolt-api "0.5.3-rc.15"
|
||||||
ulid "^2.3.0"
|
ulid "^2.3.0"
|
||||||
ws "^8.2.2"
|
ws "^8.2.2"
|
||||||
|
|
||||||
|
@ -126,6 +137,11 @@ ansi-colors@^4.1.1:
|
||||||
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
|
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
|
||||||
integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==
|
integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==
|
||||||
|
|
||||||
|
argparse@^2.0.1:
|
||||||
|
version "2.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
|
||||||
|
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
|
||||||
|
|
||||||
asynckit@^0.4.0:
|
asynckit@^0.4.0:
|
||||||
version "0.4.0"
|
version "0.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||||
|
@ -145,6 +161,13 @@ axios@^0.22.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
follow-redirects "^1.14.4"
|
follow-redirects "^1.14.4"
|
||||||
|
|
||||||
|
axios@^0.26.1:
|
||||||
|
version "0.26.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/axios/-/axios-0.26.1.tgz#1ede41c51fcf51bbbd6fd43669caaa4f0495aaa9"
|
||||||
|
integrity sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==
|
||||||
|
dependencies:
|
||||||
|
follow-redirects "^1.14.8"
|
||||||
|
|
||||||
base64-js@^1.3.1:
|
base64-js@^1.3.1:
|
||||||
version "1.5.1"
|
version "1.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
|
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
|
||||||
|
@ -301,6 +324,11 @@ follow-redirects@^1.14.0, follow-redirects@^1.14.4:
|
||||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.8.tgz#016996fb9a11a100566398b1c6839337d7bfa8fc"
|
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.8.tgz#016996fb9a11a100566398b1c6839337d7bfa8fc"
|
||||||
integrity sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==
|
integrity sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==
|
||||||
|
|
||||||
|
follow-redirects@^1.14.8:
|
||||||
|
version "1.14.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.9.tgz#dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7"
|
||||||
|
integrity sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==
|
||||||
|
|
||||||
form-data@^3.0.0:
|
form-data@^3.0.0:
|
||||||
version "3.0.1"
|
version "3.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f"
|
resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f"
|
||||||
|
@ -324,6 +352,16 @@ frac@~1.1.2:
|
||||||
resolved "https://registry.yarnpkg.com/frac/-/frac-1.1.2.tgz#3d74f7f6478c88a1b5020306d747dc6313c74d0b"
|
resolved "https://registry.yarnpkg.com/frac/-/frac-1.1.2.tgz#3d74f7f6478c88a1b5020306d747dc6313c74d0b"
|
||||||
integrity sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==
|
integrity sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==
|
||||||
|
|
||||||
|
globalyzer@0.1.0:
|
||||||
|
version "0.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/globalyzer/-/globalyzer-0.1.0.tgz#cb76da79555669a1519d5a8edf093afaa0bf1465"
|
||||||
|
integrity sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==
|
||||||
|
|
||||||
|
globrex@^0.1.2:
|
||||||
|
version "0.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/globrex/-/globrex-0.1.2.tgz#dd5d9ec826232730cd6793a5e33a9302985e6098"
|
||||||
|
integrity sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==
|
||||||
|
|
||||||
ieee754@^1.1.13:
|
ieee754@^1.1.13:
|
||||||
version "1.2.1"
|
version "1.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
||||||
|
@ -344,6 +382,13 @@ isarray@~1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
|
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
|
||||||
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
|
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
|
||||||
|
|
||||||
|
js-yaml@^4.1.0:
|
||||||
|
version "4.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
|
||||||
|
integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
|
||||||
|
dependencies:
|
||||||
|
argparse "^2.0.1"
|
||||||
|
|
||||||
lodash.defaultsdeep@^4.6.1:
|
lodash.defaultsdeep@^4.6.1:
|
||||||
version "4.6.1"
|
version "4.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz#512e9bd721d272d94e3d3a63653fa17516741ca6"
|
resolved "https://registry.yarnpkg.com/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz#512e9bd721d272d94e3d3a63653fa17516741ca6"
|
||||||
|
@ -366,6 +411,11 @@ log75@^2.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
ansi-colors "^4.1.1"
|
ansi-colors "^4.1.1"
|
||||||
|
|
||||||
|
long@^5.2.0:
|
||||||
|
version "5.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/long/-/long-5.2.0.tgz#2696dadf4b4da2ce3f6f6b89186085d94d52fd61"
|
||||||
|
integrity sha512-9RTUNjK60eJbx3uz+TEGF7fUr29ZDxR5QzXcyDpeSfeH28S9ycINflOgOlppit5U+4kNTe83KQnMEerw7GmE8w==
|
||||||
|
|
||||||
memory-pager@^1.0.2:
|
memory-pager@^1.0.2:
|
||||||
version "1.5.0"
|
version "1.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/memory-pager/-/memory-pager-1.5.0.tgz#d8751655d22d384682741c972f2c3d6dfa3e66b5"
|
resolved "https://registry.yarnpkg.com/memory-pager/-/memory-pager-1.5.0.tgz#d8751655d22d384682741c972f2c3d6dfa3e66b5"
|
||||||
|
@ -383,6 +433,11 @@ mime-types@^2.1.12:
|
||||||
dependencies:
|
dependencies:
|
||||||
mime-db "1.50.0"
|
mime-db "1.50.0"
|
||||||
|
|
||||||
|
mime@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7"
|
||||||
|
integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==
|
||||||
|
|
||||||
mobx@^6.3.2:
|
mobx@^6.3.2:
|
||||||
version "6.3.13"
|
version "6.3.13"
|
||||||
resolved "https://registry.yarnpkg.com/mobx/-/mobx-6.3.13.tgz#93e56a57ee72369f850cf3d6398fd36ee8ef062e"
|
resolved "https://registry.yarnpkg.com/mobx/-/mobx-6.3.13.tgz#93e56a57ee72369f850cf3d6398fd36ee8ef062e"
|
||||||
|
@ -464,6 +519,18 @@ object-assign@^4.1.1:
|
||||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||||
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
|
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
|
||||||
|
|
||||||
|
openapi-typescript@^5.2.0:
|
||||||
|
version "5.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/openapi-typescript/-/openapi-typescript-5.2.0.tgz#c0712d7a17e4502ac083162c42f946c0e966a505"
|
||||||
|
integrity sha512-EGoPTmxrpiN40R6An5Wqol2l74sRb773pv/KXWYCQaMCXNtMGN7Jv+y/jY4B1Bd4hsIW2j9GFmQXxqfGmOXaxA==
|
||||||
|
dependencies:
|
||||||
|
js-yaml "^4.1.0"
|
||||||
|
mime "^3.0.0"
|
||||||
|
prettier "^2.5.1"
|
||||||
|
tiny-glob "^0.2.9"
|
||||||
|
undici "^4.14.1"
|
||||||
|
yargs-parser "^21.0.0"
|
||||||
|
|
||||||
optional-require@^1.1.8:
|
optional-require@^1.1.8:
|
||||||
version "1.1.8"
|
version "1.1.8"
|
||||||
resolved "https://registry.yarnpkg.com/optional-require/-/optional-require-1.1.8.tgz#16364d76261b75d964c482b2406cb824d8ec44b7"
|
resolved "https://registry.yarnpkg.com/optional-require/-/optional-require-1.1.8.tgz#16364d76261b75d964c482b2406cb824d8ec44b7"
|
||||||
|
@ -483,6 +550,11 @@ ow@^0.27.0:
|
||||||
type-fest "^1.2.1"
|
type-fest "^1.2.1"
|
||||||
vali-date "^1.0.0"
|
vali-date "^1.0.0"
|
||||||
|
|
||||||
|
prettier@^2.5.1:
|
||||||
|
version "2.6.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.6.2.tgz#e26d71a18a74c3d0f0597f55f01fb6c06c206032"
|
||||||
|
integrity sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==
|
||||||
|
|
||||||
printj@~1.1.0:
|
printj@~1.1.0:
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222"
|
resolved "https://registry.yarnpkg.com/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222"
|
||||||
|
@ -528,10 +600,14 @@ require-at@^1.0.6:
|
||||||
resolved "https://registry.yarnpkg.com/require-at/-/require-at-1.0.6.tgz#9eb7e3c5e00727f5a4744070a7f560d4de4f6e6a"
|
resolved "https://registry.yarnpkg.com/require-at/-/require-at-1.0.6.tgz#9eb7e3c5e00727f5a4744070a7f560d4de4f6e6a"
|
||||||
integrity sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==
|
integrity sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==
|
||||||
|
|
||||||
revolt-api@0.5.3-alpha.12:
|
revolt-api@0.5.3-rc.15, revolt-api@^0.5.3-rc.15:
|
||||||
version "0.5.3-alpha.12"
|
version "0.5.3-rc.15"
|
||||||
resolved "https://registry.yarnpkg.com/revolt-api/-/revolt-api-0.5.3-alpha.12.tgz#78f25b567b840c1fd072595526592a422cb01f25"
|
resolved "https://registry.yarnpkg.com/revolt-api/-/revolt-api-0.5.3-rc.15.tgz#abd08dd8109d0ca31be118461eabbeb6c3b7792e"
|
||||||
integrity sha512-MM42oI5+5JJMnAs3JiOwSQOy/SUYzYs3M8YRC5QI4G6HU7CfyB2HNWh5jFsyRlcLdSi13dGazHm31FUPHsxOzw==
|
integrity sha512-MYin3U+KoObNkILPf2cz+FPperynExkUu7CjzurMJCRvBncpnhb2czvWDvnhLDKBHlpo8W597xNqzQnaklV4ug==
|
||||||
|
dependencies:
|
||||||
|
"@insertish/oapi" "0.1.15"
|
||||||
|
axios "^0.26.1"
|
||||||
|
lodash.defaultsdeep "^4.6.1"
|
||||||
|
|
||||||
safe-buffer@^5.1.1, safe-buffer@^5.1.2:
|
safe-buffer@^5.1.1, safe-buffer@^5.1.2:
|
||||||
version "5.2.1"
|
version "5.2.1"
|
||||||
|
@ -578,6 +654,14 @@ tdigest@^0.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
bintrees "1.0.1"
|
bintrees "1.0.1"
|
||||||
|
|
||||||
|
tiny-glob@^0.2.9:
|
||||||
|
version "0.2.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/tiny-glob/-/tiny-glob-0.2.9.tgz#2212d441ac17928033b110f8b3640683129d31e2"
|
||||||
|
integrity sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==
|
||||||
|
dependencies:
|
||||||
|
globalyzer "0.1.0"
|
||||||
|
globrex "^0.1.2"
|
||||||
|
|
||||||
tr46@~0.0.3:
|
tr46@~0.0.3:
|
||||||
version "0.0.3"
|
version "0.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
|
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
|
||||||
|
@ -603,11 +687,21 @@ typescript@^4.4.3:
|
||||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.3.tgz#bdc5407caa2b109efd4f82fe130656f977a29324"
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.3.tgz#bdc5407caa2b109efd4f82fe130656f977a29324"
|
||||||
integrity sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==
|
integrity sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==
|
||||||
|
|
||||||
|
typescript@^4.6.2:
|
||||||
|
version "4.6.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.4.tgz#caa78bbc3a59e6a5c510d35703f6a09877ce45e9"
|
||||||
|
integrity sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==
|
||||||
|
|
||||||
ulid@^2.3.0:
|
ulid@^2.3.0:
|
||||||
version "2.3.0"
|
version "2.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/ulid/-/ulid-2.3.0.tgz#93063522771a9774121a84d126ecd3eb9804071f"
|
resolved "https://registry.yarnpkg.com/ulid/-/ulid-2.3.0.tgz#93063522771a9774121a84d126ecd3eb9804071f"
|
||||||
integrity sha512-keqHubrlpvT6G2wH0OEfSW4mquYRcbe/J8NMmveoQOjUqmo+hXtO+ORCpWhdbZ7k72UtY61BL7haGxW6enBnjw==
|
integrity sha512-keqHubrlpvT6G2wH0OEfSW4mquYRcbe/J8NMmveoQOjUqmo+hXtO+ORCpWhdbZ7k72UtY61BL7haGxW6enBnjw==
|
||||||
|
|
||||||
|
undici@^4.14.1:
|
||||||
|
version "4.16.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/undici/-/undici-4.16.0.tgz#469bb87b3b918818d3d7843d91a1d08da357d5ff"
|
||||||
|
integrity sha512-tkZSECUYi+/T1i4u+4+lwZmQgLXd4BLGlrc7KZPcLIW7Jpq99+Xpc30ONv7nS6F5UNOxp/HBZSSL9MafUrvJbw==
|
||||||
|
|
||||||
util-deprecate@~1.0.1:
|
util-deprecate@~1.0.1:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||||
|
@ -666,3 +760,8 @@ xlsx@^0.17.3:
|
||||||
ssf "~0.11.2"
|
ssf "~0.11.2"
|
||||||
wmf "~1.0.1"
|
wmf "~1.0.1"
|
||||||
word "~0.3.0"
|
word "~0.3.0"
|
||||||
|
|
||||||
|
yargs-parser@^21.0.0:
|
||||||
|
version "21.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.0.1.tgz#0267f286c877a4f0f728fceb6f8a3e4cb95c6e35"
|
||||||
|
integrity sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@discordjs/rest": "^0.4.1",
|
"@discordjs/rest": "^0.4.1",
|
||||||
"@janderedev/revolt.js": "^5.2.8-patch.2",
|
"@janderedev/revolt.js": "^6.0.0-rc.21",
|
||||||
"axios": "^0.26.1",
|
"axios": "^0.26.1",
|
||||||
"discord-api-types": "^0.31.2",
|
"discord-api-types": "^0.31.2",
|
||||||
"discord.js": "^13.6.0",
|
"discord.js": "^13.6.0",
|
||||||
|
|
|
@ -3,13 +3,16 @@
|
||||||
import { client } from "./client";
|
import { client } from "./client";
|
||||||
import { REST } from '@discordjs/rest';
|
import { REST } from '@discordjs/rest';
|
||||||
import { Routes } from 'discord-api-types/v9';
|
import { Routes } from 'discord-api-types/v9';
|
||||||
import { BRIDGE_CONFIG, BRIDGE_REQUESTS, logger } from "..";
|
import { BRIDGED_MESSAGES, BRIDGE_CONFIG, BRIDGE_REQUESTS, logger } from "..";
|
||||||
import { TextChannel } from "discord.js";
|
import { MessageEmbed, TextChannel } from "discord.js";
|
||||||
|
import { revoltFetchMessage, revoltFetchUser } from "../util";
|
||||||
|
import { client as revoltClient } from "../revolt/client";
|
||||||
|
|
||||||
const COMMANDS: any[] = [
|
const COMMANDS: any[] = [
|
||||||
{
|
{
|
||||||
name: 'bridge',
|
name: 'bridge',
|
||||||
description: 'Confirm or delete Revolt bridges',
|
description: 'Confirm or delete Revolt bridges',
|
||||||
|
type: 1, // Slash command
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
name: 'confirm',
|
name: 'confirm',
|
||||||
|
@ -30,6 +33,11 @@ const COMMANDS: any[] = [
|
||||||
type: 1,
|
type: 1,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Message Info',
|
||||||
|
description: '',
|
||||||
|
type: 3, // Message context menu
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -59,63 +67,139 @@ client.once('ready', async () => {
|
||||||
|
|
||||||
client.on('interactionCreate', async interaction => {
|
client.on('interactionCreate', async interaction => {
|
||||||
try {
|
try {
|
||||||
if (!interaction.isCommand()) return;
|
if (interaction.isCommand()) {
|
||||||
|
logger.debug(`Command received: /${interaction.commandName}`);
|
||||||
|
|
||||||
logger.debug(`Command received: /${interaction.commandName}`);
|
// The revolutionary Jan command handler
|
||||||
|
switch(interaction.commandName) {
|
||||||
|
case 'bridge':
|
||||||
|
if (!interaction.memberPermissions?.has('MANAGE_GUILD')) {
|
||||||
|
return await interaction.reply(`\`MANAGE_GUILD\` permission is required for this.`);
|
||||||
|
}
|
||||||
|
|
||||||
// The revolutionary Jan command handler
|
const ownPerms = (interaction.channel as TextChannel).permissionsFor(client.user!)!;
|
||||||
switch(interaction.commandName) {
|
switch(interaction.options.getSubcommand(true)) {
|
||||||
case 'bridge':
|
case 'confirm':
|
||||||
if (!interaction.memberPermissions?.has('MANAGE_GUILD')) {
|
if (!ownPerms.has('MANAGE_WEBHOOKS'))
|
||||||
return await interaction.reply(`\`MANAGE_GUILD\` permission is required for this.`);
|
return interaction.reply('Sorry, I lack permission to manage webhooks in this channel.');
|
||||||
}
|
|
||||||
|
|
||||||
const ownPerms = (interaction.channel as TextChannel).permissionsFor(client.user!)!;
|
const id = interaction.options.getString('id', true);
|
||||||
switch(interaction.options.getSubcommand(true)) {
|
const request = await BRIDGE_REQUESTS.findOne({ id: id });
|
||||||
case 'confirm':
|
if (!request || request.expires < Date.now()) return await interaction.reply('Unknown ID.');
|
||||||
if (!ownPerms.has('MANAGE_WEBHOOKS'))
|
|
||||||
return interaction.reply('Sorry, I lack permission to manage webhooks in this channel.');
|
|
||||||
|
|
||||||
const id = interaction.options.getString('id', true);
|
const bridgedCount = await BRIDGE_CONFIG.count({ discord: interaction.channelId });
|
||||||
const request = await BRIDGE_REQUESTS.findOne({ id: id });
|
if (bridgedCount > 0) return await interaction.reply('This channel is already bridged.');
|
||||||
if (!request || request.expires < Date.now()) return await interaction.reply('Unknown ID.');
|
|
||||||
|
|
||||||
const bridgedCount = await BRIDGE_CONFIG.count({ discord: interaction.channelId });
|
const webhook = await (interaction.channel as TextChannel)
|
||||||
if (bridgedCount > 0) return await interaction.reply('This channel is already bridged.');
|
.createWebhook('AutoMod Bridge', { avatar: client.user?.avatarURL() });
|
||||||
|
|
||||||
const webhook = await (interaction.channel as TextChannel)
|
await BRIDGE_REQUESTS.remove({ id: id });
|
||||||
.createWebhook('AutoMod Bridge', { avatar: client.user?.avatarURL() });
|
await BRIDGE_CONFIG.insert({
|
||||||
|
discord: interaction.channelId,
|
||||||
|
revolt: request.revolt,
|
||||||
|
discordWebhook: {
|
||||||
|
id: webhook.id,
|
||||||
|
token: webhook.token || '',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
await BRIDGE_REQUESTS.remove({ id: id });
|
return await interaction.reply(`✅ Channel bridged!`);
|
||||||
await BRIDGE_CONFIG.insert({
|
case 'unlink':
|
||||||
discord: interaction.channelId,
|
const res = await BRIDGE_CONFIG.findOneAndDelete({ discord: interaction.channelId });
|
||||||
revolt: request.revolt,
|
if (res?._id) {
|
||||||
discordWebhook: {
|
await interaction.reply('Channel unbridged.');
|
||||||
id: webhook.id,
|
if (ownPerms.has('MANAGE_WEBHOOKS') && res.discordWebhook) {
|
||||||
token: webhook.token || '',
|
try {
|
||||||
|
const hooks = await (interaction.channel as TextChannel).fetchWebhooks();
|
||||||
|
if (hooks.get(res?.discordWebhook?.id)) await hooks.get(res?.discordWebhook?.id)
|
||||||
|
?.delete('Channel has been unbridged');
|
||||||
|
} catch(_) {}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else await interaction.reply('This channel is not bridged.');
|
||||||
|
|
||||||
|
break;
|
||||||
|
default: await interaction.reply('Unknown subcommand');
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (interaction.isMessageContextMenu()) {
|
||||||
|
logger.debug(`Received context menu: ${interaction.targetMessage.id}`);
|
||||||
|
|
||||||
|
switch(interaction.commandName) {
|
||||||
|
case 'Message Info':
|
||||||
|
const message = interaction.targetMessage;
|
||||||
|
const bridgeInfo = await BRIDGED_MESSAGES.findOne({ "discord.messageId": message.id });
|
||||||
|
const messageUrl = `https://discord.com/channels/${interaction.guildId}/${interaction.channelId}/${message.id}`;
|
||||||
|
|
||||||
|
if (!bridgeInfo) return await interaction.reply({
|
||||||
|
ephemeral: true,
|
||||||
|
embeds: [
|
||||||
|
new MessageEmbed()
|
||||||
|
.setAuthor({ name: 'Message info', url: messageUrl })
|
||||||
|
.setDescription('This message has not been bridged.')
|
||||||
|
.setColor('#7e96ff'),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
else {
|
||||||
|
const embed = new MessageEmbed();
|
||||||
|
|
||||||
|
embed.setColor('#7e96ff');
|
||||||
|
embed.setAuthor({ name: 'Message info', url: messageUrl });
|
||||||
|
|
||||||
|
embed.addField('Origin', bridgeInfo.origin == 'discord' ? 'Discord' : 'Revolt', true);
|
||||||
|
|
||||||
|
if (bridgeInfo.origin == 'discord') {
|
||||||
|
embed.addField(
|
||||||
|
'Bridge Status',
|
||||||
|
bridgeInfo.revolt.messageId
|
||||||
|
? 'Bridged'
|
||||||
|
: bridgeInfo.revolt.nonce
|
||||||
|
? 'ID unknown'
|
||||||
|
: 'Unbridged',
|
||||||
|
true
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
embed.addField(
|
||||||
|
'Bridge Status',
|
||||||
|
bridgeInfo.discord.messageId
|
||||||
|
? 'Bridged'
|
||||||
|
: 'Unbridged',
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
if (bridgeInfo.channels?.revolt) {
|
||||||
|
const channel = await revoltClient.channels.get(bridgeInfo.channels.revolt);
|
||||||
|
const revoltMsg = await revoltFetchMessage(bridgeInfo.revolt.messageId, channel);
|
||||||
|
|
||||||
|
if (revoltMsg) {
|
||||||
|
const author = await revoltFetchUser(revoltMsg.author_id);
|
||||||
|
embed.addField(
|
||||||
|
'Message Author',
|
||||||
|
`**@${author?.username}** (${revoltMsg.author_id})`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
embed.addField(
|
||||||
|
'Bridge Data',
|
||||||
|
`Origin: \`${bridgeInfo.origin}\`\n` +
|
||||||
|
`Discord ID: \`${bridgeInfo.discord.messageId}\`\n` +
|
||||||
|
`Revolt ID: \`${bridgeInfo.revolt.messageId}\`\n` +
|
||||||
|
`Revolt Nonce: \`${bridgeInfo.revolt.nonce}\`\n` +
|
||||||
|
`Discord Channel: \`${bridgeInfo.channels?.discord}\`\n` +
|
||||||
|
`Revolt Channel: \`${bridgeInfo.channels?.revolt}\``
|
||||||
|
);
|
||||||
|
|
||||||
|
return await interaction.reply({
|
||||||
|
ephemeral: true,
|
||||||
|
embeds: [ embed ],
|
||||||
});
|
});
|
||||||
|
}
|
||||||
return await interaction.reply(`✅ Channel bridged!`);
|
}
|
||||||
case 'unlink':
|
|
||||||
const res = await BRIDGE_CONFIG.findOneAndDelete({ discord: interaction.channelId });
|
|
||||||
if (res?._id) {
|
|
||||||
await interaction.reply('Channel unbridged.');
|
|
||||||
if (ownPerms.has('MANAGE_WEBHOOKS') && res.discordWebhook) {
|
|
||||||
try {
|
|
||||||
const hooks = await (interaction.channel as TextChannel).fetchWebhooks();
|
|
||||||
if (hooks.get(res?.discordWebhook?.id)) await hooks.get(res?.discordWebhook?.id)
|
|
||||||
?.delete('Channel has been unbridged');
|
|
||||||
} catch(_) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else await interaction.reply('This channel is not bridged.');
|
|
||||||
|
|
||||||
break;
|
|
||||||
default: await interaction.reply('Unknown subcommand');
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { BRIDGED_MESSAGES, BRIDGE_CONFIG, logger } from "..";
|
import { BRIDGED_MESSAGES, BRIDGE_CONFIG, logger } from "..";
|
||||||
import { client } from "./client";
|
import { client } from "./client";
|
||||||
import { AUTUMN_URL, client as revoltClient } from "../revolt/client";
|
import { AUTUMN_URL, client as revoltClient } from "../revolt/client";
|
||||||
import { ChannelPermission } from "@janderedev/revolt.js";
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { ulid } from "ulid";
|
import { ulid } from "ulid";
|
||||||
import GenericEmbed from "../types/GenericEmbed";
|
import GenericEmbed from "../types/GenericEmbed";
|
||||||
|
@ -15,6 +14,8 @@ const MAX_BRIDGED_FILE_SIZE = 8_000_000; // 8 MB
|
||||||
const RE_MENTION_USER = /<@!*[0-9]+>/g;
|
const RE_MENTION_USER = /<@!*[0-9]+>/g;
|
||||||
const RE_MENTION_CHANNEL = /<#[0-9]+>/g;
|
const RE_MENTION_CHANNEL = /<#[0-9]+>/g;
|
||||||
const RE_EMOJI = /<(a?)?:\w+:\d{18}?>/g;
|
const RE_EMOJI = /<(a?)?:\w+:\d{18}?>/g;
|
||||||
|
const RE_TENOR = /^https:\/\/tenor.com\/view\/[^\s]+$/g;
|
||||||
|
const RE_TENOR_META = /<meta class="dynamic" property="og:url" content="[^\s]+">/g
|
||||||
|
|
||||||
client.on('messageDelete', async message => {
|
client.on('messageDelete', async message => {
|
||||||
try {
|
try {
|
||||||
|
@ -84,11 +85,19 @@ client.on('messageCreate', async message => {
|
||||||
const channel = revoltClient.channels.get(bridgeCfg.revolt);
|
const channel = revoltClient.channels.get(bridgeCfg.revolt);
|
||||||
if (!channel) return logger.debug(`Discord: Cannot find associated channel`);
|
if (!channel) return logger.debug(`Discord: Cannot find associated channel`);
|
||||||
|
|
||||||
if (!(channel.permission & ChannelPermission.SendMessage)) {
|
if (!(channel.havePermission('SendMessage'))) {
|
||||||
return logger.debug(`Discord: Lacking SendMessage permission; refusing to send`);
|
return logger.debug(`Discord: Lacking SendMessage permission; refusing to send`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(channel.permission & ChannelPermission.Masquerade)) {
|
if (!(channel.havePermission('SendEmbeds'))) {
|
||||||
|
return logger.debug(`Discord: Lacking SendEmbeds permission; refusing to send`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(channel.havePermission('UploadFiles'))) {
|
||||||
|
return logger.debug(`Discord: Lacking UploadFiles permission; refusing to send`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(channel.havePermission('Masquerade'))) {
|
||||||
return logger.debug(`Discord: Lacking Masquerade permission; refusing to send`);
|
return logger.debug(`Discord: Lacking Masquerade permission; refusing to send`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,6 +214,33 @@ client.on('messageCreate', async message => {
|
||||||
|
|
||||||
// Replaces @mentions and #channel mentions
|
// Replaces @mentions and #channel mentions
|
||||||
async function renderMessageBody(message: string): Promise<string> {
|
async function renderMessageBody(message: string): Promise<string> {
|
||||||
|
|
||||||
|
// Replace Tenor URLs so they render properly.
|
||||||
|
// We have to download the page first, then extract
|
||||||
|
// the `c.tenor.com` URL from the meta tags.
|
||||||
|
// Could query autumn but that's too much effort and I already wrote this.
|
||||||
|
if (RE_TENOR.test(message)) {
|
||||||
|
try {
|
||||||
|
logger.debug('Replacing tenor URL');
|
||||||
|
|
||||||
|
const res = await axios.get(
|
||||||
|
message,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
'User-Agent': 'AutoMod/1.0; https://github.com/janderedev/automod',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const metaTag = RE_TENOR_META.exec(res.data as string)?.[0];
|
||||||
|
if (metaTag) {
|
||||||
|
return metaTag
|
||||||
|
.replace('<meta class="dynamic" property="og:url" content="', '')
|
||||||
|
.replace('">', '');
|
||||||
|
}
|
||||||
|
} catch(e) { logger.warn(`Replacing tenor URL failed: ${e}`) }
|
||||||
|
}
|
||||||
|
|
||||||
// @mentions
|
// @mentions
|
||||||
message = await smartReplace(message, RE_MENTION_USER, async (match: string) => {
|
message = await smartReplace(message, RE_MENTION_USER, async (match: string) => {
|
||||||
const id = match.replace('<@!', '').replace('<@', '').replace('>', '');
|
const id = match.replace('<@!', '').replace('<@', '').replace('>', '');
|
||||||
|
|
|
@ -4,7 +4,9 @@ import { logger } from '..';
|
||||||
|
|
||||||
let AUTUMN_URL = `http://autumnUrl`;
|
let AUTUMN_URL = `http://autumnUrl`;
|
||||||
|
|
||||||
const client = new Client({ });
|
const client = new Client({
|
||||||
|
apiURL: process.env.REVOLT_API_URL,
|
||||||
|
});
|
||||||
|
|
||||||
const login = () => new Promise((resolve: (value: Client) => void) => {
|
const login = () => new Promise((resolve: (value: Client) => void) => {
|
||||||
client.loginBot(process.env['REVOLT_TOKEN']!);
|
client.loginBot(process.env['REVOLT_TOKEN']!);
|
||||||
|
|
|
@ -43,7 +43,7 @@ client.on('message/delete', async id => {
|
||||||
});
|
});
|
||||||
|
|
||||||
client.on('message/update', async message => {
|
client.on('message/update', async message => {
|
||||||
if (message.content && typeof message.content != 'string') return;
|
if (!message.content || typeof message.content != 'string') return;
|
||||||
if (message.author_id == client.user?._id) return;
|
if (message.author_id == client.user?._id) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -37,10 +37,10 @@
|
||||||
node-fetch "^2.6.7"
|
node-fetch "^2.6.7"
|
||||||
tslib "^2.3.1"
|
tslib "^2.3.1"
|
||||||
|
|
||||||
"@insertish/exponential-backoff@3.1.0-patch.0":
|
"@insertish/exponential-backoff@3.1.0-patch.2":
|
||||||
version "3.1.0-patch.0"
|
version "3.1.0-patch.2"
|
||||||
resolved "https://registry.yarnpkg.com/@insertish/exponential-backoff/-/exponential-backoff-3.1.0-patch.0.tgz#1fff134f70fc0906d11d09069d51183b542e42cf"
|
resolved "https://registry.yarnpkg.com/@insertish/exponential-backoff/-/exponential-backoff-3.1.0-patch.2.tgz#08310c856b795c783a832f3f608c0feaff262c0d"
|
||||||
integrity sha512-1qhW81s3GDbssyaxRWdpBAn1cIw5s393HnrdYFjfa2i6rq3SEjQDK6U80g6dq/K0or6JRr2eCn75Wfc1IrGM0g==
|
integrity sha512-0lsMVexkZ7dHpQlPrTZDRsm42hZ4/CzKxP1hbAEJH8IaEwrIEhhTKJuFxPuLOi2TwPImuocncjYHpGpwVNOemQ==
|
||||||
|
|
||||||
"@insertish/isomorphic-ws@^4.0.1":
|
"@insertish/isomorphic-ws@^4.0.1":
|
||||||
version "4.0.1"
|
version "4.0.1"
|
||||||
|
@ -57,20 +57,31 @@
|
||||||
axios "^0.26.1"
|
axios "^0.26.1"
|
||||||
openapi-typescript "^5.2.0"
|
openapi-typescript "^5.2.0"
|
||||||
|
|
||||||
"@janderedev/revolt.js@^5.2.8-patch.2":
|
"@insertish/oapi@0.1.15":
|
||||||
version "5.2.8-patch.2"
|
version "0.1.15"
|
||||||
resolved "https://registry.yarnpkg.com/@janderedev/revolt.js/-/revolt.js-5.2.8-patch.2.tgz#d74a6500e217a4cb94d139027dec2acb71f73a0f"
|
resolved "https://registry.yarnpkg.com/@insertish/oapi/-/oapi-0.1.15.tgz#ee58b82d879ed5af54db846699941b8ad0262e7b"
|
||||||
integrity sha512-2nucMuToKC5F4jsajmTauBaV9Q7oyl1KWKF0ysYYPzEKxK9LfPL560v9bQR/ff1g8GkEv4biAN/A17MCcddAuw==
|
integrity sha512-2G8eFxrojF651tBoRutQ8CJOw0u8UjYSlw/LQU+xycw5KpXslhWp/KSR86uIFyDIPddwfMCNA91vwHGCFRA63w==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@insertish/exponential-backoff" "3.1.0-patch.0"
|
typescript "^4.6.2"
|
||||||
|
optionalDependencies:
|
||||||
|
axios "^0.26.1"
|
||||||
|
openapi-typescript "^5.2.0"
|
||||||
|
|
||||||
|
"@janderedev/revolt.js@^6.0.0-rc.21":
|
||||||
|
version "6.0.0-rc.21"
|
||||||
|
resolved "https://registry.yarnpkg.com/@janderedev/revolt.js/-/revolt.js-6.0.0-rc.21.tgz#0629700cd78d0f7db5f4707dc7a8f5ba67482e1a"
|
||||||
|
integrity sha512-uLFXrv6ZjLJ+e9keevv0sUeZY8gDw3RfSg07LNYVUfqi1T64WwmZypz3zc2kTacbfthIgI368K2e6f3q4toc4Q==
|
||||||
|
dependencies:
|
||||||
|
"@insertish/exponential-backoff" "3.1.0-patch.2"
|
||||||
"@insertish/isomorphic-ws" "^4.0.1"
|
"@insertish/isomorphic-ws" "^4.0.1"
|
||||||
axios "^0.21.4"
|
axios "^0.21.4"
|
||||||
eventemitter3 "^4.0.7"
|
eventemitter3 "^4.0.7"
|
||||||
lodash.defaultsdeep "^4.6.1"
|
lodash.defaultsdeep "^4.6.1"
|
||||||
lodash.flatten "^4.4.0"
|
lodash.flatten "^4.4.0"
|
||||||
lodash.isequal "^4.5.0"
|
lodash.isequal "^4.5.0"
|
||||||
|
long "^5.2.0"
|
||||||
mobx "^6.3.2"
|
mobx "^6.3.2"
|
||||||
revolt-api "0.5.3-alpha.12"
|
revolt-api "0.5.3-rc.15"
|
||||||
ulid "^2.3.0"
|
ulid "^2.3.0"
|
||||||
ws "^8.2.2"
|
ws "^8.2.2"
|
||||||
|
|
||||||
|
@ -342,6 +353,11 @@ log75@^2.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
ansi-colors "^4.1.1"
|
ansi-colors "^4.1.1"
|
||||||
|
|
||||||
|
long@^5.2.0:
|
||||||
|
version "5.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/long/-/long-5.2.0.tgz#2696dadf4b4da2ce3f6f6b89186085d94d52fd61"
|
||||||
|
integrity sha512-9RTUNjK60eJbx3uz+TEGF7fUr29ZDxR5QzXcyDpeSfeH28S9ycINflOgOlppit5U+4kNTe83KQnMEerw7GmE8w==
|
||||||
|
|
||||||
memory-pager@^1.0.2:
|
memory-pager@^1.0.2:
|
||||||
version "1.5.0"
|
version "1.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/memory-pager/-/memory-pager-1.5.0.tgz#d8751655d22d384682741c972f2c3d6dfa3e66b5"
|
resolved "https://registry.yarnpkg.com/memory-pager/-/memory-pager-1.5.0.tgz#d8751655d22d384682741c972f2c3d6dfa3e66b5"
|
||||||
|
@ -499,10 +515,14 @@ require-at@^1.0.6:
|
||||||
resolved "https://registry.yarnpkg.com/require-at/-/require-at-1.0.6.tgz#9eb7e3c5e00727f5a4744070a7f560d4de4f6e6a"
|
resolved "https://registry.yarnpkg.com/require-at/-/require-at-1.0.6.tgz#9eb7e3c5e00727f5a4744070a7f560d4de4f6e6a"
|
||||||
integrity sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==
|
integrity sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==
|
||||||
|
|
||||||
revolt-api@0.5.3-alpha.12:
|
revolt-api@0.5.3-rc.15:
|
||||||
version "0.5.3-alpha.12"
|
version "0.5.3-rc.15"
|
||||||
resolved "https://registry.yarnpkg.com/revolt-api/-/revolt-api-0.5.3-alpha.12.tgz#78f25b567b840c1fd072595526592a422cb01f25"
|
resolved "https://registry.yarnpkg.com/revolt-api/-/revolt-api-0.5.3-rc.15.tgz#abd08dd8109d0ca31be118461eabbeb6c3b7792e"
|
||||||
integrity sha512-MM42oI5+5JJMnAs3JiOwSQOy/SUYzYs3M8YRC5QI4G6HU7CfyB2HNWh5jFsyRlcLdSi13dGazHm31FUPHsxOzw==
|
integrity sha512-MYin3U+KoObNkILPf2cz+FPperynExkUu7CjzurMJCRvBncpnhb2czvWDvnhLDKBHlpo8W597xNqzQnaklV4ug==
|
||||||
|
dependencies:
|
||||||
|
"@insertish/oapi" "0.1.15"
|
||||||
|
axios "^0.26.1"
|
||||||
|
lodash.defaultsdeep "^4.6.1"
|
||||||
|
|
||||||
revolt-api@^0.5.3-rc.8:
|
revolt-api@^0.5.3-rc.8:
|
||||||
version "0.5.3-rc.8"
|
version "0.5.3-rc.8"
|
||||||
|
|
|
@ -23,6 +23,7 @@ services:
|
||||||
- BOT_METRICS_MSG_PING_CHANNEL
|
- BOT_METRICS_MSG_PING_CHANNEL
|
||||||
- BOT_STATUS
|
- BOT_STATUS
|
||||||
- BOT_STATUS_INTERVAL
|
- BOT_STATUS_INTERVAL
|
||||||
|
- API_URL
|
||||||
# Uncomment if you enabled Prometheus metrics
|
# Uncomment if you enabled Prometheus metrics
|
||||||
#ports:
|
#ports:
|
||||||
# - 127.0.0.1:${BOT_METRICS_PORT}:${BOT_METRICS_PORT}
|
# - 127.0.0.1:${BOT_METRICS_PORT}:${BOT_METRICS_PORT}
|
||||||
|
@ -53,6 +54,7 @@ services:
|
||||||
- DB_STRING=mongodb://mogus:${DB_PASS}@mongo:27017/admin
|
- DB_STRING=mongodb://mogus:${DB_PASS}@mongo:27017/admin
|
||||||
- NODE_ENV=production
|
- NODE_ENV=production
|
||||||
- BRIDGE_METRICS_PORT
|
- BRIDGE_METRICS_PORT
|
||||||
|
- REVOLT_API_URL=${API_URL}
|
||||||
# Uncomment if you enabled Prometheus metrics
|
# Uncomment if you enabled Prometheus metrics
|
||||||
#ports:
|
#ports:
|
||||||
# - 127.0.0.1:${BRIDGE_METRICS_PORT}:${BRIDGE_METRICS_PORT}
|
# - 127.0.0.1:${BRIDGE_METRICS_PORT}:${BRIDGE_METRICS_PORT}
|
||||||
|
|
Loading…
Reference in a new issue