-
Notifications
You must be signed in to change notification settings - Fork 27
/
Copy pathbot.js
114 lines (91 loc) · 3.48 KB
/
bot.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
const { Client, GatewayIntentBits } = require('discord.js');
const { OpenAI } = require("openai");
require("dotenv").config();
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY
});
// Discord Client
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent
]
});
const sleep = (ms) => {
return new Promise(resolve => setTimeout(resolve, ms));
}
// When discord bot has started up
client.once('ready', () => {
console.log('Bot is ready!');
});
const threadMap = {};
const getOpenAiThreadId = (discordThreadId) => {
// Replace this in-memory implementation with a database (e.g. DynamoDB, Firestore, Redis)
return threadMap[discordThreadId];
}
const addThreadToMap = (discordThreadId, openAiThreadId) => {
threadMap[discordThreadId] = openAiThreadId;
}
const terminalStates = ["cancelled", "failed", "completed", "expired"];
const statusCheckLoop = async (openAiThreadId, runId) => {
const run = await openai.beta.threads.runs.retrieve(
openAiThreadId,
runId
);
if(terminalStates.indexOf(run.status) < 0){
await sleep(1000);
return statusCheckLoop(openAiThreadId, runId);
}
// console.log(run);
return run.status;
}
const addMessage = (threadId, content) => {
// console.log(content);
return openai.beta.threads.messages.create(
threadId,
{ role: "user", content }
)
}
// This event will run every time a message is received
client.on('messageCreate', async message => {
if (message.author.bot || !message.content || message.content === '') return; //Ignore bot messages
// console.log(message);
const discordThreadId = message.channel.id;
let openAiThreadId = getOpenAiThreadId(discordThreadId);
let messagesLoaded = false;
if(!openAiThreadId){
const thread = await openai.beta.threads.create();
openAiThreadId = thread.id;
addThreadToMap(discordThreadId, openAiThreadId);
if(message.channel.isThread()){
//Gather all thread messages to fill out the OpenAI thread since we haven't seen this one yet
const starterMsg = await message.channel.fetchStarterMessage();
const otherMessagesRaw = await message.channel.messages.fetch();
const otherMessages = Array.from(otherMessagesRaw.values())
.map(msg => msg.content)
.reverse(); //oldest first
const messages = [starterMsg.content, ...otherMessages]
.filter(msg => !!msg && msg !== '')
// console.log(messages);
await Promise.all(messages.map(msg => addMessage(openAiThreadId, msg)));
messagesLoaded = true;
}
}
// console.log(openAiThreadId);
if(!messagesLoaded){ //If this is for a thread, assume msg was loaded via .fetch() earlier
await addMessage(openAiThreadId, message.content);
}
const run = await openai.beta.threads.runs.create(
openAiThreadId,
{ assistant_id: process.env.ASSISTANT_ID }
)
const status = await statusCheckLoop(openAiThreadId, run.id);
const messages = await openai.beta.threads.messages.list(openAiThreadId);
let response = messages.data[0].content[0].text.value;
response = response.substring(0, 1999) //Discord msg length limit when I was testing
console.log(response);
message.reply(response);
});
// Authenticate Discord
client.login(process.env.DISCORD_TOKEN);