-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathindex.js
450 lines (423 loc) · 14.1 KB
/
index.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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
//imports
const dotenv = require("dotenv");
const {
Client,
Collection,
Events,
GatewayIntentBits,
EmbedBuilder,
ActivityType,
BaseSelectMenuBuilder,
} = require("discord.js");
const { Configuration, OpenAIApi } = require("openai");
const readline = require("node:readline/promises");
const { stdin: input, stdout: output } = require("node:process");
const fs = require("node:fs");
const path = require("node:path");
dotenv.config();
//sets prefix and context
const PREFIX = "K-9";
//gets the openai api key
const configuration = new Configuration({
apiKey: process.env.OPENAI_API_KEY,
});
const openai = new OpenAIApi(configuration);
// create client with necessary intents
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
],
});
// sets the last channel
let channel = "915568009815416845";
let lastChannel = channel;
let c;
// Torchwood image cooldown
let lastTriggered = 0; // Tracks the last time any Torchwood response was triggered
const cooldownTime = 10 * 60 * 1000; // 10 minutes in milliseconds
// allows messages to be sent through the terminal to appear as the bot
async function reader() {
const rl = readline.createInterface({ input, output });
c = client.channels.cache.get(channel);
console.log(`#${c.name}`);
while (true) {
const answer = await rl.question("~> ");
if (answer.indexOf("channel") === 0) {
lastChannel = channel;
channel = answer.split(" ")[1];
c = client.channels.cache.get(channel);
if (!c) {
channel = lastChannel;
c = client.channels.cache.get(channel);
console.log("\x1b[31minvalid channel id\x1b[0m");
console.log(`\n#${c.name}`);
} else {
console.log(`\n#${c.name}`);
}
} else if (answer.trim().length) {
client.channels.cache.get(channel).send(answer);
}
}
}
//checks if the original message has been deleted, and if it has, sends message with a ping instead of a reply
function safeReply(message, reply) {
openai.createModeration({ input: reply }).then(async (res) => {
if (res.data.results[0].flagged) {
safeReply(
message,
"My response was moderated. (This is an error, not an AI response)"
);
try {
client.channels.cache
.get("1018511988478967969")
.send(`Moderated reply: ||${reply}||`);
} catch (error) {
client.channels.cache
.get("915568009815416845")
.send(`Moderated reply: ||${reply}||`);
}
}
//if nothing is flagged, set the model and send the message to the AI
else {
message
.reply(reply)
.catch(() => message.channel.send(`<@${message.author.id}> ${reply}`));
}
return;
});
}
// sets the gpt3 model
async function getGptResponse(prompt, model) {
const gptResponse = await openai.createCompletion({
model: model,
prompt: `${prompt}. ###`,
max_tokens: 60,
temperature: 0.3,
top_p: 0.3,
presence_penalty: 0,
frequency_penalty: 0.5,
stop: ["\n", "END"],
});
// sets the reply to the AI response
const reply = `${gptResponse.data.choices[0].text.trim()}`;
if (reply.length) {
if (!reply.includes("@everyone" || "@here" || "@&")) {
return reply;
} else {
const newReply = "This message could mass ping users, and has been blocked. (This is an error, not an AI response)";
return newReply;
}
} else {
return "Input unknown. Please try again. (This is an error, not an AI response)\nIf this keeps happening, please report the issue on the [support page](https://k-9.vercel.app/Support.html)";
}
}
// when the client is ready and logged into the discord bot, log in the console.
client.on("ready", async () => {
console.log("Logged in as " + client.user.username);
reader();
// Set the presence outside the callback function
client.user.setPresence({
activities: [
{
name: "the TARDIS",
type: ActivityType.Watching,
},
],
});
try {
client.channels.cache
.get("1018199943774732410")
.send(`System restarting. All primary drives functioning.`);
} catch (error) {
client.channels.cache
.get("915568009815416845")
.send(`System restarting. All primary drives functioning.`);
}
//remove members from role
try {
const guild = client.guilds.cache.get("1018199943330140170");
const members = await guild.members.fetch();
members.forEach((member) => {
setTimeout(() => {
member.roles.remove("1124478121853321328").catch(console.log);
}, 2000);
});
} catch (error) {}
setInterval(() => {
const now = new Date();
// Send the message at midnight
// if (now.getHours() === 0 && now.getMinutes() === 0) {
// try {
// const channel = client.channels.cache.get("1018199943774732410");
// channel.send(`Christmas is <t:1735128000:R>!`);
// } catch {
// const channel = client.channels.cache.get("915568009815416845");
// channel.send(`Christmas is <t:1735128000:R>!`);
// }
// }
// scheduled restart
if (now.getHours() === 6 && now.getMinutes() === 0) {
const { restart } = require("./restart");
try {
restart();
} catch (error) {
console.log("There was an issue while trying to restart");
}
}
// Send the message at midday
// if (now.getHours() === 12 && now.getMinutes() === 0) {
// try {
// const channel = client.channels.cache.get("1018199943774732410");
// channel.send(`Christmas is <t:1735128000:R>!`);
// } catch {
// const channel = client.channels.cache.get("915568009815416845");
// channel.send(`Christmas is <t:1735128000:R>!`);
// }
// }
// scheduled restart
if (now.getHours() === 18 && now.getMinutes() === 0) {
const { restart } = require("./restart");
try {
restart();
} catch (error) {
console.log("There was an issue while trying to restart");
}
}
}, 60 * 1000); // Check every minute
});
//crash prevention
process.on("unhandledRejection", async (reason, promise) => {
console.log("Unhandled Rejection at:", promise, "reason", reason);
});
process.on("uncaughtException", (err) => {
console.log("Uncaught Exception:", err);
});
process.on("uncaughtExceptionMonitor", (err, origin) => {
console.log("Uncaught Exception Monitor", err, origin);
});
//when a member joins, send them a DM
client.on("guildMemberAdd", async (member) => {
const DMEmbed = new EmbedBuilder()
.setColor("#003b6f")
.setTitle("Welcome to Bigger on the Inside!")
.setURL("https://k-9.vercel.app/index.html")
.setDescription("I'm K-9, here to help :)")
.setThumbnail("attachment://dog.png")
.addFields(
{
name: "Getting started ",
value:
'Head back to the "Channels & Roles" section to get a colour role!\n\nWant to talk to me? Just put `K-9` before your message in the server! ',
},
{ name: "\u200B", value: "\u200B" },
{
name: "Want to know what every channel is for? Click here!",
value: "<#1018443553862586388>",
inline: true,
},
{
name: "Introduce yourself!",
value: "<#1018442634005598269>",
inline: true,
}
)
.addFields({
name: "Join the conversation!",
value: "<#1018199943774732410>",
inline: true,
})
.setImage("attachment://BOTI_logo.png")
.setFooter({
text: "Hope you enjoy your stay!!",
});
try {
// Send a direct message to the member
await member.send({
embeds: [DMEmbed],
files: ["./assets/dog.png", "./assets/BOTI_logo.png"],
});
if (member.guild.id === "1018199943330140170") {
client.channels.cache
.get("1018199943330140172")
.send(
`<:Affirmative:1019680728759419011> Welcome to Bigger on the Inside <@${member.id}>!`
);
}
} catch (error) {
client.channels.cache
.get("1018199943330140172")
.send(`Welcome to Bigger on the Inside <@${member.id}>!`);
}
});
//checks if the message is from a bot or if the mesage doesn't contain the 'K-9' prefix
client.on("messageCreate", async function (message) {
if (message.content == "!!restart") {
const { restart } = require("./restart");
await message.reply("Forcing restart");
try {
restart();
} catch (error) {
await message.channel.send("There was an issue while trying to restart");
}
}
if (message.content.toLowerCase().includes("dw")) {
await message.react(":dw:1086049130075394068");
}
// Torchwood images (with cooldown)
const currentTime = Date.now();
if (
message.content.toLowerCase().includes("jack") ||
message.content.toLowerCase().includes("ianto") ||
message.content.toLowerCase().includes("gwen") ||
message.content.toLowerCase().includes("owen") ||
message.content.toLowerCase().includes("tosh")
) {
// Check if the cooldown period has passed
if (currentTime - lastTriggered < cooldownTime) {
return; // Cooldown active, do nothing
}
// Update the last triggered time
lastTriggered = currentTime;
// Send the appropriate image
if (message.content.toLowerCase().includes("jack")) {
try {
await message.reply(
"https://cdn.discordapp.com/attachments/915568009815416845/1315388340559679578/jork.png"
);
} catch {
message.channel.send(
"https://cdn.discordapp.com/attachments/915568009815416845/1315388340559679578/jork.png"
);
}
} else if (message.content.toLowerCase().includes("ianto")) {
try {
await message.reply(
"https://cdn.discordapp.com/attachments/915568009815416845/1315388341071646813/fanta.png"
);
} catch {
message.channel.send(
"https://cdn.discordapp.com/attachments/915568009815416845/1315388341071646813/fanta.png"
);
}
} else if (message.content.toLowerCase().includes("gwen")) {
try {
await message.reply(
"https://cdn.discordapp.com/attachments/915568009815416845/1315388341830811678/hen.png"
);
} catch {
message.channel.send(
"https://cdn.discordapp.com/attachments/915568009815416845/1315388341830811678/hen.png"
);
}
} else if (message.content.toLowerCase().includes("owen")) {
try {
await message.reply(
"https://cdn.discordapp.com/attachments/915568009815416845/1315388342866804736/going.png"
);
} catch {
message.channel.send(
"https://cdn.discordapp.com/attachments/915568009815416845/1315388342866804736/going.png"
);
}
} else if (message.content.toLowerCase().includes("tosh")) {
try {
await message.reply(
"https://cdn.discordapp.com/attachments/915568009815416845/1315388342451441664/bosh.png"
);
} catch {
message.channel.send(
"https://cdn.discordapp.com/attachments/915568009815416845/1315388342451441664/bosh.png"
);
}
}
}
const randomNumber = Math.random() * 1000;
// Check if the number is less than 1 (1 in 1000 chance)
if (randomNumber < 1) {
await message.react("🫃");
}
if (
message.author.bot ||
!message.content.toLowerCase().startsWith(PREFIX.toLowerCase())
) {
return;
}
//runs the message through the moderation to make sure nothing harmful is being sent
openai
.createModeration({ input: message.content.slice(3) })
.then(async (res) => {
if (res.data.results[0].flagged) {
safeReply(
message,
"Your message has been moderated. Please refrain from trying to generate the following content: hate, self-harm, sexual, violence. (This is an error, not an AI response)"
);
}
//if nothing is flagged, set the model and send the message to the AI
else {
const gptResponse = await getGptResponse(
message.content.substring(3),
"ft:babbage-002:personal::8euAZ98S"
);
safeReply(message, gptResponse);
}
return;
});
});
//set commands
client.commands = new Collection();
//set cooldowns
client.cooldowns = new Collection();
client.COOLDOWN_SECONDS = 5; // replace with desired cooldown time in seconds
const foldersPath = path.join(__dirname, "commands");
const commandFolders = fs.readdirSync(foldersPath);
//checks the commands folder for js files
for (const folder of commandFolders) {
const commandsPath = path.join(foldersPath, folder);
const commandFiles = fs
.readdirSync(commandsPath)
.filter((file) => file.endsWith(".js"));
for (const file of commandFiles) {
const filePath = path.join(commandsPath, file);
const command = require(filePath);
// Set a new item in the Collection with the key as the command name and the value as the exported module
if ("data" in command && "execute" in command) {
client.commands.set(command.data.name, command);
} else {
console.log(
`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`
);
}
}
}
//tries to run the command
client.on(Events.InteractionCreate, async (interaction) => {
if (!interaction.isChatInputCommand()) return;
const command = interaction.client.commands.get(interaction.commandName);
if (!command) {
console.error(`No command matching ${interaction.commandName} was found.`);
return;
}
try {
await command.execute(interaction);
} catch (error) {
console.error(error);
if (interaction.replied || interaction.deferred) {
await interaction.followUp({
content:
"There was an error while executing this command! If this keeps happening, please report the issue on the [support page](https://k-9.vercel.app/Support.html)",
ephemeral: true,
});
} else {
await interaction.reply({
content:
"There was an error while executing this command! If this keeps happening, please report the issue on the [support page](https://k-9.vercel.app/Support.html)",
ephemeral: true,
});
}
}
});
// log into the bot using the client token
client.login(process.env.TOKEN);