diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 177685ea..3c7e328f 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -48,25 +48,24 @@ type HubModerator { // spamFilter Boolean @default(true) // } +type hubBlacklist { + reason String + expires DateTime? + hubId String @db.ObjectId +} + model blacklistedServers { - id String @id @default(auto()) @map("_id") @db.ObjectId - serverId String + id String @id @default(auto()) @map("_id") @db.ObjectId + serverId String @unique serverName String - expires DateTime? - reason String - hub hubs @relation(fields: [hubId], references: [id]) - hubId String @db.ObjectId + hubs hubBlacklist[] } model blacklistedUsers { - id String @id @default(auto()) @map("_id") @db.ObjectId - userId String @unique - notified Boolean - reason String - expires DateTime? + id String @id @default(auto()) @map("_id") @db.ObjectId + userId String @unique username String - hub hubs @relation(fields: [hubId], references: [id]) - hubId String @db.ObjectId + hubs hubBlacklist[] } model connectedList { @@ -103,8 +102,6 @@ model hubs { messages messageData[] moderators HubModerator[] connections connectedList[] - blacklistedUsers blacklistedUsers[] - blacklistedServers blacklistedServers[] // approved Boolean @default(false) // official Boolean @default(false) } diff --git a/src/Commands/Apps/blacklist.ts b/src/Commands/Apps/blacklist.ts new file mode 100644 index 00000000..7f87b0b2 --- /dev/null +++ b/src/Commands/Apps/blacklist.ts @@ -0,0 +1,154 @@ +import { ActionRowBuilder, ApplicationCommandType, ButtonBuilder, ButtonStyle, ContextMenuCommandBuilder, EmbedBuilder, MessageContextMenuCommandInteraction, ModalBuilder, TextInputBuilder, TextInputStyle } from 'discord.js'; +import { getDb } from '../../Utils/utils'; +import { captureException } from '@sentry/node'; +import { addServerBlacklist, addUserBlacklist, scheduleUnblacklist } from '../../Utils/blacklist'; +import emojis from '../../Utils/JSON/emoji.json'; + +export default { + description: 'Blacklist the user or server that sent the message from the hub.', + data: new ContextMenuCommandBuilder() + .setName('Add to Blacklist') + .setType(ApplicationCommandType.Message) + .setDMPermission(false), + async execute(interaction: MessageContextMenuCommandInteraction) { + const db = getDb(); + const messageInDb = await db.messageData.findFirst({ where: { + channelAndMessageIds: { some: { messageId: interaction.targetId } }, + hub: { + OR: [ + { moderators: { some: { userId: interaction.user.id } } }, + { ownerId: interaction.user.id }, + ], + }, + }, + }); + + if (!messageInDb) return interaction.reply({ content: 'This message was not sent in the network or has expired.', ephemeral: true }); + + const embed = new EmbedBuilder() + .setTitle('Blacklist') + .setDescription('Blacklist a user or server from this hub. This will prevent them from sending messages in this hub.') + .setColor('Blurple'); + + const buttons = new ActionRowBuilder() + .addComponents( + new ButtonBuilder() + .setCustomId('blacklist_user') + .setLabel('Blacklist User') + .setStyle(ButtonStyle.Secondary) + .setEmoji('👤'), + new ButtonBuilder() + .setCustomId('blacklist_server') + .setLabel('Blacklist Server') + .setStyle(ButtonStyle.Secondary) + .setEmoji('🏠'), + ); + + const reply = await interaction.reply({ embeds: [embed], components: [buttons] }); + + const collector = reply.createMessageComponentCollector({ filter: (i) => i.user.id === interaction.user.id, idle: 60000 }); + collector.on('collect', async (i) => { + if (!messageInDb.hubId) return; + + const modal = new ModalBuilder() + .setTitle('Blacklist') + .setCustomId(i.id) + .addComponents( + new ActionRowBuilder().addComponents( + new TextInputBuilder() + .setCustomId('reason') + .setLabel('Reason') + .setPlaceholder('What is the reason for this blacklist?') + .setStyle(TextInputStyle.Paragraph) + .setMaxLength(500), + ), + new ActionRowBuilder().addComponents( + new TextInputBuilder() + .setCustomId('minutes') + .setLabel('Minutes') + .setPlaceholder('How many minutes should this blacklist last?') + .setStyle(TextInputStyle.Short) + .setMaxLength(2) + .setRequired(false), + ), + new ActionRowBuilder().addComponents( + new TextInputBuilder() + .setCustomId('hours') + .setLabel('Hours') + .setPlaceholder('How many hours should this blacklist last?') + .setStyle(TextInputStyle.Short) + .setMaxLength(2) + .setRequired(false), + ), + new ActionRowBuilder().addComponents( + new TextInputBuilder() + .setCustomId('days') + .setLabel('Days') + .setPlaceholder('How many days should this blacklist last?') + .setStyle(TextInputStyle.Short) + .setMaxLength(2) + .setRequired(false), + ), + ); + + await i.showModal(modal); + + const modalResp = await i.awaitModalSubmit({ time: 60000 }) + .catch((e) => { + !e.message.includes('with reason: time') ? captureException(e) : null; + return null; + }); + + if (modalResp?.customId !== i.id) return; + + await modalResp.deferUpdate(); + + const reason = modalResp.fields.getTextInputValue('reason'); + const mins = parseInt(modalResp.fields.getTextInputValue('minutes')) || 0; + const hours = parseInt(modalResp.fields.getTextInputValue('hours')) || 0; + const days = parseInt(modalResp.fields.getTextInputValue('days')) || 0; + + let expires = undefined; + if (mins || hours || days) expires = new Date(); + if (mins) expires?.setMinutes(expires.getMinutes() + mins); + if (hours) expires?.setHours(expires.getHours() + hours); + if (days) expires?.setDate(expires.getDate() + days); + + const successEmbed = new EmbedBuilder() + .setColor('Green') + .addFields( + { + name: 'Reason', + value: reason ? reason : 'No reason provided.', + inline: true, + }, + { + name: 'Expires', + value: expires ? `` : 'Never.', + inline: true, + }, + ); + + + if (i.customId === 'blacklist_user') { + const user = await i.client.users.fetch(messageInDb.authorId).catch(() => null); + successEmbed.setDescription(`${emojis.normal.tick} **${user?.username}** has been successfully blacklisted!`); + await addUserBlacklist(messageInDb.hubId, i.user, messageInDb.authorId, reason, expires); + + if (expires) scheduleUnblacklist('user', i.client, messageInDb.authorId, messageInDb.hubId, expires); + + await modalResp.editReply({ embeds: [successEmbed], components: [] }); + } + + else if (i.customId === 'blacklist_server') { + successEmbed.setDescription(`${emojis.normal.tick} **${i.client.guilds.cache.get(messageInDb.serverId)?.name}** has been successfully blacklisted!`); + await addServerBlacklist(messageInDb.serverId, i.user, messageInDb.hubId, reason, expires); + await db.connectedList.deleteMany({ where: { serverId: messageInDb.serverId, hubId: messageInDb.hubId } }); + + if (expires) scheduleUnblacklist('server', i.client, messageInDb.serverId, messageInDb.hubId, expires); + + await modalResp.editReply({ embeds: [successEmbed], components: [] }); + } + }); + }, +}; diff --git a/src/Commands/Apps/report.ts b/src/Commands/Apps/report.ts index 60490abe..01c98ed7 100644 --- a/src/Commands/Apps/report.ts +++ b/src/Commands/Apps/report.ts @@ -150,11 +150,13 @@ export default { if (!e.message.includes('with reason: time')) { logger.error(e); captureException(e); + interaction.followUp({ content: `${emojis.normal.no} An error occored while making the report.`, ephemeral: true, }); } + return null; }); }); }, diff --git a/src/Commands/Network/blacklist.ts b/src/Commands/Network/blacklist.ts index 8494a648..b60a3407 100644 --- a/src/Commands/Network/blacklist.ts +++ b/src/Commands/Network/blacklist.ts @@ -100,11 +100,6 @@ export default { .setDescription('The user to remove from the blacklist. User tag also works.') .setAutocomplete(true) .setRequired(true), - ) - .addStringOption(string => - string - .setName('reason') - .setDescription('The reason for blacklisting the server.'), ), ) .addSubcommand(subcommand => @@ -124,11 +119,6 @@ export default { .setDescription('The server to remove from the blacklist.') .setAutocomplete(true) .setRequired(true), - ) - .addStringOption(string => - string - .setName('reason') - .setDescription('The reason for blacklisting the server.'), ), ), ) @@ -204,16 +194,21 @@ export default { const userOpt = interaction.options.get('user'); if (!userOpt?.focused || typeof userOpt.value !== 'string') return; + const userHubMod = await db.hubs.findFirst({ + where: { + name: focusedHub.value, + OR: [ + { ownerId: interaction.user.id }, + { moderators: { some: { userId: interaction.user.id } } }, + ], + }, + }); + + if (!userHubMod) return interaction.respond([]); const filteredUsers = await db.blacklistedUsers.findMany({ where: { - hub: { - name: focusedHub.value, - OR: [ - { ownerId: interaction.user.id }, - { moderators: { some: { userId: interaction.user.id } } }, - ], - }, + hubs: { some: { hubId: userHubMod.id } }, OR: [ { username: { mode: 'insensitive', contains: userOpt.value } }, { userId: { mode: 'insensitive', contains: userOpt.value } }, @@ -228,18 +223,21 @@ export default { } case 'server': { const serverOpt = interaction.options.get('server', true); + const serverHubMod = await db.hubs.findFirst({ + where: { + name: focusedHub.value, + OR: [ + { ownerId: interaction.user.id }, + { moderators: { some: { userId: interaction.user.id } } }, + ], + }, + }); + if (!serverOpt.focused || typeof serverOpt.value !== 'string' || !serverHubMod) return; - if (!serverOpt.focused || typeof serverOpt.value !== 'string') return; const allServers = await db.blacklistedServers.findMany({ where: { - hub: { - name: focusedHub.value, - OR: [ - { ownerId: interaction.user.id }, - { moderators: { some: { userId: interaction.user.id } } }, - ], - }, + hubs: { some: { hubId: serverHubMod.id } }, OR: [ { serverName: { mode: 'insensitive', contains: serverOpt.value } }, { serverId: { mode: 'insensitive', contains: serverOpt.value } }, diff --git a/src/Events/messageReactionAdd.ts b/src/Events/messageReactionAdd.ts index 0bca3918..62850c58 100644 --- a/src/Events/messageReactionAdd.ts +++ b/src/Events/messageReactionAdd.ts @@ -2,6 +2,7 @@ import { MessageReaction, PartialMessageReaction, PartialUser, User } from 'disc import { getDb } from '../Utils/utils'; import updateMessageReactions from '../Scripts/reactions/updateMessage'; import { HubSettingsBitField } from '../Utils/hubSettingsBitfield'; +import { findBlacklistedServer, findBlacklistedUser } from '../Utils/blacklist'; export default { name: 'messageReactionAdd', @@ -17,19 +18,14 @@ export default { if ( !messageInDb?.hub || !messageInDb?.hubId || - !new HubSettingsBitField(messageInDb.hub?.settings).has('Reactions') + !new HubSettingsBitField(messageInDb.hub?.settings).has('Reactions') || + !reaction.message.inGuild() ) return; - const userBlacklisted = await db.blacklistedUsers.findFirst({ - where: { userId: user.id, hubId: messageInDb.hubId }, - }); - const serverBlacklisted = await db.blacklistedServers.findFirst({ - where: { serverId: reaction.message.guild?.id, hubId: messageInDb.hubId }, - }); - + const userBlacklisted = await findBlacklistedUser(messageInDb.hubId, user.id); + const serverBlacklisted = await findBlacklistedServer(messageInDb.hubId, reaction.message.guild.id); if (userBlacklisted || serverBlacklisted) return; - const cooldown = reaction.client.reactionCooldowns.get(user.id); if (cooldown && cooldown > Date.now()) return; reaction.client.reactionCooldowns.set(user.id, Date.now() + 5000); diff --git a/src/Scripts/blacklist/list.ts b/src/Scripts/blacklist/list.ts index 38845bce..c2857cfb 100644 --- a/src/Scripts/blacklist/list.ts +++ b/src/Scripts/blacklist/list.ts @@ -20,15 +20,16 @@ module.exports = { // repeat until you reach the end if (serverOpt == 'server') { - const result = await getDb().blacklistedServers.findMany({ where: { hubId: hub.id } }); + const result = await getDb().blacklistedServers.findMany({ where: { hubs: { some: { hubId: hub.id } } } }); result.forEach((data, index) => { + const hubData = data.hubs.find(({ hubId }) => hubId === hub.id); fields.push({ name: data.serverName, value: stripIndents` **ServerId:** ${data.serverId} - **Reason:** ${data.reason} - **Expires:** ${!data.expires ? 'Never.' : ``} + **Reason:** ${hubData?.reason} + **Expires:** ${!hubData?.expires ? 'Never.' : ``} `, }); @@ -48,15 +49,17 @@ module.exports = { }); } else if (serverOpt == 'user') { - const result = await getDb().blacklistedUsers.findMany({ where: { hubId: hub.id } }); + const result = await getDb().blacklistedUsers.findMany({ where: { hubs: { some: { hubId: hub.id } } } }); result.forEach((data, index) => { + const hubData = data.hubs.find(({ hubId }) => hubId === hub.id); + fields.push({ name: data.username, value: stripIndents` **UserID:** ${data.userId} - **Reason:** ${data.reason} - **Expires:** ${!data.expires ? 'Never.' : ``} + **Reason:** ${hubData?.reason} + **Expires:** ${!hubData?.expires ? 'Never.' : ``} `, }); diff --git a/src/Scripts/blacklist/server.ts b/src/Scripts/blacklist/server.ts index 66bf54f8..7ed4c7a7 100644 --- a/src/Scripts/blacklist/server.ts +++ b/src/Scripts/blacklist/server.ts @@ -4,7 +4,7 @@ import { logger } from '@sentry/utils'; import { ChatInputCommandInteraction } from 'discord.js'; import { getDb } from '../../Utils/utils'; import { modActions } from '../networkLogs/modActions'; -import { addServerBlacklist, notifyBlacklist, scheduleUnblacklist } from '../../Utils/blacklist'; +import { addServerBlacklist, notifyBlacklist, removeBlacklist, scheduleUnblacklist } from '../../Utils/blacklist'; export default { async execute(interaction: ChatInputCommandInteraction, hub: hubs) { @@ -60,19 +60,17 @@ export default { } } else if (subCommandGroup == 'remove') { - const reason = interaction.options.getString('reason'); if (!serverInBlacklist) return await interaction.reply({ content: 'The server is not blacklisted.', ephemeral: true }); - await blacklistedServers.deleteMany({ where: { serverId: serverOpt, hubId: hub.id } }); + await removeBlacklist('server', hub.id, serverInBlacklist.serverId); // Using name from DB since the bot can't access server through API. interaction.reply(`The server **${serverInBlacklist.serverName}** has been removed from the blacklist.`); modActions(interaction.user, { - serverId: serverInBlacklist.serverId, - serverName: serverInBlacklist.serverName, action: 'unblacklistServer', + oldBlacklist: serverInBlacklist, + hubId: hub.id, timestamp: new Date(), - reason, }); } }, diff --git a/src/Scripts/blacklist/user.ts b/src/Scripts/blacklist/user.ts index c026712a..39e77802 100644 --- a/src/Scripts/blacklist/user.ts +++ b/src/Scripts/blacklist/user.ts @@ -1,9 +1,8 @@ import { ChatInputCommandInteraction, EmbedBuilder } from 'discord.js'; -import { cancelJob } from 'node-schedule'; import { getDb } from '../../Utils/utils'; import { modActions } from '../networkLogs/modActions'; +import { addUserBlacklist, removeBlacklist, scheduleUnblacklist } from '../../Utils/blacklist'; import emojis from '../../Utils/JSON/emoji.json'; -import { addUserBlacklist, scheduleUnblacklist } from '../../Utils/blacklist'; export default { async execute(interaction: ChatInputCommandInteraction) { @@ -34,8 +33,9 @@ export default { }, }); if (!hubInDb) return await interaction.reply('Hub with that name not found. Or you are not a moderator of that hub.'); + const userInBlacklist = await db.blacklistedUsers.findFirst({ where: { userId: user.id, hubs: { some: { hubId: hubInDb.id } } } }); + - const userInBlacklist = await db.blacklistedUsers.findFirst({ where: { userId: user.id } }); if (subcommandGroup == 'add') { await interaction.deferReply(); @@ -84,15 +84,14 @@ export default { if (!userInBlacklist) return interaction.reply(`The user **@${user.username}** is not blacklisted.`); const userBeforeUnblacklist = await db.blacklistedUsers.findFirst({ where: { userId: user.id } }); - await db.blacklistedUsers.delete({ where: { userId: user.id } }); - interaction.reply(`**${user.username}** has been removed from the blacklist.`); + await removeBlacklist('user', hubInDb.id, user.id); + await interaction.reply(`**${user.username}** has been removed from the blacklist.`); - cancelJob(`blacklist-${user.id}`); modActions(interaction.user, { user, action: 'unblacklistUser', - blacklistReason: userBeforeUnblacklist?.reason, - reason, + blacklistedFor: userBeforeUnblacklist?.hubs.find(({ hubId }) => hubId === hubInDb.id)?.reason, + hubId: hubInDb.id, }); } }, diff --git a/src/Scripts/hub/join.ts b/src/Scripts/hub/join.ts index 45c1acc8..c2517207 100644 --- a/src/Scripts/hub/join.ts +++ b/src/Scripts/hub/join.ts @@ -4,117 +4,110 @@ import createConnection from '../network/createConnection'; import displaySettings from '../network/displaySettings'; import emojis from '../../Utils/JSON/emoji.json'; import onboarding from '../network/onboarding'; +import { findBlacklistedServer, findBlacklistedUser } from '../../Utils/blacklist'; -export async function execute(interaction: ChatInputCommandInteraction) { - if (!interaction.inCachedGuild()) return; - - const db = getDb(); - const name = interaction.options.getString('name') || undefined; - const invite = interaction.options.getString('invite') || undefined; - const channel = interaction.options.getChannel('channel', true, [ChannelType.GuildText, ChannelType.PublicThread, ChannelType.PrivateThread]); - let hubExists; - - if (!interaction.member.permissionsIn(channel).has(['ManageChannels'])) { - return await interaction.reply({ - content: `${emojis.normal.no} You need to have the \`Manage Channels\` permission in ${channel} to connect it to a hub!`, - ephemeral: true, - }); - } - - if (!invite && !name) { - return await interaction.reply({ - content: `${emojis.normal.no} You need to provide either a hub name or invite!`, - ephemeral: true, - }); - } - const channelConnected = await db.connectedList.findFirst({ where: { channelId: channel.id } }); - if (channelConnected) { - return await interaction.reply({ - content: `${channel} is already part of a hub! Please leave the hub or choose a different channel.`, - ephemeral: true, - }); - } - - if (invite) { - const inviteExists = await db.hubInvites.findFirst({ - where: { code: invite }, - include: { hub: { include: { connections: true } } }, - }); - - if (!inviteExists) { +export default { + async execute(interaction: ChatInputCommandInteraction) { + if (!interaction.inCachedGuild()) return; + + const db = getDb(); + const name = interaction.options.getString('name') || undefined; + const invite = interaction.options.getString('invite') || undefined; + const channel = interaction.options.getChannel('channel', true, [ChannelType.GuildText, ChannelType.PublicThread, ChannelType.PrivateThread]); + let hubExists; + + if (!interaction.member.permissionsIn(channel).has(['ManageChannels'])) { return await interaction.reply({ - content: `${emojis.normal.no} Invalid invite code. Please recheck if that code is correct.`, + content: `${emojis.normal.no} You need to have the \`Manage Channels\` permission in ${channel} to connect it to a hub!`, ephemeral: true, }); } - const guildInHub = inviteExists.hub.connections.find((c) => c.serverId === channel.guildId); - if (guildInHub) { + + if (!invite && !name) { return await interaction.reply({ - content: `This server has already joined hub **${inviteExists.hub.name}** from <#${guildInHub.channelId}>! Please leave the hub from that channel first, or change the channel using \`/network manage\`.!`, + content: `${emojis.normal.no} You need to provide either a hub name or invite!`, ephemeral: true, }); } - - hubExists = inviteExists?.hub; - } - - else if (name) { - hubExists = await db.hubs.findFirst({ - where: { name }, - include: { connections: true }, - }); - - if (!hubExists) { + const channelConnected = await db.connectedList.findFirst({ where: { channelId: channel.id } }); + if (channelConnected) { return await interaction.reply({ - content: `${emojis.normal.no} Unable to find a hub with that name!`, + content: `${channel} is already part of a hub! Please leave the hub or choose a different channel.`, ephemeral: true, }); } - const guildInHub = hubExists.connections.find(c => c.serverId === channel.guildId); - if (guildInHub) { - return await interaction.reply({ - content: `This server has already joined hub **${hubExists?.name}** from <#${guildInHub.channelId}>! Please leave the hub from that channel first, or change the channel using \`/network manage\`.`, - ephemeral: true, + if (invite) { + const inviteExists = await db.hubInvites.findFirst({ + where: { code: invite }, + include: { hub: { include: { connections: true } } }, }); + + if (!inviteExists) { + return await interaction.reply({ + content: `${emojis.normal.no} Invalid invite code. Please recheck if that code is correct.`, + ephemeral: true, + }); + } + const guildInHub = inviteExists.hub.connections.find((c) => c.serverId === channel.guildId); + if (guildInHub) { + return await interaction.reply({ + content: `This server has already joined hub **${inviteExists.hub.name}** from <#${guildInHub.channelId}>! Please leave the hub from that channel first, or change the channel using \`/network manage\`.!`, + ephemeral: true, + }); + } + + hubExists = inviteExists?.hub; } - // the only way to join a private hub is through it's invite code - if (hubExists?.private && !invite) { - return await interaction.reply({ - content: `${emojis.normal.no} Unable to find a hub with that name!`, - ephemeral: true, + else if (name) { + hubExists = await db.hubs.findFirst({ + where: { name }, + include: { connections: true }, }); + + if (!hubExists) { + return await interaction.reply({ + content: `${emojis.normal.no} Unable to find a hub with that name!`, + ephemeral: true, + }); + } + + const guildInHub = hubExists.connections.find(c => c.serverId === channel.guildId); + if (guildInHub) { + return await interaction.reply({ + content: `This server has already joined hub **${hubExists?.name}** from <#${guildInHub.channelId}>! Please leave the hub from that channel first, or change the channel using \`/network manage\`.`, + ephemeral: true, + }); + } + + // the only way to join a private hub is through it's invite code + if (hubExists?.private && !invite) { + return await interaction.reply({ + content: `${emojis.normal.no} Unable to find a hub with that name!`, + ephemeral: true, + }); + } + } + + if (!hubExists) return interaction.reply({ content: 'An error occured.', ephemeral: true }); + + + const serverInBlacklist = await findBlacklistedServer(hubExists.id, channel.guildId); + if (serverInBlacklist) { + await interaction.reply('This server is blacklisted from joining this hub.'); + return; + } + + const userInBlacklist = await findBlacklistedUser(hubExists.id, interaction.user.id); + if (userInBlacklist) { + await interaction.reply('You have been blacklisted from joining this hub.'); + return; } - } - - if (!hubExists) return interaction.reply({ content: 'An error occured.', ephemeral: true }); - - - const serverInBlacklist = await db.blacklistedServers.findFirst({ - where: { - serverId: interaction.guild?.id, - hubId: hubExists.id, - }, - }); - if (serverInBlacklist) { - await interaction.reply('This server is blacklisted from joining this hub.'); - return; - } - - const userInBlacklist = await db.blacklistedUsers.findFirst({ - where: { - hubId: hubExists.id, - userId: interaction.user.id, - }, - }); - if (userInBlacklist) { - await interaction.reply('You have been blacklisted from joining this hub.'); - return; - } - - if (!onboarding.execute(interaction, hubExists.name, channel.id)) return; - - const created = await createConnection.execute(interaction, hubExists, channel); - if (created) await displaySettings.execute(interaction, created.channelId); -} + + if (!onboarding.execute(interaction, hubExists.name, channel.id)) return; + + const created = await createConnection.execute(interaction, hubExists, channel); + if (created) await displaySettings.execute(interaction, created.channelId); + }, +}; \ No newline at end of file diff --git a/src/Scripts/hub/manage.ts b/src/Scripts/hub/manage.ts index f0662736..ba682f3d 100644 --- a/src/Scripts/hub/manage.ts +++ b/src/Scripts/hub/manage.ts @@ -1,4 +1,4 @@ -import { blacklistedServers, blacklistedUsers, connectedList, hubs } from '@prisma/client'; +import { connectedList, hubs } from '@prisma/client'; import { captureException } from '@sentry/node'; import { logger } from '@sentry/utils'; import { ActionRowBuilder, ChatInputCommandInteraction, ComponentType, EmbedBuilder, ModalBuilder, StringSelectMenuBuilder, TextInputBuilder, TextInputStyle } from 'discord.js'; @@ -20,11 +20,7 @@ export default { { moderators: { some: { userId: interaction.user.id, position: 'manager' } } }, ], }, - include: { - connections: true, - blacklistedServers: true, - blacklistedUsers: true, - }, + include: { connections: true }, }); if (!hubInDb) { @@ -70,7 +66,13 @@ export default { ); - const hubEmbed = (hub: hubs & { connections: connectedList[], blacklistedUsers: blacklistedUsers[], blacklistedServers: blacklistedServers[] }) => { + const hubEmbed = async (hub: hubs & { connections: connectedList[] }) => { + const hubBlacklistedUsers = await db.blacklistedUsers.count({ + where: { hubs: { some: { hubId: hub.id } } }, + }); + const hubBlacklistedServers = await db.blacklistedServers.count({ + where: { hubs: { some: { hubId: hub.id } } }, + }); return new EmbedBuilder() .setTitle(hub.name) .setColor('Random') @@ -85,8 +87,8 @@ export default { { name: 'Blacklists', value: stripIndents` - - Users: ${hub.blacklistedUsers.length.toString()} - - Servers: ${hub.blacklistedServers.length.toString()} + - Users: ${hubBlacklistedUsers} + - Servers: ${hubBlacklistedServers} `, inline: true, }, @@ -105,7 +107,7 @@ export default { }; const reply = await interaction.followUp({ - embeds: [hubEmbed(hubInDb)], + embeds: [await hubEmbed(hubInDb)], components: [actionsSelect], }); @@ -120,11 +122,7 @@ export default { hubInDb = await db.hubs.findFirst({ where: { id: hubInDb?.id }, - include: { - connections: true, - blacklistedServers: true, - blacklistedUsers: true, - }, + include: { connections: true }, }); if (!hubInDb) { @@ -359,14 +357,10 @@ export default { hubInDb = await db.hubs.findFirst({ where: { id: hubInDb?.id }, - include: { - connections: true, - blacklistedServers: true, - blacklistedUsers: true, - }, + include: { connections: true }, }); if (hubInDb) { - await interaction.editReply({ embeds: [hubEmbed(hubInDb)] }).catch(() => null); + await interaction.editReply({ embeds: [await hubEmbed(hubInDb)] }).catch(() => null); } }); diff --git a/src/Scripts/message/checks.ts b/src/Scripts/message/checks.ts index 995588bb..95b541ce 100644 --- a/src/Scripts/message/checks.ts +++ b/src/Scripts/message/checks.ts @@ -3,30 +3,17 @@ import antiSpam from './antispam'; import emojis from '../../Utils/JSON/emoji.json'; import { Message } from 'discord.js'; import { slurs } from '../../Utils/JSON/badwords.json'; -import { getDb, replaceLinks } from '../../Utils/utils'; +import { replaceLinks } from '../../Utils/utils'; import { connectedList } from '@prisma/client'; import { HubSettingsBitField } from '../../Utils/hubSettingsBitfield'; -import { addUserBlacklist, scheduleUnblacklist } from '../../Utils/blacklist'; +import { addUserBlacklist, findBlacklistedServer, findBlacklistedUser, scheduleUnblacklist } from '../../Utils/blacklist'; export default { async execute(message: Message, networkData: connectedList, settings: HubSettingsBitField) { // true = pass, false = fail (checks) - const db = getDb(); - const userInBlacklist = await db.blacklistedUsers?.findFirst({ - where: { hubId: networkData.hubId, userId: message.author.id }, - }); - const serverInBlacklist = await db.blacklistedServers?.findFirst({ - where: { hubId: networkData.hubId, serverId: message.guild?.id }, - }); - - if (userInBlacklist) { - if (!userInBlacklist.notified) { - message.author.send(`You are blacklisted from this hub for reason **${userInBlacklist.reason}**.`).catch(() => null); - await db.blacklistedUsers.update({ where: { userId: message.author.id }, data: { notified: true } }); - } - return false; - } - if (serverInBlacklist) return false; + const userBlacklisted = await findBlacklistedUser(networkData.hubId, message.author.id); + const serverBlacklisted = await findBlacklistedServer(networkData.hubId, message.guildId || ''); + if (userBlacklisted || serverBlacklisted) return false; if (settings.has('SpamFilter')) { const antiSpamResult = antiSpam.execute(message.author, 3); diff --git a/src/Scripts/network/createConnection.ts b/src/Scripts/network/createConnection.ts index c1556568..05b03b12 100644 --- a/src/Scripts/network/createConnection.ts +++ b/src/Scripts/network/createConnection.ts @@ -42,12 +42,13 @@ export default { }`, ); - sendInNetwork(stripIndents` + sendInNetwork({ + content: stripIndents` A new server has joined us! ${emoji.clipart} **Server Name:** __${interaction.guild?.name}__ **Member Count:** __${interaction.guild?.memberCount}__ - `, hub.id); + ` }, hub.id); // return the created connection so we can use it in the next step return createdConnection; diff --git a/src/Scripts/networkLogs/modActions.ts b/src/Scripts/networkLogs/modActions.ts index 571f77d0..42399dca 100644 --- a/src/Scripts/networkLogs/modActions.ts +++ b/src/Scripts/networkLogs/modActions.ts @@ -1,5 +1,5 @@ import { stripIndents } from 'common-tags'; -import { constants } from '../../Utils/utils'; +import { constants, getDb } from '../../Utils/utils'; import { EmbedBuilder, Guild, User } from 'discord.js'; import { blacklistedServers } from '.prisma/client'; import { captureMessage } from '@sentry/node'; @@ -30,23 +30,24 @@ interface blacklistUser extends actionUser { action: 'blacklistUser'; expires?: Date; } -interface unblacklistUser extends actionUser { - action: 'unblacklistUser'; - blacklistReason?: string; -} interface leaveServer extends actionServer { action: 'leave'; } interface disconnectServer extends actionServer { action: 'disconnect'; } +interface unblacklistUser { + action: 'unblacklistUser'; + hubId: string; + user: User; + blacklistedFor?: string; +} interface unblacklistServer { - serverName: string; - serverId: string; action: 'unblacklistServer'; + hubId: string; + oldBlacklist: blacklistedServers; timestamp: Date; - reason?: string | null; } // TODO: Make the logs channel into a forum, which includes the folowing posts: @@ -56,10 +57,8 @@ interface unblacklistServer { // Make sure the logs channel isn't closed before logging stuff, that will be the main problem here. // That is the reason I have left it as a todo. :D export async function modActions(moderator: User, action: blacklistUser | unblacklistUser | blacklistServer | unblacklistServer | leaveServer | disconnectServer) { - if (!action.reason) action.reason = 'No reason provided.'; - const modLogs = await moderator.client.channels.fetch(constants.channel.modlogs); - const emoji = emojis; + const emoji = emojis.normal; if (!modLogs?.isTextBased()) return captureMessage('Modlogs channel is not text based. (modActions.ts)', 'warning'); @@ -78,12 +77,12 @@ export async function modActions(moderator: User, action: blacklistUser | unblac .setTitle('User Blacklisted') .setDescription( stripIndents` - ${emoji.normal.dotBlue} **User:** ${action.user.username} (${action.user.id}) - ${emoji.normal.dotBlue} **Moderator:** ${moderator.username} (${moderator.id}) + ${emoji.dotBlue} **User:** ${action.user.username} (${action.user.id}) + ${emoji.dotBlue} **Moderator:** ${moderator.username} (${moderator.id}) `, ) .addFields( - { name: 'Reason', value: action.reason, inline: true }, + { name: 'Reason', value: `${action.reason || 'Not Provided.'}`, inline: true }, { name: 'Blacklist Expires', value: action.expires ? `` : 'Never.', inline: true }, ) .setColor(constants.colors.interchatBlue), @@ -99,11 +98,11 @@ export async function modActions(moderator: User, action: blacklistUser | unblac .setAuthor({ name: String(guild?.name), iconURL: guild?.iconURL() || undefined }) .setTitle('Server Blacklisted') .setDescription(stripIndents` - ${emoji.normal.dotBlue} **Server:** ${guild?.name} (${guild?.id}) - ${emoji.normal.dotBlue} **Moderator:** ${moderator.username} (${moderator.id}) + ${emoji.dotBlue} **Server:** ${guild?.name} (${guild?.id}) + ${emoji.dotBlue} **Moderator:** ${moderator.username} (${moderator.id}) `) .addFields( - { name: 'Reason', value: action.reason, inline: true }, + { name: 'Reason', value: `${action.reason || 'Not Provided.'}`, inline: true }, { name: 'Blacklist Expires', value: action.expires ? `` : 'Never.', inline: true }, ) .setColor(constants.colors.interchatBlue), @@ -111,7 +110,8 @@ export async function modActions(moderator: User, action: blacklistUser | unblac }); break; - case 'unblacklistUser': + case 'unblacklistUser': { + const hub = await getDb().hubs.findFirst({ where: { id: action.hubId } }); await modLogs.send({ embeds: [ new EmbedBuilder() @@ -119,29 +119,35 @@ export async function modActions(moderator: User, action: blacklistUser | unblac .setTitle('User Unblacklisted') .setColor(constants.colors.interchatBlue) .setDescription(stripIndents` - ${emoji.normal.dotBlue} **User:** ${action.user.username} (${action.user.id}) - ${emoji.normal.dotBlue} **Moderator:** ${moderator.username} (${moderator.id}) + ${emoji.dotBlue} **User:** ${action.user.username} (${action.user.id}) + ${emoji.dotBlue} **Hub:** ${hub?.name} + ${emoji.dotBlue} **Moderator:** ${moderator.username} (${moderator.id}) `) .addFields( - { name: 'Blacklisted For', value: action.blacklistReason || 'Unknown', inline: true }, - { name: 'Reason', value: action.reason, inline: true }, + { name: 'Blacklisted For', value: action.blacklistedFor || 'Unknown' }, ), ], }); break; + } case 'unblacklistServer': { - const server = await moderator.client.guilds.fetch(action.serverId).catch(() => null); + const server = await moderator.client.guilds.fetch(action.oldBlacklist.serverId).catch(() => null); + const serverName = server?.name || action.oldBlacklist.serverName; + const serverId = server?.id || action.oldBlacklist.serverId; + const blacklistData = action.oldBlacklist.hubs.find(({ hubId }) => hubId === action.hubId); + await modLogs.send({ embeds: [ new EmbedBuilder() - .setAuthor({ name: `${server?.name || action.serverName}`, iconURL: server?.iconURL()?.toString() }) + .setAuthor({ name: `${serverName}`, iconURL: server?.iconURL()?.toString() }) .setTitle('Server Unblacklisted') .setDescription(stripIndents` - ${emoji.normal.dotBlue} **Server:** ${server?.name || action.serverName} (${action.serverId}) - ${emoji.normal.dotBlue} **Moderator:** ${moderator.username} (${moderator.id}) + ${emoji.dotBlue} **Server:** ${serverName} (${serverId}) + ${emoji.dotBlue} **Moderator:** ${moderator.username} (${moderator.id}) + ${emoji.dotBlue} **Hub:** ${moderator.username} (${moderator.id}) + ${emoji.dotBlue} **Blacklisted for:** ${blacklistData?.reason} `) - .addFields({ name: 'Reason', value: action.reason }) .setTimestamp(action.timestamp) .setColor(constants.colors.interchatBlue), ], @@ -156,9 +162,9 @@ export async function modActions(moderator: User, action: blacklistUser | unblac .setAuthor({ name: String(guild?.name), iconURL: guild?.iconURL() || undefined }) .setTitle('Left Server') .setDescription(stripIndents` - ${emoji.normal.dotBlue} **Server:** ${guild?.name} (${guild?.id}) - ${emoji.normal.dotBlue} **Moderator:** ${moderator.username} (${moderator.id}) - ${emoji.normal.dotBlue} **Reason:** ${action.reason} + ${emoji.dotBlue} **Server:** ${guild?.name} (${guild?.id}) + ${emoji.dotBlue} **Moderator:** ${moderator.username} (${moderator.id}) + ${emoji.dotBlue} **Reason:** ${action.reason || 'Not Provided.'} `) .setColor(constants.colors.interchatBlue), ], @@ -172,9 +178,9 @@ export async function modActions(moderator: User, action: blacklistUser | unblac .setAuthor({ name: String(guild?.name), iconURL: guild?.iconURL() || undefined }) .setTitle('Disconnected from Server') .setDescription(stripIndents` - ${emoji.normal.dotBlue} **Server:** ${guild?.name} (${guild?.id}) - ${emoji.normal.dotBlue} **Moderator:** ${moderator.username} (${moderator.id}) - ${emoji.normal.dotBlue} **Reason:** ${action.reason} + ${emoji.dotBlue} **Server:** ${guild?.name} (${guild?.id}) + ${emoji.dotBlue} **Moderator:** ${moderator.username} (${moderator.id}) + ${emoji.dotBlue} **Reason:** ${action.reason || 'Not Provided.'} `) .setColor(constants.colors.interchatBlue), ], diff --git a/src/Scripts/reactions/reactionButton.ts b/src/Scripts/reactions/reactionButton.ts index 739a960e..a0116cd2 100644 --- a/src/Scripts/reactions/reactionButton.ts +++ b/src/Scripts/reactions/reactionButton.ts @@ -2,6 +2,7 @@ import { ButtonInteraction } from 'discord.js'; import { getDb } from '../../Utils/utils'; import updateMessageReactions from '../reactions/updateMessage'; import { HubSettingsBitField } from '../../Utils/hubSettingsBitfield'; +import { findBlacklistedServer, findBlacklistedUser } from '../../Utils/blacklist'; export default { async execute(interaction: ButtonInteraction) { @@ -14,15 +15,12 @@ export default { if ( !messageInDb?.hub || !messageInDb.hubId || - !(new HubSettingsBitField(messageInDb.hub.settings).has('Reactions')) + !(new HubSettingsBitField(messageInDb.hub.settings).has('Reactions')) || + !interaction.inCachedGuild() ) return interaction.reply({ content: 'This hub does not have reactions enabled.', ephemeral: true }); - const userBlacklisted = await db.blacklistedUsers.findFirst({ - where: { userId: interaction.user.id, hubId: messageInDb.hubId }, - }); - const serverBlacklisted = await db.blacklistedServers.findFirst({ - where: { serverId: interaction.guild?.id, hubId: messageInDb.hubId }, - }); + const userBlacklisted = await findBlacklistedUser(messageInDb.hubId, interaction.user.id); + const serverBlacklisted = await findBlacklistedServer(messageInDb.hubId, interaction.guild.id); if (userBlacklisted || serverBlacklisted) { await interaction.reply({ @@ -32,7 +30,7 @@ export default { return; } - interaction.deferUpdate(); + await interaction.deferUpdate(); const connections = await db.connectedList.findMany({ where: { diff --git a/src/Scripts/reactions/viewReactionsMenu.ts b/src/Scripts/reactions/viewReactionsMenu.ts index 0df752a1..bd2c0a96 100644 --- a/src/Scripts/reactions/viewReactionsMenu.ts +++ b/src/Scripts/reactions/viewReactionsMenu.ts @@ -5,6 +5,7 @@ import sortReactions from './sortReactions'; import updateMessageReactions from './updateMessage'; import { HubSettingsBitField } from '../../Utils/hubSettingsBitfield'; import emojis from '../../Utils/JSON/emoji.json'; +import { findBlacklistedServer, findBlacklistedUser } from '../../Utils/blacklist'; export default { async execute(interaction: ButtonInteraction) { @@ -26,12 +27,8 @@ export default { return; } - const userBlacklisted = await db.blacklistedUsers.findFirst({ - where: { userId: interaction.user.id, hubId: networkMessage.hubId }, - }); - const serverBlacklisted = await db.blacklistedServers.findFirst({ - where: { serverId: interaction.guild?.id, hubId: networkMessage.hubId }, - }); + const userBlacklisted = await findBlacklistedUser(networkMessage.hubId, interaction.user.id); + const serverBlacklisted = await findBlacklistedServer(networkMessage.hubId, interaction.guildId || ''); if (userBlacklisted || serverBlacklisted) { await interaction.reply({ diff --git a/src/Scripts/support/suggest.ts b/src/Scripts/support/suggest.ts index 6c3ab19d..65872931 100644 --- a/src/Scripts/support/suggest.ts +++ b/src/Scripts/support/suggest.ts @@ -13,7 +13,7 @@ export default { // modal const modal = new ModalBuilder() .setTitle('Suggestion') - .setCustomId('suggestion') + .setCustomId(interaction.id) .addComponents( new ActionRowBuilder() .addComponents( diff --git a/src/Utils/blacklist.ts b/src/Utils/blacklist.ts index 5f709e76..4930d5d0 100644 --- a/src/Utils/blacklist.ts +++ b/src/Utils/blacklist.ts @@ -1,23 +1,49 @@ -import { scheduleJob } from 'node-schedule'; +import { cancelJob, scheduleJob } from 'node-schedule'; import { modActions } from '../Scripts/networkLogs/modActions'; import { constants, getDb } from './utils'; import { User, EmbedBuilder, Client, TextBasedChannel } from 'discord.js'; -import logger from './logger'; import emojis from './JSON/emoji.json'; +import { blacklistedServers, blacklistedUsers } from '@prisma/client'; -export async function addUserBlacklist(hubId: string, moderator: User, user: User | string, reason: string, expires?: Date | number, notifyUser = true) { + +export async function findBlacklistedUser(hubId: string, userId: string) { + const db = getDb(); + const userBlacklisted = await db.blacklistedUsers.findFirst({ + where: { userId, hubs: { some: { hubId } } }, + }); + return userBlacklisted; +} + +export async function findBlacklistedServer(hubId: string, serverId: string) { + const db = getDb(); + const userBlacklisted = await db.blacklistedServers.findFirst({ + where: { serverId, hubs: { some: { hubId } } }, + }); + return userBlacklisted; +} + +export async function addUserBlacklist(hubId: string, moderator: User, user: User | string, reason: string, expires?: Date | number) { if (typeof user === 'string') user = await moderator.client.users.fetch(user); if (typeof expires === 'number') expires = new Date(Date.now() + expires); const db = getDb(); - const dbUser = await db.blacklistedUsers.create({ - data: { - hub: { connect: { id: hubId } }, + const dbUser = await db.blacklistedUsers.findFirst({ where: { userId: user.id } }); + + const hubs = dbUser?.hubs.filter((i) => i.hubId !== hubId) || []; + hubs?.push({ expires: expires || null, reason, hubId }); + + const updatedUser = await db.blacklistedUsers.upsert({ + where: { + userId: user.id, + }, + update: { + username: user.username, + hubs: { set: hubs }, + }, + create: { userId: user.id, username: user.username, - notified: notifyUser, - expires, - reason, + hubs, }, }); @@ -29,20 +55,25 @@ export async function addUserBlacklist(hubId: string, moderator: User, user: Use reason, }).catch(() => null); - return dbUser; + return updatedUser; } export async function addServerBlacklist(serverId: string, moderator: User, hubId: string, reason: string, expires?: Date) { const guild = await moderator.client.guilds.fetch(serverId); const db = getDb(); - const dbGuild = await db.blacklistedServers.create({ - data: { - hub: { connect: { id: hubId } }, - reason: reason, + const dbGuild = await db.blacklistedServers.upsert({ + where: { + serverId: guild.id, + }, + update: { + serverName: guild.name, + hubs: { push: { hubId, expires, reason } }, + }, + create: { serverId: guild.id, serverName: guild.name, - expires: expires, + hubs: [{ hubId, expires, reason }], }, }); @@ -57,25 +88,58 @@ export async function addServerBlacklist(serverId: string, moderator: User, hubI return dbGuild; } +export async function removeBlacklist(type: 'user', hubId: string, userId: string): Promise +export async function removeBlacklist(type: 'server', hubId: string, serverId: string): Promise +export async function removeBlacklist(type: string, hubId: string, userOrServerId: string) { + const db = getDb(); + cancelJob(`blacklist_${type}-${userOrServerId}`); + + + if (type === 'user') { + return await db.blacklistedUsers.update({ + where: { + userId: userOrServerId, + hubs: { some: { hubId } }, + }, + data: { + hubs: { deleteMany: { where: { hubId } } }, + }, + }); + } + else { + return db.blacklistedServers.update({ + where: { + serverId: userOrServerId, + hubs: { some: { hubId } }, + }, + data: { + hubs: { deleteMany: { where: { hubId } } }, + }, + }); + } +} + + export function scheduleUnblacklist(type: 'server', client: Client, serverId: string, hubId: string, expires: Date | number): void export function scheduleUnblacklist(type: 'user', client: Client, userId: string, hubId: string, expires: Date | number): void export function scheduleUnblacklist(type: string, client: Client, userOrServerId: string, hubId: string, expires: Date | number) { if (type === 'server') { - scheduleJob(`blacklist_server-${userOrServerId}`, expires, async () => { + scheduleJob(`blacklist_server-${userOrServerId}`, expires, async function() { const db = getDb(); - const filter = { where: { hubId, serverId: userOrServerId } }; - const dbServer = await db.blacklistedServers.findFirst(filter); + const dbServer = await db.blacklistedServers.findFirst({ + where: { serverId: userOrServerId, hubs: { some: { hubId } } }, + }); // only call .delete if the document exists // or prisma will error if (dbServer) { - await db.blacklistedServers.deleteMany(filter); + await removeBlacklist('server', hubId, userOrServerId); + modActions(client.user, { - serverId: dbServer.serverId, - serverName: dbServer.serverName, action: 'unblacklistServer', + oldBlacklist: dbServer, timestamp: new Date(), - reason: 'Blacklist expired for server.', + hubId, }).catch(() => null); } }); @@ -84,23 +148,21 @@ export function scheduleUnblacklist(type: string, client: Client, userOrSe if (type === 'user') { scheduleJob(`blacklist_user-${userOrServerId}`, expires, async () => { const db = getDb(); - const filter = { where: { userId: userOrServerId } }; - const dbUser = await db.blacklistedUsers.findFirst(filter); + const dbUser = await db.blacklistedUsers.findFirst({ + where: { userId: userOrServerId, hubs: { some: { hubId } } }, + }); const user = await client.users.fetch(userOrServerId).catch(() => null); - if (!user) return; + if (!user || !dbUser) return; - // only call .delete if the document exists - // or prisma will error - if (dbUser) { - await db.blacklistedUsers.delete(filter); - modActions(client.user, { - user, - action: 'unblacklistUser', - blacklistReason: dbUser.reason, - reason: 'Blacklist expired for user.', - }).catch(() => null); - } + await removeBlacklist('user', hubId, userOrServerId); + + modActions(client.user, { + user, + hubId, + action: 'unblacklistUser', + blacklistedFor: dbUser.hubs.find(h => h.hubId === hubId)?.reason, + }).catch(() => null); }); } return false; @@ -122,10 +184,7 @@ export async function notifyBlacklist(userOrChannel: User | TextBasedChannel, hu { name: 'Expires', value: expireString, inline: true }, ); - userOrChannel.send({ embeds: [embed] }).catch(async () => { - await db.blacklistedUsers.update({ where: { userId: userOrChannel.id }, data: { notified: false } }); - logger.info(`Could not notify ${(userOrChannel as User).username} about their blacklist.`); - }); + userOrChannel.send({ embeds: [embed] }).catch(async () => null); } else if (userOrChannel.isTextBased()) { const embed = new EmbedBuilder() diff --git a/src/Utils/network.ts b/src/Utils/network.ts index ac2e3f7b..f23d4f19 100644 --- a/src/Utils/network.ts +++ b/src/Utils/network.ts @@ -31,7 +31,7 @@ export async function disconnect(channelId: string) { return channelExists; } -export async function sendInNetwork(message: string | WebhookMessageCreateOptions, hubId: string) { +export async function sendInNetwork(message: WebhookMessageCreateOptions, hubId: string) { if (typeof message !== 'string' && !message.username && !message.avatarURL) { message.username = 'InterChat Network'; message.avatarURL = 'https://i.imgur.com/jHHkSrf.png'; @@ -41,7 +41,7 @@ export async function sendInNetwork(message: string | WebhookMessageCreateOption channels?.forEach(async (channelEntry) => { const webhookClient = new WebhookClient({ url: channelEntry.webhookURL }); - await webhookClient.send(message); + await webhookClient.send(channelEntry.parentId ? { ...message, threadId: channelEntry.channelId } : message); }); } diff --git a/src/Utils/timers.ts b/src/Utils/timers.ts index 0cbf9a70..5edb177e 100644 --- a/src/Utils/timers.ts +++ b/src/Utils/timers.ts @@ -2,6 +2,7 @@ import { Client } from 'discord.js'; import { scheduleJob } from 'node-schedule'; import { modActions } from '../Scripts/networkLogs/modActions'; import { getDb } from './utils'; +import { removeBlacklist } from './blacklist'; /** A function to start timers for blacklist expiry, messageData cleanup, etc. */ export default async function startTimers(client: Client) { @@ -20,65 +21,72 @@ export default async function startTimers(client: Client) { .catch(() => null); }); - const blacklistedServers = await db.blacklistedServers.findMany({ where: { expires: { isSet: true } } }); - const blacklistedUsers = await db.blacklistedUsers.findMany({ where: { expires: { isSet: true } } }); + const query = { where: { hubs: { some: { expires: { isSet: true } } } } }; + const blacklistedServers = await db.blacklistedServers.findMany(query); + const blacklistedUsers = await db.blacklistedUsers.findMany(query); // timer to unblacklist servers blacklistedServers.forEach(async (blacklist) => { - if (!blacklist.expires) return; + blacklist.hubs.forEach(({ hubId, expires }) => { + if (!expires) return; - if (blacklist.expires < new Date()) { - await db.blacklistedServers.delete({ where: { id: blacklist.id } }); + removeBlacklist('server', hubId, blacklist.serverId); - modActions(client.user, { - action: 'unblacklistServer', - serverId: blacklist.serverId, - serverName: blacklist.serverName, - timestamp: new Date(), - }); - return; - } - - scheduleJob(`blacklist_server-${blacklist.serverId}`, blacklist.expires, async function() { - await db.blacklistedServers.delete({ where: { id: blacklist.id } }); - - modActions(client.user, { - action: 'unblacklistServer', - serverId: blacklist.serverId, - serverName: blacklist.serverName, - reason: 'Blacklist expired.', - timestamp: new Date(), + if (expires < new Date()) { + + modActions(client.user, { + action: 'unblacklistServer', + oldBlacklist: blacklist, + timestamp: new Date(), + hubId, + }); + return; + } + + scheduleJob(`blacklist_server-${blacklist.serverId}`, expires, async function() { + await db.blacklistedServers.delete({ where: { id: blacklist.id } }); + + modActions(client.user, { + action: 'unblacklistServer', + oldBlacklist: blacklist, + timestamp: new Date(), + hubId, + }); }); + }); }); // timer to unblacklist users blacklistedUsers.forEach(async (blacklist) => { - if (!blacklist.expires) return; - - // if the blacklist has already expired, delete it from the database - if (blacklist.expires < new Date()) { - await db.blacklistedUsers.delete({ where: { userId: blacklist.userId } }); - const user = await client.users.fetch(blacklist.userId).catch(() => null); - - if (!user) return; - - modActions(client.user, { action: 'unblacklistUser', user, reason: 'Blacklist expired.', blacklistReason: blacklist.reason }); - return; - } - - // if the blacklist has not expired, schedule a new job to unblacklist the user - scheduleJob(`blacklist-${blacklist.userId}`, blacklist.expires, async function(job_blacklist: typeof blacklist) { - const user = await client.users.fetch(job_blacklist.userId).catch(() => null); - await db.blacklistedUsers.delete({ where: { userId: job_blacklist.userId } }); - - if (!user) return; - modActions(user.client.user, { - action: 'unblacklistUser', - reason: 'Blacklist expired.', - blacklistReason: job_blacklist.reason, - user, - }); - }.bind(null, blacklist)); + blacklist.hubs.forEach(async ({ hubId, expires, reason }) => { + if (!expires) return; + + // if the blacklist has already expired, delete it from the database + if (expires < new Date()) { + await removeBlacklist('user', hubId, blacklist.userId); + const user = await client.users.fetch(blacklist.userId).catch(() => null); + + if (!user) return; + + modActions(client.user, { action: 'unblacklistUser', user, hubId, blacklistedFor: reason }); + return; + } + + // if the blacklist has not expired, schedule a new job to unblacklist the user + scheduleJob(`blacklist-${blacklist.userId}`, expires, async function(job_blacklist: typeof blacklist) { + const user = await client.users.fetch(job_blacklist.userId).catch(() => null); + await db.blacklistedUsers.delete({ where: { userId: job_blacklist.userId } }); + + if (!user) return; + + modActions(user.client.user, { + action: 'unblacklistUser', + blacklistedFor: reason, + user, + hubId, + }); + }.bind(null, blacklist)); + }); }); } \ No newline at end of file