21 Commits

Author SHA1 Message Date
ION606 df4d21f487 Update README.md 2022-12-27 11:12:51 -08:00
ION606 697b1c0c76 Removed member message from the level-up card 2022-12-26 15:22:50 -08:00
ION606 914dc7ece4 Fixed a bug arising from new debug definitions 2022-12-26 14:49:25 -08:00
ION606 ebb34c9f89 Added cards to the leveling system, and fixed some bugs. Note that node-fetch has been bumped DOWN to v2 to avoid EMS format 2022-12-26 14:40:50 -08:00
ION606 5292bd8a09 I'm dumb yea 2022-12-19 20:49:46 -05:00
ION606 9f5f94d49e Fixed an error and added a warning message when the bot crashes 2022-12-19 20:48:01 -05:00
ION606 a41e602036 Added the 'reactionrole' command and removed some redundancies in code 2022-12-19 17:20:04 -05:00
ION606 7b247e462f Fixed a typo 2022-12-04 14:18:26 -05:00
ION606 6ae725d211 Added the framework for the message-leveling system 2022-11-18 11:01:15 -05:00
ION606 1b1932015e Transitioned all working games to Slash Commands (not Battle) 2022-11-16 16:53:24 -05:00
ION606 1324c3db8f Added Slash Command registration timing 2022-10-24 20:49:42 -04:00
ION606 b75cb7b495 Remove the 'meme' command 2022-10-24 20:44:34 -04:00
ION606 df7d79e69a Added the ability to add custom loading banners and started transitioning away from the Canvas module 2022-10-24 20:13:15 -04:00
ION606 2ff7a84bee Ignore this 2022-10-24 11:03:40 -04:00
ION606 8a47943764 Ignore this 2022-10-24 11:01:24 -04:00
ION606 47dc8e37cd Fixed a bug 2022-10-23 18:47:01 -04:00
ION606 c85bb3ef45 Added the "roles" section to the database 2022-10-23 18:38:07 -04:00
ION606 4043038162 Updated the way the verification system works and added custom admin role integration 2022-10-23 18:23:11 -04:00
ION606 18894961bd Added the 'import_ics' command 2022-10-11 16:29:49 -04:00
ION606 d69e7e0479 Fixed some remaining changes from the transition to Slash commands 2022-10-06 12:41:15 -04:00
ION606 b30fdc9e7f Added presence-changing commands to make dynamic bot moddification easier 2022-09-30 22:21:44 -04:00
41 changed files with 3092 additions and 1337 deletions
+3
View File
@@ -7,3 +7,6 @@ backup.json
!spec/LevelsXP.txt !spec/LevelsXP.txt
*.sqlite *.sqlite
temp.js temp.js
easySetup.js
meme.js
+2
View File
@@ -1,3 +1,5 @@
# THIS REPOSITORY HAS BEEN MIRRORED TO THE SELMER BOT ORGANIZATION AND IS NOW READ-ONLY
# selmerBot # selmerBot
Authors: ION606, MajorDrools Authors: ION606, MajorDrools
+41
View File
@@ -0,0 +1,41 @@
const { addxp, BASE } = require('../db/econ.js');
async function setCard(bot, interaction) {
bot.mongoconnection.then(async (client) => {
const dbo = client.db(interaction.guildId).collection('SETUP');
dbo.findOne({_id: "LEVELING"}).then((doc) => {
const bkBuffer = Buffer.from(doc.card, 'base64');
});
});
}
function textToLevels(bot, message, xp_list) {
if (!bot.inDebugMode && message.guild.id == bot.home_server) { return; }
const author = message.author;
// doc.xp + (BASE.XP * doc.rank)
bot.mongoconnection.then((client) => {
const serverOpts = client.db(message.guild.id).collection('SETUP');
serverOpts.findOne({_id: "LEVELING"}).then((doc) => {
if (!doc) {
serverOpts.insertOne({_id: "LEVELING", enabled: false, card: undefined, text: undefined, col: "#FFFFFF"});
const server = bot.guilds.cache.get(message.guild.id);
server.members.fetch(message.guild.ownerId).then(function(owner) {
// Implement `setup leveling enable`
owner.send("Interactive Leveling has been added to your server!\nTo enable it, use `/setup leveling enable`");
});
} else if (doc.enabled) {
const dbo = client.db(message.guild.id).collection(author.id);
dbo.findOne({"balance": {$exists: true}}).then((doc) => {
const newXp = doc.xp + Math.ceil((BASE.XP * doc.rank) / 4);
addxp(bot, message, dbo, newXp, xp_list, true);
});
}
});
});
}
module.exports = {textToLevels};
+54
View File
@@ -0,0 +1,54 @@
const Discord = require('discord.js');
/**
* @description a fun little easter egg mention function
* @param {Discord.Message} message
*/
function replies(bot, message) {
const c = message.content.replace(`<@${bot.user.id}>`, "").toLowerCase().trim();
var s = "";
switch (c) {
case "hi":
case "hello":
case "hya":
s = "Hi there! :wave:";
break;
case "i love you":
s = "seek help :smile:";
break;
case "chicken nuggets":
s = "nom nom nom";
break;
case "chimkin nungits":
s = "marry me :heart_eyes:";
break;
case "😉":
s = ":wink:";
break;
case "😜":
s = "😜";
break;
case "🍆":
case "🍑":
case "🍌":
s = "❌";
break;
case "💩":
s = "🤮";
break;
default: s = "I'm not sure what that means! Please use `/help` for a comprehensive list of commands!\n\n_PS - If you want to make full use of the bot's AI capabilities, consider Selmer Bot Premium. See more at https://selmerbot.com/premium _";
}
message.reply(s).catch(() => { message.channel.send(s); });
}
module.exports = replies;
+4 -3
View File
@@ -5,7 +5,7 @@ module.exports = {
description: 'See where Selmer bot\'s code is stored!', description: 'See where Selmer bot\'s code is stored!',
execute(interaction, Discord, Client, bot) { execute(interaction, Discord, Client, bot) {
const embd = new MessageEmbed() const embd = new MessageEmbed()
.setAuthor({ name: "Selmer Bot", url: bot.inviteLink, iconURL: bot.user.displayAvatarURL() }) .setAuthor({ name: "Selmer Bot", url: bot.user.inviteLink, iconURL: bot.user.displayAvatarURL() })
.setThumbnail("https://github.com/ION606/selmer-bot-website/blob/main/assets/Selmer-icon.png?raw=true") // .setThumbnail('https://repository-images.githubusercontent.com/460670550/43932b23-d795-4334-838f-f33ee8f795c4') .setThumbnail("https://github.com/ION606/selmer-bot-website/blob/main/assets/Selmer-icon.png?raw=true") // .setThumbnail('https://repository-images.githubusercontent.com/460670550/43932b23-d795-4334-838f-f33ee8f795c4')
.setDescription("Selmer Bot was created by ION606"); .setDescription("Selmer Bot was created by ION606");
@@ -18,7 +18,7 @@ module.exports = {
new MessageButton() new MessageButton()
.setStyle("LINK") .setStyle("LINK")
.setURL("https://www.selmerbot.com/") .setURL("https://selmerbot.com/")
.setLabel("Website"), .setLabel("Website"),
new MessageButton() new MessageButton()
@@ -28,5 +28,6 @@ module.exports = {
]); ]);
interaction.reply({ embeds: [embd], components: [row] }); interaction.reply({ embeds: [embd], components: [row] });
}, options: [] }, options: [],
isDm: true
} }
+5 -5
View File
@@ -7,12 +7,12 @@ const tutoText = [
"__**SETUP AND LOGGING**__\nSet up your server to take full advantage of Selmer Bot's features, this includes moderation logging, custom welcome messages, calendar event pings and more\n_Note: Most of these commands are only available to the server owner_\n\n__***COMMANDS***__\nsetup", "__**SETUP AND LOGGING**__\nSet up your server to take full advantage of Selmer Bot's features, this includes moderation logging, custom welcome messages, calendar event pings and more\n_Note: Most of these commands are only available to the server owner_\n\n__***COMMANDS***__\nsetup",
"__**ECONOMY**__\nThese commands have to do with the inventory and currency system Selmer Bot uses, although I should note that as of now Selmer Coin holds no IRL value ;-;\n\n__***COMMANDS***__\ninventory, buy, sell, shop, work, rank, balance", "__**ECONOMY**__\nThese commands have to do with the inventory and currency system Selmer Bot uses, although I should note that as of now Selmer Coin holds no IRL value ;-;\n\n__***COMMANDS***__\ninventory, buy, sell, shop, work, rank, balance",
"__**MODERATION**__\nI mean....\n\n***__COMMANDS__***\nhelp admin, warn, mute, unmute, kick, ban, unban, lock, unlock, serverlock\n\n__***NOTE:***__\nThe user needs to have either _kick_ or _ban_ permissions to use these", "__**MODERATION**__\nI mean....\n\n***__COMMANDS__***\nhelp admin, warn, mute, unmute, kick, ban, unban, lock, unlock, serverlock\n\n__***NOTE:***__\nThe user needs to have either _kick_ or _ban_ permissions to use these",
"__**AMIME AND MANGA**__\nGet info on your favorite Anime or Manga as a stat-sheet, a fancy embed, or have Selmer Bot describe it to you\n__***COMMANDS***__\nasearch, msearch", "__**AMIME AND MANGA**__\nGet info on your favorite Anime or Manga as a stat-sheet, a fancy embed, or have Selmer Bot describe it to you\n\n__***COMMANDS***__\nasearch, msearch",
"__**GAMES**__\nAt the moment Selmer Bot offers three games: Trivia, Tic Tac Toe, and Minesweeper. Both Trivia and Tic Tac Toe can be played with other people. Trivia and Minesweeper can also be played solo. Selmer Bot also has a battle game where you can use weapons, potions, attack and defend, but this is still in beta\n\n__***COMMANDS***__\nhelp game, game battle game tictactoe, game trivia, game equip, game status, game hp, game classes, game quit\n\n__**NOTE**__\nDue to how complicated this feature is, it will not be migrated to slash commands for now", "__**GAMES**__\nAt the moment Selmer Bot offers three games: Trivia, Tic Tac Toe, and Minesweeper. Both Trivia and Tic Tac Toe can be played with other people. Trivia and Minesweeper can also be played solo. Selmer Bot also has a battle game where you can use weapons, potions, attack and defend, but this is still in beta\n\n__***COMMANDS***__\nhelp game, game battle game tictactoe, game trivia, game equip, game status, game hp, game classes, game quit\n\n__**NOTE**__\nDue to how complicated this feature is, it will not be migrated to slash commands for now",
"__**SELMER SPECIFIC**__\nThese commands will probably be found nowhere else\nThese include quotes (For legal reasons I have to state they aren't real quotes, mostly), as well as varius other things I based on good old Selmer\n\n__***COMMANDS***__\narrow, extracredit, tuto, profile, quotes", "__**SELMER SPECIFIC**__\nThese commands will probably be found nowhere else\nThese include quotes (For legal reasons I have to state they aren't real quotes, mostly), as well as varius other things I based on good old Selmer\n\n__***COMMANDS***__\narrow, extracredit, tuto, profile, quotes",
"__**MISCELLANEOUS**__\nThese are the commands that are not really in any of the other categories. Don't be fooled, these are actually some of the most useful commands Selmer Bot has to offer. From playing music to web scraping to memes, I'm sure Selmer Bot has what you're looking for\n\n__***COMMANDS***__\nhelp, kareoke, link, meme, pickupline, audio, react, scrape, stocks, crypto", "__**MISCELLANEOUS**__\nThese are the commands that are not really in any of the other categories. Don't be fooled, these are actually some of the most useful commands Selmer Bot has to offer. From playing music to web scraping to memes, I'm sure Selmer Bot has what you're looking for\n\n__***COMMANDS***__\nhelp, kareoke, link, meme, pickupline, audio, react, scrape, stocks, crypto",
"__**DM COMMANDS**__\nThese commands will only work in DM's. All these commands will only work with Selmer Bot Premium (it's on the next page).\nThese features include Reminders (AKA a calendar) and Selmer Bot's own chat AI\n\n__***COMMANDS***__\nchat, startconvo, endconvo, premium", "__**DM COMMANDS**__\nThese commands will only work in DM's. All these commands will only work with Selmer Bot Premium (it's on the next page).\nThese features include Reminders (AKA a calendar) and Selmer Bot's own chat AI\n\n__***COMMANDS***__\nchat, startconvo, endconvo, premium",
"__**SELMER BOT PREMIUM**__\nUse an AI chat, complete with semi-accurate IRL data, have Selmer Bot remind you of events with an easy-to-use interface and even a clickable calendar on the Selmer Bot website (_www.selmerbot.com_)\n\n__***COMMANDS***__\npremium, premium buy, premium manage, reminders", "__**SELMER BOT PREMIUM**__\nUse an AI chat, complete with semi-accurate IRL data, have Selmer Bot remind you of events with an easy-to-use interface and even a clickable calendar on the Selmer Bot website (_ https://selmerbot.com _)\n\n__***COMMANDS***__\npremium, premium buy, premium manage, reminders",
"__**Thank you for completing the Selmer Bot Tutorial**__\n\nTry out Selmer Bot's features, play the games and most importantly, have fun\n\n-The Selmer Bot Team AKA ION606" "__**Thank you for completing the Selmer Bot Tutorial**__\n\nTry out Selmer Bot's features, play the games and most importantly, have fun\n\n-The Selmer Bot Team AKA ION606"
]; ];
@@ -29,7 +29,7 @@ function postEmbd(bot, interaction, page, refered) {
te.setAuthor(author) te.setAuthor(author)
.setTitle("Selmer Bot Tutorial") .setTitle("Selmer Bot Tutorial")
.setDescription(tutoText[page]) .setDescription(tutoText[page])
.setURL('https://www.selmerbot.com/') .setURL('https://selmerbot.com/')
.setFooter({ text: `Page ${page + 1}` }); .setFooter({ text: `Page ${page + 1}` });
@@ -66,9 +66,9 @@ function postEmbd(bot, interaction, page, refered) {
row.addComponents(prevbtn, nextbtn); row.addComponents(prevbtn, nextbtn);
if (page > 0 || refered) { if (page > 0 || refered) {
interaction.update({ content: '_Note: To see a full list of reminder stats visit www.selmerbot.com _', embeds: [te], components: [row] }); interaction.update({ content: '_Note: To see a full list of reminder stats visit selmerbot.com _', embeds: [te], components: [row] });
} else { } else {
interaction.reply({ content: '_Note: To see a full list of reminder stats visit www.selmerbot.com _', embeds: [te], components: [row] }); interaction.channel.send({ content: '_Note: To see a full list of reminder stats visit selmerbot.com _', embeds: [te], components: [row] });
} }
} }
+3 -1
View File
@@ -8,7 +8,8 @@ module.exports = {
const arg = interaction.options.data[0]; const arg = interaction.options.data[0];
const guild = bot.guilds.cache.get(interaction.guildId); const guild = bot.guilds.cache.get(interaction.guildId);
if (!checkRole(bot, guild, interaction.user.id)) { return interaction.reply('Insufficient Permissions!'); } checkRole(bot, guild, interaction.user.id).then((isAllowed) => {
if (isAllowed) { return interaction.reply('Insufficient Permissions!'); }
var channel; var channel;
if (arg) { if (arg) {
@@ -26,6 +27,7 @@ module.exports = {
}); });
interaction.reply(`${channel} has been locked!`); interaction.reply(`${channel} has been locked!`);
});
}, },
options: [{name: 'channel', description: 'The channel to lock (defaults to current channel)', type: Constants.ApplicationCommandOptionTypes.CHANNEL, required: false}] options: [{name: 'channel', description: 'The channel to lock (defaults to current channel)', type: Constants.ApplicationCommandOptionTypes.CHANNEL, required: false}]
} }
+3 -1
View File
@@ -99,7 +99,8 @@ function moderation_handler(bot, interaction, command) {
const guild = interaction.guild; const guild = interaction.guild;
//Verify //Verify
if (!checkRole(bot, guild, interaction.user.id)) { return interaction.reply('Insufficient Permission!'); } checkRole(bot, guild, interaction.user.id).then((isAllowed) => {
if (!isAllowed) { return interaction.reply('Insufficient Permission!'); }
const mentioned = interaction.options.data.filter((arg) => { return (arg.name == 'user'); })[0].user; const mentioned = interaction.options.data.filter((arg) => { return (arg.name == 'user'); })[0].user;
if (mentioned && mentioned.id == interaction.user.id) { return interaction.reply(`You can't ${command} yourself!`); } if (mentioned && mentioned.id == interaction.user.id) { return interaction.reply(`You can't ${command} yourself!`); }
@@ -144,6 +145,7 @@ function moderation_handler(bot, interaction, command) {
default: console.log(`ERROR! Moderation Command "${command}" has somehow been used!`); default: console.log(`ERROR! Moderation Command "${command}" has somehow been used!`);
} }
});
} }
module.exports = { module.exports = {
+182
View File
@@ -0,0 +1,182 @@
const {Interaction, Constants, Modal, TextInputComponent, MessageActionRow, MessageEmbed, MessageButton, Message} = require('discord.js');
const { checkRole } = require('./verify.js');
const { isValidUrl } = require('../dev only/setPresence.js');
const embdList = [{name: 'Title'}, {name: 'Image', desc: 'The image url'}, {name: 'Thumbnail', desc: 'The thumbnail url'}, {name: 'URL'}, {name: 'Description', desc: 'Use {ROLE} to insert the role'}];
async function postForm(interaction, role, useEmoji, txt) {
// Create the modal
const modal = new Modal();
modal.setTitle('Create a new reaction role!')
.setCustomId(`reactionModal|${role.id}|${useEmoji}|${txt}`);
for (let i = 0; i < 5; i++) {
const tempInp = new TextInputComponent()
.setCustomId(embdList[i].name.toLowerCase())
.setLabel(embdList[i].name);
if (embdList[i].name != 'Description') {
tempInp.setStyle('SHORT');
} else {
tempInp.setStyle('PARAGRAPH');
}
if (embdList[i].desc) {
tempInp.setPlaceholder(embdList[i].desc);
}
modal.addComponents(new MessageActionRow().addComponents(tempInp));
}
// Show the modal to the user
interaction.showModal(modal);
}
/**
* @param {Interaction} interaction
*/
function postNotif(interaction, roleId, guild, user) {
const role = guild.roles.cache.get(roleId);
const embd = new MessageEmbed()
.setTitle("You got a new role!")
.setDescription(`You were given the *${role.name}* role in **${guild}**\n_You did this by reacting to [this message](${interaction.message.url})_`)
.setTimestamp()
.setThumbnail(guild.iconURL());
user.send({embeds: [embd]});
}
/**
* @param {Interaction} interaction
*/
function processForm(interaction, bot) {
const roleId = interaction.customId.split('|')[1];
const title = interaction.fields.getTextInputValue('title');
const img = interaction.fields.getTextInputValue('image');
const thumb = interaction.fields.getTextInputValue('thumbnail');
const url = interaction.fields.getTextInputValue('url');
var desc = interaction.fields.getTextInputValue('description');
const useEmoji = (interaction.customId.split('|')[2] == 'true');
var txt = interaction.customId.split('|')[3];
var emoji = undefined;
//Emoji?
if (Number.isInteger(Number(txt))) {
emoji = interaction.guild.emojis.cache.get(txt);
}
if (desc.indexOf("{ROLE}") != -1) {
desc = desc.replaceAll("{ROLE}", `<@&${roleId}>`);
}
const embd = new MessageEmbed()
.setTitle(title)
.setDescription(desc || "");
if (img && isValidUrl(img)) embd.setImage(img);
if (thumb && isValidUrl(thumb)) embd.setThumbnail(thumb);
if (url && isValidUrl(url)) embd.setURL(url);
if (useEmoji) {
interaction.channel.send({embeds: [embd]}).then((msg) => {
try {
msg.react(emoji || txt);
const filter = (reaction, user) => {
return (!user.bot && (reaction.emoji.id == txt || reaction.emoji.name == txt));
};
const collector = msg.createReactionCollector({ filter });
collector.on('collect', (reaction, user) => {
const guildUser = reaction.message.guild.members.cache.get(user.id);
if (guildUser.roles.cache.has(roleId)) {
return guildUser.send("You already have this role!");
}
guildUser.roles.add(roleId);
postNotif(reaction, roleId, reaction.message.guild, guildUser);
});
} catch (err) {
console.error(err);
}
});
} else {
const btn = new MessageButton()
.setCustomId(`addRole|${roleId}`)
.setStyle('PRIMARY');
if (emoji) btn.setEmoji(emoji);
else btn.setLabel(txt);
const row = new MessageActionRow()
.addComponents([btn]);
interaction.channel.send({embeds: [embd], components: [row]})
}
interaction.reply({content: "Reaction role added!", ephemeral: true});
}
/**
* @param {Interaction} interaction
* @returns
*/
function handleBtn(interaction) {
const roleId = interaction.customId.split('|')[1];
const user = interaction.guild.members.cache.get(interaction.user.id);
if (user.roles.cache.has(roleId)) {
return interaction.reply({content: "You already have this role!", ephemeral: true});
}
user.roles.add(roleId);
const role = interaction.guild.roles.cache.get(roleId);
postNotif(interaction, role.id, interaction.guild, interaction.user);
}
module.exports = {
name: "reactionrole",
description: "Give someone a role when they react to a message",
/**
* @param {Interaction} interaction
*/
execute(interaction, Discord, Client, bot) {
const user = interaction.user;
checkRole(bot, interaction.guild, user.id).then((isAdmin) => {
if (isAdmin) {
const role = interaction.options.data.filter((opt) => { return(opt.name == "role"); })[0].role;
const useEmoji = interaction.options.data.filter((opt) => { return(opt.name == "useemoji"); })[0].value;
var txt = interaction.options.data.filter((opt) => { return(opt.name == "text"); })[0].value;
if (txt.startsWith('<:') && txt.endsWith(">")) {
const emoji = interaction.guild.emojis.cache.get(txt.split(":")[2].split(">")[0]);
if (!emoji) { return interaction.reply("Please use a valid emoji"); }
txt = txt.split(":")[2].split(">")[0];
}
if (role.position >= interaction.guild.me.roles.highest.position ||!interaction.guild.me.permissions.has("MANAGE_ROLES")) {
return interaction.reply({
content: "I'm not high enough in the role hierarchy to do that!\n_To raise my place, go to **Server Settings -> Roles** then drag me up!_",
ephemeral: true
});
}
postForm(interaction, role, useEmoji, txt);
}
});
}, processForm, handleBtn,
options: [
{name: "role", description: "The role to assign", type: Constants.ApplicationCommandOptionTypes.ROLE, required: true},
{name: "useemoji", description: 'React using a button or emoji', type: Constants.ApplicationCommandOptionTypes.BOOLEAN, required: true},
{name: 'text', description: 'The reaction emoji or button text', type: Constants.ApplicationCommandOptionTypes.STRING, required: true}
]
}
+96 -28
View File
@@ -2,13 +2,9 @@
const { MongoClient, ServerApiVersion } = require('mongodb'); const { MongoClient, ServerApiVersion } = require('mongodb');
const { Constants } = require('discord.js'); const { Constants } = require('discord.js');
const { CreateNewCollection } = require("../db/econ"); const { CreateNewCollection } = require("../db/econ");
const { checkRole } = require('./verify.js');
const fetch = require('node-fetch');
async function setWelcomeChannel(dbo, message, channelname) { const help = require('../misc/help.js');
const channel = message.guild.channels.cache.find(ch => ch.name === channelname);
dbo.insertOne({welcomechannel: channel});
}
async function execute(interaction, Discord, Client, bot) { async function execute(interaction, Discord, Client, bot) {
@@ -33,38 +29,33 @@ async function execute(interaction, Discord, Client, bot) {
try { try {
const command = args[i].name; const command = args[i].name;
// if (!command) {
// interaction.reply('Please use the following format _!setup help <welcome, logs>_');
// } else
if (command == 'welcome_channel') { if (command == 'welcome_channel') {
// if (args.length != 2) { return interaction.reply('The command format is _!setup welcome_channel <channel name>_'); }
// setWelcomeChannel(dbo, message, args[1]);
const channel = args[i].channel; const channel = args[i].channel;
dbo.updateOne({welcomechannel: {$exists: true}}, {$set: {welcomechannel: `${channel.id}`}}); dbo.updateOne({welcomechannel: {$exists: true}}, {$set: {welcomechannel: `${channel.id}`}});
interaction.reply({content: `Set ${channel} as the new welcome channel`, ephemeral: true}) interaction.reply({content: `Set ${channel} as the new welcome channel`, ephemeral: true})
} else if (command == 'welcome_message') { }
// if (args.length < 2) { return interaction.reply('The command format is _!setup welcome\\_message_\nUse _{sn}_ to insert the server name, _{un}_ to insert the user name, and _{ut}_ to insert the user tag\nExample: _!setup welcome\\_message Welcome to {sn} Sir {un}#{ut}_'); } else if (command == 'welcome_message') {
const msg = args[i].value; const msg = args[i].value;
if (msg.length > 30 || msg.length < 1) { return interaction.reply({content: 'Please specify a welcome message between 0 and 30 characters!', ephemeral: true}); } if (msg.length > 30 || msg.length < 1) { return interaction.reply({content: 'Please specify a welcome message between 0 and 30 characters!', ephemeral: true}); }
dbo.updateOne({welcomemessage: {$exists: true}}, {$set: {welcomemessage: msg}}) dbo.updateOne({welcomemessage: {$exists: true}}, {$set: {welcomemessage: msg}})
} else if (command == 'keep_logs') { }
else if (command == 'keep_logs') {
let keeplogs = args[i].value; let keeplogs = args[i].value;
dbo.updateOne({ _id: 'LOG'}, {$set: {keepLogs: keeplogs}}); dbo.updateOne({ _id: 'LOG'}, {$set: {keepLogs: keeplogs}});
interaction.reply({content: `Toggled log keeping to ${keeplogs}. Please use _!setup log_channel_ to choose the log channel`, ephemeral: true}); interaction.reply({content: `Toggled log keeping to ${keeplogs}. Please use _!setup log_channel_ to choose the log channel`, ephemeral: true});
} else if (command == 'log_channel') { }
// if (args.length != 2) { return message.reply('Please specify a parameter\nExample: _!setup log\\_channel true_'); } else if (command == 'log_channel') {
const channel = args[i].channel; const channel = args[i].channel;
if (!channel) { return interaction.reply({content: 'The specified channel does not exist!', ephemeral: true}); } if (!channel) { return interaction.reply({content: 'The specified channel does not exist!', ephemeral: true}); }
dbo.updateOne({_id: 'LOG'}, {$set: {logchannel: `${channel.id}`}}); dbo.updateOne({_id: 'LOG'}, {$set: {logchannel: `${channel.id}`}});
interaction.reply({content: `Made ${channel} the new Selmer Bot Logs channel!`, ephemeral: true}); interaction.reply({content: `Made ${channel} the new Selmer Bot Logs channel!`, ephemeral: true});
} else if (command == 'log_severity') { }
else if (command == 'log_severity') {
const tier = args[i].value; const tier = args[i].value;
const l = ['none', 'low', 'medium', 'high']; const l = ['none', 'low', 'medium', 'high'];
if (!l.includes(tier)) { return interaction.reply({content: "Please select an existing tier ('none', 'low', 'medium', 'high')", ephemeral: true}); } if (!l.includes(tier)) { return interaction.reply({content: "Please select an existing tier ('none', 'low', 'medium', 'high')", ephemeral: true}); }
@@ -72,7 +63,8 @@ async function execute(interaction, Discord, Client, bot) {
dbo.updateOne({_id: 'LOG'}, {$set: {severity: tier}}) dbo.updateOne({_id: 'LOG'}, {$set: {severity: tier}})
interaction.reply({content: `Severity updated to ${tier}`, ephemeral: true}); interaction.reply({content: `Severity updated to ${tier}`, ephemeral: true});
} else if (command == 'announcement_role') { }
else if (command == 'ping_role') {
const role = args[i].value; const role = args[i].value;
// if (message.mentions.roles.first() == undefined) { // if (message.mentions.roles.first() == undefined) {
// return message.reply("Please mention a role (_!setup announcement\\_role **@role**_)\n_Note: Selmer Bot does NOT ping the @everyone role_"); // return message.reply("Please mention a role (_!setup announcement\\_role **@role**_)\n_Note: Selmer Bot does NOT ping the @everyone role_");
@@ -81,12 +73,82 @@ async function execute(interaction, Discord, Client, bot) {
dbo.updateOne({_id: 'announcement'}, { $set: { 'role': role.id } }); dbo.updateOne({_id: 'announcement'}, { $set: { 'role': role.id } });
interaction.reply({content: `Role updated to ${role}`, ephemeral: true}); interaction.reply({content: `Role updated to ${role}`, ephemeral: true});
} else if (command == "announcement_channel") { }
else if (command == "ping_channel") {
const channel = args[i].channel; const channel = args[i].channel;
if (!channel) { return interaction.reply({content: 'The specified channel does not exist!', ephemeral: true}); } if (!channel) { return interaction.reply({content: 'The specified channel does not exist!', ephemeral: true}); }
dbo.updateOne({_id: 'announcement'}, { $set: { 'channel': channel.id } }); dbo.updateOne({_id: 'announcement'}, { $set: { 'channel': channel.id } });
interaction.reply({content: `Channel set to ${channel}`, ephemeral: true});
}
else if (command == "add_mod_role") {
dbo.findOne({_id: "roles"}).then((doc) => {
const role = args[i].value;
if (!doc.commands.includes(role)) {
dbo.updateOne({_id: "roles"}, { $push: { commands: role } });
interaction.reply({ content: "Role added!", ephemeral: true });
} else { } else {
interaction.reply({ content: "This role is already a command role!", ephemeral: true });
}
});
}
else if (command == "remove_mod_role") {
dbo.updateOne({_id: "roles"}, { $pull: { commands: { $in: [ args[i].value ] }} });
interaction.reply({ content: "Role removed!", ephemeral: true });
}
else if (command == "welcome_banner") {
const attachement_url = interaction.options.data[0].attachment.attachment;
const response = await fetch(attachement_url);
const arrayBuffer = await response.arrayBuffer();
const imgbfr = Buffer.from(arrayBuffer);
dbo.updateOne({_id: 'WELCOME'}, {$set: {welcomebanner: imgbfr.toString('base64')}});
interaction.reply({ content: `Banner updated to ${attachement_url}`, ephemeral: true});
}
else if (command == "welcome_text_color") {
const reg = /^#[0-9A-F]{6}$/i;
const newCol = interaction.options.data[0].value;
if (reg.test(newCol)) {
dbo.updateOne({_id: 'WELCOME'}, {$set: {welcometextcolor: newCol}});
interaction.reply({content: `Color updated to ${newCol} (https://www.color-hex.com/color/${newCol.substring(1)})`, ephemeral: true});
} else {
interaction.reply("Please chose a valid hex color\nYou can find colors here: https://www.color-hex.com/");
}
}
else if (command == "toggle_leveling") {
const tog = interaction.options.data[0].value;
dbo.updateOne({_id: 'LEVELING'}, {$set: {enabled: tog}});
interaction.reply({content: "Turned leveling " + (tog) ? "ON" : "OFF", ephemeral: true});
}
else if (command == "leveling_banner") {
const level_banner = interaction.options.data[0].attachment.attachment;
const response = await fetch(level_banner);
const arrayBuffer = await response.arrayBuffer();
const imgbfr = Buffer.from(arrayBuffer);
dbo.updateOne({_id: 'LEVELING'}, {$set: {card: imgbfr.toString('base64')}});
interaction.reply({content: `Updated leveling banner to ${level_banner}`, ephemeral: true});
}
else if (command == "leveling_text") {
dbo.updateOne({_id: 'LEVELING'}, {$set: {text: interaction.options.data[0].value}});
interaction.reply({content: `Updated leveling text to ${interaction.options.data[0].value}`, ephemeral: true});
}
else if (command == "leveling_color") {
const reg = /^#[0-9A-F]{6}$/i;
const newCol = interaction.options.data[0].value;
if (reg.test(newCol)) {
dbo.updateOne({_id: 'LEVELING'}, {$set: {col: newCol}});
interaction.reply({content: `Color updated to ${newCol} (https://www.color-hex.com/color/${newCol.substring(1)})`, ephemeral: true});
} else {
interaction.reply("Please chose a valid hex color\nYou can find colors here: https://www.color-hex.com/");
}
}
else if (command == "help") {
if (interaction.options.data[0].value) {
help.execute(interaction, Discord, Client, bot);
} else {
interaction.reply({content: 'https://docs.selmerbot.com/setup', ephemeral: true});
}
}
else {
interaction.reply({content: "Please chose a valid option", ephemeral: true}); interaction.reply({content: "Please chose a valid option", ephemeral: true});
} }
/* Made obsolete by the change to Slash Commands /* Made obsolete by the change to Slash Commands
@@ -115,20 +177,26 @@ async function execute(interaction, Discord, Client, bot) {
module.exports = { module.exports = {
name: 'setup', name: 'setup',
description: 'Set up server features', description: 'Set up server features',
execute, execute,
options: [ options: [
{name: 'welcome_channel', description: 'Sets the channel for welcome messages', type: Constants.ApplicationCommandOptionTypes.CHANNEL }, {name: 'welcome_channel', description: 'Sets the channel for welcome messages', type: Constants.ApplicationCommandOptionTypes.CHANNEL },
{name: 'welcome_message', description: 'Sets the welcome message, Use {un} for username, {ut} for user tag and {sn} for server name', type: Constants.ApplicationCommandOptionTypes.STRING }, {name: 'welcome_message', description: 'Use {un}, {ud}, {ut}, and {sn} for username, user descriminator, user tag, and server name', type: Constants.ApplicationCommandOptionTypes.STRING },
{name: 'welcome_banner', description: 'Sets the welcome banner', type: Constants.ApplicationCommandOptionTypes.ATTACHMENT},
{name: 'welcome_text_color', description: 'Sets the welcome banner text color', type: Constants.ApplicationCommandOptionTypes.STRING},
{name: 'keep_logs', description: 'Toggles logging', type: Constants.ApplicationCommandOptionTypes.BOOLEAN }, {name: 'keep_logs', description: 'Toggles logging', type: Constants.ApplicationCommandOptionTypes.BOOLEAN },
{name: 'log_channel', description: 'Sets the logging channel', type: Constants.ApplicationCommandOptionTypes.CHANNEL }, {name: 'log_channel', description: 'Sets the logging channel', type: Constants.ApplicationCommandOptionTypes.CHANNEL },
{name: 'log_severity', description: 'Sets the logging Severity (logs this/lower tiers)', type: Constants.ApplicationCommandOptionTypes.STRING, choices: [{name: 'none', value: 'none'}, {name: 'low', value: 'low'}, {name: 'medium', value: 'medium'}, {name: 'high', value: 'high'}] }, {name: 'log_severity', description: 'Sets the logging Severity (logs this/lower tiers)', type: Constants.ApplicationCommandOptionTypes.STRING, choices: [{name: 'none', value: 'none'}, {name: 'low', value: 'low'}, {name: 'medium', value: 'medium'}, {name: 'high', value: 'high'}] },
{name: 'announcement_role', description: 'Sets the role to be pinged for reminders', type: Constants.ApplicationCommandOptionTypes.ROLE}, {name: 'ping_role', description: 'Sets the role to be pinged for reminders', type: Constants.ApplicationCommandOptionTypes.ROLE},
{name: 'announcement_channel', description: 'Sets the channel for reminders', type: Constants.ApplicationCommandOptionTypes.CHANNEL} {name: 'ping_channel', description: 'Sets the channel for reminders', type: Constants.ApplicationCommandOptionTypes.CHANNEL},
// {name: 'help', description: 'gets help with setup commands', type: Constants.ApplicationCommandOptionTypes.STRING, choices: [{name: 'welcome', value: 'welcome'}, {name: 'logs', value: 'logs'}, {name: 'announcement', value: 'announcement'}]} {name: 'add_mod_role', description: 'Make a role into an admin role for Selmer Bot, able to execute ALL Selmer Bot commands', type: Constants.ApplicationCommandOptionTypes.ROLE},
{name: 'remove_mod_role', description: 'Remove a Selmer Bot moderation role', type: Constants.ApplicationCommandOptionTypes.ROLE},
{name: 'toggle_leveling', description: 'Enable or Disable the leveling system', type: Constants.ApplicationCommandOptionTypes.BOOLEAN},
{name: 'leveling_banner', description: 'Set the card background for the leveling system', type: Constants.ApplicationCommandOptionTypes.ATTACHMENT},
{name: 'leveling_text', description: 'Use {un}, {ud}, {ut}, {sn}, and {r} for username, descriminator, user tag, server name, and rank', type: Constants.ApplicationCommandOptionTypes.STRING},
{name: 'leveling_color', description: 'Set the card text color for the leveling system', type: Constants.ApplicationCommandOptionTypes.STRING},
{name: 'help', description: 'in-app?', type: Constants.ApplicationCommandOptionTypes.BOOLEAN}
] ]
} }
+35
View File
@@ -0,0 +1,35 @@
const { checkRole } = require('./verify.js');
const { Constants } = require('discord.js');
module.exports = {
name: 'unlock',
description: 'Unlock a channel',
execute(interaction, Discord, Client, bot) {
const arg = interaction.options.data[0];
const guild = bot.guilds.cache.get(interaction.guildId);
checkRole(bot, guild, interaction.user.id).then((isAllowed) => {
if (!isAllowed) { return message.reply('Insufficient Permissions!'); }
var channel;
if (arg) {
channel = arg.channel;
} else {
channel = interaction.channel;
}
let role = interaction.guild.roles.cache.find(r => r.name === "@everyone");
channel.permissionOverwrites.edit(role.id, {
VIEW_CHANNEL: true,
SEND_MESSAGES: true,
READ_MESSAGE_HISTORY: true,
ATTACH_FILES: true
});
interaction.reply(`${channel} has been unlocked!`);
});
},
options: [{name: 'channel', description: 'The channel to unlock (defaults to current channel)', type: Constants.ApplicationCommandOptionTypes.CHANNEL, required: false}]
}
-33
View File
@@ -1,33 +0,0 @@
const { checkRole } = require('./verify.js');
const { Constants } = require('discord.js');
module.exports = {
name: 'unlock',
description: 'Unlock a channel',
execute(interaction, Discord, Client, bot) {
const arg = interaction.options.data[0];
const guild = bot.guilds.cache.get(interaction.guildId);
if (!checkRole(bot, guild, interaction.user.id)) { return message.reply('Insufficient Permissions!'); }
var channel;
if (arg) {
channel = arg.channel;
} else {
channel = interaction.channel;
}
let role = interaction.guild.roles.cache.find(r => r.name === "@everyone");
channel.permissionOverwrites.edit(role.id, {
VIEW_CHANNEL: true,
SEND_MESSAGES: true,
READ_MESSAGE_HISTORY: true,
ATTACH_FILES: true
});
interaction.reply(`${channel} has been unlocked!`);
},
options: [{name: 'channel', description: 'The channel to unlock (defaults to current channel)', type: Constants.ApplicationCommandOptionTypes.CHANNEL, required: false}]
}
+30 -23
View File
@@ -1,32 +1,39 @@
function checkRole(bot, guild, userId, cal = false) { const Discord = require('discord.js');
var roleName;
if (cal) { /**
roleName = "Selmer Bot Calendar"; * @param {Discord.Guild} guild
} else { * @returns {Promise<Boolean>}
roleName = "Selmer Bot Commands"; */
} function checkRole(bot, guild, userId) {
return new Promise((resolve, reject) => {
const role = guild.roles.cache.find((role) => { return (role.name == roleName); })
const user = guild.members.cache.get(userId); const user = guild.members.cache.get(userId);
return (role != undefined && user.roles.cache.has(role.id)); // || user.id == guild.ownerId || bot.inDebugMode // return (role != undefined && user.roles.cache.has(role.id)); // || user.id == guild.ownerId || bot.inDebugMode
// Maybe implement this later, useless for now
bot.mongoconnection.then((client) => {
// const role = client.db(message.guild.id).collection("admin-roles");
const a = new Array();
client.db(guild.id).collection("SETUP").findOne({_id: "roles"}).then((doc) => {
const comRoles = doc.commands;
const role = guild.roles.cache.find((role) => { return (role.name == "Selmer Bot Commands"); });
const hasPreAdminRole = (role != undefined && user.roles.cache.has(role.id) || user.id == guild.ownerId);
/*Maybe implement this later, useless for now if (!comRoles) {
const client = new MongoClient(mongouri, { useNewUrlParser: true, useUnifiedTopology: true, serverApi: ServerApiVersion.v1 }); resolve(hasPreAdminRole);
client.connect(err => { } else {
const hasRoles = [];
Promise.all(comRoles.map((val) => {
const role = client.db(message.guild.id).collection("admin-roles"); if (user.roles.cache.has(val)) {
shop.find().toArray(function(err, itemstemp) { hasRoles.push(true);
if (err) throw err; }
})).then(() => {
items = [...itemstemp]; resolve(hasRoles.length > 0 || hasPreAdminRole);
});
client.close(); }
});
});
}); });
});*/
} }
+104 -84
View File
@@ -1,105 +1,125 @@
const { MessageAttachment } = require('discord.js'); const sharp = require('sharp');
// const { readFile } = require('fs/promises');
const fs = require("fs");
const fetch = require('node-fetch'); const fetch = require('node-fetch');
const arrayBufferToBuffer = require('arraybuffer-to-buffer'); const { GuildMember } = require('discord.js');
const { request } = require('undici');
const CanvasImport = require('@napi-rs/canvas');
const canvas = CanvasImport.createCanvas(700, 250)
const context = canvas.getContext('2d')
//https://some-random-api.ml/welcome
async function welcome(member, welcomechannel, welcomemessage = null, welcomebanner = null) {
//Draw Stuff
const context = canvas.getContext('2d');
var bkimgsrc;
let bkurl = 'https://github.com/ION606/selmerBot/blob/main/commands/admin/wallpaper.jpg';
const response = await fetch(bkurl);
response.arrayBuffer().then(async (data) => {
// const background = new CanvasImport.Image();
// background.src = arrayBufferToBuffer(data);
// This uses the canvas dimensions to stretch the image onto the entire canvas function formatMessage(member, welcomemessage, isLvl, rank = null) {
// context.drawImage(background, 0, 0, canvas.width, canvas.height); return new Promise((resolve, reject) => {
context.fillStyle = 'rgba(0,0,0,1)'; let text;
context.fillRect(0,0, canvas.width, canvas.height); if (!isLvl) {
text = `Welcome to ${member.guild.name} ${member.user.tag}!`;
//Draw the Border
context.strokeStyle = '#0099ff';
context.strokeRect(0, 0, canvas.width, canvas.height);
//Add Text
//have the function here, because returns are whack
const applyText = (canvas, text) => {
const context = canvas.getContext('2d');
// Declare a base size of the font
let fontSize = 70;
let i = 0;
do {
// Assign the font to the context and decrement it so it can be measured again
context.font = `italic ${fontSize -= 10}px sans-serif`;
// Compare pixel width of the text to the canvas minus the approximate avatar size
i ++;
} while (context.measureText(text).width > canvas.width - 100);
// Return the result to use in the actual canvas
return context.font;
};
//message.author.username == interaction.member.displayName
//message.guild.name == interaction.member.guild.name
let text = `Welcome to ${member.guild.name} ${member.user.username}#${member.user.discriminator}!`;
if (welcomemessage != null) { if (welcomemessage != null) {
text = welcomemessage; text = welcomemessage;
text = text.replace('{sn}', member.guild.name); text = text.replace('{sn}', member.guild.name);
text = text.replace('{un}', member.user.username); text = text.replace('{un}', member.user.username);
text = text.replace('{ut}', member.user.discriminator); text = text.replace('{ud}', member.user.discriminator);
text = text.replace('{ut}', member.user.tag);
}
} else {
text = `Congradulations ${member.user.tag} for reaching rank ${rank}!`;
if (welcomemessage != null) {
text = welcomemessage;
text = text.replace('{sn}', member.guild.name);
text = text.replace('{un}', member.user.username);
text = text.replace('{ud}', member.user.discriminator);
text = text.replace('{ut}', member.user.tag);
text = text.replace('{r}', rank);
}
} }
context.font= applyText(canvas, text); resolve(text);
context.fillStyle = '#ffffff'; });
context.fillText(text, (canvas.width/2) - (context.measureText(text).width)/2, canvas.height - 15); }
//Draw a white circle /**
context.beginPath(); * @param {GuildMember} member
context.arc((canvas.width/2), 90, 85, 0, 2 * Math.PI, false); * @param {*} welcomeChannel
context.fillStyle = 'white'; */
context.fill(); async function welcome(member, welcomeChannel, welcomemessage, welcomebanner, welcomeTextCol, isLvl = false, rank = null) {
context.closePath(); formatMessage(member, welcomemessage, isLvl, rank).then(async (wmsg) => {
const width = 1024;
const height = 500;
const usernameText = `${wmsg}`;
const memberCountText = (!isLvl) ? `You are member ${member.guild.memberCount}` : "";
//ANYTHING DRAWN AFTER THIS WILL BE CLIPPED!!! var uSize = 55 - Math.round(wmsg.length/2);
//Make whatever image will be draw (the user's avatar) into a circular format
context.beginPath();
context.arc((canvas.width/2), 90, 80, 0, Math.PI * 2, true);
context.closePath();
// Clip off the region you just drew (enforce template?) if (uSize < 5) { uSize = 5; }
context.clip();
const username = `
<svg width="${width}" height="${height}">
<style>
.username { fill: ${welcomeTextCol}; font-size: ${uSize}px; font-weight: bold;}
</style>
<text x="50%" y="50%" text-anchor="middle" class="username" font-family='Didot'>${usernameText}</text>
</svg>
`;
const memberCount = `
<svg width="${width}" height="${height}">
<style>
.memberCount { fill: ${welcomeTextCol}; font-size: 40px; font-weight: bold;}
</style>
<text x="50%" y="50%" text-anchor="middle" class="memberCount" font-family='Didot'>${memberCountText}</text>
</svg>
`;
//Add the user's profile pic (message.author == interaction.user) const r = 100;
const { body } = await request(member.displayAvatarURL({ format: 'jpg' })); const circleShape = Buffer.from(`<svg><circle cx="${r}" cy="${r}" r="${r}" /></svg>`);
const avatar = new CanvasImport.Image(); var response, arrayBuffer;
avatar.src = Buffer.from(await body.arrayBuffer()); const usernameBuffer = Buffer.from(username);
context.drawImage(avatar, (canvas.width/2) - 80, 10, 160, 160); const memberCountBuffer = Buffer.from(memberCount);
response = await fetch(member.displayAvatarURL());
arrayBuffer = await response.arrayBuffer();
const iconBuffer = Buffer.from(arrayBuffer);
// Use the helpful Attachment class structure to process the file for you var bkBuffer;
const attachment = new MessageAttachment(canvas.toBuffer('image/png'), 'profile-image.png');
welcomechannel.send({ files: [attachment] }); if (!welcomebanner) {
response = await fetch('https://wallpapercave.com/wp/wp3258574.png');
arrayBuffer = await response.arrayBuffer();
bkBuffer = Buffer.from(arrayBuffer);
} else {
// return console.log(welcomebanner);
bkBuffer = Buffer.from(welcomebanner, 'base64');
}
}) sharp(iconBuffer)
.resize(300, 300)
.composite([{
input: circleShape,
blend: 'dest-in'
}])
.toBuffer().then((iconBufferNew) => {
sharp(bkBuffer)
.resize(1024, 500)
.composite([
{
input: usernameBuffer,
top: 80,
left: -10,
},
{
input: memberCountBuffer,
top: 130,
left: -10,
},
{
input: iconBufferNew,
top: 10,
left: 1024/2 - 300/2,
},
]).toBuffer((err, buffer) => {
if (err) { return console.error(err); }
// return console.log(buffer.byteLength * 0.000001);
welcomeChannel.send({
files: [buffer],
});
});
});
});
} }
module.exports = { welcome } module.exports = { welcome }
+45 -22
View File
@@ -3,6 +3,7 @@ const { MongoClient, ServerApiVersion } = require('mongodb');
const { Collection, Client, Formatters, Intents, Interaction } = require('discord.js'); const { Collection, Client, Formatters, Intents, Interaction } = require('discord.js');
const { CLIENT_ODBC } = require('mysql/lib/protocol/constants/client'); const { CLIENT_ODBC } = require('mysql/lib/protocol/constants/client');
const { time } = require('@discordjs/builders'); const { time } = require('@discordjs/builders');
const { welcome } = require('../admin/welcome.js');
let currencySymbol = '$'; let currencySymbol = '$';
@@ -46,7 +47,12 @@ function CreateNewCollection(interaction, client, server, id, opponent = null, g
} }
function addxp(interaction, dbo, amt, xp_list) {
/**
* @param {Interaction} interaction
* @returns
*/
function addxp(bot, interaction, dbo, amt, xp_list, noPing = false) {
if (!isNum(amt)) { return console.log("This isn't a number...."); } if (!isNum(amt)) { return console.log("This isn't a number...."); }
dbo.find({"balance": {$exists: true}}).toArray(function(err, doc) { dbo.find({"balance": {$exists: true}}).toArray(function(err, doc) {
@@ -55,6 +61,7 @@ function addxp(interaction, dbo, amt, xp_list) {
temp = doc[0]; temp = doc[0];
let rank = temp.rank + 1; //The table starts at rank 0, the user starts at rank 1 let rank = temp.rank + 1; //The table starts at rank 0, the user starts at rank 1
const txp = amt; /*temp.xp + amt; // This part was used before the xp check was made in the 'work' function */ const txp = amt; /*temp.xp + amt; // This part was used before the xp check was made in the 'work' function */
//If the rank is less than 100, you can still advance //If the rank is less than 100, you can still advance
if (rank < 101) { if (rank < 101) {
let needed = xp_list.get(rank); let needed = xp_list.get(rank);
@@ -75,14 +82,39 @@ function addxp(interaction, dbo, amt, xp_list) {
let newmp = temp.mp + 5; let newmp = temp.mp + 5;
dbo.updateOne({balance: temp.balance, rank: temp.rank, lastdayworked: temp.lastdayworked}, { $set: { rank: rank, hpmp: {maxhp: newhp, maxmp: newmp} }}); dbo.updateOne({balance: temp.balance, rank: temp.rank, lastdayworked: temp.lastdayworked}, { $set: { rank: rank, hpmp: {maxhp: newhp, maxmp: newmp}, xp: txp }});
interaction.channel.send('Congradulations <@' + interaction.user.id + '> for reaching rank ' + String(rank) + '!');
var user;
if (interaction.user) {
user = interaction.user;
} else {
// This is a message
user = interaction.author;
}
if (bot) {
bot.mongoconnection.then((client) => {
const sbo = client.db(interaction.guildId).collection('SETUP');
sbo.findOne({_id: 'LEVELING'}).then((doc) => {
if (!doc || !doc.card) {
return interaction.channel.send('Congradulations <@' + user.id + '> for reaching rank ' + String(rank) + '!');
}
const member = interaction.guild.members.cache.get((interaction.user) ? interaction.user.id : interaction.member.id);
welcome(member, interaction.channel, doc.text, doc.card, doc.col, true, String(rank));
});
});
} else {
interaction.channel.send('Congradulations <@' + user.id + '> for reaching rank ' + String(rank) + '!');
}
} }
} else { } else {
if (!noPing) {
interaction.reply("You've already reached max level!").catch((err) => { interaction.reply("You've already reached max level!").catch((err) => {
interaction.channel.send("You've already reached max level!"); interaction.channel.send("You've already reached max level!");
}); });
} }
}
dbo.updateOne({balance: temp.balance}, { $set: { xp: txp}}); dbo.updateOne({balance: temp.balance}, { $set: { xp: txp}});
}); });
@@ -164,7 +196,7 @@ function buy(id, interaction, dbo, shop, xp_list) {
var newObj = { name: item.name, cost: item.cost, icon: item.icon, sect: item.sect}; var newObj = { name: item.name, cost: item.cost, icon: item.icon, sect: item.sect};
addxp(interaction, dbo, Math.ceil(item.cost * 1.2), xp_list); addxp(bot, interaction, dbo, Math.ceil(item.cost * 1.2), xp_list);
dbo.find(newObj, {$exists: true}).toArray(function(err, doc) { dbo.find(newObj, {$exists: true}).toArray(function(err, doc) {
if(String(doc)) { if(String(doc)) {
@@ -182,7 +214,7 @@ function buy(id, interaction, dbo, shop, xp_list) {
//FIXME //FIXME
function sell(id, interaction, dbo, shop, xp_list) { function sell(bot, id, interaction, dbo, shop, xp_list) {
const args = interaction.options.data; const args = interaction.options.data;
const query = args.filter((arg) => { return (arg.name == 'item'); })[0].value; const query = args.filter((arg) => { return (arg.name == 'item'); })[0].value;
var num = args.filter((arg) => { return (arg.name == 'amount'); })[0].value; var num = args.filter((arg) => { return (arg.name == 'amount'); })[0].value;
@@ -218,7 +250,7 @@ function sell(id, interaction, dbo, shop, xp_list) {
dbo.updateOne({"balance": {$exists: true}}, { $set: { balance: currentBal + amountSoldFor }}); dbo.updateOne({"balance": {$exists: true}}, { $set: { balance: currentBal + amountSoldFor }});
}); });
addxp(interaction, dbo, Math.ceil(functional_item.cost * 1.2), xp_list); addxp(bot, interaction, dbo, Math.ceil(functional_item.cost * 1.2), xp_list);
interaction.reply(`You've sold ${num} ${String(functional_item.name)} for ${currencySymbol}${amountSoldFor}`) interaction.reply(`You've sold ${num} ${String(functional_item.name)} for ${currencySymbol}${amountSoldFor}`)
.catch((err) => { .catch((err) => {
@@ -233,7 +265,7 @@ function sell(id, interaction, dbo, shop, xp_list) {
} }
function work(dbo, interaction, xp_list) { function work(bot, dbo, interaction, xp_list) {
let fulldate = new Date(); let fulldate = new Date();
let date = fulldate.getDate(); let date = fulldate.getDate();
dbo.find({"lastdayworked": {$exists: true}}).toArray(function(err, doc) { dbo.find({"lastdayworked": {$exists: true}}).toArray(function(err, doc) {
@@ -254,7 +286,8 @@ function work(dbo, interaction, xp_list) {
//Update the amount to the new TOTAL balance //Update the amount to the new TOTAL balance
dbo.updateOne({"balance": {$exists: true}}, { $set: { balance: doc[0].balance + amt, lastdayworked: date }}); dbo.updateOne({"balance": {$exists: true}}, { $set: { balance: doc[0].balance + amt, lastdayworked: date }});
addxp(interaction, dbo, xp_earned, xp_list);
addxp(bot, interaction, dbo, xp_earned, xp_list);
interaction.reply(`<@${interaction.user.id}> worked and earned ${currencySymbol}${amt} and ${xp_earned} xp!`).catch((err) => { interaction.reply(`<@${interaction.user.id}> worked and earned ${currencySymbol}${amt} and ${xp_earned} xp!`).catch((err) => {
interaction.channel.send(`<@${interaction.user.id}> worked and earned ${currencySymbol}${amt} and ${xp_earned} xp!`) interaction.channel.send(`<@${interaction.user.id}> worked and earned ${currencySymbol}${amt} and ${xp_earned} xp!`)
}); });
@@ -349,27 +382,17 @@ module.exports = {
currencySymbol = bot.currencysymbolmmain; currencySymbol = bot.currencysymbolmmain;
/*/test area
if (command == 'xp' || command == 'adbal') {
//Selmer Dev only command
if (message.member.roles.cache.has('944048889038774302')) {
if (command == 'xp') {
return addxp(message, dbo, Number(args[0]), xp_list);
}
}
}*/
//Command Area //Command Area
if(command == 'init') { if(command == 'init') {
//Add security check here //Add security check here
// init.execute(bot, message, args, command, dbo, Discord, connect); // init.execute(bot, message, args, command, dbo, Discord, connect);
return; return;
} else if (command == 'buy') { } else if (command == 'buy') {
buy(id, interaction, dbo, items, xp_list); buy(bot, id, interaction, dbo, items, xp_list);
} else if (command == 'shop') { } else if (command == 'shop') {
getShop(interaction, items, bot); getShop(interaction, items, bot);
} else if (command == 'work') { } else if (command == 'work') {
work(dbo, interaction, xp_list); work(bot, dbo, interaction, xp_list);
} else if (command == 'rank') { } else if (command == 'rank') {
rank(dbo, interaction, xp_list); rank(dbo, interaction, xp_list);
} else if (command == 'inventory') { } else if (command == 'inventory') {
@@ -377,7 +400,7 @@ module.exports = {
} else if (command == 'balance') { } else if (command == 'balance') {
getBalance(dbo, interaction); getBalance(dbo, interaction);
} else if (command == 'sell') { } else if (command == 'sell') {
sell(id, interaction, dbo, items, xp_list); sell(bot, id, interaction, dbo, items, xp_list);
} else { } else {
interaction.reply(`${command} is not a command`).catch((err) => { interaction.reply(`${command} is not a command`).catch((err) => {
interaction.channel.send(`${command} is not a command`); interaction.channel.send(`${command} is not a command`);
@@ -388,6 +411,6 @@ module.exports = {
}, },
//Battle Updating stuff //Battle Updating stuff
addxp, checkAndUpdateBal, CreateNewCollection, econHelp, addxp, BASE, STATE, addxp, checkAndUpdateBal, CreateNewCollection, econHelp, BASE, STATE,
options: [] options: []
} }
@@ -1,5 +1,5 @@
const fs = require('fs'); const fs = require('fs');
const {Buffer} = require('buffer'); const { Client } = require('discord.js');
function mapToObj(map){ function mapToObj(map){
const obj = {} const obj = {}
@@ -43,15 +43,20 @@ async function backupLists(bot, IDM) {
} }
} }
/**
* @param {Client} bot
* @param {Boolean} IDM
*/
async function loadBotBackups(bot, IDM) { async function loadBotBackups(bot, IDM) {
try { try {
if (IDM) { if (!process.env.backupLists) {
const botBackups = require('./backup.json').backups; const botBackups = require('../admin/backup.json').backups;
bot.lockedChannels = objToMap(botBackups.locked); bot.lockedChannels = objToMap(botBackups.locked);
} else { } else {
bot.lockedChannels = objToMap(JSON.parse(botBackups.locked)); bot.lockedChannels = objToMap(JSON.parse(process.env.backupLists.locked));
} }
// bot.user.setActivity("RESTARTING BOT, PLEASE STAND BY.mp3", { type: "LISTENING" }); // User is....undefined????
} catch (err) { } catch (err) {
console.error(err); console.error(err);
bot.lockedChannels = new Map(); bot.lockedChannels = new Map();
+84
View File
@@ -0,0 +1,84 @@
const Discord = require('discord.js')
const axios = require('axios')
const cheerio = require('cheerio');
const { URL } = require("url");
function isValidUrl(s) {
try {
new URL(s);
return true;
} catch (err) {
return false;
}
};
function handleStreamInp(bot, url, customTitle) {
return new Promise((resolve, reject) => {
if (!isValidUrl(url)) {
return reject(false);
}
axios.get(url).then(async response => {
var title;
if (customTitle) {
title = customTitle;
} else {
const html = response.data;
const $ = cheerio.load(html);
title = $('meta[name="description"]').attr("content");
}
bot.user.setActivity({name: title, type: "STREAMING", url: url});
resolve(true);
});
});
}
//Have this only visible to you.
/**
* @param {Discord.Client} bot
* @param {Discord.Interaction} interaction
*/
async function setPresence(bot, interaction) {
const command = interaction.options.data[0];
if (command.name == "setpresence") {
const txt = command.options.filter((arg) => { return(arg.name == 'pres_text'); })[0].value;
const type = command.options.filter((arg) => { return(arg.name == 'type'); })[0].value;
var sep = " ";
if (type == "LISTENING" || type == "WATCHING") {
sep = " to ";
} else if (type == "COMPETING") {
sep = " in ";
}
//Check if it's me
if (interaction.user.id == bot.guilds.cache.get(bot.home_server).ownerId) {
if (type == "STREAMING") {
const t = (command.options.length > 2) ? command.options.filter((arg) => { return(arg.name == "display_name"); })[0].value : null;
handleStreamInp(bot, txt, t, interaction).then(() => {
interaction.reply(`Set bot presence to _${type + sep + txt}_`);
}).catch(() => {
interaction.reply("Invalid URL").catch((err) => {
interaction.channel.send("Invalid URL");
});
});
} else {
bot.user.setActivity(txt, { type: type });
interaction.reply(`Set bot presence to _${type + sep + txt}_`);
}
}
} else if (command.name == "setactivity") {
const stat = command.options[0];
bot.user.setStatus(stat.value);
interaction.reply(`Set bot status to ${stat.value}`);
}
}
module.exports = { setPresence, isValidUrl }
+4 -2
View File
@@ -27,10 +27,12 @@ function handle_dm(message, bot) {
handleInp(bot, message); handleInp(bot, message);
} else if (message.content.indexOf('!reminders') != -1) { } else if (message.content.indexOf('!reminders') != -1) {
reminders.execute(message, null, null, null, bot); reminders.execute(message, null, null, null, bot);
} else if (message.content.indexOf('!repo') != -1 || message.content.indexOf('!code') != -1) {
repo.execute(message, null, null, null, bot);
} }
// else if (message.content.indexOf('!repo') != -1 || message.content.indexOf('!code') != -1) {
// repo.execute(message, null, null, null, bot);
// }
else { else {
return message.reply('UNUSABLE DM COMMAND DETECTED'); return message.reply('UNUSABLE DM COMMAND DETECTED');
} }
+16 -13
View File
@@ -5,16 +5,16 @@ const { addComplaintButton } = require('../dev only/submitcomplaint');
//#region game lose/win //#region game lose/win
function loseGame(user_dbo, xp_collection, message, bot = null) { function loseGame(user_dbo, xp_collection, interaction, bot = null) {
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
user_dbo.find({"game": {$exists: true}}).toArray(function(err, docs) { user_dbo.find({"game": {$exists: true}}).toArray(function(err, docs) {
const doc = docs[0]; const doc = docs[0];
if (doc == undefined) { if (doc == undefined) {
message.reply("Oops! There's been an error, click the ✅ to report this!"); interaction.reply("Oops! There's been an error, click the ✅ to report this!");
addComplaintButton(bot, message); addComplaintButton(bot, interaction);
return; return;
} }
if (doc.game == null) { return message.reply("You're not even in a game and you're trying to quit! Sad..."); } if (doc.game == null) { return interaction.reply("You're not even in a game and you're trying to quit! Sad..."); }
var addbal; var addbal;
//If this function was called from "winGame", return //If this function was called from "winGame", return
@@ -25,10 +25,13 @@ function loseGame(user_dbo, xp_collection, message, bot = null) {
if (doc.balance > 5) { if (doc.balance > 5) {
user_dbo.updateOne(doc, { $set: { balance: doc.balance - addbal}}); user_dbo.updateOne(doc, { $set: { balance: doc.balance - addbal}});
} }
} else { message.channel.delete(); } } else {
//Check if the channel is a thread
interaction.channel.delete();
}
//Update the player's xp //Update the player's xp
addxp(message, user_dbo, Math.ceil((BASE.XP * doc.rank)/2),xp_collection) addxp(bot, interaction, user_dbo, Math.ceil((BASE.XP * doc.rank)/2),xp_collection);
user_dbo.updateOne({"game": {$exists: true}}, { $set: { game: null, opponent: null, state: STATE.IDLE, 'hpmp.hp': doc.hpmp.maxhp, 'hpmp.mp': doc.hpmp.maxmp }}); user_dbo.updateOne({"game": {$exists: true}}, { $set: { game: null, opponent: null, state: STATE.IDLE, 'hpmp.hp': doc.hpmp.maxhp, 'hpmp.mp': doc.hpmp.maxmp }});
resolve(addbal); resolve(addbal);
@@ -38,14 +41,14 @@ function loseGame(user_dbo, xp_collection, message, bot = null) {
} }
function winGame(client, bot, db, user_dbo, xp_collection, message, singlePlayer = false) { function winGame(client, bot, db, user_dbo, xp_collection, interaction, singlePlayer = false) {
user_dbo.find({"game": {$exists: true}}).toArray(function(err, docs){ user_dbo.find({"game": {$exists: true}}).toArray(function(err, docs){
const doc = docs[0]; const doc = docs[0];
//Check for an opponent //Check for an opponent
if (doc.opponent != null) { if (doc.opponent != null) {
let other = db.collection(doc.opponent); let other = db.collection(doc.opponent);
let promise_temp = loseGame(other, xp_collection, message); let promise_temp = loseGame(other, xp_collection, interaction);
promise_temp.then(function(result) { promise_temp.then(function(result) {
var amt_taken = result; var amt_taken = result;
@@ -55,7 +58,7 @@ function winGame(client, bot, db, user_dbo, xp_collection, message, singlePlayer
//Delete the bot's record of the game //Delete the bot's record of the game
if (!singlePlayer) { if (!singlePlayer) {
client.db('B|S' + bot.user.id).collection(message.guild.id).drop(); client.db('B|S' + bot.user.id).collection(interaction.guildId).drop();
} }
@@ -63,16 +66,16 @@ function winGame(client, bot, db, user_dbo, xp_collection, message, singlePlayer
user_dbo.updateOne({"game": {$exists: true}}, { $set: { game: null, opponent: null, state: STATE.IDLE, xp: doc.xp + (BASE.XP * doc.rank), 'hpmp.hp': doc.hpmp.maxhp, 'hpmp.mp': doc.hpmp.maxmp }}); user_dbo.updateOne({"game": {$exists: true}}, { $set: { game: null, opponent: null, state: STATE.IDLE, xp: doc.xp + (BASE.XP * doc.rank), 'hpmp.hp': doc.hpmp.maxhp, 'hpmp.mp': doc.hpmp.maxmp }});
if (!singlePlayer) { if (!singlePlayer) {
const channel = bot.channels.cache.get(message.channel.parentId); const channel = bot.channels.cache.get(interaction.channel.parentId);
channel.send(`<@${user_dbo.s.namespace.collection}> just won a game of "${docs[0].game}"!`); channel.send(`<@${user_dbo.s.namespace.collection}> just won a game of "${docs[0].game}"!`);
} }
message.channel.delete(); interaction.channel.delete();
}); });
} }
function equipItem(client, bot, db, dbo, message) { function equipItem(client, bot, db, dbo, interaction) {
return interaction.reply("This command is not implemented yet!");
if (!bot.inDebugMode) { return; } if (!bot.inDebugMode) { return; }
let items = [ let items = [
{ name: 'HP Potion', cost: 20, icon: 'CUSTOM|healing_potion', sect: 'HP', num: 2 }, { name: 'HP Potion', cost: 20, icon: 'CUSTOM|healing_potion', sect: 'HP', num: 2 },
+110 -94
View File
@@ -1,5 +1,7 @@
// // @ts-check //Disabled // // @ts-check //Disabled
// Maybe have the interaction type be "user" https://canary.discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-types
const { MessageActionRow, MessageButton, Message } = require('discord.js');
const { MongoClient, ServerApiVersion } = require('mongodb'); const { MongoClient, ServerApiVersion } = require('mongodb');
let ecoimport = require("../db/econ.js"); let ecoimport = require("../db/econ.js");
@@ -20,7 +22,7 @@ const { chooseClass, presentClasses } = require('./game_classes.js');
//Has a list of all games (used to change player state) //Has a list of all games (used to change player state)
const allGames = ['battle', 'Tic Tac Toe']; const allGames = ['battle', 'Tic Tac Toe'];
// const { NULL } = require('mysql/lib/protocol/constants/types');
//#region functions (NOT GAME SPECIFIC) //#region functions (NOT GAME SPECIFIC)
@@ -69,18 +71,18 @@ async function Initialize(bot, user_dbo, command, message, first, second, other_
//#endregion //#endregion
//replies to the message with current game specifics //replies to the message with current game specifics
function getGame(message, args, db) { function getGame(interaction, args, db) {
let id; let id;
var temp; var temp;
if (args.length == 1 && String(args[0]).startsWith('<')) { id = args[0].substr(2, args[0].length - 3)} if (args.length == 1 && String(args[0]).startsWith('<')) { id = args[0].substr(2, args[0].length - 3)}
else { id = message.author.id; } else { id = interaction.user.id; }
var user_dbo = db.collection(message.author.id); var user_dbo = db.collection(interaction.user.id);
user_dbo.find({"game": {$exists: true}}).toArray(function(err, docs){ user_dbo.find({"game": {$exists: true}}).toArray(function(err, docs){
const doc = docs[0]; const doc = docs[0];
if (doc.game == null) { if (doc.game == null) {
return message.reply(`<@${id}> is not currently playing a game!`); return interaction.reply(`<@${id}> is not currently playing a game!`);
} }
temp = `<@${id}> is currently playing "${doc.game}"`; temp = `<@${id}> is currently playing "${doc.game}"`;
@@ -89,58 +91,64 @@ function getGame(message, args, db) {
temp += ` with <@${doc.opponent}>` temp += ` with <@${doc.opponent}>`
} }
message.reply(temp); interaction.reply(temp);
}); });
} }
function acceptIsValid(bot, other_discord, message, msg, tag_len) { function acceptIsValid(bot, other_discord, interaction, invUserId, message) {
if (other_discord == undefined) { if (other_discord == undefined) {
message.reply("This is not a valid invite!"); interaction.reply("This is not a valid invite!");
return false; return false;
} }
//Make sure the bot was the one creating the invite //Make sure the bot was the one creating the invite
let check0 = msg.author.bot; let check0 = message.author.bot;
//Author //Author
let tag = msg.content.substr(2, tag_len); let check1 = Number(other_discord.id) == Number(invUserId);
let check1 = Number(tag) == Number(message.author.id);
//Time (within the last 5 min) //Time (within the last 5 min)
let prev = snowflake.convertSnowflakeToDate(msg.id); let prev = snowflake.convertSnowflakeToDate(message.id);
let now = snowflake.convertSnowflakeToDate(message.id); let now = snowflake.convertSnowflakeToDate(interaction.id);
// @ts-ignore // @ts-ignore
let diff = now - prev; let diff = now - prev;
var minutes = Math.floor((diff/1000)/60); var minutes = Math.floor((diff/1000)/60);
let check2 = minutes <= 5 || bot.inDebugMode; let check2 = minutes <= 5 || bot.inDebugMode;
if (!check0) { message.reply("really?"); } if (!check0) { interaction.reply("really?"); }
else if (!check1 && check2) { message.reply("_INVALID USER_"); } else if (!check1 && check2) { interaction.reply("_INVALID USER_"); }
else if (check1 && !check2) { message.reply("_THIS INVITE EXPIRED!_"); } else if (check1 && !check2) { interaction.reply("_THIS INVITE EXPIRED!_"); }
else if (!check1 && !check2) { message.reply("_THIS MESSAGE HAS AN INVALID USER AND HAS EXPIRED_")} else if (!check1 && !check2) { interaction.reply("_THIS MESSAGE HAS AN INVALID USER AND HAS EXPIRED_")}
return (check0 && check1 && check2); return (check0 && check1 && check2);
} }
function hpmp(message, command, dbo) { function hpmp(interaction, command, dbo) {
// throw 'THIS HAS NOT BEEN UPDATED WITH THE MOST RECENT VERSION OF THE MONGODB STRUCTURE!'; // throw 'THIS HAS NOT BEEN UPDATED WITH THE MOST RECENT VERSION OF THE MONGODB STRUCTURE!';
dbo.find({"hpmp": {$exists: true}}).toArray(function(err, doc) {
interaction.reply(`You have ${String(doc[0].hpmp.hp)} hp and ${String(doc[0].hpmp.mp)} mp left!`);
});
/*
if (command == 'hp') { if (command == 'hp') {
dbo.find({"hpmp": {$exists: true}}).toArray(function(err, doc) { dbo.find({"hpmp": {$exists: true}}).toArray(function(err, doc) {
return message.reply(`You have ${String(doc[0].hpmp.hp)} hp left!`); return interaction.reply(`You have ${String(doc[0].hpmp.hp)} hp left!`);
}); });
} else if (command == 'mp') { } else if (command == 'mp') {
dbo.find({"hpmp": {$exists: true}}).toArray(function(err, doc) { dbo.find({"hpmp": {$exists: true}}).toArray(function(err, doc) {
return message.reply(`You have ${String(doc[0].hpmp.hp)} mp left!`); return interaction.reply(`You have ${String(doc[0].hpmp.MP)} mp left!`);
}); });
} }
*/
} }
function equip(message, args, command, dbo, bot, shop) { function equip(interaction, inp, command, dbo, bot, shop) {
const inp = args[1]; // const inp = args[1];
if (!inp) { return message.reply("Please provide input (either a weapon for main or shield for secondary)")} if (!inp) { return interaction.reply("Please provide input (either a weapon for main or shield for secondary)"); }
//Check if the user is already in a game //Check if the user is already in a game
dbo.find({'game': {$exists: true}}).toArray(function(err, docs) { dbo.find({'game': {$exists: true}}).toArray(function(err, docs) {
@@ -149,7 +157,7 @@ function equip(message, args, command, dbo, bot, shop) {
if (doc.game != null) { if (doc.game != null) {
ret = true; ret = true;
// console.log(doc.game); // console.log(doc.game);
return message.reply('You can\'t equip while in a game!'); return interaction.reply('You can\'t equip while in a game!');
} }
//If the thing is a shield, add it to secondary //If the thing is a shield, add it to secondary
@@ -158,7 +166,7 @@ function equip(message, args, command, dbo, bot, shop) {
if (docs[0] != undefined) { if (docs[0] != undefined) {
dbo.updateOne({}, {$set: {'equipped.weapons.secondary': docs[0]}}); dbo.updateOne({}, {$set: {'equipped.weapons.secondary': docs[0]}});
} else { } else {
message.reply("You don't own a shield!"); interaction.reply("You don't own a shield!");
} }
}); });
@@ -170,7 +178,7 @@ function equip(message, args, command, dbo, bot, shop) {
//Equip the weapon //Equip the weapon
dbo.updateOne({}, {$set: {'equipped.weapons.main': docs[0]}}); dbo.updateOne({}, {$set: {'equipped.weapons.main': docs[0]}});
} else { } else {
message.reply(`You don't own any ${inp}s!`); interaction.reply(`You don't own any ${inp}s!`);
} }
}); });
} }
@@ -213,12 +221,11 @@ function in_game_redirector(bot, interaction, threadname, doc, client, mongouri,
module.exports ={ module.exports ={
name: "game", name: "game",
description: "Play a game using Selmer Bot!", description: "Play a game using Selmer Bot!",
async execute(bot, message, args, command, Discord, mongouri, items, xp_collection) { async execute(bot, interaction, command, Discord, mongouri, items, xp_collection) {
//#region Setup //#region Setup
const id = message.author.id; const id = interaction.user.id;
const server = message.guild.id; const server = interaction.guildId;
// // @ts-ignore // // @ts-ignore
// const client = new MongoClient(mongouri, { useNewUrlParser: true, useUnifiedTopology: true, serverApi: ServerApiVersion.v1 }); // const client = new MongoClient(mongouri, { useNewUrlParser: true, useUnifiedTopology: true, serverApi: ServerApiVersion.v1 });
@@ -235,12 +242,12 @@ module.exports ={
const serverinbotdb = botdb.collection(server); const serverinbotdb = botdb.collection(server);
//Initialize if necessary //Initialize if necessary
ecoimport.CreateNewCollection(message, client, server, id); ecoimport.CreateNewCollection(interaction, client, server, id);
command = args[0]; var commandName = command.name;
//Check for a second person and create a second database entry if neccessary //Check for a second person and create a second database entry if neccessary
if (message.mentions.users.first() != undefined) { if (command.options && command.options.length > 0 && command.options[0].type == "USER") {
ecoimport.CreateNewCollection(message, client, server, message.mentions.users.first().id); ecoimport.CreateNewCollection(interaction, client, server, command.options[0].value);
} }
//#endregion //#endregion
@@ -258,41 +265,30 @@ module.exports ={
//#region non-game-specific commands //#region non-game-specific commands
//For TWO+ PLAYER games only!!! //For TWO+ PLAYER games only!!!
if (command == 'accept') { if (commandName == 'accept') {
//Handle the messages const args = interaction.customId.split('|');
if (message.reference == null) { return message.reply("Please reply to a valid battle request message!"); } // console.log(interaction.message.interaction);
let mid = message.reference.messageId; // console.log(interaction.user);
let msg = await message.channel.messages.fetch(mid); // return console.log(args);
//Check if the person actually challenged you
//Get the length of any user tag
let mentioned = msg.mentions.users.keys();
let tag_len = String(mentioned.next().value).length;
//<@tage_len>, <@ --2+tag_len+2+3 = 7+tag_len
let other_tag = msg.content.substr(7+tag_len, tag_len);
const other_discord = msg.mentions.users.get(other_tag);
//Should also check if the player is already playing a game!!! //Should also check if the player is already playing a game!!!
if (!acceptIsValid(bot, other_discord, message, msg, tag_len)) { return; } if (!acceptIsValid(bot, interaction.user, interaction, args[1], interaction.message)) { return; }
//Get the opponent //Get the opponent
const other = db.collection(other_discord.id); const other_id = interaction.message.interaction.user.id;
let startPos = msg.content.indexOf('"') + 1; const other = db.collection(other_id);
let newCommand = msg.content.substr(startPos, msg.content.lastIndexOf('"') - startPos); // return console.log(args, interaction.message.interaction);
let newCommand = interaction.message.interaction.commandName.split(" ")[1];
//#region BOT SECTION //#region BOT SECTION
//Store both IDs in the database (for turns) //Store both IDs in the database (for turns)
let name_first = await bot.users.cache.get(id); let name_first = await bot.users.cache.get(id);
let name_second = await bot.users.cache.get(other_discord.id); let name_second = await bot.users.cache.get(other_id);
// message.reply(`${first} [${name_first}], ${second} [${name_second}]`); throw 'ERR'; // message.reply(`${first} [${name_first}], ${second} [${name_second}]`); throw 'ERR';
const threadname = `${name_first.username} VS ${name_second.username} [${newCommand.toUpperCase()}]`; const threadname = `${name_first.username} VS ${name_second.username} [${newCommand.toUpperCase()}]`;
var newObj = {0: id, 1: other_discord.id, turn: 0, thread: threadname}; var newObj = {0: id, 1: other_id, turn: 0, thread: threadname};
if (newCommand.replaceAll(" ", "").toLowerCase() == 'tictactoe') { newCommand = 'Tic Tac Toe'; } if (newCommand.replaceAll(" ", "").toLowerCase() == 'tictactoe') { newCommand = 'Tic Tac Toe'; }
@@ -316,90 +312,110 @@ module.exports ={
//#endregion //#endregion
const remAccptBtn = (msgToDel) => {
try {
msgToDel.edit({components: []});
} catch(err) {
console.error(err);
}
}
//Need this for all 2 player games //Need this for all 2 player games
const result = Initialize(bot, dbo, newCommand, msg, id, other_discord.id, other); const result = Initialize(bot, dbo, newCommand, interaction.message, id, other_id, other);
if (newCommand == 'battle') { if (newCommand == 'battle') {
result.then(function (thread) { result.then(function (thread) {
battle.handle(client, dbo, other, bot, thread, 'initalize', mongouri, items, null, xp_collection); battle.handle(client, dbo, other, bot, thread, 'initalize', mongouri, items, null, xp_collection);
remAccptBtn(interaction.message);
}); });
} else if (newCommand == 'Tic Tac Toe') { } else if (newCommand == 'Tic Tac Toe') {
result.then(function (thread) { result.then(function (thread) {
ttt.handle(client, db, dbo, other, bot, thread, 'initalize', mongouri, null, xp_collection); ttt.handle(client, db, dbo, other, bot, thread, 'initalize', mongouri, null, xp_collection);
remAccptBtn(interaction.message);
}); });
} }
} else if (command == 'quit') { } else if (commandName == 'quit') {
const channel = bot.channels.cache.get(interaction.channel.parentId);
const channel = bot.channels.cache.get(message.channel.parentId);
//Remove the turn counter from the bot's database //Remove the turn counter from the bot's database
serverinbotdb.deleteOne({0: id} || {1: id}); serverinbotdb.deleteOne({0: id} || {1: id});
if (doc.opponent != null) { if (doc.opponent != null) {
// let other = message.guild.members.cache.get(doc.opponent); // let other = message.guild.members.cache.get(doc.opponent);
let other = db.collection(doc.opponent); let other = db.collection(doc.opponent);
channel.send(`<@${message.author.id}> has quit a game of "${game}" with <@${doc.opponent}>!`); channel.send(`<@${interaction.user.id}> has quit a game of "${game}" with <@${doc.opponent}>!`);
winGame(client, bot, db, other, xp_collection, message); winGame(client, bot, db, other, xp_collection, interaction);
} else { } else {
loseGame(dbo, xp_collection, message, bot); loseGame(dbo, xp_collection, interaction, bot);
channel.send(`<@${message.author.id}> has quit a game of "${game}"!`); channel.send(`<@${interaction.user.id}> has quit a game of "${game}"!`);
} }
} }
else if (command == 'status') { else if (commandName == 'status') {
getGame(message, args, db); getGame(interaction, args, db);
} else if (command == 'hp' || command == 'mp') { } else if (commandName == 'hpmp') {
hpmp(message, command, dbo); hpmp(interaction, commandName, dbo);
} else if (command == 'equip') { } else if (command == 'equip') {
// equipItem(client, bot, db, dbo, message); // equipItem(client, bot, db, dbo, message);
equip(message, args, command, dbo, bot, items); // This does not work
equip(interaction, args, command, dbo, bot, items);
} else if (command == 'classes') { } else if (command == 'classes') {
// This does not work
presentClasses(message, args[1]); presentClasses(message, args[1]);
} }
//#endregion //#endregion
//#region game-specific commands //#region game-specific commands
else { else {
if (command == undefined) { return message.reply("Please specify a game or use _!game help_"); } if (commandName == undefined) { return interaction.reply("Please specify a game or use _!game help_"); }
//Make change to new name if necessary //Make change to new name if necessary
if (command.replaceAll(" ", "").toLowerCase() == 'tictactoe') { command = 'Tic Tac Toe'; } if (commandName.replaceAll(" ", "").toLowerCase() == 'tictactoe') { commandName = 'Tic Tac Toe'; }
if (game == 'battle' || command == 'battle') { //RETURN TO THIS LATER
if (!bot.inDebugMode) { return message.reply("This command is currently in development!"); } if (game == 'battle' || commandName == 'battle') {
if (!bot.inDebugMode) { return interaction.reply("This command is currently in development!"); }
//Handle sending the request and making sure the user exists here const row = new MessageActionRow()
let other_discord = message.mentions.users.first(); .addComponents(
if (other_discord == undefined) { new MessageButton()
return message.reply(`"${args[1]}" is not a valid user (use _!game battle @user_)`); .setCustomId(`gameaccept|${command.options[0].value}|${interaction.user.id}`)
} .setLabel('Accept Invite')
.setStyle('SUCCESS')
);
message.channel.send(`${other_discord}, <@${message.author.id}> has invited you to play _"battle"_. To accept, please reply to this message with _!game accept_`); const content = {content: `${command.options[0].user}, ${interaction.user} has invited you to play _"Tic Tac Toe"_. Click the button to accept the invitation!`, components: [row]};
} else if (game == 'Tic Tac Toe' || command == 'Tic Tac Toe') { interaction.reply(content).catch((err) => interaction.channel.send(content));
let other_discord = message.mentions.users.first();
if (other_discord == undefined) {
return message.reply(`"${args[1]}" is not a valid user (use _!game tictactoe @user_)`);
}
message.channel.send(`${other_discord}, <@${message.author.id}> has invited you to play _"Tic Tac Toe"_. To accept, please reply to this message with _!game accept_`); } else if (game == 'Tic Tac Toe' || commandName == 'Tic Tac Toe') {
} else if (game == 'trivia' || command == 'trivia') { const row = new MessageActionRow()
trivia.execute(message, args, Discord, client, bot); .addComponents(
} else if (game == "minesweeper" || command == 'minesweeper') { new MessageButton()
if (game == "minesweeper" && command == 'minesweeper') { .setCustomId(`gameaccept|${command.options[0].value}|${interaction.user.id}`)
.setLabel('Accept Invite')
.setStyle('SUCCESS')
);
const content = {content: `${command.options[0].user}, ${interaction.user} has invited you to play _"Tic Tac Toe"_. Click the button to accept the invitation!`, components: [row]};
interaction.reply(content).catch((err) => interaction.channel.send(content));
} else if (game == 'trivia' || commandName == 'trivia') {
trivia.execute(interaction, Discord, client, bot);
} else if (game == "minesweeper" || commandName == 'minesweeper') {
if (game == "minesweeper" && commandName == 'minesweeper') {
return message.reply("You're already in a game!"); return message.reply("You're already in a game!");
} }
const threadname = `${message.author.username} has started a solo game of Minesweeper`; const threadname = `${interaction.user.username} is playing Minesweeper`;
const thread = await message.channel.threads.create({ const thread = await interaction.channel.threads.create({
name: threadname, name: threadname,
// type: 'GUILD_PRIVATE_THREAD', // type: 'GUILD_PRIVATE_THREAD',
autoArchiveDuration: 60, autoArchiveDuration: 60,
reason: `N/A`, reason: `N/A`,
}); });
mnswpr.handle(bot, null, thread, message, args); mnswpr.handle(bot, interaction, thread);
} }
//Catch statement (invalid command) //Catch statement (invalid command)
else { else {
message.reply(`'${bot.prefix}game ${command}' is not a command!`); interaction.reply(`'/game ${commandName}' is not a command!`);
} }
} }
//#endregion //#endregion
+61
View File
@@ -0,0 +1,61 @@
const { Constants } = require('discord.js');
const { trivia_categories } = require('./trivia_categories.json');
module.exports = [
{
name: "trivia",
description: 'Start a game of Trivia',
type: Constants.ApplicationCommandOptionTypes.SUB_COMMAND,
options: [
{name: 'difficulty', description: 'The question difficulty OR "help"', type: Constants.ApplicationCommandOptionTypes.STRING, required: true, choices: [{name: 'easy', value: 'easy'}, {name: 'medium', value: 'medium'}, {name: 'hard', value: 'hard'}]},
{name: 'category', description: 'The trivia Category', type: Constants.ApplicationCommandOptionTypes.INTEGER, required: false, choices: trivia_categories},
{name: 'time', description: 'Set the round length (in seconds)', type: Constants.ApplicationCommandOptionTypes.INTEGER, required: false},
]},
{
name: "battle",
description: 'Start a game of Batte',
type: Constants.ApplicationCommandOptionTypes.SUB_COMMAND,
options: [
{name: 'opponent', description: 'Who do you want to battle against?', type: Constants.ApplicationCommandOptionTypes.USER, required: true},
]},
{
name: "minesweeper",
description: "Start a game of Minesweeper",
type: Constants.ApplicationCommandOptionTypes.SUB_COMMAND,
options: [
{name: 'difficulty', description: 'Set the diffficulty', type: Constants.ApplicationCommandOptionTypes.STRING, required: true, choices: [{name: 'easy', value: 'easy'}, {name: 'medium', value: 'medium'}, {name: 'hard', value: 'hard'}]},
// {name: 'opponent', description: 'Play a game against someone else', type: Constants.ApplicationCommandOptionTypes.USER, required: false}
]
},
{
name: "tictactoe",
description: 'Start a game of TicTacToe',
type: Constants.ApplicationCommandOptionTypes.SUB_COMMAND,
options: [
{name: 'opponent', description: 'Who do you want to play against?', type: Constants.ApplicationCommandOptionTypes.USER, required: true},
]},
{
name: "quit",
description: "Quit your current game",
type: Constants.ApplicationCommandOptionTypes.SUB_COMMAND,
options: []
},
{
name: "status",
description: "Check your current game status",
type: Constants.ApplicationCommandOptionTypes.SUB_COMMAND,
options: []
},
{
name: "hpmp",
description: "Check your current game status",
type: Constants.ApplicationCommandOptionTypes.SUB_COMMAND,
options: []
},
]
+24 -17
View File
@@ -3,23 +3,24 @@ const { winGame, loseGame, equipItem } = require('./external_game_functions.js')
const wait = require('node:timers/promises').setTimeout; const wait = require('node:timers/promises').setTimeout;
const { STATE } = require('../db/econ.js') const { STATE } = require('../db/econ.js')
function startGame(bot, channel, message, args) { function startGame(bot, channel, interaction) {
const args = interaction.options.data;
let componentlist = []; let componentlist = [];
var diff; var diff;
if (args.length < 1 || args[0] == 'easy') { if (args.length < 1 || args[0].value == 'easy') {
diff = 0; diff = 0;
} else if (args[0] == 'medium') { } else if (args[0].value == 'medium') {
diff = 0.1; diff = 0.1;
} else if (args[0] == 'hard') { } else if (args[0].value == 'hard') {
diff = 0.2; diff = 0.2;
} else { } else {
diff = 0; diff = 0;
} }
let user = ''; let user = '';
if (args.length < 2 || args[1] == 'solo') { if (args.length < 2) {
user = message.author.id; user = interaction.user.id;
} }
for (let i = 0; i < 5; i ++) { for (let i = 0; i < 5; i ++) {
@@ -45,6 +46,7 @@ function startGame(bot, channel, message, args) {
componentlist.push(row); componentlist.push(row);
} }
interaction.reply(`${interaction.user} has started a solo game of Minesweeper!`);
channel.send({ content: `SCORE: \`0\`\nTILES LEFT: \`25\``, components: componentlist }); channel.send({ content: `SCORE: \`0\`\nTILES LEFT: \`25\``, components: componentlist });
} }
@@ -90,7 +92,7 @@ async function changeBoard(bot, interaction, xp_collection) {
const user = id[4]; const user = id[4];
if (user && user != '') { if (user && user != '') {
if (interaction.user.id != user) { if (interaction.user.id != user) {
interaction.user.send(`Message from a Minesweeper game in <#${interaction.channel.id}>: ***It's not your turn!***`); interaction.user.send(`Message from a Minesweeper game in <#${interaction.channel.id}>: ***This is a solo game!***`);
return; // interaction.reply({ content: "It's not your turn!", ephemeral: true }); //Can only reply once return; // interaction.reply({ content: "It's not your turn!", ephemeral: true }); //Can only reply once
} }
} }
@@ -103,7 +105,7 @@ async function changeBoard(bot, interaction, xp_collection) {
bot.mongoconnection.then((client) => { client.db(interaction.guildId).collection(interaction.user.id).updateOne({ game: {$exists: true} }, { $set: { game: null } }); }); bot.mongoconnection.then((client) => { client.db(interaction.guildId).collection(interaction.user.id).updateOne({ game: {$exists: true} }, { $set: { game: null } }); });
const channel = bot.channels.cache.get(interaction.message.channel.parentId); const channel = bot.channels.cache.get(interaction.message.channel.parentId);
channel.send(`${interaction.user} found a bomb in Minesweeper!`); channel.send(`${interaction.user} found a bomb in Minesweeper!`);
interaction.channel.send(`\`Thread closing\` <t:${Math.floor((new Date()).getTime()/1000) + 8}:R>`); interaction.channel.send(`\`Thread closing\` <t:${Math.floor((new Date()).getTime()/1000) + 10}:R>`);
await wait(7000); await wait(7000);
interaction.channel.delete(); interaction.channel.delete();
@@ -140,29 +142,34 @@ async function changeBoard(bot, interaction, xp_collection) {
} }
function checkAndStartGame(bot, message, channel, args) { function checkAndStartGame(bot, interaction, channel) {
bot.mongoconnection.then(client => { bot.mongoconnection.then(client => {
const db = client.db(message.guild.id); const db = client.db(interaction.guildId);
const dbo = db.collection(message.author.id); const dbo = db.collection(interaction.user.id);
dbo.findOne({game: {$exists: true}}).then((doc) => { dbo.findOne({game: {$exists: true}}).then((doc) => {
try { try {
if (doc.game != null) { return message.reply("You're already in a game!"); } if (doc.game != null) {
console.log(doc);
return interaction.reply("You're already in a game!").catch((err) => {
interaction.channel.send("You're already in a game!");
});
}
dbo.updateOne({ "game": {$exists: true} }, { $set: { game: "minesweeper", state: STATE.FIGHTING }}); dbo.updateOne({ "game": {$exists: true} }, { $set: { game: "minesweeper", state: STATE.FIGHTING }});
startGame(bot, channel, message, args); startGame(bot, channel, interaction);
} catch (err) { } catch (err) {
console.log(err); console.log(err);
const { addComplaintButton } = require('../dev only/submitcomplaint.js'); const { addComplaintButton } = require('../dev only/submitcomplaint.js');
addComplaintButton(bot, message); addComplaintButton(bot, interaction.message);
} }
}); });
}); });
} }
function handle(bot, interaction, channel = null, message = null, args = null, xp_collection = null) { function handle(bot, interaction, channel = null, isStart = true, xp_collection = null) {
if (channel != null && args != null) { if (isStart) {
checkAndStartGame(bot, message, channel, args); checkAndStartGame(bot, interaction, channel);
} else { } else {
//Maybe add player checking later? //Maybe add player checking later?
changeBoard(bot, interaction, xp_collection); changeBoard(bot, interaction, xp_collection);
+2 -1
View File
@@ -124,7 +124,6 @@ async function handle(client, db, dbo, other, bot, thread, command, doc, interac
let board = ["", "", "", "", "", "", "", "", ""]; let board = ["", "", "", "", "", "", "", "", ""];
postActionBar(thread, dbo, board, false,true); postActionBar(thread, dbo, board, false,true);
} else { } else {
//Change the board //Change the board
let square = Number(interaction.customId.split('|')[1]); let square = Number(interaction.customId.split('|')[1]);
let symbol = doc.symbols[doc.turn]; let symbol = doc.symbols[doc.turn];
@@ -143,6 +142,8 @@ async function handle(client, db, dbo, other, bot, thread, command, doc, interac
changeTurn(client, bot, interaction); changeTurn(client, bot, interaction);
} else { } else {
postActionBar(interaction, dbo, board, won); postActionBar(interaction, dbo, board, won);
//Maybe add a "close board" button instead of this
await wait(7000); await wait(7000);
winGame(client, bot, db, dbo, xp_collection, interaction.message); winGame(client, bot, db, dbo, xp_collection, interaction.message);
} }
+32 -21
View File
@@ -3,11 +3,12 @@ const fetch = require('node-fetch');
const categoriesJSON = require('./trivia_categories.json').trivia_categories; const categoriesJSON = require('./trivia_categories.json').trivia_categories;
const { decode } = require('html-entities'); const { decode } = require('html-entities');
const { MongoClient, ServerApiVersion } = require('mongodb'); const { MongoClient, ServerApiVersion } = require('mongodb');
const { Interaction } = require('discord.js');
const categories = new Map(); const categories = new Map();
for (i in categoriesJSON) { for (i in categoriesJSON) {
categories.set(categoriesJSON[i].name, categoriesJSON[i].id); categories.set(categoriesJSON[i].name, categoriesJSON[i].value);
} }
// const { jsonToMapRecursive, mapToTableRecursive } = require('../utils/jsonFormatters.js'); // const { jsonToMapRecursive, mapToTableRecursive } = require('../utils/jsonFormatters.js');
@@ -41,11 +42,11 @@ function changeDB(bot, message, m) {
/** /**
* @param {*} message * @param {Interaction} interaction
* @param {Map<string, object>} m * @param {Map<string, object>} m
* @param {int} time * @param {int} time
*/ */
function startTrivia(message, m, time, bot) { function startTrivia(interaction, m, time, bot) {
var iter = m.values().next(); var iter = m.values().next();
var obj = iter.value; var obj = iter.value;
@@ -63,8 +64,10 @@ function startTrivia(message, m, time, bot) {
return (response.content.toLowerCase() == answer.toLowerCase()); return (response.content.toLowerCase() == answer.toLowerCase());
}; };
message.reply({ content: `${question}\n(Type your answers below!)`, fetchReply: true }) interaction.channel.send({ content: `${question}\n(Type your answers below!)`, fetchReply: true })
.then(() => { .then((message) => {
interaction.reply({content: `Trivia started by ${interaction.user}`});
const timeList = ['🔟', '9️⃣', '8️⃣', '7️⃣', '6️⃣', '5️⃣', '4️⃣', '3️⃣', '2️⃣', '1️⃣', '0️⃣' ]; const timeList = ['🔟', '9️⃣', '8️⃣', '7️⃣', '6️⃣', '5️⃣', '4️⃣', '3️⃣', '2️⃣', '1️⃣', '0️⃣' ];
var i = 0; var i = 0;
const intId = setInterval(() => { if (i < timeList.length) { message.react(timeList[i]); i++ } }, Math.round(time/11)); const intId = setInterval(() => { if (i < timeList.length) { message.react(timeList[i]); i++ } }, Math.round(time/11));
@@ -72,9 +75,9 @@ function startTrivia(message, m, time, bot) {
message.channel.awaitMessages({ filter, max: 10, time: time }) // , errors: ['time'] message.channel.awaitMessages({ filter, max: 10, time: time }) // , errors: ['time']
.then((collected) => { .then((collected) => {
if (collected.size > 0) { if (collected.size > 0) {
message.reply(`${collected.first().author} got the correct answer (${answer})!`); message.reply(`${collected.first().author} got the correct answer (||${answer}||) first!`);
} else { } else {
message.reply('Tsk Tsk, looks like nobody got the answer this time.'); message.reply(`Tsk Tsk, looks like nobody got the answer (||${answer}||) this time.`);
} }
// changeDB(bot, message, null); // changeDB(bot, message, null);
@@ -82,7 +85,7 @@ function startTrivia(message, m, time, bot) {
}) })
.catch((collected) => { .catch((collected) => {
console.log(collected); console.log(collected);
message.reply('Tsk Tsk, looks like nobody got the answer this time.'); message.reply(`Tsk Tsk, looks like nobody got the answer (||${answer}||) this time.`);
// changeDB(bot, message, null); // changeDB(bot, message, null);
clearInterval(intId); clearInterval(intId);
}); });
@@ -94,25 +97,31 @@ function startTrivia(message, m, time, bot) {
module.exports = { module.exports = {
name: 'trivia', name: 'trivia',
async execute(message, args, Discord, Client, bot) { async execute(interaction, Discord, Client, bot) {
const difficult = ['easy', 'medium', 'hard']; const opts = interaction.options.data[0].options;
const args = [];
args[0] = opts.filter((o) => { return (o.name == 'difficulty'); })[0];
args[1] = opts.filter((o) => { return (o.name == 'category'); })[0];
args[2] = opts.filter((o) => { return (o.name == 'time'); })[0];
const difficult = ['hard', 'medium', 'easy'];
let inputs = ['easy', '']; let inputs = ['easy', ''];
if (args[0] && difficult.includes(args[0].toLowerCase())) { if (args[0] && difficult.includes(args[0].value.toLowerCase())) {
inputs[0] = args[0].toLowerCase(); inputs[0] = args[0].value.toLowerCase();
} else if (args[0] == 'help') { } else if (args[0].value == 'help') {
let temp = `Use ${bot.prefix}trivia [difficulty (easy, medium, hard)] [topic] [time]\n`; let temp = `Use /trivia [difficulty (easy, medium, hard)] [category] [time]\n`;
temp += '**__Trivia Categories__**\n'; temp += '**__Trivia Categories__**\n';
categories.forEach((val, key) => { categories.forEach((val, key) => {
temp += `_${key}_\n`; temp += `_${key}_\n`;
}) });
temp += '_Please copy and paste the FULL NAME if you want to use a category'; temp += '_Please copy and paste the FULL NAME if you want to use a category';
return message.reply(temp); return interaction.reply(temp);
} }
if (args[1] && Array.from(categories.keys()).includes(args[1])) { if (args[1] && Array.from(categories.keys()).includes(args[1].value)) {
inputs[1] = categories.get(args[1]); inputs[1] = categories.get(args[1].value);
} }
// Get all categories mapped to their ids // Get all categories mapped to their ids
@@ -142,9 +151,11 @@ module.exports = {
// console.log(decode(query)); // console.log(decode(query));
query = decode(query); query = decode(query);
if (bot.inDebugMode) {
//Get the answer (may have "" in it) //Get the answer (may have "" in it)
const question = query.substring(query.indexOf('question":') + 10, query.indexOf('","correct_answer')); // const question = query.substring(query.indexOf('question":') + 10, query.indexOf('","correct_answer'));
// console.log(`Q: ${question}\n\nActual: ${query}\n---------------------------------------`); // console.log(`Q: ${question}\n\nActual: ${query}\n---------------------------------------`);
}
let q = query.split('","'); let q = query.split('","');
// queries[ind] = q; // queries[ind] = q;
@@ -156,11 +167,11 @@ module.exports = {
i ++; i ++;
}); });
const time = args[2] || (difficult.indexOf(inputs[0]) + 1) * 10000; const time = (args[2]) ? args[2].value : (difficult.indexOf(inputs[0]) + 1) * 10000;
// console.log(m, time); // console.log(m, time);
// changeDB(bot, message, m); // changeDB(bot, message, m);
startTrivia(message, m, time, bot); startTrivia(interaction, m, time, bot);
} }
}); });
} }
+24 -24
View File
@@ -1,28 +1,28 @@
{ {
"trivia_categories": [ "trivia_categories": [
{ "id": 9, "name": "General Knowledge" }, { "value": 9, "name": "General Knowledge" },
{ "id": 10, "name": "Entertainment: Books" }, { "value": 10, "name": "Entertainment: Books" },
{ "id": 11, "name": "Entertainment: Film" }, { "value": 11, "name": "Entertainment: Film" },
{ "id": 12, "name": "Entertainment: Music" }, { "value": 12, "name": "Entertainment: Music" },
{ "id": 13, "name": "Entertainment: Musicals & Theatres" }, { "value": 13, "name": "Entertainment: Musicals & Theatres" },
{ "id": 14, "name": "Entertainment: Television" }, { "value": 14, "name": "Entertainment: Television" },
{ "id": 15, "name": "Entertainment: Video Games" }, { "value": 15, "name": "Entertainment: Video Games" },
{ "id": 16, "name": "Entertainment: Board Games" }, { "value": 16, "name": "Entertainment: Board Games" },
{ "id": 17, "name": "Science & Nature" }, { "value": 17, "name": "Science & Nature" },
{ "id": 18, "name": "Science: Computers" }, { "value": 18, "name": "Science: Computers" },
{ "id": 19, "name": "Science: Mathematics" }, { "value": 19, "name": "Science: Mathematics" },
{ "id": 20, "name": "Mythology" }, { "value": 20, "name": "Mythology" },
{ "id": 21, "name": "Sports" }, { "value": 21, "name": "Sports" },
{ "id": 22, "name": "Geography" }, { "value": 22, "name": "Geography" },
{ "id": 23, "name": "History" }, { "value": 23, "name": "History" },
{ "id": 24, "name": "Politics" }, { "value": 24, "name": "Politics" },
{ "id": 25, "name": "Art" }, { "value": 25, "name": "Art" },
{ "id": 26, "name": "Celebrities" }, { "value": 26, "name": "Celebrities" },
{ "id": 27, "name": "Animals" }, { "value": 27, "name": "Animals" },
{ "id": 28, "name": "Vehicles" }, { "value": 28, "name": "Vehicles" },
{ "id": 29, "name": "Entertainment: Comics" }, { "value": 29, "name": "Entertainment: Comics" },
{ "id": 30, "name": "Science: Gadgets" }, { "value": 30, "name": "Science: Gadgets" },
{ "id": 31, "name": "Entertainment: Japanese Anime & Manga" }, { "value": 31, "name": "Entertainment: Japanese Anime & Manga" },
{ "id": 32, "name": "Entertainment: Cartoon & Animations" } { "value": 32, "name": "Entertainment: Cartoon & Animations" }
] ]
} }
+28 -5
View File
@@ -1,13 +1,16 @@
const { MongoClient, ServerApiVersion } = require('mongodb');
const { createSubscriptionManual } = require('./premium/stripe.js'); const { createSubscriptionManual } = require('./premium/stripe.js');
const { pause_start_stop, playNext, showQueue } = require('./audio/audioMain.js'); const { pause_start_stop, playNext, showQueue } = require('./audio/audioMain.js');
const { resolveComplaint } = require('./dev only/submitcomplaint.js'); const { resolveComplaint } = require('./dev only/submitcomplaint.js');
const { RSSInteractionHandler } = require('../side projects/RSSHandlers/rssFeed.js'); const { RSSInteractionHandler } = require('../side projects/RSSHandlers/rssFeed.js');
const reminders = require('./premium/reminders.js'); const reminders = require('./premium/reminders.js');
const reactionrole = require('./admin/reactionrole.js');
const tuto = require('./Selmer Specific/tuto'); const tuto = require('./Selmer Specific/tuto');
const mswpr = require('./games/minesweeper.js'); const mswpr = require('./games/minesweeper.js');
const giveaway = require('./misc/giveaway.js');
const setup = require('./admin/easySetup.js');
// const { RSSInteractionHandler } = require('./premium/rssFeed.js'); // const { RSSInteractionHandler } = require('./premium/rssFeed.js');
const { Interaction } = require('discord.js') const { Interaction, Client } = require('discord.js');
const Discord = require('discord.js');
/** /**
* *
@@ -88,10 +91,16 @@ async function handle_interaction(interaction, mongouri, turnManager, bot, STATE
const page = Number(interaction.customId.split('|')[1]); const page = Number(interaction.customId.split('|')[1]);
tuto.postEmbd(bot, interaction, page, true); tuto.postEmbd(bot, interaction, page, true);
} else if (interaction.customId.indexOf("mswpr|") != -1) { } else if (interaction.customId.indexOf("mswpr|") != -1) {
mswpr.handle(bot, interaction, interaction.channel, interaction.message, null, xp_collection); mswpr.handle(bot, interaction, interaction.channel, false, xp_collection);
} else if (interaction.customId.indexOf("sbtutorial") != -1) { } else if (interaction.customId.indexOf("sbtutorial") != -1) {
interaction.deferUpdate(); interaction.deferUpdate();
tuto.execute(interaction.message, null, null, null, bot); tuto.execute(interaction, null, null, bot);
} else if (interaction.customId.indexOf("gameaccept") != -1) {
bot.commands.get('game').execute(bot, interaction, {name: 'accept'}, Discord, mongouri, items, xp_collection);
} else if (interaction.customId.indexOf("setupBtn") != -1) {
setup.handle(bot, interaction);
} else if (interaction.customId.indexOf('addRole') != -1) {
reactionrole.handleBtn(interaction);
} //Button else ifs here } //Button else ifs here
}); });
} }
@@ -157,12 +166,26 @@ async function handle_interaction(interaction, mongouri, turnManager, bot, STATE
//Forms //Forms
else if (interaction.isModalSubmit()) { else if (interaction.isModalSubmit()) {
if (interaction.customId.indexOf('newEventModal') != -1) {
reminders.modalHandle(bot, interaction); reminders.modalHandle(bot, interaction);
} else if (interaction.customId.indexOf('giveawayModal') != -1) {
giveaway.processForm(interaction, bot);
} else if (interaction.customId.indexOf('reactionModal') != -1) {
reactionrole.processForm(interaction, bot);
}
} //other selection types here } //other selection types here
} }
/**
* @param {Client} bot
* @param {Interaction} interaction
*/
async function handleContext(bot, interaction) {
const { targetId, commandName, user } = interaction;
console.log(interaction);
}
module.exports = { handle_interaction } module.exports = { handle_interaction, handleContext }
//values: [ 'price_1LI5pzFtuywsbrwdlY1gWMkV' ] //values: [ 'price_1LI5pzFtuywsbrwdlY1gWMkV' ]
//values: [ 'price_1LIpROFtuywsbrwdmxOb8Baj' ] //values: [ 'price_1LIpROFtuywsbrwdmxOb8Baj' ]
+11 -10
View File
@@ -18,10 +18,11 @@ getAllCoins();
module.exports = { module.exports = {
name: 'crypto', name: 'crypto',
description: 'Get the prices for most cryptocurrencies!', description: 'Get the prices for most cryptocurrencies!',
async execute(message, args, Discord, Client, bot) { async execute(interaction, Discord, Client, bot) {
if (args.length < 1 || args[0] == 'help') { const args = interaction.options.data;
return message.reply("Please specify at least one cryptocurrency (_ex: !crypto BTC_) or list all currencies (_!crypto list_)"); if (args.length < 1 || args[0].value == 'help') {
} else if (args[0] == 'list') { return interaction.reply("Please specify at least one cryptocurrency (_ex: !crypto BTC_) or list all currencies (_!crypto list_)");
} else if (args[0].value == 'list') {
try { try {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let temp = "```Name --> Symbol\n\n"; let temp = "```Name --> Symbol\n\n";
@@ -32,11 +33,11 @@ module.exports = {
resolve(temp); resolve(temp);
}).then((temp) => { }).then((temp) => {
message.reply(temp); interaction.reply(temp);
}) })
} catch (err) { } catch (err) {
console.error(err); console.error(err);
return message.reply("Uh Oh! There's been an error!"); return interaction.reply("Uh Oh! There's been an error!");
} }
} }
@@ -47,7 +48,7 @@ module.exports = {
var datacc = data.data.tickers.filter(t => t.target == 'USD'); var datacc = data.data.tickers.filter(t => t.target == 'USD');
const temp = datacc.filter(t => t.base == args[0]); const temp = datacc.filter(t => t.base == args[0].value);
const res = temp.length == 0 ? [] : temp[0]; const res = temp.length == 0 ? [] : temp[0];
//price: res.last, symbol: base, trust score: trust_score //price: res.last, symbol: base, trust score: trust_score
@@ -67,11 +68,11 @@ module.exports = {
.setTimestamp() .setTimestamp()
.setFooter({ text: 'Selmer Bot uses CoinGecko for cryptocurrency information'}); .setFooter({ text: 'Selmer Bot uses CoinGecko for cryptocurrency information'});
message.reply({ embeds: [embd] }); interaction.reply({ embeds: [embd] });
} catch (err) { } catch (err) {
console.error(err); console.error(err);
return message.reply("Uh Oh! There's been an error!"); return interaction.reply("Uh Oh! There's been an error!");
} }
}, },
options: [{name: 'qeury', description: 'Name or List', type: Constants.ApplicationCommandOptionTypes.STRING, required: true}] options: [{name: 'query', description: 'Name or List', type: Constants.ApplicationCommandOptionTypes.STRING, required: true}]
} }
+182
View File
@@ -0,0 +1,182 @@
const { Interaction, MessageActionRow, MessageButton, MessageEmbed, Modal, TextInputComponent } = require('discord.js');
const { checkRole } = require('../admin/verify.js');
async function postForm(interaction) {
// Create the modal
const modal = new Modal();
modal.setTitle('Creating a new giveaway')
.setCustomId('giveawayModal');
// Add components to modal
// Create the text input components
// The label is the prompt the user sees for this input
// Short means only a single line of text
// Paragraph means multiple lines of text
const durationInp = new TextInputComponent()
.setCustomId('duration')
.setLabel("How long should the givaway last?")
.setPlaceholder('10S or 10M or 10H or 10D between 1 minute and 30 days')
.setStyle('SHORT');
const titleInp = new TextInputComponent()
.setCustomId('title')
.setLabel("What should the giveaway be called?")
.setStyle('SHORT');
const descriptionInp = new TextInputComponent()
.setCustomId('description')
.setLabel("Describe the giveaway")
.setPlaceholder('A fun giveaway!')
.setStyle('PARAGRAPH');
const prizeInp = new TextInputComponent()
.setCustomId('prize')
.setLabel("What does the winner....win?")
.setPlaceholder('Discord Nitro')
.setStyle('SHORT');
const winnersInp = new TextInputComponent()
.setCustomId('winners')
.setLabel("Number of winners")
.setPlaceholder('Between 1 and 99 winners')
.setMinLength(1)
.setMaxLength(2)
.setStyle('SHORT');
// An action row only holds one text input,
// so you need one action row per text input.
const title = new MessageActionRow().addComponents(titleInp);
const desc = new MessageActionRow().addComponents(descriptionInp);
const dur = new MessageActionRow().addComponents(durationInp);
const prize = new MessageActionRow().addComponents(prizeInp);
const winners = new MessageActionRow().addComponents(winnersInp);
// Add inputs to the modal
modal.addComponents(title, desc, dur, prize, winners);
// Show the modal to the user
interaction.showModal(modal);
}
/**
* @param {Interaction} interaction
*/
function processForm(interaction, bot) {
const title = interaction.fields.getTextInputValue('title');
const desc = interaction.fields.getTextInputValue('description');
const dur = interaction.fields.getTextInputValue('duration');
const prize = interaction.fields.getTextInputValue('prize');
const winners = interaction.fields.getTextInputValue('winners');
postGiveawayMessage(bot, interaction, title, desc, dur, prize, winners);
}
/**
* @param {Interaction} interaction
*/
function postGiveawayMessage(bot, interaction, title, desc, dur, prize, winners) {
const author = {
name: "Selmer Bot",
url: "",
iconURL: bot.user.displayAvatarURL()
};
var timeAdjuster = 1;
var time;
if (dur.indexOf('M') != -1) {
timeAdjuster = 60;
time = dur.replace("M", "");
} else if (dur.indexOf('H') != -1) {
timeAdjuster = 3600;
time = dur.replace("H", "");
} else if (dur.indexOf('D') != -1) {
timeAdjuster = 86400;
time = dur.replace("D", "");
}
if (!Number.isInteger(Number(time))) {
return interaction.reply("Please enter a valid time in the following format: 10[S, M, H, D]");
} else if (!Number.isInteger(Number(winners))) {
return interaction.reply("Please enter a valid NUMBER of winners");
}
const embd = new MessageEmbed()
.setTitle(title)
.setAuthor(author)
.setDescription(desc)
.addFields([
{name: 'Prize', value: prize},
{name: 'Ends in', value: `<t:${Math.floor((new Date()).getTime()/1000) + (Number(time) * timeAdjuster)}:R>`},
{name: 'Host', value: `${interaction.user}`},
{name: 'Number of Contestants', value: '0'},
{name: 'Number of Winners', value: winners}
]);
const msgPromise = interaction.channel.send({ embeds: [embd] });
msgPromise.then((msg) => {
msg.react('🎉');
var nonbots = [];
const filter = (reaction, user) => {
if (!user.bot) {
nonbots.push(user);
}
return (reaction.emoji.name === '🎉');
};
const collector = msg.createReactionCollector({ filter, time: 5000 });
// collector.on('collect', (reaction, user) => {
// console.log(`Collected ${reaction.emoji.name} from ${user.tag}`);
// });
collector.on('end', collected => {
const finalists = [];
if (winners >= nonbots.length) {
for (let i = 0; i < nonbots.length; i++) {
finalists.push(`<@${nonbots[i].id}>`);
}
} else {
for (let i = 0; i < winners; i++) {
const ind = Math.floor(nonbots.length * Math.random());
finalists.push(`<@${nonbots[ind].id}>`);
delete nonbots[ind];
nonbots = nonbots.filter((val) => { return (val != null); });
}
}
let embd = msg.embeds[0];
if (winners > 1) {
msg.reply(`And the winners are:\n${finalists.join("\n")}`);
embd.fields.push({name: 'winners:', value: `${finalists.join("\n")}`, inline: true});
} else {
msg.reply(`And the winner is:\n${finalists.join("\n")}`);
embd.fields.push({name: 'winner:', value: `${finalists.join("\n")}`, inline: true});
}
msg.edit({ embeds: [embd] });
});
interaction.reply({ content: 'Giveaway posted!', ephemeral: true });
});
}
module.exports = {
name: 'giveaway',
description: 'Create a giveaway',
execute(interaction, Discord, Client, bot) {
postForm(interaction);
},
processForm,
options: []
}
+11 -8
View File
@@ -17,14 +17,15 @@ module.exports ={
if (spec == 'econ') { if (spec == 'econ') {
let temp = "***Selmer Bot Commands (Econ):***\n"; let temp = "***Selmer Bot Commands (Econ):***\n";
temp += bot.commands.get('econ').econHelp(); temp += bot.commands.get('econ').econHelp();
temp += `\n\n(remember to use _'${bot.prefix}'_ before the command!)`; temp += `\n\n(remember to use \`/\` before the command!)`;
return interaction.reply({ content: temp, ephemeral: true }); return interaction.reply({ content: temp, ephemeral: true });
} }
else if (spec == 'game') { else if (spec == 'game') {
let temp = "***Selmer Bot Commands (Games):***\n"; let temp = "***Selmer Bot Commands (Games):***\n";
temp += bot.commands.get('game').allGames.join(", "); temp += bot.commands.get('game').allGames.join(", ");
temp += `\n\n_Note: due to how complicated this feature is, it will not be migrated to slash commands for now_`; // temp += `\n\n_Note: due to how complicated this feature is, it will not be migrated to slash commands for now_`;
temp += `\n\n(remember to use \'/\' before the command!)`;
return interaction.reply({ content: temp, ephemeral: true }); return interaction.reply({ content: temp, ephemeral: true });
} }
@@ -39,8 +40,8 @@ module.exports ={
temp += modHelp(); temp += modHelp();
//Uses a different format, only the server owner can use it //Uses a different format, only the server owner can use it
temp += '\n_setup_ - ***SERVER OWNER ONLY*** - use _!setup help_\n'; temp += '\n_setup_ - ***SERVER OWNER ONLY*** - use \`setup help\`\n';
temp += `\n\n(remember to use _'${bot.prefix}'_ before the command!)`; temp += `\n\n(remember to use \`/\` before the command!)`;
return interaction.reply({ content: temp, ephemeral: true }); return interaction.reply({ content: temp, ephemeral: true });
} }
@@ -55,10 +56,10 @@ module.exports ={
bot.commands.forEach((comm) => { bot.commands.forEach((comm) => {
if (comm.name != 'verify') { if (comm.name != 'verify') {
if (comm.name == 'econ') { if (comm.name == 'econ') {
temp += `**econ** - use _!help econ_\n`; temp += `**econ** - use \`/help econ\`\n`;
} }
else if (comm.name == 'game') { else if (comm.name == 'game') {
temp += `**games** - use _!help game_\n`; temp += `**games** - use \`/help game\`\n`;
} }
else { else {
if (comm.name && comm.description && !noPostList.includes(comm.name)) { if (comm.name && comm.description && !noPostList.includes(comm.name)) {
@@ -68,16 +69,18 @@ module.exports ={
} }
}); });
temp += '**admin/moderation commands** - use !help admin\n'; temp += '**admin/moderation commands** - use `/help admin`\n';
//Selmer Specific //Selmer Specific
temp += '\n__**Selmer\'s \\*Special\\* Commands**__\n' temp += '\n__**Selmer\'s \\*Special\\* Commands**__\n'
sList.forEach((commName) => { sList.forEach((commName) => {
const comm = bot.commands.get(commName); const comm = bot.commands.get(commName);
if (comm && comm.name && comm.description) {
temp += `${comm.name.toLowerCase()} - _${comm.description}_\n`; temp += `${comm.name.toLowerCase()} - _${comm.description}_\n`;
}
}) })
temp += `\n_(remember to use '${bot.prefix}' before the command!)_`; temp += `\n_(remember to use \`/\` before the command!)_`;
interaction.reply({ content: temp, ephemeral: true }); interaction.reply({ content: temp, ephemeral: true });
}, },
-40
View File
@@ -1,40 +0,0 @@
const memes = require("random-memes");
const { randomHexColor } = require('../admin/colorgen.js');
module.exports = {
name: 'meme',
description: 'Selmer Bot will post a random meme from reddit',
async execute(interaction, Discord, Client, bot) {
interaction.deferReply();
memes.random().then(meme => {
const newEmbed = new Discord.MessageEmbed()
.setColor(randomHexColor())
.setTitle(meme.caption)
// .setURL(meme.image)
.setDescription(`category: ${meme.category}`)
.setImage(meme.image);
interaction.editReply({ embeds: [newEmbed] });
}).catch(async err => {
console.log(err);
//Try a different way
const fetch = require('node-fetch');
const response = await fetch('https://some-random-api.ml/meme');
const data = await response.json().catch(err => {
console.log(err);
return interaction.reply("_Uh oh, something's gone wrong!_");
});
const newEmbed = new Discord.MessageEmbed()
.setColor(randomHexColor())
.setTitle(data.caption)
// .setURL(data.image)
.setDescription(`category: ${data.category}`)
.setImage(data.image);
interaction.editReply({ embeds: [newEmbed] });
});
}, options: []
}
-9
View File
@@ -1,9 +0,0 @@
module.exports = {
name: 'reactionrole',
description: 'Creates an embed that will give a role when reacted to',
async execute(message, args, Discord, bot) {
if (bot.commands.get('verify').checkRole(message, args)) {
console.log("IS ADMNIN");
}
}
}
+11 -1
View File
@@ -1,14 +1,24 @@
const hastebin = require("hastebin-gen"); const hastebin = require("hastebin-gen");
const { addComplaintButton } = require('../dev only/submitcomplaint'); const { addComplaintButton } = require('../dev only/submitcomplaint');
const { Constants } = require('discord.js'); const { Constants } = require('discord.js');
const { URL } = require("url");
const axios = require('axios');
const { isValidUrl } = require('../dev only/setPresence.js');
module.exports ={ module.exports ={
name: "scrape", name: "scrape",
description: "Scrapes a website, then puts the result into a hastebin", description: "Scrapes a website, then puts the result into a hastebin",
async execute(interaction, Discord, Client, bot) { async execute(interaction, Discord, Client, bot) {
const axios = require('axios');
// const cheerio = require('cheerio'); // const cheerio = require('cheerio');
const url = interaction.options.data[0].value; const url = interaction.options.data[0].value;
if (!isValidUrl(url)) {
return interaction.reply("Please enter a valid url").catch((err) => {
interaction.channel.send("Please enter a valid url");
});
}
axios(url) axios(url)
.then(async response => { .then(async response => {
const html = response.data; const html = response.data;
+10
View File
@@ -24,6 +24,7 @@ async function messageExists(message) {
async function getResponse(convo, bot) { async function getResponse(convo, bot) {
try {
const response = await bot.openai.createCompletion({ const response = await bot.openai.createCompletion({
model: "text-davinci-002", model: "text-davinci-002",
prompt: convo, prompt: convo,
@@ -36,6 +37,11 @@ async function getResponse(convo, bot) {
}); });
return response; return response;
} catch (err) {
console.error(err);
return false;
}
} }
async function convoManager(clientinp, bot, message) { async function convoManager(clientinp, bot, message) {
@@ -78,6 +84,10 @@ async function convoManager(clientinp, bot, message) {
//Get the response //Get the response
const r = await getResponse(convo, bot); const r = await getResponse(convo, bot);
if (!r) {
return message.channel.send("Uh oh! There's been an error! Please contact support \:[");
}
let response = r.data.choices[0].text; let response = r.data.choices[0].text;
convo += (response + '\n'); convo += (response + '\n');
+241
View File
@@ -0,0 +1,241 @@
const { ICalParser } = require('cozy-ical');
const { URL } = require('url');
const { Constants } = require('discord.js');
const request = require('request');
const { verPremium } = require('../premium/verifyPremium.js');
const { isValidUrl } = require('../dev only/setPresence.js');
//#region SET REMINDERS
function addReminder(interaction, bot, obj, Id) {
return new Promise((resolve, reject) => {
try {
bot.mongoconnection.then((client) => {
// Update the Key object first to check if the time is already there
const kbo = client.db('main').collection('reminderKeys');
kbo.findOne(({ 'userId': Id })).then((doc) => {
const t = obj.time.toString();
try {
if (doc.times.indexOf(obj.time) == -1) {
kbo.updateOne({ 'userId': Id }, { $push: { times: t } })
} else {
//Event already exists at this time
reject("An event already exists at this time!");
return; // interaction.channel.send("An event already exists at this time!");
}
//Update the Time object
const dbo = client.db('main').collection('reminders');
dbo.findOne({ time: t }).then((doc) => {
let n = 0;
if (doc) {
n = doc.amt;
doc.amt ++;
doc[`${n}`] = obj.event;
dbo.findOneAndReplace({ time: t }, doc);
} else {
const d = new Date(Number(obj.time));
doc = { "0": obj.event, "time": t, "month": d.getMonth(), "amt": 1 }; //Month used for clearing when the calendar month begins (maybe modify the garbage collection with an `else if (day == 1? clear last month)` )
dbo.insertOne(doc);
}
//Reply with the reminder in correct format
// interaction.reply({ content: "REMINDER SAVED!", embeds: [embd], ephemeral: true });
resolve(true);
}).catch((err) => {
console.error(err);
// interaction.reply("Uh Oh! An error has occured!");
});
} catch (err) {
console.error(err); //interaction.reply("Uh Oh! An error has occured!");
reject(err);
}
}).catch((err) => {
console.log("ERR");
console.error(err);
reject(false);
// interaction.reply("Uh Oh! An error has occured!");
});
});
} catch (err) {
console.error(err);
// return interaction.reply("Uh Oh! An error has occured!"); // Gets "acknowledged" too many times
}
});
}
//#endregion
//#region SETUP AND PARSING
class calClass {
constructor(vevent) {
const model = vevent.model;
const alarms = vevent.subComponents;
if (alarms && alarms[0] && alarms[0].model) {
let temp = alarms[0].model.trigger;
temp = temp.split('DT')[1];
temp = temp.split("H");
let hours = (temp[0] && temp[0] != '0') ? Number(temp[0]) : 0;
let minutesStr = temp[1].split('M')[0];
let minutes = (minutesStr && !isNaN(minutesStr)) ? hours + Number(minutesStr) : hours;
this.offset = minutes;
} else {
this.offset = 0;
}
this.name = model.summary;
this.description = (model.description) ? model.description : "N/A";
const dateTime = new Date(model.startDate);
this.time = dateTime.getTime()/1000;
if (isValidUrl(model.location)) {
this.url = model.location || undefined;
this.loc = undefined;
} else {
this.url = undefined;
this.loc = model.location || undefined;
}
}
isValidUrl(s) {
try {
new URL(s);
return true;
} catch (err) {
return false;
}
}
exportAsObj(gid, uid) {
const obj = { time: this.time, event: { guildId: gid, userId: uid, name: this.name, description: this.description, offset: this.offset, link: this.url, location: this.loc } }
return obj;
}
}
function parseData(calStr, gid, uid) {
return new Promise((resolve, reject) => {
const parser = new ICalParser();
parser.parseString(calStr, function(err, cal) {
try {
const arr = [];
for (i in cal.subComponents) {
const a = new calClass(cal.subComponents[i]);
arr.push(a.exportAsObj(gid, uid));
}
resolve(arr);
} catch (err) {
console.log(err);
reject(err);
}
});
});
}
/**
* @param {String} fileName
*/
function readFileAndParse(url, bot, interaction, gid, uid) {
request.get(url, function (error, response, body) {
try {
if (!error && response.statusCode == 200) {
const isGuild = (gid && !uid) || false;
const notAdded = [];
const Id = (isGuild) ? gid : uid;
parseData(body, gid, uid).then((arr) => {
new Promise((resolve, reject) => {
// If the key does not exist, create it
if (arr.length > 0) {
bot.mongoconnection.then((client) => {
const kbo = client.db('main').collection('reminderKeys');
kbo.findOne(({ 'userId': Id })).then((doc) => {
if (!doc) {
doc = { userId: Id, times: [] }
kbo.insertOne(doc);
reject("New user created, please try again!");
} else {
resolve(true);
}
});
});
} else {
reject("No data...");
}
// const m = new Map(arr.map((obj, ind) => { return [ind, obj]; }));
}).then(() => {
Promise.all(arr.map((obj, ind) => {
addReminder(interaction, bot, obj, Id).then(() => {})
.catch((err) => {
notAdded.push(err);
});
})).then((t) => {
const r1 = { content: `ITEMS NOT ADDED:\n${notAdded.join("\n")}`, ephemeral: true }
if (r1.content != "ITEMS NOT ADDED:\n") {
interaction.reply(r1).catch((err) => { interaction.channel.send(r1); });
} else {
const r2 = `All ${arr.length} items added to calendar!`;
interaction.reply(r2).catch((err) => { interaction.channel.send(r2); });
}
});
}).catch((err) => {
interaction.reply(err);
})
}).catch((err) => {
console.log(err);
});
}
} catch (err) {
console.log(err);
interaction.reply({ content: "Uh oh, there's been an error!", ephemeral: true});
}
});
}
//#endregion
module.exports = {
name: 'import_ics',
description: 'Import events using a calendar',
async execute(interaction, Discord, Client, bot) {
//Check if the user has premium
await verPremium(bot, interaction.user.id).then(() => {
const url = interaction.options.data[0].attachment.attachment;
if (!url.endsWith(".ics")) {
return interaction.reply("Please use a valid ***.ics*** file!")
}
let uid, gid;
if (interaction.channel.type == 'DM') {
uid = interaction.user.id;
} else {
gid = interaction.guildId;
}
readFileAndParse(url, bot, interaction, gid, uid);
}).catch(() => {
interaction.reply("You have to be a premium subscriber to use this feature!");
});
},
options: [
{name: 'ics_file', description: 'The ics file to input', type: Constants.ApplicationCommandOptionTypes.ATTACHMENT, required: true},
],
isDm: true
}
+28 -8
View File
@@ -1,5 +1,4 @@
const { Modal, TextInputComponent, MessageActionRow, MessageButton, MessageEmbed, Interaction } = require('discord.js'); const { Modal, TextInputComponent, MessageActionRow, MessageButton, MessageEmbed, Interaction } = require('discord.js');
const { checkRole } = require('../admin/verify');
/** /**
@@ -51,9 +50,9 @@ function postEmbd(bot, desc, interaction, page, isGuild, id, refered) {
row.addComponents(prevbtn, nextbtn); row.addComponents(prevbtn, nextbtn);
if (page > 0 || refered) { if (page > 0 || refered) {
interaction.update({ content: '_Note: To see a full list of reminder stats visit www.selmerbot.com _', embeds: [newEmbed], components: [row] }); interaction.update({ content: '_Note: To see a full list of reminder stats visit https://selmerbot.com _', embeds: [newEmbed], components: [row] });
} else { } else {
interaction.reply({ content: '_Note: To see a full list of reminder stats visit www.selmerbot.com _', embeds: [newEmbed], components: [row] }); interaction.reply({ content: '_Note: To see a full list of reminder stats visit https://selmerbot.com _', embeds: [newEmbed], components: [row] });
} }
} catch (err) { } catch (err) {
console.log(err); console.log(err);
@@ -190,8 +189,11 @@ function addEvent(obj, connection, interaction, embd) {
} }
} }
/**
function getEvents(bot, interaction, id, jpage = 0, isGuild = false, refered = false) { * @returns { Promise<[]> | Promise<[false, []] | [true, String]>} (all events) || (custom err) ? [true, err] : [false, err]
*/
function getEvents(bot, interaction, id, jpage = 0, isGuild = false, refered = false, isExport = false) {
return new Promise((resolve, reject) => {
var userId = false; var userId = false;
var guildId = false; var guildId = false;
const numperpage = 5; const numperpage = 5;
@@ -209,11 +211,23 @@ function getEvents(bot, interaction, id, jpage = 0, isGuild = false, refered = f
//ReminderKeys are all stored as userId, the reminders themselves are not //ReminderKeys are all stored as userId, the reminders themselves are not
dbo.findOne({$or: [ {userId: userId}, {userId: guildId} ]}).then((doc) => { dbo.findOne({$or: [ {userId: userId}, {userId: guildId} ]}).then((doc) => {
if (!doc) { return interaction.reply("No events exist!"); } if (!doc) {
if (isExport) {
return reject([true, "No events exist!"]);
}
return interaction.reply("No events exist!");
}
times = doc.times; times = doc.times;
const tbo = client.db('main').collection('reminders'); const tbo = client.db('main').collection('reminders');
tbo.find({time: {$in: times}}).toArray((err, docs) => { tbo.find({time: {$in: times}}).toArray((err, docs) => {
if (isExport) {
return resolve(docs);
}
//There's gotta be a better way //There's gotta be a better way
var temp = [""]; var temp = [""];
var page = 0; var page = 0;
@@ -234,13 +248,19 @@ function getEvents(bot, interaction, id, jpage = 0, isGuild = false, refered = f
//Create the embed //Create the embed
postEmbd(bot, temp, interaction, jpage, isGuild, id, refered); postEmbd(bot, temp, interaction, jpage, isGuild, id, refered);
resolve(true);
}); });
}); });
} catch (err) { } catch (err) {
console.log(err); console.log(err);
if (isExport) {
return reject([false, err]);
}
return interaction.reply("Uh Oh! There's been an error!"); return interaction.reply("Uh Oh! There's been an error!");
} }
}); });
});
} }
//#endregion //#endregion
@@ -404,12 +424,12 @@ module.exports = {
); );
} }
return interaction.reply({ content: 'Please select an action\n_Notes: Adding offset to an event is only supported on the website and personal reminders can be viewed in DM\'s_', components: [row] }); return interaction.reply({ content: 'Please select an action\n_Notes: Adding offset to an event is only supported on the website and personal reminders can be viewed in DM\'s_', components: [row], ephemeral: true });
} else { } else {
interaction.reply("You have to be a premium subscriber to use this feature!\n_support coming soon_"); interaction.reply("You have to be a premium subscriber to use this feature!\n_support coming soon_");
} }
}); });
}); });
}, modalHandle, turnPage, }, modalHandle, turnPage, addEvent, getEvents,
options: [] options: []
} }
+4 -2
View File
@@ -185,6 +185,8 @@ module.exports = {
execute(interaction, Discord, Client, bot) { execute(interaction, Discord, Client, bot) {
handleInp(bot, interaction); handleInp(bot, interaction);
}, handleInp, createSubscriptionManual, }, handleInp, createSubscriptionManual,
options: [{name: 'input', description: 'What do you want to do?', type: Constants.ApplicationCommandOptionTypes.STRING, required: true, choices: [{name: 'help', value: 'help'}, {name: 'buy', value: 'buy'}, {name: 'manage', value: 'manage'}]}], options: [
isDM: true {name: 'option', description: 'What do you want to do?', type: Constants.ApplicationCommandOptionTypes.STRING, required: true, choices: [{name: 'help', value: 'help'}, {name: 'buy', value: 'buy'}, {name: 'manage', value: 'manage'}]}
],
isDm: true
} }
+1 -1
View File
@@ -34,7 +34,7 @@
<body> <body>
<div class="row"> <div class="row">
<div style="text-align: center;"> <div style="text-align: center;">
<button onclick="window.open('https://www.selmerbot.com/', target='_blank')" class="webBtn">selmerbot.com</button> <button onclick="window.open('https://selmerbot.com/', target='_blank')" class="webBtn">selmerbot.com</button>
<script type="text/javascript" src="https://cdnjs.buymeacoffee.com/1.0.0/button.prod.min.js" data-name="bmc-button" data-slug="ion606" data-color="#FFDD00" data-emoji="" data-font="Cookie" data-text="Buy me a coffee" data-outline-color="#000000" data-font-color="#000000" data-coffee-color="#ffffff"></script> <script type="text/javascript" src="https://cdnjs.buymeacoffee.com/1.0.0/button.prod.min.js" data-name="bmc-button" data-slug="ion606" data-color="#FFDD00" data-emoji="" data-font="Cookie" data-text="Buy me a coffee" data-outline-color="#000000" data-font-color="#000000" data-coffee-color="#ffffff"></script>
</div> </div>
</div> </div>
+111 -31
View File
@@ -1,7 +1,7 @@
//#region imports //#region imports
const { Client, Intents } = require('discord.js'); const { Client, Intents } = require('discord.js');
const Discord = require('discord.js'); const Discord = require('discord.js');
const { MongoClient, ServerApiVersion } = require('mongodb'); const { MongoClient, ServerApiVersion, GridFSBucket } = require('mongodb');
const fs = require('fs'); const fs = require('fs');
// const OpenAI = require('openai-api') // const OpenAI = require('openai-api')
const { Configuration, OpenAIApi } = require("openai"); const { Configuration, OpenAIApi } = require("openai");
@@ -9,13 +9,15 @@ const Stripe = require('stripe');
const turnManager = require('./commands/turnManager.js'); const turnManager = require('./commands/turnManager.js');
const { welcome } = require('./commands/admin/welcome.js'); const { welcome } = require('./commands/admin/welcome.js');
const { handle_interaction } = require('./commands/interactionhandler.js'); const { handle_interaction, handleContext } = require('./commands/interactionhandler.js');
const { handle_dm } = require('./commands/dm_handler'); const { handle_dm } = require('./commands/dm_handler');
const { devCheck } = require('./commands/dev only/devcheck.js'); const { devCheck } = require('./commands/dev only/devcheck.js');
const { moderation_handler } = require('./commands/admin/moderation.js'); const { moderation_handler } = require('./commands/admin/moderation.js');
const { registerCommands } = require('./registerCommands.js'); const { registerCommands } = require('./registerCommands.js');
const { backupLists, loadBotBackups } = require('./commands/admin/backupBot.js'); const { backupLists, loadBotBackups } = require('./commands/dev only/backupBot.js');
const { setPresence } = require('./commands/dev only/setPresence.js');
const { exit } = require('process'); const { exit } = require('process');
const {textToLevels} = require('./commands/Selmer Specific/msgLevels.js');
//#endregion //#endregion
const BASE_LVL_XP = 20; const BASE_LVL_XP = 20;
@@ -50,7 +52,7 @@ if (process.env.token != undefined) {
StripeAPIKey = require('./config.json').StripeAPIKey; StripeAPIKey = require('./config.json').StripeAPIKey;
youtubeAPIKey = require('./config.json').youtubeAPIKey; youtubeAPIKey = require('./config.json').youtubeAPIKey;
IDM = true; IDM = token.startsWith("OTI2NT");
} }
//#endregion //#endregion
@@ -105,6 +107,11 @@ bot.mongouri = mongouri;
const client = new MongoClient(mongouri, { useNewUrlParser: true, useUnifiedTopology: true, serverApi: ServerApiVersion.v1 }); const client = new MongoClient(mongouri, { useNewUrlParser: true, useUnifiedTopology: true, serverApi: ServerApiVersion.v1 });
bot.mongoconnection = client.connect(); bot.mongoconnection = client.connect();
//Error stuff
var preverr = "";
var errmsg;
var errTimes = 1;
//#endregion MongoDB Integration end //#endregion MongoDB Integration end
@@ -114,12 +121,45 @@ process.on("SIGTERM", (signal) => {
console.log(`Process ${process.pid} received a SIGTERM signal`); console.log(`Process ${process.pid} received a SIGTERM signal`);
backupLists(bot, IDM); backupLists(bot, IDM);
// process.exit(0); // process.exit(0);
bot.user.setStatus('invisible');
}); });
process.on("SIGINT", (signal) => { process.on("SIGINT", (signal) => {
console.log(`Process ${process.pid} has been interrupted`); console.log(`Process ${process.pid} has been interrupted`);
backupLists(bot, IDM); backupLists(bot, IDM);
// process.exit(0); // process.exit(0);
bot.user.setStatus('invisible');
});
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;
}
console.log(signal);
if (bot.inDebugMode) { 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);
bot.user.setStatus('dnd');
});
});
});
}); });
//#endregion //#endregion
@@ -150,6 +190,7 @@ fs.readdirSync('./commands')
//Set these two manually because all the seperate games can't be included in the command list (all managed by the 'game' file) //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"); let temp_command = require("./commands/db/econ.js");
const { STATE } = require('./commands/db/econ.js'); const { STATE } = require('./commands/db/econ.js');
const replies = require('./commands/Selmer Specific/replies.js');
bot.commands.set('econ', temp_command); bot.commands.set('econ', temp_command);
temp_command = require('./commands/games/game.js'); temp_command = require('./commands/games/game.js');
bot.commands.set('game', temp_command); bot.commands.set('game', temp_command);
@@ -165,16 +206,18 @@ bot.commands.set('game', temp_command);
//#endregion //#endregion
//#region bot.[anything] section //#region bot.[anything] section
//XP Table section //XP Table section
let xp_collection = new Map(); let xp_collection = new Map();
let items; let items;
var botIsReady = bot.inDebugMode;
bot.on('ready', async () => { bot.on('ready', async () => {
registerCommands(bot); const startTime = new Date().getTime();
bot.user.setPresence({ activities: [{ name: 'Booting up, please hold!', type: "PLAYING" }], status: 'idle' });
registerCommands(bot).then(() => {
//Make then copy the shop //Make then copy the shop
bot.mongoconnection.then(client => { bot.mongoconnection.then(client => {
const shop = client.db("main").collection("shop"); const shop = client.db("main").collection("shop");
@@ -183,10 +226,6 @@ bot.on('ready', async () => {
items = [...itemstemp]; items = [...itemstemp];
}); });
//Srt status and Activity (idle and listening to !help)
bot.user.setActivity(`${bot.prefix}help`, { type: "LISTENING" });
// bot.user.setStatus('idle');
}); });
//Note the xp numbers are a little wonky on levels 6, 8 and 13 (why though?) //Note the xp numbers are a little wonky on levels 6, 8 and 13 (why though?)
@@ -198,7 +237,7 @@ bot.on('ready', async () => {
} }
//Reaction map area bot.user.setPresence({ activities: [{ name: '/help', type: 'PLAYING' }], status: 'online' });
if (!bot.inDebugMode) { if (!bot.inDebugMode) {
console.log('SLEEMER BOT ONLINE!!!!! OH MY GOD OH MY GOD!!!'); console.log('SLEEMER BOT ONLINE!!!!! OH MY GOD OH MY GOD!!!');
} else { } else {
@@ -210,25 +249,53 @@ bot.on('ready', async () => {
let srv = bot.guilds.cache.get(bot.home_server).emojis.cache; let srv = bot.guilds.cache.get(bot.home_server).emojis.cache;
emj = srv.find((g) => { return g.name == 'selmer_coin' }); emj = srv.find((g) => { return g.name == 'selmer_coin' });
bot.currencysymbolmmain = `${emj}`; 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!`);
});
}); });
//Button Section //Button Section
bot.on('interactionCreate', async interaction => { bot.on('interactionCreate', async interaction => {
const { commandName } = interaction; const { commandName } = interaction;
bot.lockedChannels.set(interaction.guildId, ["NUMBERS HERE"]); 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); // console.log(bot.lockedChannels);
//Slash commands //Slash commands
if (interaction.isApplicationCommand()) { if (interaction.isApplicationCommand()) {
if (interaction.isUserContextMenu()) {
return handleContext(bot, interaction.options.data[0]);
}
const logable = ['kick', 'ban', 'unban', 'mute', 'unmute', 'timeout']; const logable = ['kick', 'ban', 'unban', 'mute', 'unmute', 'timeout'];
const econList = ["buy", 'shop', 'work', 'rank', 'inventory', 'balance', 'sell']; const econList = ["buy", 'shop', 'work', 'rank', 'inventory', 'balance', 'sell'];
const adminList = ["setpresence", "setactivity"];
if (logable.includes(commandName)) { 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); moderation_handler(bot, interaction, commandName);
} else if (econList.includes(commandName)) { } else if (econList.includes(commandName)) {
bot.commands.get('econ').execute(bot, interaction, Discord, mongouri, items, xp_collection); bot.commands.get('econ').execute(bot, interaction, Discord, mongouri, items, xp_collection);
} } else if (commandName == 'game') {
else if (bot.commands.has(commandName)) { 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);
} else if (bot.commands.has(commandName)) {
bot.commands.get(commandName).execute(interaction, Discord, Client, bot); bot.commands.get(commandName).execute(interaction, Discord, Client, bot);
} else { } else {
interaction.reply("Unknown command detected!"); interaction.reply("Unknown command detected!");
@@ -253,16 +320,17 @@ bot.on("guildCreate", guild => {
//const role = guild.roles.cache.find((role) => role.name === 'Selmer Bot Mod'); // member.roles.cache.has('role-id-here'); //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); const server = bot.guilds.cache.get(guild.id);
const owner = server.members.fetch(guild.ownerId).then(function(owner) { 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('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!'); 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 //Set up the server
bot.mongoconnection.then(client => { bot.mongoconnection.then(client => {
const dbo = client.db(guild.id).collection('SETUP'); 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}]); dbo.insertMany([{_id: 'WELCOME', 'welcomechannel': null, 'welcomemessage': null, 'welcomebanner': null, 'col': "#FFFFFF"}, {_id: 'LOG', 'keepLogs': false, 'logchannel': null, 'severity': 0},
{_id: 'announcement', channel: null, role: null}, {_id: 'roles', commands: ["Selmer Bot Commands"], announcements: "Selmer Bot Calendar"}]);
}); });
}); });
@@ -322,29 +390,29 @@ bot.on('guildMemberAdd', async (member) => {
if (member.guild.id == bot.home_server && !bot.inDebugMode) { return; } if (member.guild.id == bot.home_server && !bot.inDebugMode) { return; }
//Check for impartial data //Check for impartial data
if(member.partial) await member.fetch(); if (member.partial) { member = await member.fetch(); }
const guild = bot.guilds.cache.get(member.guild.id); const guild = bot.guilds.cache.get(member.guild.id);
bot.mongoconnection.then(client => { bot.mongoconnection.then(client => {
const dbo = client.db(member.guild.id).collection('SETUP'); const dbo = client.db(member.guild.id).collection('SETUP');
dbo.find({_id: 'WELCOME'}).toArray(async (err, docs) => { dbo.findOne({_id: 'WELCOME'}).then(async (doc) => {
if (!docs) { return; } if (!doc) { return; }
var welcomechannel; var welcomechannel;
if (docs[0].welcomechannel == null) { if (doc.welcomechannel == null) {
welcomechannel = guild.channels.cache.find(channel => channel.name.toLowerCase() === 'welcome'); welcomechannel = guild.channels.cache.find(channel => channel.name.toLowerCase() === 'welcome');
} else { } else {
welcomechannel = guild.channels.cache.get(docs[0].welcomechannel) welcomechannel = guild.channels.cache.get(doc.welcomechannel)
} }
if (welcomechannel == null) { if (welcomechannel == null) {
return console.log('No welcome channel detected'); return; // console.log('No welcome channel detected');
} }
await welcome(member, welcomechannel, docs[0].welcomemessage); await welcome(member, welcomechannel, doc.welcomemessage, doc.welcomebanner, (doc.welcometextcolor) ? doc.welcometextcolor : "#FFFFFF");
}) });
}) })
}); });
@@ -366,11 +434,18 @@ bot.on('messageCreate', (message) => {
//Special case, testing server (still need the emojis and error logging) //Special case, testing server (still need the emojis and error logging)
if (!bot.inDebugMode && message.guild.id == bot.home_server) { return; } if (!bot.inDebugMode && message.guild.id == bot.home_server) { return; }
//Check if the prefix exists if (message.mentions.has(bot.user.id)) {
if (!message.content.startsWith(prefix) || message.author.bot) { if (message.content == `<@${bot.user.id}>`) {
//Use for the leveling-by-interaction system return message.reply("What?");
return;
} else { } else {
return replies(bot, message);
}
}
//Check if the prefix exists
if (message.author.bot) { return; }
if (message.content.startsWith(prefix)) {
//Game section (too complicated to move to Slash Commands) //Game section (too complicated to move to Slash Commands)
//Note: Slash commands do not register as valid replies //Note: Slash commands do not register as valid replies
const args = message.content.slice(prefix.length).split(' '); const args = message.content.slice(prefix.length).split(' ');
@@ -380,7 +455,12 @@ bot.on('messageCreate', (message) => {
} else if (command == 'rss' && bot.inDebugMode) { } else if (command == 'rss' && bot.inDebugMode) {
const rss = require('./side projects/RSSHandlers/rssFeed.js'); const rss = require('./side projects/RSSHandlers/rssFeed.js');
rss.execute(message, args, Discord, client, bot); 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);
} }
}); });
+1197 -632
View File
File diff suppressed because it is too large Load Diff
+7 -4
View File
@@ -4,15 +4,14 @@
"@discordjs/opus": "github:discordjs/opus", "@discordjs/opus": "github:discordjs/opus",
"@discordjs/rest": "^1.1.0", "@discordjs/rest": "^1.1.0",
"@discordjs/voice": "^0.8.0", "@discordjs/voice": "^0.8.0",
"@napi-rs/canvas": "^0.1.22",
"apt": "^0.0.2", "apt": "^0.0.2",
"arraybuffer-to-buffer": "^0.0.7", "arraybuffer-to-buffer": "^0.0.7",
"axios": "^0.27.2", "axios": "^0.27.2",
"body-parser": "^1.20.0", "body-parser": "^1.20.0",
"canvas": "^2.9.3",
"cheerio": "^1.0.0-rc.10", "cheerio": "^1.0.0-rc.10",
"coingecko-api": "^1.0.10", "coingecko-api": "^1.0.10",
"cors": "^2.8.5", "cors": "^2.8.5",
"cozy-ical": "^1.1.22",
"date-fns": "^2.29.2", "date-fns": "^2.29.2",
"date-fns-timezone": "^0.1.4", "date-fns-timezone": "^0.1.4",
"discord-reply": "^0.1.2", "discord-reply": "^0.1.2",
@@ -29,16 +28,17 @@
"mal-scraper": "^2.11.4", "mal-scraper": "^2.11.4",
"mongoose": "^6.3.2", "mongoose": "^6.3.2",
"mysql": "^2.18.1", "mysql": "^2.18.1",
"node-fetch": "^2.6.7",
"node.js": "^0.0.1-security", "node.js": "^0.0.1-security",
"npm": "^8.13.2", "npm": "^8.13.2",
"openai": "^3.0.0", "openai": "^3.0.0",
"play-dl": "^1.9.4", "play-dl": "^1.9.4",
"pusher": "^5.1.1-beta", "pusher": "^5.1.1-beta",
"random-memes": "^3.1.0",
"request": "^2.88.2", "request": "^2.88.2",
"robinhood": "^1.8.0", "robinhood": "^1.8.0",
"rss-parser": "^3.12.0", "rss-parser": "^3.12.0",
"sequelize": "^6.19.0", "sequelize": "^6.19.0",
"sharp": "^0.31.1",
"sqlite3": "^5.0.3", "sqlite3": "^5.0.3",
"stripe": "^9.11.0", "stripe": "^9.11.0",
"sudo": "^1.0.3", "sudo": "^1.0.3",
@@ -63,5 +63,8 @@
"bugs": { "bugs": {
"url": "https://github.com/ION606/selmerBot/issues" "url": "https://github.com/ION606/selmerBot/issues"
}, },
"homepage": "https://github.com/ION606/selmerBot#readme" "homepage": "https://github.com/ION606/selmerBot#readme",
"devDependencies": {
"@types/node-fetch": "^2.6.2"
}
} }
+70 -3
View File
@@ -5,6 +5,7 @@ const {Client, Constants} = require('discord.js');
* @param {Client} bot * @param {Client} bot
*/ */
function registerCommands(bot) { function registerCommands(bot) {
return new Promise((resolve, reject) => {
const commands = bot.application.commands; const commands = bot.application.commands;
/* /*
@@ -16,10 +17,11 @@ function registerCommands(bot) {
key: code key: code
*/ */
bot.commands.forEach((val, key) => {
if (val.options && val.name != 'econ') { //#region Slash Commands
if (val.isDM) { bot.commands.forEach((val, key) => {
if ((val.options && val.name != 'econ') || val.isDm) {
if (val.isDm) {
commands.create({ commands.create({
name: val.name, name: val.name,
description: val.description, description: val.description,
@@ -76,6 +78,71 @@ function registerCommands(bot) {
// comm.setDefaultMemberPermissions(Discord.PermissionFlagsBits.KickMembers | Discord.PermissionFlagsBits.BanMembers); // comm.setDefaultMemberPermissions(Discord.PermissionFlagsBits.KickMembers | Discord.PermissionFlagsBits.BanMembers);
// }); // });
} }
//Admin commands (Home Server only)
const guild = bot.guilds.cache.get(bot.home_server);
guild.commands.create({
name: "admin",
description: "admin commands",
// type: Constants.ApplicationCommandOptionTypes.SUB_COMMAND_GROUP,
options: [
{
name: "setpresence",
description: "Change the bot's presence",
type: Constants.ApplicationCommandOptionTypes.SUB_COMMAND,
options: [
{name: "pres_text", description: "The new presence text", type: Constants.ApplicationCommandOptionTypes.STRING, required: true },
{name: "type", description: "The new presence text", type: Constants.ApplicationCommandOptionTypes.STRING, required: true, choices: [
{name: "LISTENING", value: "LISTENING"}, {name: "WATCHING", value: "WATCHING"}, {name: "COMPETING", value: "COMPETING"}, {name: "PLAYING", value: "PLAYING"}, { name: "STREAMING", value: "STREAMING"}
]},
{name: 'display_name', description: "What to display instead of the stream's title", type: Constants.ApplicationCommandOptionTypes.STRING, required: false}
],
dm_permission: false
},
{
name: "setactivity",
description: "Change the bot's activity",
type: Constants.ApplicationCommandOptionTypes.SUB_COMMAND,
options: [
{name: "type", description: "The new presence text", type: Constants.ApplicationCommandOptionTypes.STRING, required: true, choices: [
{name: "Do Not Disturb", value: "dnd"}, {name: "Idle", value: "idle"}, {name: "invisible", value: "invisible"}, {name: "online", value: "online"}
]},
],
dm_permission: false
},
]
});
//Takes much longer, so it'll be the benchmark for when the Promise resolves
//#region GAMES
const gameOpts = require('./commands/games/gameCommandOptions.js');
commands.create({
name: 'game',
description: 'Play one of Selmer Bot\'s games!', //NOT APPLICABLE USING SUB COMMAND GROUPS???
// type: Constants.ApplicationCommandOptionTypes.SUB_COMMAND_GROUP,
options: gameOpts,
dm_permission: false
}).then(() => {
if (!bot.inDebugMode) { return resolve(true); }
commands.create({
name: 'setup_embed',
description: 'Create a row of buttons for easier setup',
options: []
});
//#region Context Menus
commands.create({
name: "Temp",
type: 'USER'
}).then(() => { resolve(true); });
//#endregion
}).catch((err) => { reject(err); });
//#endregion
//#endregion
});
} }