Files
selmerBot/main.js
T

455 lines
16 KiB
JavaScript
Raw Normal View History

2022-07-09 20:30:31 +03:00
//#region imports
const { Client, Intents } = require('discord.js');
2022-02-17 21:42:57 -05:00
const Discord = require('discord.js');
const { MongoClient, ServerApiVersion, GridFSBucket } = require('mongodb');
const fs = require('fs');
// const OpenAI = require('openai-api')
const { Configuration, OpenAIApi } = require("openai");
const Stripe = require('stripe');
const turnManager = require('./commands/turnManager.js');
const { welcome } = require('./commands/admin/welcome.js');
2022-10-24 11:01:24 -04:00
const { handle_interaction, handleContext } = require('./commands/interactionhandler.js');
const { handle_dm } = require('./commands/dm_handler');
const { devCheck } = require('./commands/dev only/devcheck.js');
2022-07-09 20:30:31 +03:00
const { moderation_handler } = require('./commands/admin/moderation.js');
const { registerCommands } = require('./registerCommands.js');
const { backupLists, loadBotBackups } = require('./commands/dev only/backupBot.js');
const { setPresence } = require('./commands/dev only/setPresence.js');
const { exit } = require('process');
const {textToLevels} = require('./commands/Selmer Specific/msgLevels.js');
2022-07-09 20:30:31 +03:00
//#endregion
const BASE_LVL_XP = 20;
//#region Token area
//Adding integration for development mode
let token;
let IDM = false;
let home_server;
let debug_channel;
let MLAIKEY;
let StripeAPIKey;
let youtubeAPIKey;
if (process.env.token != undefined) {
//Use "setx NAME VALUE" in the local powershell terminal to set
token = process.env.token;
home_server = process.env.home_server;
debug_channel = process.env.debug_channel;
MLAIKEY = process.env.MLAIKEY;
StripeAPIKey = process.env.StripeAPIKey;
youtubeAPIKey = process.env.youtubeAPIKey;
} else {
token = require('./config.json').token;
home_server = require('./config.json').home_server;
debug_channel = require('./config.json').debug_channel;
MLAIKEY = require('./config.json').MLAIKEY;
StripeAPIKey = require('./config.json').StripeAPIKey;
youtubeAPIKey = require('./config.json').youtubeAPIKey;
2022-08-18 14:25:25 -07:00
IDM = true;
}
//#endregion
2022-04-17 08:51:30 -04:00
2022-04-30 15:51:55 -04:00
const bot = new Client({
2022-02-17 21:42:57 -05:00
intents: [
Intents.FLAGS.GUILDS,
Intents.FLAGS.GUILD_MESSAGES,
2022-04-30 15:51:55 -04:00
Intents.FLAGS.GUILD_MESSAGE_REACTIONS,
Intents.FLAGS.GUILD_VOICE_STATES,
Intents.FLAGS.GUILD_EMOJIS_AND_STICKERS,
Intents.FLAGS.GUILD_PRESENCES,
Intents.FLAGS.GUILD_MEMBERS,
Intents.FLAGS.DIRECT_MESSAGES,
Intents.FLAGS.DIRECT_MESSAGE_REACTIONS,
Intents.FLAGS.DIRECT_MESSAGE_TYPING,
2022-02-17 21:42:57 -05:00
],
partials: [ 'CHANNEL' ]
2022-02-17 21:42:57 -05:00
});
const prefix = '!';
bot.prefix = new String;
bot.prefix = prefix;
bot.inDebugMode = IDM;
bot.home_server = home_server;
bot.debug_channel = debug_channel;
bot.inviteLink = 'https://discord.com/oauth2/authorize?client_id=944046902415093760&scope=applications.commands+bot&permissions=549755289087';
bot.youtubeAPIKey = youtubeAPIKey;
2022-02-17 21:42:57 -05:00
const configuration = new Configuration({
apiKey: MLAIKEY,
});
bot.openai = new OpenAIApi(configuration);
bot.temptext = '';
bot.stripe = Stripe(StripeAPIKey);
//The first thing will be an audioPlayer(), the second a queue
bot.audioData = new Map();
bot.lockedChannels = new Map();
2022-02-17 21:42:57 -05:00
//#region MongoDB integration
//Development support
let mongouritemp;
if (process.env.MONGODB_URI) {
mongouritemp = process.env.MONGODB_URI;
} else {
mongouritemp = require('./config.json').mongooseURI;
}
const mongouri = mongouritemp;
bot.mongouri = mongouri;
const client = new MongoClient(mongouri, { useNewUrlParser: true, useUnifiedTopology: true, serverApi: ServerApiVersion.v1 });
bot.mongoconnection = client.connect();
//Error stuff
var preverr = "";
var errmsg;
var errTimes = 1;
//#endregion MongoDB Integration end
//#region PROCESS STUFF
loadBotBackups(bot, IDM);
process.on("SIGTERM", (signal) => {
console.log(`Process ${process.pid} received a SIGTERM signal`);
backupLists(bot, IDM);
// process.exit(0);
});
process.on("SIGINT", (signal) => {
console.log(`Process ${process.pid} has been interrupted`);
backupLists(bot, IDM);
// process.exit(0);
});
process.on('uncaughtException', (signal) => {
//Check if this was the last err and if so, ignore
if (preverr == signal.stack.toString()) {
var tempmsg = errmsg.content;
tempmsg.replaceAll(`{${errTimes}}`, `{${errTimes + 1}}`);
errTimes++;
errmsg.edit(tempmsg);
return;
}
const guild = bot.guilds.cache.get(bot.home_server);
const owner = guild.members.cache.get(guild.ownerId);
preverr = signal.stack.toString();
owner.send(`${owner} SELMER BOT IS DOWN!!!`).then(() => {
guild.channels.cache.get("1054550753982828624").send(`<@&944048889038774302> Selmer Bot is down!\n***ERROR STACK:***\n`).then(() => {
guild.channels.cache.get("1054550753982828624").send(`\`\`\`${preverr}\`\`\`\nTHIS ERROR HAS OCCURED {1} TIMES IN A ROW`).then((msg) => {
errmsg = msg;
preverr = signal.stack.toString();
// exit(12);
});
});
});
});
//#endregion
//#region set up bot commands
// const commandFiles = fs.readdirSync('./commands/').filter(file => file.endsWith('.js')); // Obsolete?
2022-05-09 12:11:18 +03:00
2022-04-30 15:51:55 -04:00
bot.commands = new Discord.Collection();
const forbiddenFolders = ['db', 'dev only']; //premium,
2022-02-17 21:42:57 -05:00
fs.readdirSync('./commands')
.forEach(dir => {
if (!forbiddenFolders.includes(dir) && !dir.endsWith('.js')) {
fs.readdirSync(`./commands/${dir}`)
.filter(file => file.endsWith('.js'))
.forEach(file => {
const command = require(`./commands/${dir}/${file}`);
if (command.name && command.description) {
bot.commands.set(command.name.toLowerCase(), command);
}
});
2022-07-08 15:43:41 +03:00
}
});
//Set these two manually because all the seperate games can't be included in the command list (all managed by the 'game' file)
let temp_command = require("./commands/db/econ.js");
const { STATE } = require('./commands/db/econ.js');
bot.commands.set('econ', temp_command);
2022-07-01 15:00:52 +03:00
temp_command = require('./commands/games/game.js');
bot.commands.set('game', temp_command);
//Everything in the API should be handled by specific handler functions
// const chat = require('./commands/premium/chat.js');
// bot.commands.set('chat', chat);
// const stripeCommands = require('./commands/premium/stripe.js');
// bot.commands.set('premium', stripeCommands);
// const
// bot.commands.set('RSS', )
//#endregion
//#region bot.[anything] section
2022-02-17 21:42:57 -05:00
//XP Table section
let xp_collection = new Map();
let items;
var botIsReady = bot.inDebugMode;
2022-02-17 21:42:57 -05:00
2022-04-30 15:51:55 -04:00
bot.on('ready', async () => {
2022-10-24 11:01:24 -04:00
const startTime = new Date().getTime();
registerCommands(bot).then(() => {
//Make then copy the shop
bot.mongoconnection.then(client => {
const shop = client.db("main").collection("shop");
shop.find().toArray(function(err, itemstemp) {
if (err) throw err;
items = [...itemstemp];
});
2022-10-24 11:01:24 -04:00
bot.user.setStatus('online');
});
2022-10-24 11:01:24 -04:00
//Note the xp numbers are a little wonky on levels 6, 8 and 13 (why though?)
//See https://stackoverflow.com/questions/72212928/why-are-the-differences-between-my-numbers-inconsistent-sort-of-compund-interes
for (let i = 1; i < 101; i ++) {
// xp_collection.set(i, BASE_LVL_XP * .1);
let amount = BASE_LVL_XP * (Math.ceil(Math.pow((1.1), (2 * i))) + i);
xp_collection.set(i+1, amount);
}
2022-04-17 08:51:30 -04:00
2022-10-24 11:01:24 -04:00
//Reaction map area
if (!bot.inDebugMode) {
console.log('SLEEMER BOT ONLINE!!!!! OH MY GOD OH MY GOD!!!');
} else {
console.log("Testing testing 1 2 5...");
}
2022-10-24 11:01:24 -04:00
//Add the money symbol
let srv = bot.guilds.cache.get(bot.home_server).emojis.cache;
emj = srv.find((g) => { return g.name == 'selmer_coin' });
bot.currencysymbolmmain = `${emj}`;
}).catch((err) => {
console.log(err);
}).finally(() => {
botIsReady = true;
console.log(`Setting up Slash Commands took ${(new Date().getTime() - startTime) / 1000} seconds to complete!`);
});
2022-10-24 11:01:24 -04:00
});
2022-02-17 21:42:57 -05:00
//Button Section
bot.on('interactionCreate', async interaction => {
const { commandName } = interaction;
if (!botIsReady) {
return interaction.reply("The bot is still warming up. This is process can take up to 5 minutes. Please try again in a bit! \:(");
}
// console.log(bot.lockedChannels);
//Slash commands
if (interaction.isApplicationCommand()) {
2022-10-24 11:01:24 -04:00
if (interaction.isUserContextMenu()) {
return handleContext(bot, interaction.options.data[0]);
}
const logable = ['kick', 'ban', 'unban', 'mute', 'unmute', 'timeout'];
const econList = ["buy", 'shop', 'work', 'rank', 'inventory', 'balance', 'sell'];
const adminList = ["setpresence", "setactivity"];
if (commandName == "admin" && adminList.includes(interaction.options.data[0].name)) {
if (interaction.user.id == bot.guilds.cache.get(bot.home_server).ownerId) {
setPresence(bot, interaction);
} else {
return interaction.reply({ content: "HAHAHAHAHAHAHAHAHAHAHA\n\nno.", ephemeral: true }).catch((err) => {
interaction.channel.send({ content: "HAHAHAHAHAHAHAHAHAHAHA\n\nno.", ephemeral: true });
});
}
} else if (logable.includes(commandName)) {
moderation_handler(bot, interaction, commandName);
} else if (econList.includes(commandName)) {
bot.commands.get('econ').execute(bot, interaction, Discord, mongouri, items, xp_collection);
2022-10-24 11:01:24 -04:00
} else if (commandName == 'game') {
if (!bot.inDebugMode) { interaction.reply("This command is still in development, use normal text\nEx: _!game tictactoe @opponent_"); }
const command = interaction.options.data[0];
bot.commands.get('game').execute(bot, interaction, command, Discord, mongouri, items, xp_collection);
} else if (commandName == 'setup_embed') {
const {generateMsg} = require('./commands/admin/easySetup.js')
generateMsg(bot, interaction);
2022-10-24 11:01:24 -04:00
} else if (bot.commands.has(commandName)) {
bot.commands.get(commandName).execute(interaction, Discord, Client, bot);
} else {
interaction.reply("Unknown command detected!");
}
} else {
handle_interaction(interaction, mongouri, turnManager, bot, STATE, items, xp_collection);
}
});
//Add the bot to a server setup
bot.on("guildCreate", guild => {
2022-07-09 20:30:31 +03:00
if (guild.roles.cache.find((role) => { return (role.name == 'Selmer Bot Commands'); }) == undefined) {
guild.roles.create({ name: 'Selmer Bot Commands' });
}
if (guild.roles.cache.find((role) => { return (role.name == 'Selmer Bot Calendar'); }) == undefined) {
guild.roles.create({ name: 'Selmer Bot Calendar' });
}
//const role = guild.roles.cache.find((role) => role.name === 'Selmer Bot Mod'); // member.roles.cache.has('role-id-here');
const server = bot.guilds.cache.get(guild.id);
2022-10-24 11:01:24 -04:00
server.members.fetch(guild.ownerId).then(function(owner) {
owner.send('Thank you for adding Selmer Bot to your server!\nPlease give people you want to have access to Selmer Bot\'s restricted commands the "_Selmer Bot Commands_" role and people you want to access set the calendar the "_Selmer Bot Calendar_" role');
owner.send('To help set up Selmer Bot to work better with your server, use _/setup help_ in a channel Selmer Bot is in!');
});
//Set up the server
bot.mongoconnection.then(client => {
const dbo = client.db(guild.id).collection('SETUP');
dbo.insertMany([{_id: 'WELCOME', 'welcomechannel': null, 'welcomemessage': null, 'welcomebanner': null}, {_id: 'LOG', 'keepLogs': false, 'logchannel': null, 'severity': 0},
{_id: 'announcement', channel: null, role: null}, {_id: 'roles', commands: ["Selmer Bot Commands"], announcements: "Selmer Bot Calendar"}]);
});
});
bot.on("guildDelete", guild => {
bot.mongoconnection.then((client) => {
//Insufficient Permission????
// db.dropDatabase();
try {
const db = client.db(guild.id);
db.listCollections().forEach(function(x) { db.collection(x.name).drop(); });
var times;
const dbo = client.db('main').collection('reminderKeys');
//ReminderKeys are all stored as userId, the reminders themselves are not
dbo.findOne({userId: guild.id}).then((doc) => {
2022-09-03 20:27:09 -04:00
if (!doc || !doc.times) { return; }
times = doc.times;
const tbo = client.db('main').collection('reminders');
tbo.find({time: {$in: times}}).toArray((err, docs) => {
2022-09-03 20:27:09 -04:00
try {
for (let i = 0; i < docs.length; i ++) {
for (let j in docs[i]) {
if (!isNaN(j) && (docs[i][j].guildId == guild.id)) {
delete docs[i][j];
docs[i].amt --;
}
}
2022-09-03 20:27:09 -04:00
if (docs.amt > 0) {
tbo.replaceOne({ time: docs[i].time }, docs[i]);
} else {
tbo.deleteOne({ time: docs[i].time });
}
}
2022-09-03 20:27:09 -04:00
} catch (err) {
console.error(err);
}
});
});
dbo.deleteOne({ userId: guild.id });
} catch (err) {
2022-09-03 20:27:09 -04:00
console.error(err);
}
})
});
//Welcome new members
bot.on('guildMemberAdd', async (member) => {
if (member.guild.id == bot.home_server && !bot.inDebugMode) { return; }
2022-07-09 20:30:31 +03:00
//Check for impartial data
2022-10-24 11:01:24 -04:00
if (member.partial) { member = await member.fetch(); }
const guild = bot.guilds.cache.get(member.guild.id);
bot.mongoconnection.then(client => {
const dbo = client.db(member.guild.id).collection('SETUP');
dbo.find({_id: 'WELCOME'}).toArray(async (err, docs) => {
if (!docs) { return; }
var welcomechannel;
if (docs[0].welcomechannel == null) {
welcomechannel = guild.channels.cache.find(channel => channel.name.toLowerCase() === 'welcome');
} else {
welcomechannel = guild.channels.cache.get(docs[0].welcomechannel)
}
if (welcomechannel == null) {
return; // console.log('No welcome channel detected');
}
await welcome(member, welcomechannel, docs[0].welcomemessage, docs[0].welcomebanner, (docs[0].welcometextcolor) ? docs[0].welcometextcolor : "#FFFFFF");
})
})
});
bot.on('messageCreate', (message) => { console.log(y);
//DM SECTION
if (message.channel.type === "DM") {
return handle_dm(message, bot);
} else if (message.content.indexOf('!spam_collection') != -1) {
//Handle spam collection/Dev commands
return devCheck(message, bot);
} else if (message.type === "CHANNEL_PINNED_MESSAGE") {
//Debug log stuff
if (message.guild.id == bot.home_server && message.channel.id == bot.debug_channel) {
message.delete();
}
}
//Special case, testing server (still need the emojis and error logging)
2022-06-11 18:47:49 +03:00
if (!bot.inDebugMode && message.guild.id == bot.home_server) { return; }
2022-02-17 21:42:57 -05:00
//Check if the prefix exists
if (message.author.bot) { return }
if (message.content.startsWith(prefix)) {
//Game section (too complicated to move to Slash Commands)
//Note: Slash commands do not register as valid replies
const args = message.content.slice(prefix.length).split(' ');
const command = args.shift().toLowerCase();
if (command == 'game' || command == 'accept') {
bot.commands.get(command).execute(bot, message, args, command, Discord, mongouri, items, xp_collection);
} else if (command == 'rss' && bot.inDebugMode) {
const rss = require('./side projects/RSSHandlers/rssFeed.js');
rss.execute(message, args, Discord, client, bot);
} else {
textToLevels(bot, message, xp_collection);
}
} else {
//Use for the leveling-by-interaction system
textToLevels(bot, message, xp_collection);
}
});
2022-02-17 21:42:57 -05:00
//#endregion
2022-02-17 21:42:57 -05:00
//Last Line(s)
bot.login(token);