diff --git a/commands/anime/asearch.js b/commands/anime/asearch.js index 0ba8294..d6616dc 100644 --- a/commands/anime/asearch.js +++ b/commands/anime/asearch.js @@ -13,9 +13,10 @@ module.exports = { } } else { name = args[0]; } - if (args[args.length - 1] != args[args.length - 1] != '~fancy' && args[args.length - 1] != '~summary' && args[args.length - 1] != '~stats') { args.push('~stats'); } + if (args[args.length - 1] != '~fancy' && args[args.length - 1] != '~summary' && args[args.length - 1] != '~stats') { args.push('~stats'); } - scraper.getInfoFromName(name).then((data) => { + //When set to true, getInfoFromName.getBestMatch did not, in fact, return the best results + scraper.getInfoFromName(name, false).then((data) => { try { if (args[args.length - 1] == '~stats') { const newEmbed = new Discord.MessageEmbed() @@ -51,7 +52,14 @@ module.exports = { } catch (err) { if (err.message.indexOf('MessageEmbed field values must be non-empty strings') != -1) { message.reply(`Insufficient information on website!\nThe page can be found here: ${data.url}`); + } else { + message.reply("Uh oh, an unknown error occured, click the ✅ to report this!"); + + const { addComplaintButton } = require('../dev only/submitcomplaint'); + addComplaintButton(bot, message); } + + console.log(err); } }); diff --git a/commands/anime/msearch.js b/commands/anime/msearch.js index aecb6bc..a96bb4e 100644 --- a/commands/anime/msearch.js +++ b/commands/anime/msearch.js @@ -6,6 +6,8 @@ module.exports = { description: 'Selmer bot gives you info on a manga', async execute(message, args, Discord, Client, bot) { if (args.length < 1) { return message.reply("Please specify a manga!"); } + if (args[args.length - 1] != '~fancy' && args[args.length - 1] != '~summary' && args[args.length - 1] != '~stats') { args.push('~stats'); } + let name = ""; if (args.length > 1) { let i = 0; @@ -16,37 +18,52 @@ module.exports = { } let cmd = args[args.length - 1]; - search.search(type, { - maxResults: 1, - term: name - }).then((data1) => { - let data = data1[0]; - if (cmd == "~stats") { - const newEmbed = new Discord.MessageEmbed() - .setColor('#ff9900') - .setTitle(data.title) - .setURL(data.url) - .setImage(data.thumbnail) - //.setDescription('My professional resume') - .addFields( - {name: 'Type:', value: data.type}, - {name: 'Score:', value: data.score}, - {name: 'Volumes:', value: data.vols} - ); - - message.channel.send({ embeds: [newEmbed] }); - } else if (cmd == "~fancy") { - let temp = `The ${data.type} _${data.title}_ currently has ${data.vols} volumes with ${data.nbChapters} chapters, `; - temp += `running from _${data.startDate.replace(/-/g, "/")}_ to _${data.endDate.replace(/-/g, "/")}_, and has a score of ${data.score} on MyAnimeList!\n`; - temp += `You can read more about _${data.title}_ at ${data.url}`; - message.channel.send(temp); - } else if (cmd == "~summary") { - //Remove the "read more." at the end - let temp = data.shortDescription.slice(0, -10); - temp += ` _read more at_ ${data.url}`; - return message.channel.send(temp); + try { + search.search(type, { + maxResults: 1, + term: name + }).then((data1) => { + let data = data1[0]; + if (cmd == "~stats") { + const newEmbed = new Discord.MessageEmbed() + .setColor('#ff9900') + .setTitle(data.title) + .setURL(data.url) + .setImage(data.thumbnail) + //.setDescription('My professional resume') + .addFields( + {name: 'Type:', value: data.type}, + {name: 'Score:', value: data.score}, + {name: 'Volumes:', value: data.vols} + ); + + message.channel.send({ embeds: [newEmbed] }); + } else if (cmd == "~fancy") { + let temp = `The ${data.type} _${data.title}_ currently has ${data.vols} volumes with ${data.nbChapters} chapters, `; + temp += `running from _${data.startDate.replace(/-/g, "/")}_ to _${data.endDate.replace(/-/g, "/")}_, and has a score of ${data.score} on MyAnimeList!\n`; + temp += `You can read more about _${data.title}_ at ${data.url}`; + + message.channel.send(temp); + } else if (cmd == "~summary") { + //Remove the "read more." at the end + let temp = data.shortDescription.slice(0, -10); + temp += ` _read more at_ ${data.url}`; + return message.channel.send(temp); + } else { + message.reply(`Unknown command, try using the format '${bot.prefix}msearch [~stats or ~fancy or ~summary]`); + } + }); + } catch (err) { + if (err.message.indexOf('MessageEmbed field values must be non-empty strings') != -1) { + message.reply(`Insufficient information on website!\nThe page can be found here: ${data.url}`); + } else { + message.reply("Uh oh, an unknown error occured, click the ✅ to report this!"); + const { addComplaintButton } = require('../dev only/submitcomplaint'); + addComplaintButton(bot, message); } - }); + + console.log(err); + } } } \ No newline at end of file diff --git a/commands/db/addons/snowflake.js b/commands/db/addons/snowflake.js index 9585469..a65526b 100644 --- a/commands/db/addons/snowflake.js +++ b/commands/db/addons/snowflake.js @@ -12,27 +12,31 @@ function convertSnowflakeToDate(snowflake, epoch = DISCORD_EPOCH) { // Validates a snowflake ID string and returns a JS Date object if valid function validateSnowflake(snowflake, epoch) { - if (!Number.isInteger(+snowflake)) { - throw new Error( - "That doesn't look like a snowflake. Snowflakes contain only numbers." - ) + try { + if (!Number.isInteger(+snowflake)) { + throw new Error( + "That doesn't look like a snowflake. Snowflakes contain only numbers." + ) + } + + if (snowflake < 4194304) { + throw new Error( + "That doesn't look like a snowflake. Snowflakes are much larger numbers." + ) + } + + const timestamp = convertSnowflakeToDate(snowflake, epoch) + + if (Number.isNaN(timestamp.getTime())) { + throw new Error( + "That doesn't look like a snowflake. Snowflakes have fewer digits." + ) + } + + return timestamp + } catch(err) { + console.log(err); } - - if (snowflake < 4194304) { - throw new Error( - "That doesn't look like a snowflake. Snowflakes are much larger numbers." - ) - } - - const timestamp = convertSnowflakeToDate(snowflake, epoch) - - if (Number.isNaN(timestamp.getTime())) { - throw new Error( - "That doesn't look like a snowflake. Snowflakes have fewer digits." - ) - } - - return timestamp } module.exports = { convertSnowflakeToDate, validateSnowflake } diff --git a/commands/dev only/submitcomplaint.js b/commands/dev only/submitcomplaint.js new file mode 100644 index 0000000..e68faae --- /dev/null +++ b/commands/dev only/submitcomplaint.js @@ -0,0 +1,105 @@ +const { MessageActionRow, MessageButton, MessageEmbed, DiscordAPIError, Message } = require('discord.js'); +const complaintRow = new MessageActionRow(); +const green = '#00f035'; +const red = '#f30000'; + + +complaintRow.setComponents( + new MessageButton() + .setCustomId('SUBMITCOMPLAINT') + .setLabel('Submit Complaint') + .setStyle('DANGER') //Maybe change this to 'PRIMARY' +); + + +function submitComplaint(message, bot) { + const complaint = message.content; + const channel = bot.guilds.cache.get(bot.home_server).channels.cache.get('998899306671124501'); + + const author = { + name: "Selmer Bot", + url: "", + iconURL: bot.user.displayAvatarURL() + } + + const newEmbed = new MessageEmbed() + .setColor(red) + .setTitle(`Submitted by _${message.author.username}#${message.author.discriminator} ${message.author}_ in *${message.guild}* (OPEN)`) + .setAuthor(author) + .setDescription(`Content: ${complaint}`) + .setTimestamp(); + + const row = new MessageActionRow() + .addComponents( + new MessageButton() + .setCustomId('DEBUGDONE') + .setLabel('Done') + .setStyle('SUCCESS'), + new MessageButton() + .setCustomId('DEBUGURGENT') + .setLabel('Mark as Urgent') + .setStyle('DANGER'), + ); + + channel.send({ embeds: [newEmbed], components: [row] }); +} + + +function resolveComplaint(interaction) { + if (interaction.customId == 'DEBUGDONE') { + var embd = new MessageEmbed(interaction.message.embeds[0]); + embd.setColor(green); + embd.title = embd.title.replace('(OPEN)', '(CLOSED)').replace('(URGENT)', '(CLOSED)'); + interaction.update({ embeds: [embd], components: [] }); + interaction.message.unpin(); + } else { + var embd = new MessageEmbed(interaction.message.embeds[0]); + const row = new MessageActionRow(); + row.addComponents( + new MessageButton() + .setCustomId('DEBUGDONE') + .setLabel('Done') + .setStyle('SUCCESS'), + ); + + embd.title = embd.title.replace('(OPEN)', '(URGENT)'); + interaction.update({ embeds: [embd], components: [row] }); + const m = interaction.message.pin(); + // m.then((msg) => { + // msg.delete(); + // }); + } +} + +module.exports = { + name: 'Complaints', + + /** + * @param {Message} message + */ + async addComplaintButton(bot, message) { + try { + function filter(reaction) { + return (reaction.emoji.name == '✅'); + } + message.react('✅').then(() => { + message.awaitReactions({ filter, max: 1, time: 60000, errors: ['time'] }) + .then(collected => { + const reaction = collected.first(); + submitComplaint(message, bot); + }) + .catch(collected => { message.reactions.cache.get('✅').remove(); }); + }); + } catch (err) { + console.error(err); + } + + }, submitComplaint, resolveComplaint +} + + + +/* + const { addComplaintButton } = require('../dev only/submitcomplaint'); + addComplaintButton(bot, message); +*/ \ No newline at end of file diff --git a/commands/games/external_game_functions.js b/commands/games/external_game_functions.js index 746e7e5..c95fd8e 100644 --- a/commands/games/external_game_functions.js +++ b/commands/games/external_game_functions.js @@ -1,6 +1,7 @@ //@ts-check const { addxp, STATE, BASE } = require("../db/econ"); const turnManger = require('../turnManager.js'); +const { addComplaintButton } = require('../dev only/submitcomplaint'); //#region game lose/win @@ -8,7 +9,11 @@ function loseGame(user_dbo, xp_collection, message, bot = null) { return new Promise(function(resolve, reject) { user_dbo.find({"game": {$exists: true}}).toArray(function(err, docs){ const doc = docs[0]; - if (doc == undefined) { return message.reply("Oops! There's been an error! Please contact support if this problem persists!"); } + if (doc == undefined) { + message.reply("Oops! There's been an error, click the ✅ to report this!"); + addComplaintButton(bot, message); + return; + } if (doc.game == null) { return message.reply("You're not even in a game and you're trying to quit! Sad..."); } var addbal; @@ -49,7 +54,7 @@ function winGame(client, bot, db, user_dbo, xp_collection, message) { } //Delete the bot's record of the game - client.db('B|S' + bot.user.id).collection(user_dbo.s.namespace.db.substr(0, user_dbo.s.namespace.db.length - 6)).drop(); + client.db('B|S' + bot.user.id).collection(message.guild.id).drop(); //Update the player with xp diff --git a/commands/games/game.js b/commands/games/game.js index d72176e..b20558b 100644 --- a/commands/games/game.js +++ b/commands/games/game.js @@ -6,6 +6,7 @@ let ecoimport = require("../db/econ.js"); //#region Game Imports const battle = require("./battle.js"); const ttt = require('./tictactoe.js'); +const trivia = require('./trivia.js'); //#endregion @@ -147,7 +148,7 @@ function equip(message, args, command, dbo, bot, shop) { if (doc.game != null) { ret = true; - console.log(doc.game); + // console.log(doc.game); return message.reply('You can\'t equip while in a game!'); } @@ -357,6 +358,8 @@ module.exports ={ //#region game-specific commands else { + if (command == undefined) { return message.reply("Please specify a game or use _!game help_"); } + //Make change to new name if necessary if (command.replaceAll(" ", "").toLowerCase() == 'tictactoe') { command = 'Tic Tac Toe'; } @@ -377,12 +380,14 @@ module.exports ={ } 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 == 'trivia' || command == 'trivia') { + trivia.execute(message, args, Discord, client, bot); } + //Catch statement (invalid command) else { - if (command == undefined) { message.reply("Please specify a game or use _!game help_"); } - else { message.reply(`'!game ${command}' is not a command!`); } + message.reply(`'${bot.prefix}game ${command}' is not a command!`); } } //#endregion diff --git a/commands/games/tictactoe.js b/commands/games/tictactoe.js index 233d0de..276bfb3 100644 --- a/commands/games/tictactoe.js +++ b/commands/games/tictactoe.js @@ -108,7 +108,7 @@ function postActionBar(interaction, user_dbo, board, won, initial = false) { } } - console.log(componentlist); + // console.log(componentlist); if (initial) { interaction.send({ content: `Your turn <@${user_dbo.s.namespace.collection}>!`, components: componentlist }); @@ -124,12 +124,15 @@ async function handle(client, db, dbo, other, bot, thread, command, doc, interac let board = ["", "", "", "", "", "", "", "", ""]; postActionBar(thread, dbo, board, false,true); } else { + //Change the board let square = Number(interaction.customId.split('|')[1]); let symbol = doc.symbols[doc.turn]; let board = doc.board; board[square] = symbol; - client.db('B|S' + bot.user.id).collection(dbo.s.namespace.db.substr(0, dbo.s.namespace.db.length - 6)).updateOne({'board': {$exists: true}}, {$set: {board: board}}); + const gamedbo = client.db('B|S' + bot.user.id).collection(interaction.guildId); + + gamedbo.updateOne({$or: [ {0: interaction.user.id}, {1: interaction.user.id} ], 'board': {$exists: true}}, {$set: {board: board}}); //Check if the game is over let won = isTerminal(board); diff --git a/commands/games/trivia.js b/commands/games/trivia.js index 80f7836..bc88282 100644 --- a/commands/games/trivia.js +++ b/commands/games/trivia.js @@ -47,7 +47,15 @@ function changeDB(bot, message, m) { * @param {int} time */ function startTrivia(message, m, time, bot) { - const obj = m.values().next().value; + var iter = m.values().next(); + var obj = iter.value; + + //Get rid of the "answers required" ones + while (obj.question.toLowerCase().indexOf('which of these') != -1 && obj.question.toLowerCase().indexOf('which of the following') != -1) { + iter = iter.next(); + obj = iter.value; + } + const question = obj.question; const answer = obj.answer; console.log(answer); @@ -57,8 +65,11 @@ function startTrivia(message, m, time, bot) { return (response.content.toLowerCase() == answer.toLowerCase()); }; - message.reply({ content: question, fetchReply: true }) + message.reply({ content: `${question}\n(Type your answers below!)`, fetchReply: true }) .then(() => { + const timeList = ['🔟', '9️⃣', '8️⃣', '7️⃣', '6️⃣', '5️⃣', '4️⃣', '3️⃣', '2️⃣', '1️⃣', '0️⃣' ]; + var i = 0; + const intId = setInterval(() => { if (i < timeList.length) { message.react(timeList[i]); i++ } }, Math.round(time/11)); //time: 1000 = 1 second message.channel.awaitMessages({ filter, max: 10, time: time }) // , errors: ['time'] .then((collected) => { @@ -68,22 +79,23 @@ function startTrivia(message, m, time, bot) { message.reply('Tsk Tsk, looks like nobody got the answer this time.'); } - changeDB(bot, message, null); + // changeDB(bot, message, null); + clearInterval(intId); }) .catch((collected) => { console.log(collected); message.reply('Tsk Tsk, looks like nobody got the answer this time.'); - changeDB(bot, message, null); + // changeDB(bot, message, null); + clearInterval(intId); }); }); } -//Add shuffle button +//Add shuffle button? module.exports = { name: 'trivia', - description: 'Play a game of Trivia with yourself or others! - (use _trivia help_)', async execute(message, args, Discord, Client, bot) { const difficult = ['easy', 'medium', 'hard']; let inputs = ['easy', '']; @@ -93,7 +105,7 @@ module.exports = { } else if (args[0] == 'help') { let temp = `Use ${bot.prefix}trivia [difficulty (easy, medium, hard)] [topic] [time]\n`; temp += '**__Trivia Categories__**\n'; - m.forEach((val, key) => { + categories.forEach((val, key) => { temp += `_${key}_\n`; }) temp += '_Please copy and paste the FULL NAME if you want to use a category'; @@ -110,7 +122,7 @@ module.exports = { // const json = await a.json(); // console.log(json); - var url = `https://opentdb.com/api.php?amount=${5}&difficulty=${inputs[0]}&type=multiple`; + var url = `https://opentdb.com/api.php?amount=${3}&difficulty=${inputs[0]}&type=multiple`; if (inputs[1] != '') { url += `&category=${inputs[1]}`; } @@ -146,12 +158,12 @@ module.exports = { i ++; }); - const time = args[2] || (difficult[0].indexOf(inputs[0]) + 1) * 10000; - changeDB(bot, message, m); + const time = args[2] || (difficult.indexOf(inputs[0]) + 1) * 10000; + + // console.log(m, time); + // changeDB(bot, message, m); startTrivia(message, m, time, bot); } - }) - - + }); } } \ No newline at end of file diff --git a/commands/interactionhandler.js b/commands/interactionhandler.js index bee3df7..4a12cfc 100644 --- a/commands/interactionhandler.js +++ b/commands/interactionhandler.js @@ -1,6 +1,7 @@ const { MongoClient, ServerApiVersion } = require('mongodb'); const { createSubscriptionManual } = require('./premium/stripe.js'); const { pause_start_stop, playNext, showQueue } = require('./misc/playAudio.js'); +const { resolveComplaint } = require('./dev only/submitcomplaint.js'); // const { RSSInteractionHandler } = require('./premium/rssFeed.js'); @@ -70,6 +71,8 @@ async function handle_interaction(interaction, mongouri, turnManager, bot, STATE pause_start_stop(interaction, bot); } + } else if (interaction.customId == 'DEBUGURGENT' || interaction.customId == 'DEBUGDONE') { + resolveComplaint(interaction); } //Button else ifs here }); diff --git a/commands/misc/scraper.js b/commands/misc/scraper.js index 290e71e..e9a34c5 100644 --- a/commands/misc/scraper.js +++ b/commands/misc/scraper.js @@ -1,4 +1,5 @@ const hastebin = require("hastebin-gen"); +const { addComplaintButton } = require('../dev only/submitcomplaint'); module.exports ={ name: "scrape", @@ -23,10 +24,10 @@ module.exports ={ } else if (err.code == 'ERR_BAD_REQUEST') { message.reply("404 link not valid!") } else { - message.reply("Oops! There's been an error"); + message.reply("Oops! There's been an error, click the ✅ to report this!"); + addComplaintButton(bot, message); + console.log(err); } - - console.log(err); }); } } diff --git a/commands/premium/stripe.js b/commands/premium/stripe.js index 372722e..c1b0ecd 100644 --- a/commands/premium/stripe.js +++ b/commands/premium/stripe.js @@ -6,6 +6,7 @@ https://glitch.com/edit/#!/selmer-bot-listener const { MongoClient, ServerApiVersion } = require('mongodb'); const { MessageActionRow, MessageSelectMenu } = require('discord.js'); +const { addComplaintButton } = require('../dev only/submitcomplaint'); //Called from the dropdown menu @@ -71,7 +72,8 @@ async function createSubscriptionManual(bot, interaction, id, priceID) { interaction.editReply(err); } else { console.log(err); - interaction.editReply("A Stripe error occured! Please contact support ASAP!") + interaction.editReply("A Stripe error occured! Please click the ✅ to report this ASAP!"); + addComplaintButton(bot, interaction.message); } }); } @@ -119,7 +121,8 @@ async function changeSubscriptionManual(bot, message) { message.reply(err); } else { console.log(err); - message.reply("A Stripe error occured! Please contact support ASAP!"); + message.reply("A Stripe error occured! Please click the ✅ to report this ASAP!"); + addComplaintButton(bot, interaction.message); } }); } diff --git a/main.js b/main.js index 2794bc9..b58d8a9 100644 --- a/main.js +++ b/main.js @@ -25,6 +25,7 @@ const BASE_LVL_XP = 20; let token; let IDM = false; let home_server; +let debug_channel; let MLAIKEY; let StripeAPIKey; @@ -33,14 +34,18 @@ if (process.env.token != undefined) { //Use "setx NAME VALUE" in the local powershell terminal to set token = process.env.token; home_server = process.env.home_server; + debug_channel = process.env.debug_channel; MLAIKEY = process.env.MLAIKEY; StripeAPIKey = process.env.StripeAPIKey; } else { token = require('./config.json').token; home_server = require('./config.json').home_server; - IDM = true; + debug_channel = require('./config.json').debug_channel; + MLAIKEY = require('./config.json').MLAIKEY; StripeAPIKey = require('./config.json').StripeAPIKey; + // { token, home_server, debug_channel, MLAIKEY, StripeAPIKey } = require('./config.json'); // Doesn't work + IDM = true; } //#endregion @@ -66,6 +71,7 @@ bot.prefix = new String; bot.prefix = prefix; bot.inDebugMode = IDM; bot.home_server = home_server; +bot.debug_channel = debug_channel; const configuration = new Configuration({ apiKey: MLAIKEY, @@ -256,9 +262,14 @@ bot.on('messageCreate', (message) => { } else if (message.content.indexOf('!spam_collection') != -1) { //Handle spam collection/Dev commands return devCheck(message, bot); + } else if (message.type === "CHANNEL_PINNED_MESSAGE") { + //Debug log stuff + if (message.guild.id == bot.home_server && message.channel.id == bot.debug_channel) { + message.delete(); + } } - //Special case, testing server (still need the emojis) + //Special case, testing server (still need the emojis and error logging) if (!bot.inDebugMode && message.guild.id == bot.home_server) { return; } //COMMAND AREA diff --git a/side projects/rssFeed.js b/side projects/rssFeed.js index 28b738d..96b9a05 100644 --- a/side projects/rssFeed.js +++ b/side projects/rssFeed.js @@ -5,6 +5,7 @@ var FeedParser = require('feedparser'); const fetch = require('node-fetch'); const { VoiceConnectionStatus, AudioPlayerStatus, createAudioPlayer, StreamType, joinVoiceChannel, createAudioResource, getVoiceConnection } = require('@discordjs/voice'); const play = require('play-dl'); +const { addComplaintButton } = require('../dev only/submitcomplaint'); const hastebin = require("hastebin-gen"); const { simpleCast } = require('./RSSHandlers/simplecast.js') @@ -154,6 +155,8 @@ async function getAndFormatRSS(bot, message, user, inp) { feedparser.on('error', function (error) { // always handle errors + addComplaintButton(bot, message); + console.log(error); }); const items = new Array();