#!/usr/bin/env node require('dotenv').config(); const Discord = require("discord.js"); const Intents = Discord.Intents; const client = new Discord.Client({ intents: ["GUILDS", "GUILD_MESSAGES", "GUILD_MESSAGE_REACTIONS", "DIRECT_MESSAGES", "DIRECT_MESSAGE_REACTIONS"/*, "GUILD_MEMBERS", "GUILD_PRESENCES"*/], partials: ["MESSAGE", "CHANNEL", "REACTION"], }); const fetch = require("node-fetch"); const axios = require("axios"); const userScore = require("./mongooseModels/mongooseUserScoreModel.js"); const generatedRound = require("./mongooseModels/mongooseGeneratedRoundModel.js"); const mongoose = require("mongoose"); const gitlog = require("gitlog").default; const config = require("./config.json"); const decode = require('html-entities').decode; const helpMessage = "AwesomeSciBo has migrated to using slash commands! You can take a look at the different commands by typing `/` and clicking on the AwesomeSciBo icon." const slashCommands = require('./slashCommands.json') client.once("ready", () => { client.application.commands.set(slashCommands); // Connect to MongoDB using mongoose if (!process.env.CI) { mongoose .connect(process.env.MONGO_URI, { useUnifiedTopology: true, useNewUrlParser: true, }) .then(() => { // Log client tag and set status console.log(`Logged in as: ${client.user.username}!`); client.user.setActivity( 'for /help', { type: "WATCHING" } ); }) .catch((err) => console.log(err)); } }); client.on("guildCreate", (guild) => { const topggAuthHeader = { headers: { 'Authorization': config.topggauth } }; axios.post(`https://top.gg/api/bots/${client.user.id}/stats`, { server_count: client.guilds.cache.size }, topggAuthHeader).then(response => { console.log(response); }) //guild.commands.set(slashCommands); const welcomeChannel = guild.channels.cache .find( (channel) => // Find channel by name channel.name === "general" && channel.type === "text" ) if (welcomeChannel) { welcomeChannel.send("'Sup, I'm the AwesomeSciBo bot! Use `/help` to learn more about me!") .catch(console.error); } }); client.on("guildDelete", guild => { const topggAuthHeader = { headers: { 'Authorization': config.topggauth } }; axios.post(`https://top.gg/api/bots/${client.user.id}/stats`, { server_count: client.guilds.cache.size }, topggAuthHeader); }); async function updateScore(isCorrect, score, authorId) { if (!isCorrect) { return `Nice try! Your score is still ${score}.`; } else { score += 4; if (score == 4) { const newUserScore = new userScore({ authorID: authorId, score: score, }); newUserScore.save((err) => err ? console.log("Error creating new user for scoring") : console.log("Sucessfully created user to score.") ); } else { const doc = await userScore.findOne({ authorID: authorId, }); doc.score = doc.score + 4; doc.save(); } return `Great job! Your score is now ${score}.`; } } async function training(subject, interaction) { const authorId = interaction.user.id; let score; userScore .findOne({ authorID: authorId }) .lean() .then((obj, err) => { if (!obj) { score = 0; } else if (obj) { score = obj.score; } else { console.log(err); } }); let categoryArray = []; switch (subject) { case null: categoryArray = ["BIOLOGY", "PHYSICS", "CHEMISTRY", "EARTH AND SPACE", "ASTRONOMY", "MATH"]; break; case "astro": case "astronomy": categoryArray = ["ASTRONOMY"] break; case "bio": case "biology": categoryArray = ["BIOLOGY"]; break; case "ess": case "earth science": case "es": categoryArray = ["EARTH SCIENCE"]; break; case "chem": case "chemistry": categoryArray = ["CHEMISTRY"]; break; case "phys": case "physics": categoryArray = ["PHYSICS"]; break; case "math": categoryArray = ["MATH"]; break; case "energy": categoryArray = ["ENERGY"]; break; default: interaction.reply( new Discord.MessageEmbed() .setDescription("<:red_x:816791117671825409> Not a valid subject!") .setColor("#ffffff") ); return; } axios .post("https://scibowldb.com/api/questions/random", { categories: categoryArray }) .then((res) => { data = res.data.question; const tossupQuestion = data.tossup_question; const tossupAnswer = data.tossup_answer; const messageFilter = (m) => m.author.id === authorId; interaction.reply({ content: decode(tossupQuestion) + `\n\n||Source: ${data.uri}||` }) .then(() => { interaction.channel.awaitMessages({ messageFilter, max: 1 }) .then(collected => { answerMsg = collected.first(); let predicted = null; if (data.tossup_format === "Multiple Choice") { if ( answerMsg.content.charAt(0).toLowerCase() === tossupAnswer.charAt(0).toLowerCase() ) { predicted = "correct"; } else { predicted = "incorrect"; } } else { if ( answerMsg.content.toLowerCase() === tossupAnswer.toLowerCase() ) { predicted = "correct"; } else { predicted = "incorrect"; } } if (predicted === "correct") { updateScore(true, score, authorId).then((msgToReply) => answerMsg.reply(msgToReply) ); } else { const overrideEmbed = new Discord.MessageEmbed() .setAuthor(answerMsg.author.tag, answerMsg.author.displayAvatarURL()) .addField("Correct answer", `\`${tossupAnswer}\``) .setDescription(`It seems your answer was incorrect. Please react with <:override:842778128966615060> to override your answer if you think you got it right.`) .setColor("#ffffff") .setTimestamp(); const overrideMsg = answerMsg.channel.send({ embeds: [overrideEmbed] }) .then(overrideMsg => { overrideMsg.react("<:override:842778128966615060>"); const filter = (reaction, user) => { return ( ["override"].includes(reaction.emoji.name) && user.id === answerMsg.author.id ); }; overrideMsg .awaitReactions({ filter, max: 1 }) .then((userReaction) => { updateScore(true, score, authorId).then((msgToReply) => answerMsg.reply(msgToReply) ); }).catch(console.error); }).catch(console.error); } }).catch(console.error); }).catch(console.error); }).catch(console.error); } function sendHelpMessage(interaction) { const helpEmbed = new Discord.MessageEmbed().setDescription(helpMessage).setColor("ffffff"); interaction.reply({ embeds: [helpEmbed] }); } async function startScoring(message) { let scoreA = 0; let scoreB = 0; await message.channel .send(`Here's the score:\nTeam A: ${scoreA}\nTeam B: ${scoreB}`) .then((scoreboard) => { const filter = (m) => m.content.includes("do be"); const collector = message.channel.createMessageCollector(filter, { time: 1500000, }); collector.on("collect", (m) => { if (m.content.toLowerCase() === "/scoring a 4") { // A team gets toss-up m.delete({ timeout: 1000 }).catch(console.error); scoreA += 4; scoreboard.channel.send( `Here's the score:\nTeam A: ${scoreA}\nTeam B: ${scoreB}` ); } else if (m.content.toLowerCase() === "/scoring a 10") { // A team gets bonus m.delete({ timeout: 1000 }).catch(console.error); scoreA += 10; scoreboard.channel.send( `Here's the score:\nTeam A: ${scoreA}\nTeam B: ${scoreB}` ); } else if (m.content.toLowerCase() === "/scoring b 4") { // B team gets toss up m.delete({ timeout: 1000 }).catch(console.error); scoreB += 4; scoreboard.channel.send( `Here's the score:\nTeam A: ${scoreA}\nTeam B: ${scoreB}` ); } else if (m.content.toLowerCase() === "/scoring b 10") { // B team gets bonus m.delete({ timeout: 1000 }).catch(console.error); scoreB += 10; scoreboard.channel.send( `Here's the score:\nTeam A: ${scoreA}\nTeam B: ${scoreB}` ); } else if (m.content === "/scoring stop") { m.delete({ timeout: 1000 }).catch(console.error); scoreboard.delete({ timeout: 1000 }); m.channel.send( `**FINAL SCORE:**\nTeam A: ${scoreA}\nTeam B: ${scoreB}` ); collector.stop(); } }); }); } function dontWorryBeHappy(message) { message.channel.send( new Discord.MessageEmbed() .setTitle(`Don't Worry Be Happy!`) .setImage("https://media.giphy.com/media/7OKC8ZpTT0PVm/giphy.gif") .setURL("https://youtu.be/d-diB65scQU") .setColor("#ffffff") ); } function showServerNumber(message) { message.channel.send(client.guilds.cache.size); } function showLeaderboard(interaction) { let messageContent = ""; userScore .find({}) .sort({ score: -1 }) // Sort by descending order .exec((err, obj) => { if (err) { console.log(err); return interaction.reply( "Uh oh! :( There was an internal error. Please try again." ); } if (obj.length < 10) { // Need at least 10 scores for top 10 return interaction.reply( `There are only ${obj.length} users, we need at least 10!` ); } for (let i = 0; i < 10; i++) { messageContent += `${i + 1}: <@${obj[i].authorID}>: ${obj[i].score}\n`; // Loop through each user and add their name and score to leaderboard content } const leaderboardEmbed = new Discord.MessageEmbed() .setTitle("Top Ten!") .setDescription(messageContent) .setColor("#ffffff") interaction.reply({ embeds: [leaderboardEmbed] }); }); } async function about(action, interaction) { if (action === "contributors") { const contributorEmbed = new Discord.MessageEmbed().setTitle("Contributors") .addField("Creator", `<@745063586422063214> [ADawesomeguy#3602]`, true) .addField("Contributors", `<@650525101048987649> [tEjAs#8127]\n<@426864344463048705> [tetrident#9396]`, true) // Add more contributors here, first one is Abheek, second one is Tejas .setTimestamp() .setColor("#ffffff"); interaction.reply({ embeds: [contributorEmbed] }); } else if (action === "changelog") { const gitRepoLocation = __dirname; const commits = gitlog({ repo: gitRepoLocation, number: 5, fields: ["hash", "abbrevHash", "subject", "authorName", "authorDateRel"], }); const changelogEmbed = new Discord.MessageEmbed() .setAuthor(interaction.user.tag, interaction.user.displayAvatarURL()) .setTitle("Changelog") .setColor("#ffffff") .setTimestamp(); commits.forEach(commit => { changelogEmbed.addField(commit.abbrevHash, `> \`Hash:\`${commit.hash}\n> \`Subject:\`${commit.subject}\n> \`Author:\`${commit.authorName}\n> \`Date:\`${commit.authorDateRel}\n> \`Link\`: [GitHub](https://github.com/ADawesomeguy/AwesomeSciBo/commit/${commit.hash})\n`); }); interaction.reply({ embeds: [changelogEmbed] }); } else if (action === "bot") { await client.guilds.fetch(); const trainingDocuments = await userScore.countDocuments({}); const aboutBotEmbed = new Discord.MessageEmbed() .setAuthor(interaction.user.tag, interaction.user.displayAvatarURL()) .setTitle("About AwesomeSciBo") .addField("Servers", `${client.guilds.cache.size}`, true) .addField("Training Users", `${trainingDocuments}`, true) .setTimestamp(); interaction.reply({ embeds: [aboutBotEmbed] }); } } async function rounds(action, interaction) { if (action === "generate") { let i; let finalizedHTML = '