diff options
author | IRONM00N <64110067+IRONM00N@users.noreply.github.com> | 2022-02-16 17:40:02 -0500 |
---|---|---|
committer | IRONM00N <64110067+IRONM00N@users.noreply.github.com> | 2022-02-16 17:40:02 -0500 |
commit | 43428f8a747f1b3e6b2a3418173910ce3ff1866c (patch) | |
tree | d1e7892fbd9d5f5881e9f34d3053a9fceb796c1d /src | |
parent | b04c2b02c012baba9bbf2b8f3fb1a08c7796d38e (diff) | |
download | tanzanite-43428f8a747f1b3e6b2a3418173910ce3ff1866c.tar.gz tanzanite-43428f8a747f1b3e6b2a3418173910ce3ff1866c.tar.bz2 tanzanite-43428f8a747f1b3e6b2a3418173910ce3ff1866c.zip |
feat: start testing perspectiveApi, and fix checkScamMentions
Diffstat (limited to 'src')
-rw-r--r-- | src/config/example-options.ts | 3 | ||||
-rw-r--r-- | src/lib/common/AutoMod.ts | 163 | ||||
-rw-r--r-- | src/lib/extensions/discord-akairo/BushClient.ts | 8 | ||||
-rw-r--r-- | src/lib/models/instance/Guild.ts | 17 | ||||
-rw-r--r-- | src/lib/utils/Config.ts | 1 |
5 files changed, 133 insertions, 59 deletions
diff --git a/src/config/example-options.ts b/src/config/example-options.ts index 338428e..1b384c4 100644 --- a/src/config/example-options.ts +++ b/src/config/example-options.ts @@ -9,7 +9,8 @@ export default new Config({ wolframAlphaAppId: '[APP_ID]', imgurClientId: '[CLIENT_ID]', imgurClientSecret: '[CLIENT_SECRET]', - sentryDsn: 'SENTRY_DSN' + sentryDsn: 'SENTRY_DSN', + perspectiveApiKey: '[PERSPECTIVE_API_KEY]' }, environment: 'development', owners: [ diff --git a/src/lib/common/AutoMod.ts b/src/lib/common/AutoMod.ts index 784085d..fc5532b 100644 --- a/src/lib/common/AutoMod.ts +++ b/src/lib/common/AutoMod.ts @@ -1,14 +1,7 @@ import { banResponse, Moderation, type BushButtonInteraction, type BushMessage } from '#lib'; -import { - ActionRow, - ButtonComponent, - ButtonStyle, - ChannelType, - Embed, - GuildMember, - PermissionFlagsBits, - type TextChannel -} from 'discord.js'; +import assert from 'assert'; +import chalk from 'chalk'; +import { ActionRow, ButtonComponent, ButtonStyle, Embed, GuildMember, PermissionFlagsBits, type TextChannel } from 'discord.js'; /** * Handles auto moderation functionality. @@ -33,59 +26,77 @@ export class AutoMod { void this.handle(); } + private get isImmune() { + if (!this.message.inGuild()) return false; + assert(this.message.member); + + if (this.message.author.isOwner()) return true; + if (this.message.guild.ownerId === this.message.author.id) return true; + if (this.message.member.permissions.has('Administrator')) return true; + + return false; + } + /** * Handles the auto moderation */ private async handle() { - if (this.message.channel.type === ChannelType.DM || !this.message.guild) return; + if (!this.message.inGuild()) return; if (!(await this.message.guild.hasFeature('automod'))) return; if (this.message.author.bot) return; - if (this.message.author.isOwner()) return; - - 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])]; - - const badLinks: BadWordDetails[] = uniqueLinks.map((link) => ({ - match: link, - severity: Severity.PERM_MUTE, - ignoreSpaces: false, - 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')) ? [] : parsedBadWords), - ...this.checkWords((await this.message.guild.hasFeature('excludeAutomodScamLinks')) ? [] : badLinks) - ]; - - if (result.length === 0) return; - - const highestOffence = result.sort((a, b) => b.severity - a.severity)[0]; + traditional: { + if (this.isImmune) break traditional; + 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])]; + + const badLinks: BadWordDetails[] = uniqueLinks.map((link) => ({ + match: link, + severity: Severity.PERM_MUTE, + ignoreSpaces: false, + 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')) ? [] : parsedBadWords), + ...this.checkWords((await this.message.guild.hasFeature('excludeAutomodScamLinks')) ? [] : badLinks) + ]; + + if (result.length === 0) break traditional; + + 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.match)}`, + color: util.colors.error + } + ] + }); + } else { + const color = this.punish(highestOffence); + void this.log(highestOffence, color, result); + } + } - 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.match)}`, - color: util.colors.error - } - ] - }); - } else { - const color = this.punish(highestOffence); - void this.log(highestOffence, color, result); + other: { + if (this.isImmune) break other; + if (!this.punished && (await this.message.guild.hasFeature('delScamMentions'))) void this.checkScamMentions(); } - if (!this.punished && (await this.message.guild.hasFeature('delScamMentions'))) void this.checkScamMentions(); + if (!this.punished && (await this.message.guild.hasFeature('perspectiveApi'))) void this.checkPerspectiveApi(); } /** @@ -166,6 +177,52 @@ export class AutoMod { } } + private async checkPerspectiveApi() { + if (!client.config.isDevelopment) return; + + if (!this.message.content) return; + client.perspective.comments.analyze( + { + key: client.config.credentials.perspectiveApiKey, + resource: { + comment: { + text: this.message.content + }, + requestedAttributes: { + TOXICITY: {}, + SEVERE_TOXICITY: {}, + IDENTITY_ATTACK: {}, + INSULT: {}, + PROFANITY: {}, + THREAT: {}, + SEXUALLY_EXPLICIT: {}, + FLIRTATION: {} + } + } + }, + (err: any, response: any) => { + if (err) return console.log(err?.message); + + const normalize = (val: number, min: number, max: number) => (val - min) / (max - min); + + const color = (val: number) => { + if (val >= 0.5) { + const x = 194 - Math.round(normalize(val, 0.5, 1) * 194); + return chalk.rgb(194, x, 0)(val); + } else { + const x = Math.round(normalize(val, 0, 0.5) * 194); + return chalk.rgb(x, 194, 0)(val); + } + }; + + console.log(chalk.cyan(this.message.content)); + Object.entries(response.data.attributeScores) + .sort(([a], [b]) => a.localeCompare(b)) + .forEach(([key, value]: any[]) => console.log(chalk.white(key), color(value.summaryScore.value))); + } + ); + } + /** * Format a string according to the word options * @param string The string to format diff --git a/src/lib/extensions/discord-akairo/BushClient.ts b/src/lib/extensions/discord-akairo/BushClient.ts index 904ab51..43ae139 100644 --- a/src/lib/extensions/discord-akairo/BushClient.ts +++ b/src/lib/extensions/discord-akairo/BushClient.ts @@ -41,6 +41,7 @@ import { type WebhookEditMessageOptions } from 'discord.js'; import EventEmitter from 'events'; +import { google } from 'googleapis'; import path from 'path'; import readline from 'readline'; import type { Options as SequelizeOptions, Sequelize as SequelizeType } from 'sequelize'; @@ -191,6 +192,11 @@ export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Re public highlightManager = new HighlightManager(); /** + * The perspective api + */ + public perspective: any; + + /** * @param config The configuration for the bot. */ public constructor(config: Config) { @@ -335,6 +341,8 @@ export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Re process.exit(2); } + this.perspective = await google.discoverAPI<any>('https://commentanalyzer.googleapis.com/$discovery/rest?version=v1alpha1'); + this.commandHandler.useInhibitorHandler(this.inhibitorHandler); this.commandHandler.useListenerHandler(this.listenerHandler); this.commandHandler.useTaskHandler(this.taskHandler); diff --git a/src/lib/models/instance/Guild.ts b/src/lib/models/instance/Guild.ts index 4d7f208..cdf3552 100644 --- a/src/lib/models/instance/Guild.ts +++ b/src/lib/models/instance/Guild.ts @@ -342,11 +342,12 @@ export const guildFeaturesObj = asGuildFeature({ default: false }, // todo implement a better auto thread system - // autoThread: { - // name: 'Auto Thread', - // description: 'Creates a new thread for messages in configured channels.', - // default: false - // }, + autoThread: { + name: 'Auto Thread', + description: 'Creates a new thread for messages in configured channels.', + default: false, + notConfigurable: true + }, blacklistedFile: { name: 'Blacklisted File', description: 'Automatically deletes malicious files.', @@ -392,6 +393,12 @@ export const guildFeaturesObj = asGuildFeature({ description: 'Allow users to appeal their punishments and send the appeal to the configured channel.', default: false, notConfigurable: true + }, + perspectiveApi: { + name: 'Perspective API', + description: 'Use the Perspective API to detect toxicity.', + default: false, + notConfigurable: true } }); diff --git a/src/lib/utils/Config.ts b/src/lib/utils/Config.ts index bc31964..ce5ec06 100644 --- a/src/lib/utils/Config.ts +++ b/src/lib/utils/Config.ts @@ -62,6 +62,7 @@ interface Credentials { imgurClientId: string; imgurClientSecret: string; sentryDsn: string; + perspectiveApiKey: string; } type Environment = 'production' | 'beta' | 'development'; |