You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

119 lines
3.3 KiB

2 years ago
import * as dotenv from "dotenv"; // see https://github.com/motdotla/dotenv#how-do-i-use-dotenv-with-import
dotenv.config();
import {
ChannelType,
Client,
Colors,
EmbedBuilder,
GatewayIntentBits,
SnowflakeUtil,
} from "discord.js";
import {
type ChatCompletionRequestMessage,
Configuration,
OpenAIApi,
} from "openai";
const SYSTEM_MESSAGE =
2 years ago
"You are Smolhaj, a Discord bot. You are helpful and friendly, and answers concisely. Due to the group nature of Discord, Messages not by you will be prefixed with a username, followed by a colon.";
2 years ago
const client = new Client({
intents: [
GatewayIntentBits.MessageContent,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.Guilds
],
});
const configuration = new Configuration({
apiKey: process.env.OPENAI_API_KEY,
});
const openai = new OpenAIApi(configuration);
client.on("ready", () => {
console.log(`Logged in as ${client.user?.tag}!`);
});
client.on("messageCreate", async (message) => {
if (message.channelId != process.env.CHANNEL) return;
if (message.webhookId) return;
if (message.author.bot) return;
if (message.content.startsWith("\\")) return;
if (message.channel.type != ChannelType.GuildText) return;
await message.channel.sendTyping();
const typingTimer = setInterval(() => {
if (message.channel.type == ChannelType.GuildText)
message.channel.sendTyping();
}, 5000);
try {
const msgs = await message.channel.messages.fetch({
after: SnowflakeUtil.generate({
timestamp: Date.now() - 5 * 60 * 1000,
}).toString(),
});
const context = [
...msgs
.filter((msg) => {
2 years ago
if (msg.webhookId) return false;
if (msg.author.bot && msg.author !== msg.author.client.user)
2 years ago
return false;
2 years ago
if (msg.content.startsWith("\\")) return false;
2 years ago
return true;
})
.mapValues<ChatCompletionRequestMessage>((msg) => {
if (msg.author === msg.author.client.user) {
return { role: "assistant", content: msg.content };
}
return {
role: "user",
content: `${msg.member?.displayName ?? msg.author.username}:${
msg.content
}`,
};
})
.values(),
].reverse();
const response = await openai.createChatCompletion({
model: "gpt-3.5-turbo",
messages: [{ role: "system", content: SYSTEM_MESSAGE }, ...context],
});
const responseMessage = response.data.choices[0].message;
if (!responseMessage) return;
const isAppropriate = await openai
.createModeration({ input: responseMessage.content })
.then(({ data }) => !data.results[0].flagged);
if (isAppropriate) {
await message.channel.send({
content: responseMessage.content,
allowedMentions: { parse: ["users"] },
});
} else {
await message.channel.send({
embeds: [
new EmbedBuilder()
.setTitle("Response flagged!")
.setDescription(
"The generated response may have been inappropriate."
)
.setColor(Colors.Red),
],
});
}
clearInterval(typingTimer);
} catch (e) {
clearInterval(typingTimer);
throw e;
}
});
client.login(process.env.TOKEN);