From 7411648d022db823fffe7c12e884ccc6305b83d6 Mon Sep 17 00:00:00 2001 From: Wroclaw Date: Tue, 14 Mar 2023 23:44:43 +0100 Subject: [PATCH] Check messages aganist OpenAI moderation API --- src/index.ts | 9 +++++++-- src/moderation.ts | 31 +++++++++++++++++++++++++++++++ src/toOpenAIMessages.ts | 2 +- 3 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 src/moderation.ts diff --git a/src/index.ts b/src/index.ts index b739929..63f4424 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,6 +3,7 @@ import { Configuration as OpenAIApiConfiguration, OpenAIApi } from "openai"; import config from "./config.json"; import toOpenAIMessages from "./toOpenAIMessages"; +import Moderation from "./moderation"; const discord = new DiscordApi.Client({ intents: [ @@ -12,7 +13,7 @@ const discord = new DiscordApi.Client({ ] }); -const openai = new OpenAIApi(new OpenAIApiConfiguration({ +export const openai = new OpenAIApi(new OpenAIApiConfiguration({ apiKey: config.tokens.OpenAI })); @@ -29,6 +30,8 @@ discord.on("messageCreate", async message => { messages = messages.filter(m => message.createdTimestamp - m.createdTimestamp < 1000*60*60 ); + messages.forEach(m => Moderation.checkMessage(m)); + message.channel.sendTyping(); const answer = await openai.createChatCompletion({ model: "gpt-3.5-turbo", @@ -36,7 +39,7 @@ discord.on("messageCreate", async message => { max_tokens: 168 }); - message.reply({ + const response = message.reply({ content: answer.data.choices[0].message?.content, allowedMentions: { repliedUser: false, @@ -48,6 +51,8 @@ discord.on("messageCreate", async message => { const channelName: string = message.inGuild() ? `${message.channel.name} (${message.guild.name})` : `@${message.author.tag}`; console.log(`Used ${usage.total_tokens} (${usage.prompt_tokens} + ${usage.completion_tokens}) tokens for ${message.author.tag} (${message.author.id}) in #${channelName}`); } + + Moderation.checkMessage(await response); } catch (e) { console.error(e); diff --git a/src/moderation.ts b/src/moderation.ts new file mode 100644 index 0000000..293753e --- /dev/null +++ b/src/moderation.ts @@ -0,0 +1,31 @@ +import { Collection, Message } from "discord.js"; +import { openai } from "./index"; +import { formatMessage } from "./toOpenAIMessages"; + +export default class Moderation { + /** Represents cache of messages that have been checked aganist OpenAI moderation API. */ + private static cache = new Collection(); + + public static async checkMessage(message: Message): Promise { + if (this.cache.has(message.id)) { + return this.cache.get(message.id) as boolean; + } + + const warningReaction = message.reactions.resolve("⚠"); + // if bot reacted to that message, we already know that it returned true for moderation API + if (warningReaction && warningReaction.me) { + this.cache.set(message.id, true); + return true; + } + + const answer = await openai.createModeration({ + input: formatMessage(message), + }); + + const flagged = answer.data.results[0].flagged; + this.cache.set(message.id, flagged); + if (flagged) message.react("⚠"); + + return flagged; + } +} diff --git a/src/toOpenAIMessages.ts b/src/toOpenAIMessages.ts index 3fd3897..1e89867 100644 --- a/src/toOpenAIMessages.ts +++ b/src/toOpenAIMessages.ts @@ -3,7 +3,7 @@ import { Collection, Message as DiscordMessage } from "discord.js"; import config from "./config.json"; -function formatMessage(message: DiscordMessage): string { +export function formatMessage(message: DiscordMessage): string { let rvalue: string = message.cleanContent; for (const attachment of message.attachments) {