diff options
author | IRONM00N <64110067+IRONM00N@users.noreply.github.com> | 2022-01-08 20:08:16 -0500 |
---|---|---|
committer | IRONM00N <64110067+IRONM00N@users.noreply.github.com> | 2022-01-08 20:08:16 -0500 |
commit | e0531157a745ac6178d55cc159b5932fa36ff20f (patch) | |
tree | a8de340d0c48269619e9bfde536932eb08556593 | |
parent | 0e160ae77477f0986a02746e84158329299f438f (diff) | |
download | tanzanite-e0531157a745ac6178d55cc159b5932fa36ff20f.tar.gz tanzanite-e0531157a745ac6178d55cc159b5932fa36ff20f.tar.bz2 tanzanite-e0531157a745ac6178d55cc159b5932fa36ff20f.zip |
database migrations - use jsonb over text + JSON.parse, refactor bad word & automod - store word in shared db
closes: #53
-rw-r--r-- | src/commands/config/config.ts | 2 | ||||
-rw-r--r-- | src/commands/dev/eval.ts | 18 | ||||
-rw-r--r-- | src/commands/dev/test.ts | 10 | ||||
-rw-r--r-- | src/lib/badlinks.ts | 15 | ||||
-rw-r--r-- | src/lib/badwords.ts | 1006 | ||||
-rw-r--r-- | src/lib/common/AutoMod.ts | 86 | ||||
-rw-r--r-- | src/lib/extensions/discord-akairo/BushClient.ts | 8 | ||||
-rw-r--r-- | src/lib/extensions/discord-akairo/BushClientUtil.ts | 4 | ||||
-rw-r--r-- | src/lib/models/Global.ts | 9 | ||||
-rw-r--r-- | src/lib/models/Guild.ts | 42 | ||||
-rw-r--r-- | src/lib/models/ModLog.ts | 5 | ||||
-rw-r--r-- | src/lib/models/Shared.ts | 42 | ||||
-rw-r--r-- | src/lib/models/Stat.ts | 13 | ||||
-rw-r--r-- | src/lib/models/StickyRole.ts | 3 | ||||
-rw-r--r-- | src/lib/models/__helpers.ts | 65 | ||||
-rw-r--r-- | src/lib/utils/BushCache.ts | 9 |
16 files changed, 710 insertions, 627 deletions
diff --git a/src/commands/config/config.ts b/src/commands/config/config.ts index 9d8ba60..b7b3f0e 100644 --- a/src/commands/config/config.ts +++ b/src/commands/config/config.ts @@ -324,7 +324,7 @@ export default class ConfigCommand extends BushCommand { return Array.isArray(feat) ? feat.length - ? feat.map(func).join('\n') + ? (<string[]>feat).map(func).join('\n') : '[Empty Array]' : feat !== null ? func(feat) diff --git a/src/commands/dev/eval.ts b/src/commands/dev/eval.ts index 5b2f27a..4eb25dc 100644 --- a/src/commands/dev/eval.ts +++ b/src/commands/dev/eval.ts @@ -8,6 +8,7 @@ import { Guild, Level, ModLog, + Shared, StickyRole, type ArgType } from '#lib'; @@ -132,6 +133,15 @@ export default class EvalCommand extends BushCommand { prompt: 'Would you like to inspect the prototype chain to find methods?', slashType: 'BOOLEAN', optional: true + }, + { + id: 'async', + description: 'Whether or not to wrap the code in an async function.', + match: 'flag', + flag: '--async', + prompt: 'Would you like to wrap the code in an async function?', + slashType: 'BOOLEAN', + optional: true } ], slash: true, @@ -144,8 +154,8 @@ export default class EvalCommand extends BushCommand { public override async exec( message: BushMessage | BushSlashMessage, args: { - sel_depth: ArgType<'integer'>; code: ArgType<'string'>; + sel_depth: ArgType<'integer'>; sudo: ArgType<'boolean'>; silent: ArgType<'boolean'>; deleteMSG: ArgType<'boolean'>; @@ -153,6 +163,7 @@ export default class EvalCommand extends BushCommand { hidden: ArgType<'boolean'>; show_proto: ArgType<'boolean'>; show_methods: ArgType<'boolean'>; + async: ArgType<'boolean'>; } ) { if (!message.author.isOwner()) @@ -161,7 +172,8 @@ export default class EvalCommand extends BushCommand { await message.interaction.deferReply({ ephemeral: args.silent }); } const isTypescript = args.typescript || args.code.includes('```ts'); - const rawCode = args.code.replace(/[“”]/g, '"').replace(/```*(?:js|ts)?/g, ''); + let rawCode = args.code.replace(/[“”]/g, '"').replace(/```*(?:js|ts)?/g, ''); + if (args.async) rawCode = `(async () => {${rawCode}})()`; const code: { ts: string | null; js: string; lang: 'ts' | 'js' } = { ts: isTypescript ? rawCode : null, @@ -237,4 +249,4 @@ export default class EvalCommand extends BushCommand { } } -/** @typedef {ActivePunishment|Global|Guild|Level|ModLog|StickyRole|ButtonInteraction|Collection|Collector|CommandInteraction|ContextMenuInteraction|DMChannel|Emoji|Interaction|InteractionCollector|Message|MessageActionRow|MessageAttachment|MessageButton|MessageCollector|MessageSelectMenu|ReactionCollector|Util|Canvas} VSCodePleaseDontRemove */ +/** @typedef {ActivePunishment|Global|Guild|Level|ModLog|StickyRole|ButtonInteraction|Collection|Collector|CommandInteraction|ContextMenuInteraction|DMChannel|Emoji|Interaction|InteractionCollector|Message|MessageActionRow|MessageAttachment|MessageButton|MessageCollector|MessageSelectMenu|ReactionCollector|Util|Canvas|Shared} VSCodePleaseDontRemove */ diff --git a/src/commands/dev/test.ts b/src/commands/dev/test.ts index 2c4e34d..50532f8 100644 --- a/src/commands/dev/test.ts +++ b/src/commands/dev/test.ts @@ -1,6 +1,8 @@ -import { BushCommand, ButtonPaginator, type BushMessage } from '#lib'; +import { BushCommand, ButtonPaginator, Shared, type BushMessage } from '#lib'; import { MessageActionRow, MessageButton, MessageEmbed, type ApplicationCommand, type Collection } from 'discord.js'; import { MessageButtonStyles } from 'discord.js/typings/enums'; +import badLinksSecretArray from '../../lib/badlinks-secret.js'; +import badLinksArray from '../../lib/badlinks.js'; export default class TestCommand extends BushCommand { public constructor() { @@ -148,6 +150,12 @@ export default class TestCommand extends BushCommand { return await message.util.reply(`${util.emojis.success} Removed guild commands and global commands.`); } else if (['drop down', 'drop downs', 'select menu', 'select menus'].includes(args?.feature?.toLowerCase())) { + } else if (['sync links'].includes(args?.feature?.toLowerCase())) { + const row = (await Shared.findByPk(0))!; + row.badLinks = badLinksArray; + row.badLinksSecret = badLinksSecretArray; + await row.save(); + return await message.util.reply(`${util.emojis.success} Updated bad links.`); } return await message.util.reply(responses[Math.floor(Math.random() * responses.length)]); } diff --git a/src/lib/badlinks.ts b/src/lib/badlinks.ts index 6cabd65..3a5b171 100644 --- a/src/lib/badlinks.ts +++ b/src/lib/badlinks.ts @@ -628,6 +628,7 @@ export default [ "discardapp.fun", "disccor.com", "disccord-apps.com", + "disccord-appss.ru", "disccord-club.com", "disccord-gift.com", "disccord.gg", @@ -638,8 +639,10 @@ export default [ "disccords.com", "disccrd.gifts", "discford.com", + "dischrd.com", "discird.gg", "discird.me", + "discjrd.com", "disckordapp.com", "disclord.com", "disclrd.com", @@ -688,6 +691,7 @@ export default [ "disconrd.com", "discontro.ru", "discoogs.com", + "discoord-apps.com", "discoord-nitro.com", "discoord.space", "discor-dnitro.fun", @@ -1024,6 +1028,7 @@ export default [ "discord-tech.com", "discord-tester.com", "discord-to.com", + "discord-true.com", "discord-trustandsafety.com", "discord-up.ru", "discord-verif.ga", @@ -1033,6 +1038,7 @@ export default [ "discord-verify.com", "discord-verify.ru", "discord-vetify.com", + "discord-web.co", "discord-xnitro.com", "discord.1nitro.club", "discord.ac", @@ -1167,6 +1173,7 @@ export default [ "discorddiscord.com", "discorddrop.com", "discorde-gift.com", + "discorde-gifte.com", "discorde-nitro.com", "discorde.gift", "discorde.xyz", @@ -1496,6 +1503,8 @@ export default [ "disordnitros.gifts", "disordnitros.xyz", "disordnltro.xyz", + "disordnltros.com", + "disordnltros.com", "disordnltros.gifts", "disordsnitro.gifts", "disordsnitros.gifts", @@ -1680,6 +1689,7 @@ export default [ "dlscrod.ru.com", "dlscrodapp.ru", "dlsordnitro.gifts", + "dlsordnltros.gifts", "dmarkef.com", "dmarket-place.pp.ua", "dmcordsteamnitro.de", @@ -2128,6 +2138,8 @@ export default [ "ggnavincere.xyz", "ggtour.ru", "ghostgame.ru", + "gif-discord.com", + "gife-discorde.com", "gift-discord.online", "gift-discord.ru", "gift-discord.shop", @@ -3987,7 +3999,6 @@ export default [ "steamcommunity.cloud", "steamcommunity.cn", "steamcommunity.co.ua", - // "steamcommunity.co", "steamcommunity.com-id-k4tushatwitchbabydota.ru", "steamcommunity.com.ru", "steamcommunity.comlappl251490lrust.ru", @@ -4703,6 +4714,7 @@ export default [ "steamnconmunity.work", "steamnconnmunity.com", "steamnitro.com", + "steamnitrol.com", "steamnitros.com", "steamnitros.ru", "steamnltro.com", @@ -6879,4 +6891,5 @@ export default [ "zipsetgo.com", "zonewarco.org.ru", "zonewarco.org.ru", + // "steamcommunity.co", ]; diff --git a/src/lib/badwords.ts b/src/lib/badwords.ts index 90f5a64..326e4b8 100644 --- a/src/lib/badwords.ts +++ b/src/lib/badwords.ts @@ -4,488 +4,572 @@ export default { /* -------------------------------------------------------------------------- */ /* Slurs */ /* -------------------------------------------------------------------------- */ - "faggot": { - severity: Severity.TEMP_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "racial slur", - regex: false, - }, - "nigga": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "racial slur", - regex: false, - }, - "nigger": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "racial slur", - regex: false, - }, - "nigra": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "racial slur", - regex: false, - }, - "retard": { - severity: Severity.TEMP_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "ableist slur", - regex: false, - }, - "retarted": { - severity: Severity.TEMP_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "ableist slur", - regex: false, - }, - "slut": { - severity: Severity.WARN, - ignoreSpaces: false, - ignoreCapitalization: true, - reason: "derogatory term", - regex: false, - }, - "tar baby": { - severity: Severity.TEMP_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "racial slur", - regex: false, - }, - "whore": { - severity: Severity.WARN, - ignoreSpaces: false, - ignoreCapitalization: true, - reason: "derogatory term", - regex: false, - }, - "卍": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "racist symbol", - regex: false, - }, - "space movie 1992": { - //? N word - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "racial slur", - regex: false, - }, + "Slurs": [ + { + match: "faggot", + severity: Severity.TEMP_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "racial slur", + regex: false, + }, + { + match: "nigga", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "racial slur", + regex: false, + }, + { + match: "nigger", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "racial slur", + regex: false, + }, + { + match: "nigra", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "racial slur", + regex: false, + }, + { + match: "retard", + severity: Severity.TEMP_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "ableist slur", + regex: false, + }, + { + match: "retarted", + severity: Severity.TEMP_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "ableist slur", + regex: false, + }, + { + match: "slut", + severity: Severity.WARN, + ignoreSpaces: false, + ignoreCapitalization: true, + reason: "derogatory term", + regex: false, + }, + { + match: "tar baby", + severity: Severity.TEMP_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "racial slur", + regex: false, + }, + { + match: "whore", + severity: Severity.WARN, + ignoreSpaces: false, + ignoreCapitalization: true, + reason: "derogatory term", + regex: false, + }, + { + match: "卍", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "racist symbol", + regex: false, + }, + { + //? N word + match: "space movie 1992", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "racial slur", + regex: false, + }, + ], /* -------------------------------------------------------------------------- */ /* Steam Scams */ /* -------------------------------------------------------------------------- */ - 'Я в тильте, в кс дали статус "Ненадежный"': { - //? I'm on tilt, in the cop they gave the status "Unreliable" - severity: Severity.WARN, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "steam scam phrase", - regex: false, - }, - "hello i am leaving cs:go": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "steam scam phrase", - regex: false, - }, - "hello! I'm done with csgo": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "steam scam phrase", - regex: false, - }, - "hi bro, i'm leaving this fucking game, take my skin": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "steam scam phrase", - regex: false, - }, - "hi friend, today i am leaving this fucking game": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "steam scam phrase", - regex: false, - }, - "hi guys, i'm leaving this fucking game, take my": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "steam scam phrase", - regex: false, - }, - "hi, bro h am leaving cs:go and giving away my skin": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "steam scam phrase", - regex: false, - }, - "hi, bro i am leaving cs:go and giving away my skin": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "steam scam phrase", - regex: false, - }, - "i confirm all exchanges, there won't be enough": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "steam scam phrase", - regex: false, - }, - "i quit csgo": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "steam scam phrase", - regex: false, - }, - "the first three who send a trade": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "steam scam phrase", - regex: false, - }, - "you can choose any skin for yourself": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "steam scam phrase", - regex: false, - }, - "Hey, I'm leaving for the army and giving the skins": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "steam scam phrase", - regex: false, - }, - "fuck this trash called CS:GO, deleted,": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "steam scam phrase", - regex: false, - }, + "Steam Scams": [ + { + //? I'm on tilt, in the cop they gave the status "Unreliable" + match: 'Я в тильте, в кс дали статус "Ненадежный"', + severity: Severity.WARN, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "steam scam phrase", + regex: false, + }, + { + match: "hello i am leaving cs:go", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "steam scam phrase", + regex: false, + }, + { + match: "hello! I'm done with csgo", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "steam scam phrase", + regex: false, + }, + { + match: "hi bro, i'm leaving this fucking game, take my skin", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "steam scam phrase", + regex: false, + }, + { + match: "hi friend, today i am leaving this fucking game", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "steam scam phrase", + regex: false, + }, + { + match: "hi guys, i'm leaving this fucking game, take my", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "steam scam phrase", + regex: false, + }, + { + match: "hi, bro h am leaving cs:go and giving away my skin", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "steam scam phrase", + regex: false, + }, + { + match: "hi, bro i am leaving cs:go and giving away my skin", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "steam scam phrase", + regex: false, + }, + { + match: "i confirm all exchanges, there won't be enough", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "steam scam phrase", + regex: false, + }, + { + match: "i quit csgo", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "steam scam phrase", + regex: false, + }, + { + match: "the first three who send a trade", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "steam scam phrase", + regex: false, + }, + { + match: "you can choose any skin for yourself", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "steam scam phrase", + regex: false, + }, + { + match: "Hey, I'm leaving for the army and giving the skins", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "steam scam phrase", + regex: false, + }, + { + match: "fuck this trash called CS:GO, deleted,", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "steam scam phrase", + regex: false, + }, + ], /* -------------------------------------------------------------------------- */ /* Nitro Scams */ /* -------------------------------------------------------------------------- */ - "and there is discord hallween's giveaway": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "discord nitro for free - steam store": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "free 3 months of discord nitro": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "free discord nitro airdrop": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "get 3 months of discord nitro": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "get discord nitro for free": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "get free discord nitro from steam": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "lol, jahjajha free discord nitro for 3 month!!": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "steam is giving away 3 months of discord nitro for free to all no limited steam users": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "Лол, бесплатный дискорд нитро на 1 месяц!": { - //? Lol, 1 month free discord nitro! - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "Airdrop Discord FREE NITRO from Steam —": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "take nitro faster, it's already running out": { - severity: Severity.PERM_MUTE, - ignoreSpaces: false, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "only the first 10 people will have time to take nitro": { - severity: Severity.PERM_MUTE, - ignoreSpaces: false, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "Discord is giving away nitro!": { - severity: Severity.PERM_MUTE, - ignoreSpaces: false, - ignoreCapitalization: false, - reason: "discord nitro scam phrase", - regex: false, - }, - "Free gift discord nitro for 1 month!": { - severity: Severity.PERM_MUTE, - ignoreSpaces: false, - ignoreCapitalization: false, - reason: "discord nitro scam phrase", - regex: false, - }, - "Hi i claim this nitro for free 3 months lol!": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "bro watch this, working nitro gen": { - severity: Severity.PERM_MUTE, - ignoreSpaces: false, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "Free distribution of discord nitro for 3 months from steam!": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "Get 3 Months of Discord Nitro. Personalize your profile, screen share in HD, upgrade your emojis, and more!": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "Steam is giving away free discord nitro, have time to pick up at my link": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "Airdrop Discord NITRO with": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "Check this lol, there nitro is handed out for free, take it until everything is sorted out": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "A free Discord Nitro | Steam Store Discord Nitro Distribution.": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "Xbox gives away discord nitro for free": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "airdrop discord nitro by steam": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "3 месяца нитро бесплатно от стима, забирайте тоже": { - //? 3 months nitro free from steam, take too - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "Free distributiοn of discοrd nitrο for 3 months from steаm!": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "Free discord nitro for 1 month!": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "I got some nitro left over here": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "Hey, steam gived nitro": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "nitro giveaway by steam, take it": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "3 months nitro from styme,": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "XBOX and DISCORD are giving away free NITRO FULL for a month.": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "Hi,take the Discord Nitro for free": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "Дискорд нитро получил бесплатно,забирай пока не поздно": { - //? Discord nitro got free, take it before it's too late - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "1 month nitro for free": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "Gifts for the new year, nitro for 3 months": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, - "1 month nitro from steam, take it guys": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "discord nitro scam phrase", - regex: false, - }, + "Nitro Scams": [ + { + match: "and there is discord hallween's giveaway", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "discord nitro for free - steam store", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "free 3 months of discord nitro", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "free discord nitro airdrop", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "get 3 months of discord nitro", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "get discord nitro for free", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "get free discord nitro from steam", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "lol, jahjajha free discord nitro for 3 month!!", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "steam is giving away 3 months of discord nitro for free to all no limited steam users", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + //? Lol, 1 month free discord nitro! + match: "Лол, бесплатный дискорд нитро на 1 месяц!", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "Airdrop Discord FREE NITRO from Steam —", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "take nitro faster, it's already running out", + severity: Severity.PERM_MUTE, + ignoreSpaces: false, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "only the first 10 people will have time to take nitro", + severity: Severity.PERM_MUTE, + ignoreSpaces: false, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "Discord is giving away nitro!", + severity: Severity.PERM_MUTE, + ignoreSpaces: false, + ignoreCapitalization: false, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "Free gift discord nitro for 1 month!", + severity: Severity.PERM_MUTE, + ignoreSpaces: false, + ignoreCapitalization: false, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "Hi i claim this nitro for free 3 months lol!", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "bro watch this, working nitro gen", + severity: Severity.PERM_MUTE, + ignoreSpaces: false, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "Free distribution of discord nitro for 3 months from steam!", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "Get 3 Months of Discord Nitro. Personalize your profile, screen share in HD, upgrade your emojis, and more!", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "Steam is giving away free discord nitro, have time to pick up at my link", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "Airdrop Discord NITRO with", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "Check this lol, there nitro is handed out for free, take it until everything is sorted out", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "A free Discord Nitro | Steam Store Discord Nitro Distribution.", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "Xbox gives away discord nitro for free", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "airdrop discord nitro by steam", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + //? 3 months nitro free from steam, take too + match: "3 месяца нитро бесплатно от стима, забирайте тоже", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "Free distributiοn of discοrd nitrο for 3 months from steаm!", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "Free discord nitro for 1 month!", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "I got some nitro left over here", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "Hey, steam gived nitro", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "nitro giveaway by steam, take it", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "3 months nitro from styme,", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "XBOX and DISCORD are giving away free NITRO FULL for a month.", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "Hi,take the Discord Nitro for free", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + //? Discord nitro got free, take it before it's too late + match: "Дискорд нитро получил бесплатно,забирай пока не поздно", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "1 month nitro for free", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "Gifts for the new year, nitro for 3 months", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "1 month nitro from steam, take it guys", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + { + match: "Hello, discord and steam are giving away nitro, take it away", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "discord nitro scam phrase", + regex: false, + }, + ], /* -------------------------------------------------------------------------- */ /* Misc Scams */ /* -------------------------------------------------------------------------- */ - "found a cool software that improves the": { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "misc. scam phrase", - regex: false, - }, - "there is a possible chance tomorrow there will be a cyber-attack event where on all social networks including Discord there will be people trying": + "Misc Scams": [ { + match: "found a cool software that improves the", + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "misc. scam phrase", + regex: false, + }, + { + match: + "there is a possible chance tomorrow there will be a cyber-attack event where on all social networks including Discord there will be people trying", severity: Severity.WARN, ignoreSpaces: false, ignoreCapitalization: true, reason: "annoying copy pasta", regex: false, }, + ], /* -------------------------------------------------------------------------- */ /* Frequently Advertised Discord Severs */ /* -------------------------------------------------------------------------- */ - "https://discord.gg/7CaCvDXs": { - severity: Severity.TEMP_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: "blacklisted server link", - regex: false, - }, + "Frequently Advertised Discord Severs": [ + { + match: "https://discord.gg/7CaCvDXs", + severity: Severity.TEMP_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: "blacklisted server link", + regex: false, + }, + ], } as BadWords; diff --git a/src/lib/common/AutoMod.ts b/src/lib/common/AutoMod.ts index 1bc26fb..595f025 100644 --- a/src/lib/common/AutoMod.ts +++ b/src/lib/common/AutoMod.ts @@ -1,8 +1,5 @@ import { Moderation, type BushButtonInteraction, type BushMessage } from '#lib'; import { GuildMember, MessageActionRow, MessageButton, MessageEmbed, type TextChannel } from 'discord.js'; -import badLinksSecretArray from '../badlinks-secret.js'; // I cannot make this public so just make a new file that export defaults an empty array -import badLinksArray from '../badlinks.js'; -import badWords from '../badwords.js'; /** * Handles auto moderation functionality. @@ -36,39 +33,40 @@ export class AutoMod { if (this.message.author.bot) return; if (this.message.author.isOwner()) return; - const customAutomodPhrases = (await this.message.guild.getSetting('autoModPhases')) ?? {}; - const badLinks: BadWords = {}; + const badLinksArray = util.getShared('badLinks'); + const badLinksSecretArray = util.getShared('badLinksSecret'); + const badWordsRaw = util.getShared('badWords'); + const customAutomodPhrases = (await this.message.guild.getSetting('autoModPhases')) ?? []; const uniqueLinks = [...new Set([...badLinksArray, ...badLinksSecretArray])]; - uniqueLinks.forEach((link) => { - badLinks[link] = { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: 'malicious link', - regex: false - }; - }); + const badLinks: BadWordDetails[] = uniqueLinks.map((link) => ({ + match: link, + severity: Severity.PERM_MUTE, + ignoreSpaces: true, + ignoreCapitalization: true, + reason: 'malicious link', + regex: false + })); + + const parsedBadWords = Object.values(badWordsRaw).flat(); const result = { ...this.checkWords(customAutomodPhrases), - ...this.checkWords((await this.message.guild.hasFeature('excludeDefaultAutomod')) ? {} : badWords), - ...this.checkWords((await this.message.guild.hasFeature('excludeAutomodScamLinks')) ? {} : badLinks) + ...this.checkWords((await this.message.guild.hasFeature('excludeDefaultAutomod')) ? [] : parsedBadWords), + ...this.checkWords((await this.message.guild.hasFeature('excludeAutomodScamLinks')) ? [] : badLinks) }; - if (Object.keys(result).length === 0) return; + if (result.length === 0) return; - const highestOffence = Object.entries(result) - .map(([key, value]) => ({ word: key, ...value })) - .sort((a, b) => b.severity - a.severity)[0]; + const highestOffence = result.sort((a, b) => b.severity - a.severity)[0]; if (highestOffence.severity === undefined || highestOffence.severity === null) { void this.message.guild.sendLogChannel('error', { embeds: [ { title: 'AutoMod Error', - description: `Unable to find severity information for ${util.format.inlineCode(highestOffence.word)}`, + description: `Unable to find severity information for ${util.format.inlineCode(highestOffence.match)}`, color: util.colors.error } ] @@ -86,19 +84,18 @@ export class AutoMod { * @param words The words to check for * @returns The blacklisted words found in the message */ - private checkWords(words: BadWords): BadWords { - if (Object.keys(words).length === 0) return {}; - - const matchedWords: BadWords = {}; - for (const word in words) { - const wordOptions = words[word]; - if (wordOptions.regex) { - if (new RegExp(word).test(this.format(word, wordOptions))) { - matchedWords[word] = wordOptions; + private checkWords(words: BadWordDetails[]): BadWordDetails[] { + if (words.length === 0) return []; + + const matchedWords: BadWordDetails[] = []; + for (const word of words) { + if (word.regex) { + if (new RegExp(word.match).test(this.format(word.match, word))) { + matchedWords.push(word); } } else { - if (this.format(this.message.content, wordOptions).includes(this.format(word, wordOptions))) { - matchedWords[word] = wordOptions; + if (this.format(this.message.content, word).includes(this.format(word.match, word))) { + matchedWords.push(word); } } } @@ -130,7 +127,7 @@ export class AutoMod { includes('check this lol') || includes('airdrop') ) { - const color = this.punish({ severity: Severity.TEMP_MUTE, reason: 'everyone mention and scam phrase' } as HighestOffence); + const color = this.punish({ severity: Severity.TEMP_MUTE, reason: 'everyone mention and scam phrase' } as BadWordDetails); void this.message.guild!.sendLogChannel('automod', { embeds: [ new MessageEmbed() @@ -173,7 +170,7 @@ export class AutoMod { * @param highestOffence The highest offence to punish the user for * @returns The color of the embed that the log should, based on the severity of the offence */ - private punish(highestOffence: HighestOffence) { + private punish(highestOffence: BadWordDetails) { let color; switch (highestOffence.severity) { case Severity.DELETE: { @@ -241,7 +238,7 @@ export class AutoMod { * @param color The color that the log embed should be (based on the severity) * @param offences The other offences that were also matched in the message */ - private async log(highestOffence: HighestOffence, color: `#${string}`, offences: BadWords) { + private async log(highestOffence: BadWordDetails, color: `#${string}`, offences: BadWordDetails[]) { void client.console.info( 'autoMod', `Severity <<${highestOffence.severity}>> action performed on <<${this.message.author.tag}>> (<<${ @@ -360,7 +357,12 @@ export const enum Severity { /** * Details about a blacklisted word */ -interface BadWordDetails { +export interface BadWordDetails { + /** + * The word that is blacklisted + */ + match: string; + /** * The severity of the word */ @@ -387,19 +389,9 @@ interface BadWordDetails { regex: boolean; } -interface HighestOffence extends BadWordDetails { - /** - * The word that is blacklisted - */ - word: string; -} - /** * Blacklisted words mapped to their details */ export interface BadWords { - /** - * The blacklisted word - */ - [key: string]: BadWordDetails; + [category: string]: BadWordDetails[]; } diff --git a/src/lib/extensions/discord-akairo/BushClient.ts b/src/lib/extensions/discord-akairo/BushClient.ts index 65b60eb..cb1e50b 100644 --- a/src/lib/extensions/discord-akairo/BushClient.ts +++ b/src/lib/extensions/discord-akairo/BushClient.ts @@ -419,7 +419,11 @@ export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Re Stat.initModel(this.sharedDB); Global.initModel(this.sharedDB); Shared.initModel(this.sharedDB); - await this.sharedDB.sync({ alter: true }); // Sync all tables to fix everything if updated + await this.sharedDB.sync({ + // Sync all tables to fix everything if updated + // if another instance restarts we don't want to overwrite new changes made in development + alter: this.config.isDevelopment ? true : false + }); await this.console.success('startup', `Successfully connected to <<shared database>>.`, false); } catch (e) { await this.console.error( @@ -473,7 +477,7 @@ export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Re public override isSuperUser(user: BushUserResolvable): boolean { const userID = this.users.resolveId(user)!; - return !!client.cache.shared.superUsers.includes(userID) || this.config.owners.includes(userID); + return client.cache.shared.superUsers.includes(userID) || this.config.owners.includes(userID); } } diff --git a/src/lib/extensions/discord-akairo/BushClientUtil.ts b/src/lib/extensions/discord-akairo/BushClientUtil.ts index cdb883d..3e066c8 100644 --- a/src/lib/extensions/discord-akairo/BushClientUtil.ts +++ b/src/lib/extensions/discord-akairo/BushClientUtil.ts @@ -476,7 +476,7 @@ export class BushClientUtil extends ClientUtil { * @param key The key of the element in the shared cache to update. * @param value The value to add/remove from the array. */ - public async insertOrRemoveFromShared<K extends keyof typeof client['cache']['shared']>( + public async insertOrRemoveFromShared<K extends Exclude<keyof typeof client['cache']['shared'], 'badWords'>>( action: 'add' | 'remove', key: K, value: typeof client['cache']['shared'][K][0] @@ -510,7 +510,7 @@ export class BushClientUtil extends ClientUtil { * @param key The key in the shared cache to update. * @param value The value to set the key to. */ - public async setShared<K extends keyof typeof client['cache']['shared']>( + public async setShared<K extends Exclude<keyof typeof client['cache']['shared'], 'badWords'>>( key: K, value: typeof client['cache']['shared'][K] ): Promise<Shared | void> { diff --git a/src/lib/models/Global.ts b/src/lib/models/Global.ts index 1deb090..8e467f6 100644 --- a/src/lib/models/Global.ts +++ b/src/lib/models/Global.ts @@ -1,7 +1,6 @@ import { type Snowflake } from 'discord.js'; import { type Sequelize } from 'sequelize'; import { BaseModel } from './BaseModel.js'; -import { jsonArray } from './__helpers.js'; const { DataTypes } = (await import('sequelize')).default; export interface GlobalModel { @@ -54,10 +53,10 @@ export class Global extends BaseModel<GlobalModel, GlobalModelCreationAttributes Global.init( { environment: { type: DataTypes.STRING, primaryKey: true }, - disabledCommands: jsonArray('disabledCommands'), - blacklistedUsers: jsonArray('blacklistedUsers'), - blacklistedGuilds: jsonArray('blacklistedGuilds'), - blacklistedChannels: jsonArray('blacklistedChannels') + disabledCommands: { type: DataTypes.JSONB, allowNull: false, defaultValue: [] }, + blacklistedUsers: { type: DataTypes.JSONB, allowNull: false, defaultValue: [] }, + blacklistedGuilds: { type: DataTypes.JSONB, allowNull: false, defaultValue: [] }, + blacklistedChannels: { type: DataTypes.JSONB, allowNull: false, defaultValue: [] } }, { sequelize } ); diff --git a/src/lib/models/Guild.ts b/src/lib/models/Guild.ts index 80bd119..34f6747 100644 --- a/src/lib/models/Guild.ts +++ b/src/lib/models/Guild.ts @@ -1,10 +1,9 @@ import { ExcludeEnum, type Snowflake } from 'discord.js'; import { ChannelTypes } from 'discord.js/typings/enums'; import { type Sequelize } from 'sequelize'; -import { type BadWords } from '../common/AutoMod.js'; +import { BadWordDetails } from '../common/AutoMod.js'; import { type BushClient } from '../extensions/discord-akairo/BushClient.js'; import { BaseModel } from './BaseModel.js'; -import { jsonArray, jsonObject } from './__helpers.js'; const { DataTypes } = (await import('sequelize')).default; export interface GuildModel { @@ -18,7 +17,7 @@ export interface GuildModel { punishmentEnding: string; disabledCommands: string[]; lockdownChannels: Snowflake[]; - autoModPhases: BadWords; + autoModPhases: BadWordDetails[]; enabledFeatures: GuildFeatures[]; joinRoles: Snowflake[]; logChannels: LogChannelDB; @@ -39,7 +38,7 @@ export interface GuildModelCreationAttributes { punishmentEnding?: string; disabledCommands?: string[]; lockdownChannels?: Snowflake[]; - autoModPhases?: BadWords; + autoModPhases?: BadWordDetails[]; enabledFeatures?: GuildFeatures[]; joinRoles?: Snowflake[]; logChannels?: LogChannelDB; @@ -103,7 +102,7 @@ export class Guild extends BaseModel<GuildModel, GuildModelCreationAttributes> i /** * Custom automod phases */ - public declare autoModPhases: BadWords; + public declare autoModPhases: BadWordDetails[]; /** * The features enabled in a guild @@ -149,24 +148,27 @@ export class Guild extends BaseModel<GuildModel, GuildModelCreationAttributes> i { id: { type: DataTypes.STRING, primaryKey: true }, prefix: { type: DataTypes.TEXT, allowNull: false, defaultValue: client.config.prefix }, - autoPublishChannels: jsonArray('autoPublishChannels'), - blacklistedChannels: jsonArray('blacklistedChannels'), - blacklistedUsers: jsonArray('blacklistedChannels'), + autoPublishChannels: { type: DataTypes.JSONB, allowNull: false, defaultValue: [] }, + blacklistedChannels: { type: DataTypes.JSONB, allowNull: false, defaultValue: [] }, + blacklistedUsers: { type: DataTypes.JSONB, allowNull: false, defaultValue: [] }, welcomeChannel: { type: DataTypes.STRING, allowNull: true }, muteRole: { type: DataTypes.STRING, allowNull: true }, punishmentEnding: { type: DataTypes.TEXT, allowNull: true }, - disabledCommands: jsonArray('disabledCommands'), - lockdownChannels: jsonArray('lockdownChannels'), - autoModPhases: jsonObject('autoModPhases'), - enabledFeatures: jsonArray( - 'enabledFeatures', - Object.keys(guildFeaturesObj).filter((key) => guildFeaturesObj[key as keyof typeof guildFeaturesObj].default) - ), - joinRoles: jsonArray('joinRoles'), - logChannels: jsonObject('logChannels'), - bypassChannelBlacklist: jsonArray('bypassChannelBlacklist'), - noXpChannels: jsonArray('noXpChannels'), - levelRoles: jsonObject('levelRoles'), + disabledCommands: { type: DataTypes.JSONB, allowNull: false, defaultValue: [] }, + lockdownChannels: { type: DataTypes.JSONB, allowNull: false, defaultValue: [] }, + autoModPhases: { type: DataTypes.JSONB, allowNull: false, defaultValue: [] }, + enabledFeatures: { + type: DataTypes.JSONB, + allowNull: false, + defaultValue: Object.keys(guildFeaturesObj).filter( + (key) => guildFeaturesObj[key as keyof typeof guildFeaturesObj].default + ) + }, + joinRoles: { type: DataTypes.JSONB, allowNull: false, defaultValue: [] }, + logChannels: { type: DataTypes.JSONB, allowNull: false, defaultValue: {} }, + bypassChannelBlacklist: { type: DataTypes.JSONB, allowNull: false, defaultValue: [] }, + noXpChannels: { type: DataTypes.JSONB, allowNull: false, defaultValue: [] }, + levelRoles: { type: DataTypes.JSONB, allowNull: false, defaultValue: {} }, levelUpChannel: { type: DataTypes.STRING, allowNull: true } }, { sequelize } diff --git a/src/lib/models/ModLog.ts b/src/lib/models/ModLog.ts index 7ddd64c..8d6a08c 100644 --- a/src/lib/models/ModLog.ts +++ b/src/lib/models/ModLog.ts @@ -2,7 +2,6 @@ import { type Snowflake } from 'discord.js'; import { nanoid } from 'nanoid'; import { type Sequelize } from 'sequelize'; import { BaseModel } from './BaseModel.js'; -import { jsonBoolean } from './__helpers.js'; const { DataTypes } = (await import('sequelize')).default; export enum ModLogType { @@ -116,8 +115,8 @@ export class ModLog extends BaseModel<ModLogModel, ModLogModelCreationAttributes reason: { type: DataTypes.TEXT, allowNull: true }, guild: { type: DataTypes.STRING, references: { model: 'Guilds', key: 'id' } }, evidence: { type: DataTypes.TEXT, allowNull: true }, - pseudo: jsonBoolean('pseudo'), - hidden: jsonBoolean('hidden') + pseudo: { type: DataTypes.BOOLEAN, allowNull: false, defaultValue: false }, + hidden: { type: DataTypes.BOOLEAN, allowNull: false, defaultValue: false } }, { sequelize } ); diff --git a/src/lib/models/Shared.ts b/src/lib/models/Shared.ts index dd7682b..a240ef9 100644 --- a/src/lib/models/Shared.ts +++ b/src/lib/models/Shared.ts @@ -1,18 +1,25 @@ -import { type Sequelize } from 'sequelize'; +import { Snowflake } from 'discord.js'; +import type { Sequelize } from 'sequelize'; +import type { BadWords } from '../common/AutoMod.js'; import { BaseModel } from './BaseModel.js'; -import { jsonArray } from './__helpers.js'; const { DataTypes } = (await import('sequelize')).default; export interface SharedModel { primaryKey: 0; - superUsers: string[]; + superUsers: Snowflake[]; + privilegedUsers: Snowflake[]; + badLinksSecret: string[]; badLinks: string[]; + badWords: BadWords; } export interface SharedModelCreationAttributes { primaryKey?: 0; - superUsers?: string[]; + superUsers?: Snowflake[]; + privilegedUsers?: Snowflake[]; + badLinksSecret?: string[]; badLinks?: string[]; + badWords?: BadWords; } export class Shared extends BaseModel<SharedModel, SharedModelCreationAttributes> implements SharedModel { @@ -24,15 +31,29 @@ export class Shared extends BaseModel<SharedModel, SharedModelCreationAttributes /** * Trusted users. */ - public declare superUsers: string[]; + public declare superUsers: Snowflake[]; - //todo /** - * Bad links. + * Users that have all permissions that devs have except eval. + */ + public declare privilegedUsers: Snowflake[]; + + /** + * Non-public bad links. + */ + public declare badLinksSecret: string[]; + + /** + * Public Bad links. */ public declare badLinks: string[]; /** + * Bad words. + */ + public declare badWords: BadWords; + + /** * Initializes the model. * @param sequelize The sequelize instance. */ @@ -40,8 +61,11 @@ export class Shared extends BaseModel<SharedModel, SharedModelCreationAttributes Shared.init( { primaryKey: { type: DataTypes.INTEGER, primaryKey: true, validate: { min: 0, max: 0 } }, - superUsers: jsonArray('superUsers'), - badLinks: jsonArray('badLinks') + superUsers: { type: DataTypes.JSONB, allowNull: false, defaultValue: [] }, + privilegedUsers: { type: DataTypes.JSONB, allowNull: false, defaultValue: [] }, + badLinksSecret: { type: DataTypes.JSONB, allowNull: false, defaultValue: [] }, + badLinks: { type: DataTypes.JSONB, allowNull: false, defaultValue: [] }, + badWords: { type: DataTypes.JSONB, allowNull: false, defaultValue: {} } }, { sequelize, freezeTableName: true } ); diff --git a/src/lib/models/Stat.ts b/src/lib/models/Stat.ts index 06ee21f..8f90724 100644 --- a/src/lib/models/Stat.ts +++ b/src/lib/models/Stat.ts @@ -1,6 +1,5 @@ import { type Sequelize } from 'sequelize'; import { BaseModel } from './BaseModel.js'; -import { jsonBigint } from './__helpers.js'; const { DataTypes } = (await import('sequelize')).default; type Environment = 'production' | 'development' | 'beta'; @@ -34,7 +33,17 @@ export class Stat extends BaseModel<StatModel, StatModelCreationAttributes> impl Stat.init( { environment: { type: DataTypes.STRING, primaryKey: true }, - commandsUsed: jsonBigint('commandsUsed') + commandsUsed: { + type: DataTypes.TEXT, + get: function (): bigint { + return BigInt(this.getDataValue('commandsUsed')); + }, + set: function (val: bigint) { + return this.setDataValue('commandsUsed', <any>`${val}`); + }, + allowNull: false, + defaultValue: `${0n}` + } }, { sequelize } ); diff --git a/src/lib/models/StickyRole.ts b/src/lib/models/StickyRole.ts index bbe81ae..4beb4cf 100644 --- a/src/lib/models/StickyRole.ts +++ b/src/lib/models/StickyRole.ts @@ -1,7 +1,6 @@ import { type Snowflake } from 'discord.js'; import { type Sequelize } from 'sequelize'; import { BaseModel } from './BaseModel.js'; -import { jsonArray } from './__helpers.js'; const { DataTypes } = (await import('sequelize')).default; export interface StickyRoleModel { @@ -47,7 +46,7 @@ export class StickyRole extends BaseModel<StickyRoleModel, StickyRoleModelCreati { user: { type: DataTypes.STRING, allowNull: false }, guild: { type: DataTypes.STRING, allowNull: false }, - roles: jsonArray('roles'), + roles: { type: DataTypes.JSONB, allowNull: false, defaultValue: [] }, nickname: { type: DataTypes.STRING, allowNull: true } }, { sequelize } diff --git a/src/lib/models/__helpers.ts b/src/lib/models/__helpers.ts deleted file mode 100644 index bbfe328..0000000 --- a/src/lib/models/__helpers.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { type Model } from 'sequelize'; -const { DataTypes } = (await import('sequelize')).default; - -export function jsonParseGet(this: Model, key: string): any { - return JSON.parse(this.getDataValue(key)); -} -export function jsonParseSet(this: Model, key: string, value: any): any { - return this.setDataValue(key, JSON.stringify(value)); -} - -export function jsonObject(key: string): any { - return { - type: DataTypes.TEXT, - get: function (): Record<string, unknown> { - return jsonParseGet.call(this, key); - }, - set: function (val: Record<string, unknown>) { - return jsonParseSet.call(this, key, val); - }, - allowNull: false, - defaultValue: '{}' - }; -} - -export function jsonArray(key: string, defaultValue: string[] = []): any { - return { - type: DataTypes.TEXT, - get: function (): string[] { - return jsonParseGet.call(this, key); - }, - set: function (val: string[]) { - return jsonParseSet.call(this, key, val); - }, - allowNull: false, - defaultValue: JSON.stringify(defaultValue) - }; -} - -export function jsonBoolean(key: string, defaultVal = false): any { - return { - type: DataTypes.STRING, - get: function (): boolean { - return jsonParseGet.call(this, key); - }, - set: function (val: boolean) { - return jsonParseSet.call(this, key, val); - }, - allowNull: false, - defaultValue: `${defaultVal}` - }; -} - -export function jsonBigint(key: string, defaultVal = 0n): any { - return { - type: DataTypes.TEXT, - get: function (): bigint { - return BigInt(this.getDataValue(key)); - }, - set: function (val: bigint) { - return this.setDataValue(key, `${val}`); - }, - allowNull: false, - defaultValue: `${defaultVal}` - }; -} diff --git a/src/lib/utils/BushCache.ts b/src/lib/utils/BushCache.ts index 5654495..1f50fba 100644 --- a/src/lib/utils/BushCache.ts +++ b/src/lib/utils/BushCache.ts @@ -1,4 +1,4 @@ -import { type Guild } from '#lib'; +import { BadWords, GlobalModel, SharedModel, type Guild } from '#lib'; import { Collection, type Snowflake } from 'discord.js'; export class BushCache { @@ -7,16 +7,19 @@ export class BushCache { public guilds = new GuildCache(); } -export class GlobalCache { +export class GlobalCache implements Omit<GlobalModel, 'environment'> { public disabledCommands: string[] = []; public blacklistedChannels: Snowflake[] = []; public blacklistedGuilds: Snowflake[] = []; public blacklistedUsers: Snowflake[] = []; } -export class SharedCache { +export class SharedCache implements Omit<SharedModel, 'primaryKey'> { public superUsers: Snowflake[] = []; + public privilegedUsers: Snowflake[] = []; + public badLinksSecret: string[] = []; public badLinks: string[] = []; + public badWords: BadWords = {}; } export class GuildCache extends Collection<Snowflake, Guild> {} |