Abheek Dhawan
2 years ago
19 changed files with 1340 additions and 1085 deletions
@ -1,58 +1,72 @@ |
|||
import { SlashCommandBuilder } from '@discordjs/builders'; |
|||
import { MessageEmbed, CommandInteraction } from 'discord.js'; |
|||
|
|||
import gitlog from 'gitlog'; |
|||
|
|||
import userScore from '../models/userScore'; |
|||
|
|||
import { paginateInteraction } from '../helpers/util/pagination'; |
|||
|
|||
export const data = new SlashCommandBuilder() |
|||
.setName('about') |
|||
.setDescription('Commands regarding the creation/development of the bot'); |
|||
|
|||
export async function execute(interaction: CommandInteraction) { |
|||
await interaction.deferReply(); |
|||
|
|||
const client = interaction.client; |
|||
const embeds: MessageEmbed[] = []; |
|||
|
|||
const contributorEmbed = new 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'); |
|||
embeds.push(contributorEmbed); |
|||
|
|||
const gitRepoLocation = __dirname; |
|||
|
|||
const commits = gitlog({ |
|||
repo: gitRepoLocation, |
|||
number: 5, |
|||
fields: ['hash', 'abbrevHash', 'subject', 'authorName', 'authorDateRel'], |
|||
}); |
|||
|
|||
const changelogEmbed = new MessageEmbed() |
|||
.setAuthor({ name: interaction.user.tag, iconURL: 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`); |
|||
}); |
|||
embeds.push(changelogEmbed); |
|||
|
|||
await client.guilds.fetch(); |
|||
const trainingDocuments = await userScore.countDocuments({}); |
|||
const aboutBotEmbed = new MessageEmbed() |
|||
.setAuthor({ name: interaction.user.tag, iconURL: interaction.user.displayAvatarURL() }) |
|||
.setTitle('About AwesomeSciBo') |
|||
.addField('Servers', `${client.guilds.cache.size}`, true) |
|||
.addField('Training Users', `${trainingDocuments}`, true) |
|||
.setTimestamp(); |
|||
|
|||
embeds.push(aboutBotEmbed); |
|||
|
|||
paginateInteraction(interaction, embeds); |
|||
} |
|||
import { SlashCommandBuilder } from "@discordjs/builders"; |
|||
import { MessageEmbed, CommandInteraction } from "discord.js"; |
|||
|
|||
import gitlog from "gitlog"; |
|||
|
|||
import userScore from "../models/userScore"; |
|||
|
|||
import { paginateInteraction } from "../helpers/util/pagination"; |
|||
|
|||
export const data = new SlashCommandBuilder() |
|||
.setName("about") |
|||
.setDescription("Commands regarding the creation/development of the bot"); |
|||
|
|||
export async function execute(interaction: CommandInteraction) { |
|||
await interaction.deferReply(); |
|||
|
|||
const client = interaction.client; |
|||
const embeds: MessageEmbed[] = []; |
|||
|
|||
const contributorEmbed = new 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"); |
|||
embeds.push(contributorEmbed); |
|||
|
|||
const gitRepoLocation = __dirname; |
|||
|
|||
const commits = gitlog({ |
|||
repo: gitRepoLocation, |
|||
number: 5, |
|||
fields: ["hash", "abbrevHash", "subject", "authorName", "authorDateRel"], |
|||
}); |
|||
|
|||
const changelogEmbed = new MessageEmbed() |
|||
.setAuthor({ |
|||
name: interaction.user.tag, |
|||
iconURL: 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` |
|||
); |
|||
}); |
|||
embeds.push(changelogEmbed); |
|||
|
|||
await client.guilds.fetch(); |
|||
const trainingDocuments = await userScore.countDocuments({}); |
|||
const aboutBotEmbed = new MessageEmbed() |
|||
.setAuthor({ |
|||
name: interaction.user.tag, |
|||
iconURL: interaction.user.displayAvatarURL(), |
|||
}) |
|||
.setTitle("About AwesomeSciBo") |
|||
.addField("Servers", `${client.guilds.cache.size}`, true) |
|||
.addField("Training Users", `${trainingDocuments}`, true) |
|||
.setTimestamp(); |
|||
|
|||
embeds.push(aboutBotEmbed); |
|||
|
|||
paginateInteraction(interaction, embeds); |
|||
} |
|||
|
@ -1,16 +1,18 @@ |
|||
import { SlashCommandBuilder } from '@discordjs/builders'; |
|||
import { MessageEmbed, CommandInteraction } from 'discord.js'; |
|||
|
|||
export const data = new SlashCommandBuilder() |
|||
.setName('help') |
|||
.setDescription('Replies with a help message explaining what the bot can do'); |
|||
|
|||
export async function execute(interaction: CommandInteraction) { |
|||
await interaction.deferReply(); |
|||
await interaction.deferReply(); |
|||
|
|||
const helpEmbed = new MessageEmbed() |
|||
.setDescription('AwesomeSciBo has migrated to using slash commands! You can take a look at the different commands by typing `/` and clicking on the AwesomeSciBo icon.') |
|||
.setColor('#ffffff'); |
|||
interaction.followUp({ embeds: [helpEmbed] }); |
|||
} |
|||
import { SlashCommandBuilder } from "@discordjs/builders"; |
|||
import { MessageEmbed, CommandInteraction } from "discord.js"; |
|||
|
|||
export const data = new SlashCommandBuilder() |
|||
.setName("help") |
|||
.setDescription("Replies with a help message explaining what the bot can do"); |
|||
|
|||
export async function execute(interaction: CommandInteraction) { |
|||
await interaction.deferReply(); |
|||
await interaction.deferReply(); |
|||
|
|||
const helpEmbed = new MessageEmbed() |
|||
.setDescription( |
|||
"AwesomeSciBo has migrated to using slash commands! You can take a look at the different commands by typing `/` and clicking on the AwesomeSciBo icon." |
|||
) |
|||
.setColor("#ffffff"); |
|||
interaction.followUp({ embeds: [helpEmbed] }); |
|||
} |
|||
|
@ -1,125 +1,178 @@ |
|||
import { SlashCommandBuilder } from '@discordjs/builders'; |
|||
import { MessageEmbed, CommandInteraction } from 'discord.js'; |
|||
|
|||
import axios from 'axios'; |
|||
|
|||
import log from '../helpers/log'; |
|||
import generatedRound from '../models/generatedRound'; |
|||
|
|||
export const data = new SlashCommandBuilder() |
|||
.setName('rounds') |
|||
.setDescription('Commands regarding the generation of rounds') |
|||
.addSubcommand(subcommand => { |
|||
subcommand |
|||
.setName('generate') |
|||
.setDescription('Generates a round with randomized questions from https://scibowldb.com/'); |
|||
return subcommand; |
|||
}) |
|||
.addSubcommand(subcommand => { |
|||
subcommand |
|||
.setName('list') |
|||
.setDescription('Lists your 5 most recently generated rounds with links'); |
|||
return subcommand; |
|||
}) |
|||
.addSubcommand(subcommand => { |
|||
subcommand |
|||
.setName('hit') |
|||
.setDescription('Shows the total number of rounds hit as well as the number for the specific user'); |
|||
return subcommand; |
|||
}); |
|||
|
|||
export async function execute(interaction: CommandInteraction) { |
|||
const action = interaction.options.getSubcommand(); |
|||
switch (action) { |
|||
case 'generate': { |
|||
interaction.deferReply({ ephemeral: true }); |
|||
|
|||
let finalizedHTML = '<html><head><link rel=\'preconnect\' href=\'https://fonts.gstatic.com\'><link href=\'https://fonts.googleapis.com/css2?family=Ubuntu&display=swap\' rel=\'stylesheet\'> </head><body style=\'width: 70%; margin-left: auto; margin-right: auto;\'><h2 style=\'text-align: center; text-decoration: underline overline; padding: 7px;\'>ROUND GENERATED BY AWESOMESCIBO USING THE SCIBOWLDB API</h2>'; |
|||
let tossup_question: string; |
|||
let question_category: string; |
|||
let tossup_format: string; |
|||
let tossup_answer: string; |
|||
let bonus_question: string; |
|||
let bonus_format: string; |
|||
let bonus_answer: string; |
|||
let htmlContent = ''; |
|||
await axios.post('https://scibowldb.com/api/questions', { categories: ['BIOLOGY', 'PHYSICS', 'CHEMISTRY', 'EARTH AND SPACE', 'ASTRONOMY', 'MATH'] }) |
|||
.then((response) => { |
|||
for (let i = 1; i < 26; i++) { |
|||
const questionData = response.data.questions[Math.floor(Math.random() * response.data.questions.length)]; |
|||
tossup_question = questionData.tossup_question; |
|||
tossup_answer = questionData.tossup_answer; |
|||
question_category = questionData.category; |
|||
tossup_format = questionData.tossup_format; |
|||
bonus_question = questionData.bonus_question; |
|||
bonus_answer = questionData.bonus_answer; |
|||
bonus_format = questionData.bonus_format; |
|||
htmlContent = '<br><br><h3 style=\'text-align: center;\'><strong>TOSS-UP</strong></h3>\n<br>' + `${i}) <strong>${question_category}</strong>` + ' ' + `<em>${tossup_format}</em>` + ' ' + tossup_question + '<br><br>' + '<strong>ANSWER:</strong> ' + tossup_answer + '<br>'; |
|||
htmlContent += '<br><br><h3 style=\'text-align: center;\'><strong>BONUS</strong></h3>\n<br>' + `${i}) <strong>${question_category}</strong>` + ' ' + `<em>${bonus_format}</em>` + ' ' + bonus_question + '<br><br>' + '<strong>ANSWER:</strong> ' + bonus_answer + '<br><br><hr><br>'; |
|||
htmlContent = htmlContent.replace(/\n/g, '<br>'); |
|||
finalizedHTML += htmlContent; |
|||
} |
|||
|
|||
const newGeneratedRound = new generatedRound({ |
|||
htmlContent: finalizedHTML, |
|||
requestedBy: interaction.user.id, |
|||
authorTag: interaction.user.tag, |
|||
timestamp: new Date().toISOString(), |
|||
}); |
|||
|
|||
newGeneratedRound.save((err, round) => { |
|||
if (err) { |
|||
log({ logger: 'rounds', content: `Saving round to DB failed: ${err}`, level: 'error' }); |
|||
return; |
|||
} |
|||
interaction.followUp({ |
|||
content: `Here's your round: https://api.adawesome.tech/round/${round._id.toString()}`, |
|||
ephemeral: true, |
|||
}); |
|||
}); |
|||
}); |
|||
break; |
|||
} |
|||
|
|||
case 'list': { |
|||
interaction.deferReply({ ephemeral: true }); |
|||
|
|||
let roundsList = await generatedRound.find({ requestedBy: interaction.user.id }).sort({ timestamp: -1 }); |
|||
let finalMessage = ''; |
|||
if (!roundsList) { |
|||
interaction.followUp('You haven\'t requested any rounds!'); |
|||
return; |
|||
} |
|||
|
|||
if (roundsList.length > 5) { |
|||
roundsList = roundsList.slice(0, 5); |
|||
} |
|||
|
|||
roundsList.forEach(async (item, index) => { |
|||
finalMessage += `${index + 1}. [${item.timestamp.split('T')[0]}](https://api.adawesome.tech/round/${item._id.toString()})\n`; |
|||
}); |
|||
|
|||
const roundsListEmbed = new MessageEmbed() |
|||
.setAuthor({ name: interaction.user.tag, iconURL: interaction.user.displayAvatarURL() }) |
|||
.setTitle('Last 5 rounds requested') |
|||
.setDescription(finalMessage) |
|||
.setTimestamp(); |
|||
|
|||
interaction.followUp({ |
|||
embeds: [roundsListEmbed], |
|||
ephemeral: true, |
|||
}); |
|||
break; |
|||
} |
|||
|
|||
case 'hit': { |
|||
await interaction.deferReply(); |
|||
|
|||
const totalCount = await generatedRound.countDocuments({}); |
|||
const userCount = await generatedRound.countDocuments({ requestedBy: interaction.user.id }); |
|||
|
|||
interaction.followUp(`Total Hits: ${totalCount}\nYour Hits: ${userCount}`); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
import { SlashCommandBuilder } from "@discordjs/builders"; |
|||
import { MessageEmbed, CommandInteraction } from "discord.js"; |
|||
|
|||
import axios from "axios"; |
|||
|
|||
import log from "../helpers/log"; |
|||
import generatedRound from "../models/generatedRound"; |
|||
|
|||
export const data = new SlashCommandBuilder() |
|||
.setName("rounds") |
|||
.setDescription("Commands regarding the generation of rounds") |
|||
.addSubcommand((subcommand) => { |
|||
subcommand |
|||
.setName("generate") |
|||
.setDescription( |
|||
"Generates a round with randomized questions from https://scibowldb.com/" |
|||
); |
|||
return subcommand; |
|||
}) |
|||
.addSubcommand((subcommand) => { |
|||
subcommand |
|||
.setName("list") |
|||
.setDescription("Lists your 5 most recently generated rounds with links"); |
|||
return subcommand; |
|||
}) |
|||
.addSubcommand((subcommand) => { |
|||
subcommand |
|||
.setName("hit") |
|||
.setDescription( |
|||
"Shows the total number of rounds hit as well as the number for the specific user" |
|||
); |
|||
return subcommand; |
|||
}); |
|||
|
|||
export async function execute(interaction: CommandInteraction) { |
|||
const action = interaction.options.getSubcommand(); |
|||
switch (action) { |
|||
case "generate": { |
|||
interaction.deferReply({ ephemeral: true }); |
|||
|
|||
let finalizedHTML = |
|||
"<html><head><link rel='preconnect' href='https://fonts.gstatic.com'><link href='https://fonts.googleapis.com/css2?family=Ubuntu&display=swap' rel='stylesheet'> </head><body style='width: 70%; margin-left: auto; margin-right: auto;'><h2 style='text-align: center; text-decoration: underline overline; padding: 7px;'>ROUND GENERATED BY AWESOMESCIBO USING THE SCIBOWLDB API</h2>"; |
|||
let tossup_question: string; |
|||
let question_category: string; |
|||
let tossup_format: string; |
|||
let tossup_answer: string; |
|||
let bonus_question: string; |
|||
let bonus_format: string; |
|||
let bonus_answer: string; |
|||
let htmlContent = ""; |
|||
await axios |
|||
.post("https://scibowldb.com/api/questions", { |
|||
categories: [ |
|||
"BIOLOGY", |
|||
"PHYSICS", |
|||
"CHEMISTRY", |
|||
"EARTH AND SPACE", |
|||
"ASTRONOMY", |
|||
"MATH", |
|||
], |
|||
}) |
|||
.then((response) => { |
|||
for (let i = 1; i < 26; i++) { |
|||
const questionData = |
|||
response.data.questions[ |
|||
Math.floor(Math.random() * response.data.questions.length) |
|||
]; |
|||
tossup_question = questionData.tossup_question; |
|||
tossup_answer = questionData.tossup_answer; |
|||
question_category = questionData.category; |
|||
tossup_format = questionData.tossup_format; |
|||
bonus_question = questionData.bonus_question; |
|||
bonus_answer = questionData.bonus_answer; |
|||
bonus_format = questionData.bonus_format; |
|||
htmlContent = |
|||
"<br><br><h3 style='text-align: center;'><strong>TOSS-UP</strong></h3>\n<br>" + |
|||
`${i}) <strong>${question_category}</strong>` + |
|||
" " + |
|||
`<em>${tossup_format}</em>` + |
|||
" " + |
|||
tossup_question + |
|||
"<br><br>" + |
|||
"<strong>ANSWER:</strong> " + |
|||
tossup_answer + |
|||
"<br>"; |
|||
htmlContent += |
|||
"<br><br><h3 style='text-align: center;'><strong>BONUS</strong></h3>\n<br>" + |
|||
`${i}) <strong>${question_category}</strong>` + |
|||
" " + |
|||
`<em>${bonus_format}</em>` + |
|||
" " + |
|||
bonus_question + |
|||
"<br><br>" + |
|||
"<strong>ANSWER:</strong> " + |
|||
bonus_answer + |
|||
"<br><br><hr><br>"; |
|||
htmlContent = htmlContent.replace(/\n/g, "<br>"); |
|||
finalizedHTML += htmlContent; |
|||
} |
|||
|
|||
const newGeneratedRound = new generatedRound({ |
|||
htmlContent: finalizedHTML, |
|||
requestedBy: interaction.user.id, |
|||
authorTag: interaction.user.tag, |
|||
timestamp: new Date().toISOString(), |
|||
}); |
|||
|
|||
newGeneratedRound.save((err, round) => { |
|||
if (err) { |
|||
log({ |
|||
logger: "rounds", |
|||
content: `Saving round to DB failed: ${err}`, |
|||
level: "error", |
|||
}); |
|||
return; |
|||
} |
|||
interaction.followUp({ |
|||
content: `Here's your round: https://api.adawesome.tech/round/${round._id.toString()}`, |
|||
ephemeral: true, |
|||
}); |
|||
}); |
|||
}); |
|||
break; |
|||
} |
|||
|
|||
case "list": { |
|||
interaction.deferReply({ ephemeral: true }); |
|||
|
|||
let roundsList = await generatedRound |
|||
.find({ requestedBy: interaction.user.id }) |
|||
.sort({ timestamp: -1 }); |
|||
let finalMessage = ""; |
|||
if (!roundsList) { |
|||
interaction.followUp("You haven't requested any rounds!"); |
|||
return; |
|||
} |
|||
|
|||
if (roundsList.length > 5) { |
|||
roundsList = roundsList.slice(0, 5); |
|||
} |
|||
|
|||
roundsList.forEach(async (item, index) => { |
|||
finalMessage += `${index + 1}. [${ |
|||
item.timestamp.split("T")[0] |
|||
}](https://api.adawesome.tech/round/${item._id.toString()})\n`;
|
|||
}); |
|||
|
|||
const roundsListEmbed = new MessageEmbed() |
|||
.setAuthor({ |
|||
name: interaction.user.tag, |
|||
iconURL: interaction.user.displayAvatarURL(), |
|||
}) |
|||
.setTitle("Last 5 rounds requested") |
|||
.setDescription(finalMessage) |
|||
.setTimestamp(); |
|||
|
|||
interaction.followUp({ |
|||
embeds: [roundsListEmbed], |
|||
ephemeral: true, |
|||
}); |
|||
break; |
|||
} |
|||
|
|||
case "hit": { |
|||
await interaction.deferReply(); |
|||
|
|||
const totalCount = await generatedRound.countDocuments({}); |
|||
const userCount = await generatedRound.countDocuments({ |
|||
requestedBy: interaction.user.id, |
|||
}); |
|||
|
|||
interaction.followUp( |
|||
`Total Hits: ${totalCount}\nYour Hits: ${userCount}` |
|||
); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
@ -1,43 +1,47 @@ |
|||
import { SlashCommandBuilder } from '@discordjs/builders'; |
|||
import { CommandInteraction, MessageEmbed } from 'discord.js'; |
|||
|
|||
import log from '../helpers/log'; |
|||
import userScore from '../models/userScore'; |
|||
|
|||
export const data = new SlashCommandBuilder() |
|||
.setName('score') |
|||
.setDescription('Returns the score of the current user or another') |
|||
.addUserOption(option => { |
|||
option |
|||
.setName('user') |
|||
.setDescription('The user to find the score for') |
|||
.setRequired(false); |
|||
|
|||
return option; |
|||
}); |
|||
|
|||
export async function execute(interaction: CommandInteraction) { |
|||
const scoreEmbed = new MessageEmbed() |
|||
.setColor('#ffffff'); |
|||
|
|||
const user = interaction.options.getUser('user') || interaction.user; |
|||
userScore.findOne({ authorID: user.id }, async (err, score) => { |
|||
if (err) { |
|||
log({ logger: 'db', content: `Unable to obtain user: ${err}`, level: 'info' }); |
|||
} |
|||
|
|||
if (!score) { |
|||
await interaction.reply({ |
|||
content: 'Unfortunately, that user does not seem to have used AwesomeSciBo yet.', |
|||
ephemeral: true, |
|||
}); |
|||
return; |
|||
} |
|||
|
|||
scoreEmbed |
|||
.setAuthor({ name: user.tag, iconURL: user.displayAvatarURL() }) |
|||
.setDescription(`Score: \`${score.score}\``); |
|||
|
|||
await interaction.reply({ embeds: [scoreEmbed] }); |
|||
}); |
|||
} |
|||
import { SlashCommandBuilder } from "@discordjs/builders"; |
|||
import { CommandInteraction, MessageEmbed } from "discord.js"; |
|||
|
|||
import log from "../helpers/log"; |
|||
import userScore from "../models/userScore"; |
|||
|
|||
export const data = new SlashCommandBuilder() |
|||
.setName("score") |
|||
.setDescription("Returns the score of the current user or another") |
|||
.addUserOption((option) => { |
|||
option |
|||
.setName("user") |
|||
.setDescription("The user to find the score for") |
|||
.setRequired(false); |
|||
|
|||
return option; |
|||
}); |
|||
|
|||
export async function execute(interaction: CommandInteraction) { |
|||
const scoreEmbed = new MessageEmbed().setColor("#ffffff"); |
|||
|
|||
const user = interaction.options.getUser("user") || interaction.user; |
|||
userScore.findOne({ authorID: user.id }, async (err, score) => { |
|||
if (err) { |
|||
log({ |
|||
logger: "db", |
|||
content: `Unable to obtain user: ${err}`, |
|||
level: "info", |
|||
}); |
|||
} |
|||
|
|||
if (!score) { |
|||
await interaction.reply({ |
|||
content: |
|||
"Unfortunately, that user does not seem to have used AwesomeSciBo yet.", |
|||
ephemeral: true, |
|||
}); |
|||
return; |
|||
} |
|||
|
|||
scoreEmbed |
|||
.setAuthor({ name: user.tag, iconURL: user.displayAvatarURL() }) |
|||
.setDescription(`Score: \`${score.score}\``); |
|||
|
|||
await interaction.reply({ embeds: [scoreEmbed] }); |
|||
}); |
|||
} |
|||
|
@ -1,251 +1,289 @@ |
|||
import { SlashCommandBuilder } from '@discordjs/builders'; |
|||
import { Message, MessageActionRow, MessageSelectMenu } from 'discord.js'; |
|||
import { CommandInteraction, MessageEmbed } from 'discord.js'; |
|||
import log from '../helpers/log'; |
|||
import userConfig from '../models/userConfig'; |
|||
import { SlashCommandBuilder } from "@discordjs/builders"; |
|||
import { Message, MessageActionRow, MessageSelectMenu } from "discord.js"; |
|||
import { CommandInteraction, MessageEmbed } from "discord.js"; |
|||
import log from "../helpers/log"; |
|||
import userConfig from "../models/userConfig"; |
|||
|
|||
export const data = new SlashCommandBuilder() |
|||
.setName('settings') |
|||
.setDescription('BETA - settings configuration') |
|||
.addSubcommand(subcommand => { |
|||
subcommand |
|||
.setName('subject') |
|||
.setDescription('Changes subject of problems'); |
|||
return subcommand; |
|||
}) |
|||
.addSubcommand(subcommand => { |
|||
subcommand |
|||
.setName('display') |
|||
.setDescription('Displays current settings'); |
|||
return subcommand; |
|||
}) |
|||
.addSubcommand(subcommand => { |
|||
subcommand |
|||
.setName('gradelevels') |
|||
.setDescription('Changes grade level of problems'); |
|||
return subcommand; |
|||
}); |
|||
.setName("settings") |
|||
.setDescription("BETA - settings configuration") |
|||
.addSubcommand((subcommand) => { |
|||
subcommand.setName("subject").setDescription("Changes subject of problems"); |
|||
return subcommand; |
|||
}) |
|||
.addSubcommand((subcommand) => { |
|||
subcommand.setName("display").setDescription("Displays current settings"); |
|||
return subcommand; |
|||
}) |
|||
.addSubcommand((subcommand) => { |
|||
subcommand |
|||
.setName("gradelevels") |
|||
.setDescription("Changes grade level of problems"); |
|||
return subcommand; |
|||
}); |
|||
|
|||
export async function execute(interaction: CommandInteraction) { |
|||
const action = interaction.options.getSubcommand(); |
|||
switch (action) { |
|||
case 'display': { |
|||
await interaction.deferReply(); |
|||
const settingsEmbed = new MessageEmbed() |
|||
.setColor('#ffffff'); |
|||
const action = interaction.options.getSubcommand(); |
|||
switch (action) { |
|||
case "display": { |
|||
await interaction.deferReply(); |
|||
const settingsEmbed = new MessageEmbed().setColor("#ffffff"); |
|||
|
|||
const user = interaction.options.getUser('user') || interaction.user; |
|||
const user = interaction.options.getUser("user") || interaction.user; |
|||
|
|||
settingsEmbed |
|||
.setAuthor({ name: user.tag, iconURL: user.displayAvatarURL() }) |
|||
.setDescription('Current selections: '); |
|||
const menu = new MessageActionRow() |
|||
.addComponents( |
|||
new MessageSelectMenu() |
|||
.setCustomId('selectdisp') |
|||
.setPlaceholder('Nothing selected') |
|||
.addOptions([ |
|||
{ |
|||
label: 'subjects', |
|||
description: 'subjects', |
|||
value: 'subjects', |
|||
}, |
|||
{ |
|||
label: 'gradelevels', |
|||
description: 'grade levels', |
|||
value: 'gradelevels', |
|||
}, |
|||
]), |
|||
); |
|||
settingsEmbed |
|||
.setAuthor({ name: user.tag, iconURL: user.displayAvatarURL() }) |
|||
.setDescription("Current selections: "); |
|||
const menu = new MessageActionRow().addComponents( |
|||
new MessageSelectMenu() |
|||
.setCustomId("selectdisp") |
|||
.setPlaceholder("Nothing selected") |
|||
.addOptions([ |
|||
{ |
|||
label: "subjects", |
|||
description: "subjects", |
|||
value: "subjects", |
|||
}, |
|||
{ |
|||
label: "gradelevels", |
|||
description: "grade levels", |
|||
value: "gradelevels", |
|||
}, |
|||
]) |
|||
); |
|||
|
|||
interaction.followUp({ |
|||
embeds: [/* settingsEmbed*/], |
|||
components: [menu], |
|||
}) |
|||
.then((dispMsg => { |
|||
const w = dispMsg as Message; |
|||
const dispFilter = i => ['selectdisp'].includes(i.customId) && i.user.id == interaction.user.id; // <== ATTENTION! First argument...
|
|||
w.awaitMessageComponent({ filter: dispFilter, componentType: 'SELECT_MENU' }) |
|||
.then(async dispChoice => { |
|||
const vals = dispChoice.values; |
|||
const config = await userConfig.findById(interaction.user.id); |
|||
if (!config) { |
|||
await interaction.editReply({ |
|||
content: 'You don\'t have a configuration!', |
|||
embeds: [], |
|||
components: [], |
|||
}); |
|||
} |
|||
else if (vals.length === 1 && vals.at(0) === 'subjects') { |
|||
await interaction.editReply({ |
|||
content: `Current subjects setting: ${config.subjects.toString().split(',').join(', ')}`, |
|||
components: [], |
|||
}); |
|||
} |
|||
else if (vals.length === 1 && vals.at(0) === 'gradelevels') { |
|||
await interaction.editReply({ |
|||
content: `Current grade level setting: ${config.gradeLevels.toString().split(',').join(', ')}`, |
|||
components: [], |
|||
}); |
|||
} |
|||
else { |
|||
err => log({ |
|||
logger: '\'Error occurred: /settings:display did not equal subjects or gradelevels.\'', |
|||
content: `${err}`, |
|||
level: 'error', |
|||
}); |
|||
} |
|||
}); |
|||
})); |
|||
break; |
|||
} |
|||
case 'gradelevels': { |
|||
await interaction.deferReply(); |
|||
interaction |
|||
.followUp({ |
|||
embeds: [ |
|||
/* settingsEmbed*/ |
|||
], |
|||
components: [menu], |
|||
}) |
|||
.then((dispMsg) => { |
|||
const w = dispMsg as Message; |
|||
const dispFilter = (i) => |
|||
["selectdisp"].includes(i.customId) && |
|||
i.user.id == interaction.user.id; // <== ATTENTION! First argument...
|
|||
w.awaitMessageComponent({ |
|||
filter: dispFilter, |
|||
componentType: "SELECT_MENU", |
|||
}).then(async (dispChoice) => { |
|||
const vals = dispChoice.values; |
|||
const config = await userConfig.findById(interaction.user.id); |
|||
if (!config) { |
|||
await interaction.editReply({ |
|||
content: "You don't have a configuration!", |
|||
embeds: [], |
|||
components: [], |
|||
}); |
|||
} else if (vals.length === 1 && vals.at(0) === "subjects") { |
|||
await interaction.editReply({ |
|||
content: `Current subjects setting: ${config.subjects |
|||
.toString() |
|||
.split(",") |
|||
.join(", ")}`,
|
|||
components: [], |
|||
}); |
|||
} else if (vals.length === 1 && vals.at(0) === "gradelevels") { |
|||
await interaction.editReply({ |
|||
content: `Current grade level setting: ${config.gradeLevels |
|||
.toString() |
|||
.split(",") |
|||
.join(", ")}`,
|
|||
components: [], |
|||
}); |
|||
} else { |
|||
(err) => |
|||
log({ |
|||
logger: |
|||
"'Error occurred: /settings:display did not equal subjects or gradelevels.'", |
|||
content: `${err}`, |
|||
level: "error", |
|||
}); |
|||
} |
|||
}); |
|||
}); |
|||
break; |
|||
} |
|||
case "gradelevels": { |
|||
await interaction.deferReply(); |
|||
|
|||
const settingsEmbed = new MessageEmbed() |
|||
.setColor('#ffffff'); |
|||
const settingsEmbed = new MessageEmbed().setColor("#ffffff"); |
|||
|
|||
const user = interaction.options.getUser('user') || interaction.user; |
|||
const user = interaction.options.getUser("user") || interaction.user; |
|||
|
|||
settingsEmbed |
|||
.setAuthor({ name: user.tag, iconURL: user.displayAvatarURL() }) |
|||
.setDescription('Current level settings: '); |
|||
const menu = new MessageActionRow() |
|||
.addComponents( |
|||
new MessageSelectMenu() |
|||
.setCustomId('selectlvl') |
|||
.setPlaceholder('Nothing selected') |
|||
.setMinValues(1) |
|||
.setMaxValues(2) |
|||
.addOptions([ |
|||
{ |
|||
label: 'Middle School', |
|||
description: 'Middle school level problems', |
|||
value: 'MS', |
|||
}, |
|||
{ |
|||
label: 'High School', |
|||
description: 'High school level problems', |
|||
value: 'HS', |
|||
}, |
|||
]), |
|||
); |
|||
settingsEmbed |
|||
.setAuthor({ name: user.tag, iconURL: user.displayAvatarURL() }) |
|||
.setDescription("Current level settings: "); |
|||
const menu = new MessageActionRow().addComponents( |
|||
new MessageSelectMenu() |
|||
.setCustomId("selectlvl") |
|||
.setPlaceholder("Nothing selected") |
|||
.setMinValues(1) |
|||
.setMaxValues(2) |
|||
.addOptions([ |
|||
{ |
|||
label: "Middle School", |
|||
description: "Middle school level problems", |
|||
value: "MS", |
|||
}, |
|||
{ |
|||
label: "High School", |
|||
description: "High school level problems", |
|||
value: "HS", |
|||
}, |
|||
]) |
|||
); |
|||
|
|||
interaction.followUp({ |
|||
embeds: [/* settingsEmbed*/], |
|||
components: [menu], |
|||
}) |
|||
.then((lvlMsg => { |
|||
const w = lvlMsg as Message; |
|||
const lvlFilter = i => ['selectlvl'].includes(i.customId) && i.user.id == interaction.user.id; // <== ATTENTION! First argument...
|
|||
w.awaitMessageComponent({ filter: lvlFilter, componentType: 'SELECT_MENU' }) |
|||
.then(async lvlChoice => { |
|||
const vals = lvlChoice.values; |
|||
const levels = new Array<string>(); |
|||
await userConfig.findOneAndUpdate({ _id: interaction.user.id }, { gradeLevels: vals }, { |
|||
upsert: true, |
|||
new: true, |
|||
}); |
|||
await vals.forEach(v => { |
|||
switch (v) { |
|||
case 'MS': |
|||
levels.push('Middle School'); |
|||
break; |
|||
case 'HS': |
|||
levels.push('High School'); |
|||
} |
|||
}); |
|||
await interaction.editReply({ |
|||
content: `Level set to: ${levels.toString().split(',').join(', ')}`, |
|||
embeds: [], |
|||
components: [], |
|||
}); |
|||
}); |
|||
})); |
|||
break; |
|||
} |
|||
case 'subject': { |
|||
await interaction.deferReply(); |
|||
interaction |
|||
.followUp({ |
|||
embeds: [ |
|||
/* settingsEmbed*/ |
|||
], |
|||
components: [menu], |
|||
}) |
|||
.then((lvlMsg) => { |
|||
const w = lvlMsg as Message; |
|||
const lvlFilter = (i) => |
|||
["selectlvl"].includes(i.customId) && |
|||
i.user.id == interaction.user.id; // <== ATTENTION! First argument...
|
|||
w.awaitMessageComponent({ |
|||
filter: lvlFilter, |
|||
componentType: "SELECT_MENU", |
|||
}).then(async (lvlChoice) => { |
|||
const vals = lvlChoice.values; |
|||
const levels = new Array<string>(); |
|||
await userConfig.findOneAndUpdate( |
|||
{ _id: interaction.user.id }, |
|||
{ gradeLevels: vals }, |
|||
{ |
|||
upsert: true, |
|||
new: true, |
|||
} |
|||
); |
|||
await vals.forEach((v) => { |
|||
switch (v) { |
|||
case "MS": |
|||
levels.push("Middle School"); |
|||
break; |
|||
case "HS": |
|||
levels.push("High School"); |
|||
} |
|||
}); |
|||
await interaction.editReply({ |
|||
content: `Level set to: ${levels |
|||
.toString() |
|||
.split(",") |
|||
.join(", ")}`,
|
|||
embeds: [], |
|||
components: [], |
|||
}); |
|||
}); |
|||
}); |
|||
break; |
|||
} |
|||
case "subject": { |
|||
await interaction.deferReply(); |
|||
|
|||
const settingsEmbed = new MessageEmbed() |
|||
.setColor('#ffffff'); |
|||
const settingsEmbed = new MessageEmbed().setColor("#ffffff"); |
|||
|
|||
const user = interaction.options.getUser('user') || interaction.user; |
|||
const user = interaction.options.getUser("user") || interaction.user; |
|||
|
|||
settingsEmbed |
|||
.setAuthor({ name: user.tag, iconURL: user.displayAvatarURL() }) |
|||
.setDescription('Current subject settings: '); |
|||
const menu = new MessageActionRow() |
|||
.addComponents( |
|||
new MessageSelectMenu() |
|||
.setCustomId('selectsubject') |
|||
.setPlaceholder('Nothing selected') |
|||
.setMinValues(1) |
|||
.setMaxValues(7) |
|||
.addOptions([ |
|||
{ |
|||
label: 'Astronomy', |
|||
description: 'Astronomy', |
|||
value: 'ASTRONOMY', |
|||
}, |
|||
{ |
|||
label: 'Biology', |
|||
description: 'Biology', |
|||
value: 'BIOLOGY', |
|||
}, |
|||
{ |
|||
label: 'Earth Science', |
|||
description: 'Earth Science', |
|||
value: 'EARTH SCIENCE', |
|||
}, |
|||
{ |
|||
label: 'Chemistry', |
|||
description: 'Chemistry', |
|||
value: 'CHEMISTRY', |
|||
}, |
|||
{ |
|||
label: 'Physics', |
|||
description: 'Physics', |
|||
value: 'PHYSICS', |
|||
}, |
|||
{ |
|||
label: 'Mathematics', |
|||
description: 'Mathematics', |
|||
value: 'MATH', |
|||
}, |
|||
{ |
|||
label: 'Energy', |
|||
description: 'Energy', |
|||
value: 'ENERGY', |
|||
}, |
|||
]), |
|||
); |
|||
settingsEmbed |
|||
.setAuthor({ name: user.tag, iconURL: user.displayAvatarURL() }) |
|||
.setDescription("Current subject settings: "); |
|||
const menu = new MessageActionRow().addComponents( |
|||
new MessageSelectMenu() |
|||
.setCustomId("selectsubject") |
|||
.setPlaceholder("Nothing selected") |
|||
.setMinValues(1) |
|||
.setMaxValues(7) |
|||
.addOptions([ |
|||
{ |
|||
label: "Astronomy", |
|||
description: "Astronomy", |
|||
value: "ASTRONOMY", |
|||
}, |
|||
{ |
|||
label: "Biology", |
|||
description: "Biology", |
|||
value: "BIOLOGY", |
|||
}, |
|||
{ |
|||
label: "Earth Science", |
|||
description: "Earth Science", |
|||
value: "EARTH SCIENCE", |
|||
}, |
|||
{ |
|||
label: "Chemistry", |
|||
description: "Chemistry", |
|||
value: "CHEMISTRY", |
|||
}, |
|||
{ |
|||
label: "Physics", |
|||
description: "Physics", |
|||
value: "PHYSICS", |
|||
}, |
|||
{ |
|||
label: "Mathematics", |
|||
description: "Mathematics", |
|||
value: "MATH", |
|||
}, |
|||
{ |
|||
label: "Energy", |
|||
description: "Energy", |
|||
value: "ENERGY", |
|||
}, |
|||
]) |
|||
); |
|||
|
|||
interaction.followUp({ |
|||
embeds: [/* settingsEmbed*/], |
|||
components: [menu], |
|||
}) |
|||
.then((subjectMsg => { |
|||
const subjectFilter = i => ['selectsubject'].includes(i.customId) && i.user.id == interaction.user.id; // <== ATTENTION! First argument...
|
|||
(subjectMsg as Message).awaitMessageComponent({ filter: subjectFilter, componentType: 'SELECT_MENU' }) |
|||
.then(async subjectChoice => { |
|||
const vals = subjectChoice.values; |
|||
await userConfig.findOneAndUpdate({ _id: interaction.user.id }, { subjects: vals }, { |
|||
upsert: true, |
|||
new: true, |
|||
}); |
|||
const subjects = new Array<string>(); |
|||
await vals.forEach(v => { |
|||
subjects.push(v.toLowerCase().split(' ').map(w => w[0].toUpperCase() + w.substring(1)).join(' ')); |
|||
}); |
|||
await interaction.editReply({ |
|||
content: `Subjects set to: ${subjects.toString().split(',').join(', ')}`, |
|||
components: [], |
|||
embeds: [], |
|||
}); |
|||
}); |
|||
})); |
|||
break; |
|||
} |
|||
} |
|||
interaction |
|||
.followUp({ |
|||
embeds: [ |
|||
/* settingsEmbed*/ |
|||
], |
|||
components: [menu], |
|||
}) |
|||
.then((subjectMsg) => { |
|||
const subjectFilter = (i) => |
|||
["selectsubject"].includes(i.customId) && |
|||
i.user.id == interaction.user.id; // <== ATTENTION! First argument...
|
|||
(subjectMsg as Message) |
|||
.awaitMessageComponent({ |
|||
filter: subjectFilter, |
|||
componentType: "SELECT_MENU", |
|||
}) |
|||
.then(async (subjectChoice) => { |
|||
const vals = subjectChoice.values; |
|||
await userConfig.findOneAndUpdate( |
|||
{ _id: interaction.user.id }, |
|||
{ subjects: vals }, |
|||
{ |
|||
upsert: true, |
|||
new: true, |
|||
} |
|||
); |
|||
const subjects = new Array<string>(); |
|||
await vals.forEach((v) => { |
|||
subjects.push( |
|||
v |
|||
.toLowerCase() |
|||
.split(" ") |
|||
.map((w) => w[0].toUpperCase() + w.substring(1)) |
|||
.join(" ") |
|||
); |
|||
}); |
|||
await interaction.editReply({ |
|||
content: `Subjects set to: ${subjects |
|||
.toString() |
|||
.split(",") |
|||
.join(", ")}`,
|
|||
components: [], |
|||
embeds: [], |
|||
}); |
|||
}); |
|||
}); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
@ -1,63 +1,75 @@ |
|||
import { SlashCommandBuilder } from '@discordjs/builders'; |
|||
import { CommandInteraction, MessageEmbed } from 'discord.js'; |
|||
|
|||
import log from '../helpers/log'; |
|||
import userScore from '../models/userScore'; |
|||
|
|||
export const data = new SlashCommandBuilder() |
|||
.setName('top') |
|||
.setDescription('Lists top ten scores across servers and in the current server'); |
|||
|
|||
export async function execute(interaction: CommandInteraction) { |
|||
await interaction.deferReply(); |
|||
|
|||
userScore |
|||
.find({}) |
|||
.sort({ score: -1 }) // Sort by descending order
|
|||
.exec(async (err, obj) => { |
|||
if (err) { |
|||
log({ logger: 'top', content: `Getting top players failed: ${err}`, level: 'error' }); |
|||
console.log(err); |
|||
} |
|||
|
|||
if (obj.length < 10) { |
|||
// Need at least 10 scores for top 10
|
|||
return interaction.followUp( |
|||
`There are only ${obj.length} users, we need at least 10!`, |
|||
); |
|||
} |
|||
|
|||
const embeds: MessageEmbed[] = []; |
|||
let lbMessageContent = ''; |
|||
|
|||
for (let i = 0; i < 10; i++) { |
|||
lbMessageContent += `${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 MessageEmbed() |
|||
.setTitle('Top Ten!') |
|||
.setDescription(lbMessageContent) |
|||
.setColor('#ffffff'); |
|||
|
|||
embeds.push(leaderboardEmbed); |
|||
|
|||
let sMessageContent = ''; |
|||
const members = await interaction.guild?.members.fetch(); |
|||
|
|||
const serverLeaderBoardArray = await obj.filter(o => members?.some(m => m.user.id === o.authorID)); |
|||
if (serverLeaderBoardArray.length > 10) { |
|||
for (let i = 0; i < 10; i++) { |
|||
sMessageContent += `${i + 1}: <@${serverLeaderBoardArray[i].authorID}>: ${serverLeaderBoardArray[i].score}\n`; |
|||
} |
|||
|
|||
const sLeaderboardEmbed = new MessageEmbed() |
|||
.setTitle(`Top Ten in ${interaction.guild?.name}!`) |
|||
.setDescription(sMessageContent) |
|||
.setColor('#ffffff'); |
|||
|
|||
embeds.push(sLeaderboardEmbed); |
|||
} |
|||
|
|||
interaction.followUp({ embeds: embeds }); |
|||
}); |
|||
} |
|||
import { SlashCommandBuilder } from "@discordjs/builders"; |
|||
import { CommandInteraction, MessageEmbed } from "discord.js"; |
|||
|
|||
import log from "../helpers/log"; |
|||
import userScore from "../models/userScore"; |
|||
|
|||
export const data = new SlashCommandBuilder() |
|||
.setName("top") |
|||
.setDescription( |
|||
"Lists top ten scores across servers and in the current server" |
|||
); |
|||
|
|||
export async function execute(interaction: CommandInteraction) { |
|||
await interaction.deferReply(); |
|||
|
|||
userScore |
|||
.find({}) |
|||
.sort({ score: -1 }) // Sort by descending order
|
|||
.exec(async (err, obj) => { |
|||
if (err) { |
|||
log({ |
|||
logger: "top", |
|||
content: `Getting top players failed: ${err}`, |
|||
level: "error", |
|||
}); |
|||
console.log(err); |
|||
} |
|||
|
|||
if (obj.length < 10) { |
|||
// Need at least 10 scores for top 10
|
|||
return interaction.followUp( |
|||
`There are only ${obj.length} users, we need at least 10!` |
|||
); |
|||
} |
|||
|
|||
const embeds: MessageEmbed[] = []; |
|||
let lbMessageContent = ""; |
|||
|
|||
for (let i = 0; i < 10; i++) { |
|||
lbMessageContent += `${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 MessageEmbed() |
|||
.setTitle("Top Ten!") |
|||
.setDescription(lbMessageContent) |
|||
.setColor("#ffffff"); |
|||
|
|||
embeds.push(leaderboardEmbed); |
|||
|
|||
let sMessageContent = ""; |
|||
const members = await interaction.guild?.members.fetch(); |
|||
|
|||
const serverLeaderBoardArray = await obj.filter((o) => |
|||
members?.some((m) => m.user.id === o.authorID) |
|||
); |
|||
if (serverLeaderBoardArray.length > 10) { |
|||
for (let i = 0; i < 10; i++) { |
|||
sMessageContent += `${i + 1}: <@${ |
|||
serverLeaderBoardArray[i].authorID |
|||
}>: ${serverLeaderBoardArray[i].score}\n`;
|
|||
} |
|||
|
|||
const sLeaderboardEmbed = new MessageEmbed() |
|||
.setTitle(`Top Ten in ${interaction.guild?.name}!`) |
|||
.setDescription(sMessageContent) |
|||
.setColor("#ffffff"); |
|||
|
|||
embeds.push(sLeaderboardEmbed); |
|||
} |
|||
|
|||
interaction.followUp({ embeds: embeds }); |
|||
}); |
|||
} |
|||
|
@ -1,259 +1,322 @@ |
|||
import { SlashCommandBuilder } from '@discordjs/builders'; |
|||
import { MessageEmbed, MessageActionRow, MessageButton, CommandInteraction, Message } from 'discord.js'; |
|||
|
|||
import { decode } from 'html-entities'; |
|||
import axios from 'axios'; |
|||
|
|||
import userScore from '../models/userScore'; |
|||
import userConfig from '../models/userConfig'; |
|||
|
|||
import log from '../helpers/log.js'; |
|||
import { updateScore } from '../helpers/db.js'; |
|||
|
|||
export const data = new SlashCommandBuilder() |
|||
.setName('train') |
|||
.setDescription('Sends a training question to be answered') |
|||
.addStringOption(option => { |
|||
option |
|||
.setName('subject') |
|||
.setDescription('Optional subject to be used as a filter') |
|||
.setRequired(false) |
|||
.addChoices( |
|||
{ name: 'astro', value: 'astro' }, |
|||
{ name: 'bio', value: 'bio' }, |
|||
{ name: 'chem', value: 'chem' }, |
|||
{ name: 'ess', value: 'ess' }, |
|||
{ name: 'phys', value: 'phys' }, |
|||
{ name: 'math', value: 'math' }, |
|||
{ name: 'energy', value: 'energy' }, |
|||
) |
|||
.setRequired(false); |
|||
return option; |
|||
}); |
|||
|
|||
export async function execute(interaction: CommandInteraction) { |
|||
await interaction.deferReply(); |
|||
|
|||
const subject = interaction.options.get('subject') ? interaction.options.get('subject')?.value : null; |
|||
const authorId = interaction.user.id; |
|||
let score: number; |
|||
userScore |
|||
.findOne({ authorID: authorId }) |
|||
.lean() |
|||
.then((obj: { score: number; }, err: unknown) => { |
|||
if (!obj) { |
|||
score = 0; |
|||
const firstTimeEmbed = new MessageEmbed() |
|||
.setAuthor({ |
|||
name: interaction.client.user?.tag ? interaction.client.user?.tag : '', |
|||
iconURL: interaction.client.user?.displayAvatarURL(), |
|||
}) |
|||
.setDescription('Hey! It seems like it\'s your first time using AwesomeSciBo. Here\'s some information regarding the bot if you need it (for issues, contributions, etc.):') |
|||
.addField('Creator', '<@745063586422063214> [@abheekd#3602]') |
|||
.addField('GitHub', '[Link](https://github.com/ADawesomeguy/AwesomeSciBo) (a star couldn\'t hurt...)') |
|||
.setColor('#ffffff') |
|||
.setTimestamp(); |
|||
interaction.user.send({ embeds: [firstTimeEmbed] }) |
|||
.catch(err => log({ logger: 'train', content: `${err}`, level: 'error' })); |
|||
} |
|||
else if (obj) { |
|||
score = obj.score; |
|||
} |
|||
else { |
|||
log({ logger: 'train', content: `Getting user score failed: ${err}`, level: 'error' }); |
|||
} |
|||
}); |
|||
|
|||
let categoryArray: string[] = []; |
|||
const allCategories = ['BIOLOGY', 'PHYSICS', 'CHEMISTRY', 'EARTH AND SPACE', 'ASTRONOMY', 'MATH']; |
|||
const configCategories = await userConfig.findById(interaction.user.id); |
|||
|
|||
switch (subject) { |
|||
case null: |
|||
categoryArray = (configCategories ? (configCategories.subjects || allCategories) : allCategories); |
|||
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.followUp({ |
|||
embeds: [new MessageEmbed() |
|||
.setDescription('<:red_x:816791117671825409> Not a valid subject!') |
|||
.setColor('#ffffff')], |
|||
}); |
|||
return; |
|||
} |
|||
|
|||
axios |
|||
.post('https://scibowldb.com/api/questions/random', { categories: categoryArray }) |
|||
.then((res) => { |
|||
const questionData = res.data.question; |
|||
const tossupQuestion = questionData.tossup_question; |
|||
const tossupAnswer = questionData.tossup_answer; |
|||
const tossupFormat = questionData.tossup_format; |
|||
let answers = tossupAnswer.split(' (ACCEPT: '); |
|||
if (answers.length > 1) { |
|||
answers[1] = answers[1].slice(0, answers[1].length - 1); // If there are multiple elements, it means there was an 'accept' and therefore a trailing ')' which should be removed
|
|||
answers = [answers[0], ...answers[1].split(new RegExp(' OR ', 'i'))]; // Use the first element plus the last element split by 'OR' case insensitive
|
|||
} |
|||
interaction.followUp({ content: decode(tossupQuestion), fetchReply: true }) |
|||
.then(q => { |
|||
const questionMessage = q as Message; |
|||
const sourceButton = new MessageActionRow() |
|||
.addComponents( |
|||
new MessageButton() |
|||
.setURL(questionData.uri) |
|||
.setLabel('Source') |
|||
.setStyle('LINK'), |
|||
); |
|||
switch (tossupFormat) { |
|||
case 'Short Answer': { |
|||
// eslint-disable-next-line no-case-declarations
|
|||
const messageFilter = m => m.author.id === interaction.user.id || m.author.id === interaction.client.user?.id; |
|||
interaction.channel?.awaitMessages({ |
|||
filter: messageFilter, |
|||
max: 1, |
|||
}) |
|||
.then(collected => { |
|||
const answerMsg = collected.first(); |
|||
|
|||
if (answerMsg?.author.id === interaction.client.user?.id) return; |
|||
|
|||
let predicted = ''; |
|||
if (answerMsg?.content.toLowerCase() === tossupAnswer.toLowerCase() || answers.includes(answerMsg?.content.toUpperCase())) { |
|||
predicted = 'correct'; |
|||
} |
|||
else { |
|||
predicted = 'incorrect'; |
|||
} |
|||
|
|||
if (predicted === 'correct') { |
|||
updateScore(true, score, authorId).then((msgToReply) => |
|||
answerMsg?.reply(msgToReply), |
|||
); |
|||
} |
|||
else { |
|||
const overrideEmbed = new MessageEmbed() |
|||
.setAuthor({ |
|||
name: answerMsg?.author.tag ? answerMsg.author.tag : '', |
|||
iconURL: answerMsg?.author.displayAvatarURL(), |
|||
}) |
|||
.addField('Correct answer', `\`${tossupAnswer}\``) |
|||
.setDescription('It seems your answer was incorrect. Please react with <:override:955265585086857236> to override your answer if you think you got it right.') |
|||
.setColor('#ffffff') |
|||
.setTimestamp(); |
|||
const overrideButton = new MessageActionRow() |
|||
.addComponents( |
|||
new MessageButton() |
|||
.setCustomId('override') |
|||
.setEmoji('<:override:955265585086857236>') |
|||
.setStyle('SECONDARY'), |
|||
); |
|||
answerMsg?.channel.send({ |
|||
embeds: [overrideEmbed], |
|||
components: [overrideButton], |
|||
}) |
|||
.then(overrideMsg => { |
|||
const overrideFilter = i => { |
|||
return ( |
|||
['override'].includes(i.customId) && |
|||
i.user.id === answerMsg.author.id |
|||
); |
|||
}; |
|||
overrideMsg |
|||
.awaitMessageComponent({ |
|||
filter: overrideFilter, |
|||
}) |
|||
.then(i => { |
|||
updateScore(true, score, authorId).then(async msgToReply => { |
|||
await i.reply(msgToReply); |
|||
overrideMsg.edit({ components: [] }); |
|||
}); |
|||
}).catch(err => log({ |
|||
logger: 'train', |
|||
content: `Failed to override score: ${err}`, |
|||
level: 'error', |
|||
})); |
|||
}).catch(err => log({ |
|||
logger: 'train', |
|||
content: `Failed to send override message: ${err}`, |
|||
level: 'error', |
|||
})); |
|||
} |
|||
interaction.editReply({ components: [sourceButton] }); |
|||
}).catch(err => log({ logger: 'train', content: `${err}`, level: 'error' })); |
|||
break; |
|||
} |
|||
case 'Multiple Choice': { |
|||
const choices = new MessageActionRow() |
|||
.addComponents( |
|||
new MessageButton() |
|||
.setCustomId('w') |
|||
.setLabel('W') |
|||
.setStyle('SECONDARY'), |
|||
new MessageButton() |
|||
.setCustomId('x') |
|||
.setLabel('X') |
|||
.setStyle('SECONDARY'), |
|||
new MessageButton() |
|||
.setCustomId('y') |
|||
.setLabel('Y') |
|||
.setStyle('SECONDARY'), |
|||
new MessageButton() |
|||
.setCustomId('z') |
|||
.setLabel('Z') |
|||
.setStyle('SECONDARY'), |
|||
); |
|||
interaction.editReply({ components: [choices] }); |
|||
const mcFilter = i => ['w', 'x', 'y', 'z'].includes(i.customId) && i.user.id === interaction.user.id; |
|||
questionMessage.awaitMessageComponent({ filter: mcFilter }) |
|||
.then(mcChoice => { |
|||
if (tossupAnswer.charAt(0).toLowerCase() === mcChoice.customId) { |
|||
updateScore(true, score, authorId).then((msgToReply) => |
|||
mcChoice.reply(msgToReply), |
|||
); |
|||
} |
|||
else { |
|||
const incorrectEmbed = new MessageEmbed() |
|||
.setAuthor({ |
|||
name: interaction.user.tag, |
|||
iconURL: interaction.user.displayAvatarURL(), |
|||
}) |
|||
.addField('Correct answer', `\`${tossupAnswer}\``) |
|||
.setDescription(`It seems your answer ${mcChoice.customId.toUpperCase()} was incorrect.`) |
|||
.setColor('#ffffff') |
|||
.setTimestamp(); |
|||
mcChoice.reply({ embeds: [incorrectEmbed] }); |
|||
} |
|||
interaction.editReply({ components: [sourceButton] }); |
|||
}); |
|||
break; |
|||
} |
|||
} |
|||
}).catch(err => log({ logger: 'train', content: `${err}`, level: 'error' })); |
|||
}).catch(err => log({ logger: 'train', content: `${err}`, level: 'error' })); |
|||
} |
|||
import { SlashCommandBuilder } from "@discordjs/builders"; |
|||
import { |
|||
MessageEmbed, |
|||
MessageActionRow, |
|||
MessageButton, |
|||
CommandInteraction, |
|||
Message, |
|||
} from "discord.js"; |
|||
|
|||
import { decode } from "html-entities"; |
|||
import axios from "axios"; |
|||
|
|||
import userScore from "../models/userScore"; |
|||
import userConfig from "../models/userConfig"; |
|||
|
|||
import log from "../helpers/log.js"; |
|||
import { updateScore } from "../helpers/db.js"; |
|||
|
|||
export const data = new SlashCommandBuilder() |
|||
.setName("train") |
|||
.setDescription("Sends a training question to be answered") |
|||
.addStringOption((option) => { |
|||
option |
|||
.setName("subject") |
|||
.setDescription("Optional subject to be used as a filter") |
|||
.setRequired(false) |
|||
.addChoices( |
|||
{ name: "astro", value: "astro" }, |
|||
{ name: "bio", value: "bio" }, |
|||
{ name: "chem", value: "chem" }, |
|||
{ name: "ess", value: "ess" }, |
|||
{ name: "phys", value: "phys" }, |
|||
{ name: "math", value: "math" }, |
|||
{ name: "energy", value: "energy" } |
|||
) |
|||
.setRequired(false); |
|||
return option; |
|||
}); |
|||
|
|||
export async function execute(interaction: CommandInteraction) { |
|||
await interaction.deferReply(); |
|||
|
|||
const subject = interaction.options.get("subject") |
|||
? interaction.options.get("subject")?.value |
|||
: null; |
|||
const authorId = interaction.user.id; |
|||
let score: number; |
|||
userScore |
|||
.findOne({ authorID: authorId }) |
|||
.lean() |
|||
.then((obj: { score: number }, err: unknown) => { |
|||
if (!obj) { |
|||
score = 0; |
|||
const firstTimeEmbed = new MessageEmbed() |
|||
.setAuthor({ |
|||
name: interaction.client.user?.tag |
|||
? interaction.client.user?.tag |
|||
: "", |
|||
iconURL: interaction.client.user?.displayAvatarURL(), |
|||
}) |
|||
.setDescription( |
|||
"Hey! It seems like it's your first time using AwesomeSciBo. Here's some information regarding the bot if you need it (for issues, contributions, etc.):" |
|||
) |
|||
.addField("Creator", "<@745063586422063214> [@abheekd#3602]") |
|||
.addField( |
|||
"GitHub", |
|||
"[Link](https://github.com/ADawesomeguy/AwesomeSciBo) (a star couldn't hurt...)" |
|||
) |
|||
.setColor("#ffffff") |
|||
.setTimestamp(); |
|||
interaction.user |
|||
.send({ embeds: [firstTimeEmbed] }) |
|||
.catch((err) => |
|||
log({ logger: "train", content: `${err}`, level: "error" }) |
|||
); |
|||
} else if (obj) { |
|||
score = obj.score; |
|||
} else { |
|||
log({ |
|||
logger: "train", |
|||
content: `Getting user score failed: ${err}`, |
|||
level: "error", |
|||
}); |
|||
} |
|||
}); |
|||
|
|||
let categoryArray: string[] = []; |
|||
const allCategories = [ |
|||
"BIOLOGY", |
|||
"PHYSICS", |
|||
"CHEMISTRY", |
|||
"EARTH AND SPACE", |
|||
"ASTRONOMY", |
|||
"MATH", |
|||
]; |
|||
const configCategories = await userConfig.findById(interaction.user.id); |
|||
|
|||
switch (subject) { |
|||
case null: |
|||
categoryArray = configCategories |
|||
? configCategories.subjects || allCategories |
|||
: allCategories; |
|||
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.followUp({ |
|||
embeds: [ |
|||
new MessageEmbed() |
|||
.setDescription("<:red_x:816791117671825409> Not a valid subject!") |
|||
.setColor("#ffffff"), |
|||
], |
|||
}); |
|||
return; |
|||
} |
|||
|
|||
axios |
|||
.post("https://scibowldb.com/api/questions/random", { |
|||
categories: categoryArray, |
|||
}) |
|||
.then((res) => { |
|||
const questionData = res.data.question; |
|||
const tossupQuestion = questionData.tossup_question; |
|||
const tossupAnswer = questionData.tossup_answer; |
|||
const tossupFormat = questionData.tossup_format; |
|||
let answers = tossupAnswer.split(" (ACCEPT: "); |
|||
if (answers.length > 1) { |
|||
answers[1] = answers[1].slice(0, answers[1].length - 1); // If there are multiple elements, it means there was an 'accept' and therefore a trailing ')' which should be removed
|
|||
answers = [answers[0], ...answers[1].split(new RegExp(" OR ", "i"))]; // Use the first element plus the last element split by 'OR' case insensitive
|
|||
} |
|||
interaction |
|||
.followUp({ content: decode(tossupQuestion), fetchReply: true }) |
|||
.then((q) => { |
|||
const questionMessage = q as Message; |
|||
const sourceButton = new MessageActionRow().addComponents( |
|||
new MessageButton() |
|||
.setURL(questionData.uri) |
|||
.setLabel("Source") |
|||
.setStyle("LINK") |
|||
); |
|||
switch (tossupFormat) { |
|||
case "Short Answer": { |
|||
// eslint-disable-next-line no-case-declarations
|
|||
const messageFilter = (m) => |
|||
m.author.id === interaction.user.id || |
|||
m.author.id === interaction.client.user?.id; |
|||
interaction.channel |
|||
?.awaitMessages({ |
|||
filter: messageFilter, |
|||
max: 1, |
|||
}) |
|||
.then((collected) => { |
|||
const answerMsg = collected.first(); |
|||
|
|||
if (answerMsg?.author.id === interaction.client.user?.id) |
|||
return; |
|||
|
|||
let predicted = ""; |
|||
if ( |
|||
answerMsg?.content.toLowerCase() === |
|||
tossupAnswer.toLowerCase() || |
|||
answers.includes(answerMsg?.content.toUpperCase()) |
|||
) { |
|||
predicted = "correct"; |
|||
} else { |
|||
predicted = "incorrect"; |
|||
} |
|||
|
|||
if (predicted === "correct") { |
|||
updateScore(true, score, authorId).then((msgToReply) => |
|||
answerMsg?.reply(msgToReply) |
|||
); |
|||
} else { |
|||
const overrideEmbed = new MessageEmbed() |
|||
.setAuthor({ |
|||
name: answerMsg?.author.tag ? answerMsg.author.tag : "", |
|||
iconURL: answerMsg?.author.displayAvatarURL(), |
|||
}) |
|||
.addField("Correct answer", `\`${tossupAnswer}\``) |
|||
.setDescription( |
|||
"It seems your answer was incorrect. Please react with <:override:955265585086857236> to override your answer if you think you got it right." |
|||
) |
|||
.setColor("#ffffff") |
|||
.setTimestamp(); |
|||
const overrideButton = new MessageActionRow().addComponents( |
|||
new MessageButton() |
|||
.setCustomId("override") |
|||
.setEmoji("<:override:955265585086857236>") |
|||
.setStyle("SECONDARY") |
|||
); |
|||
answerMsg?.channel |
|||
.send({ |
|||
embeds: [overrideEmbed], |
|||
components: [overrideButton], |
|||
}) |
|||
.then((overrideMsg) => { |
|||
const overrideFilter = (i) => { |
|||
return ( |
|||
["override"].includes(i.customId) && |
|||
i.user.id === answerMsg.author.id |
|||
); |
|||
}; |
|||
overrideMsg |
|||
.awaitMessageComponent({ |
|||
filter: overrideFilter, |
|||
}) |
|||
.then((i) => { |
|||
updateScore(true, score, authorId).then( |
|||
async (msgToReply) => { |
|||
await i.reply(msgToReply); |
|||
overrideMsg.edit({ components: [] }); |
|||
} |
|||
); |
|||
}) |
|||
.catch((err) => |
|||
log({ |
|||
logger: "train", |
|||
content: `Failed to override score: ${err}`, |
|||
level: "error", |
|||
}) |
|||
); |
|||
}) |
|||
.catch((err) => |
|||
log({ |
|||
logger: "train", |
|||
content: `Failed to send override message: ${err}`, |
|||
level: "error", |
|||
}) |
|||
); |
|||
} |
|||
interaction.editReply({ components: [sourceButton] }); |
|||
}) |
|||
.catch((err) => |
|||
log({ logger: "train", content: `${err}`, level: "error" }) |
|||
); |
|||
break; |
|||
} |
|||
case "Multiple Choice": { |
|||
const choices = new MessageActionRow().addComponents( |
|||
new MessageButton() |
|||
.setCustomId("w") |
|||
.setLabel("W") |
|||
.setStyle("SECONDARY"), |
|||
new MessageButton() |
|||
.setCustomId("x") |
|||
.setLabel("X") |
|||
.setStyle("SECONDARY"), |
|||
new MessageButton() |
|||
.setCustomId("y") |
|||
.setLabel("Y") |
|||
.setStyle("SECONDARY"), |
|||
new MessageButton() |
|||
.setCustomId("z") |
|||
.setLabel("Z") |
|||
.setStyle("SECONDARY") |
|||
); |
|||
interaction.editReply({ components: [choices] }); |
|||
const mcFilter = (i) => |
|||
["w", "x", "y", "z"].includes(i.customId) && |
|||
i.user.id === interaction.user.id; |
|||
questionMessage |
|||
.awaitMessageComponent({ filter: mcFilter }) |
|||
.then((mcChoice) => { |
|||
if ( |
|||
tossupAnswer.charAt(0).toLowerCase() === mcChoice.customId |
|||
) { |
|||
updateScore(true, score, authorId).then((msgToReply) => |
|||
mcChoice.reply(msgToReply) |
|||
); |
|||
} else { |
|||
const incorrectEmbed = new MessageEmbed() |
|||
.setAuthor({ |
|||
name: interaction.user.tag, |
|||
iconURL: interaction.user.displayAvatarURL(), |
|||
}) |
|||
.addField("Correct answer", `\`${tossupAnswer}\``) |
|||
.setDescription( |
|||
`It seems your answer ${mcChoice.customId.toUpperCase()} was incorrect.` |
|||
) |
|||
.setColor("#ffffff") |
|||
.setTimestamp(); |
|||
mcChoice.reply({ embeds: [incorrectEmbed] }); |
|||
} |
|||
interaction.editReply({ components: [sourceButton] }); |
|||
}); |
|||
break; |
|||
} |
|||
} |
|||
}) |
|||
.catch((err) => |
|||
log({ logger: "train", content: `${err}`, level: "error" }) |
|||
); |
|||
}) |
|||
.catch((err) => |
|||
log({ logger: "train", content: `${err}`, level: "error" }) |
|||
); |
|||
} |
|||
|
@ -1,20 +1,23 @@ |
|||
#!/usr/bin/env node
|
|||
|
|||
const fs = require('node:fs'); |
|||
const {REST} = require('@discordjs/rest'); |
|||
const {Routes} = require('discord-api-types/v9'); |
|||
const {clientId, token} = require('./helpers/env'); |
|||
const { REST } = require('@discordjs/rest'); |
|||
const { Routes } = require('discord-api-types/v9'); |
|||
const { clientId, token } = require('./helpers/env'); |
|||
|
|||
const commands = []; |
|||
const commandFiles = fs.readdirSync(__dirname + '/commands').filter(file => file.endsWith('.js')); |
|||
const commandFiles = fs |
|||
.readdirSync(__dirname + '/commands') |
|||
.filter((file) => file.endsWith('.js')); |
|||
|
|||
for (const file of commandFiles) { |
|||
const command = require(`${__dirname}/commands/${file}`); |
|||
commands.push(command.data.toJSON()); |
|||
const command = require(`${__dirname}/commands/${file}`); |
|||
commands.push(command.data.toJSON()); |
|||
} |
|||
|
|||
const rest = new REST({version: '9'}).setToken(token); |
|||
const rest = new REST({ version: '9' }).setToken(token); |
|||
|
|||
rest.put(Routes.applicationCommands(clientId), {body: commands}) |
|||
.then(() => console.log('Successfully registered application commands.')) |
|||
.catch(console.error); |
|||
rest |
|||
.put(Routes.applicationCommands(clientId), { body: commands }) |
|||
.then(() => console.log('Successfully registered application commands.')) |
|||
.catch(console.error); |
|||
|
@ -1,23 +1,29 @@ |
|||
import log from '../helpers/log'; |
|||
import log from "../helpers/log"; |
|||
|
|||
export const name = 'interactionCreate'; |
|||
export const name = "interactionCreate"; |
|||
|
|||
export const once = false; |
|||
|
|||
export async function execute(interaction) { |
|||
const client = interaction.client; |
|||
const client = interaction.client; |
|||
|
|||
if (!interaction.isCommand()) return; |
|||
if (!interaction.isCommand()) return; |
|||
|
|||
const command = client.commands.get(interaction.commandName); |
|||
const command = client.commands.get(interaction.commandName); |
|||
|
|||
if (!command) return; |
|||
if (!command) return; |
|||
|
|||
try { |
|||
await command.execute(interaction); |
|||
} |
|||
catch (error) { |
|||
log({ logger: 'interaction', content: `Interaction ${interaction.commandName} failed!`, level: 'error' }); |
|||
await interaction.followUp({ content: 'There was an error while executing this command!', ephemeral: true }); |
|||
} |
|||
try { |
|||
await command.execute(interaction); |
|||
} catch (error) { |
|||
log({ |
|||
logger: "interaction", |
|||
content: `Interaction ${interaction.commandName} failed!`, |
|||
level: "error", |
|||
}); |
|||
await interaction.followUp({ |
|||
content: "There was an error while executing this command!", |
|||
ephemeral: true, |
|||
}); |
|||
} |
|||
} |
|||
|
@ -1,36 +1,36 @@ |
|||
import axios from 'axios'; |
|||
import { MessageEmbed } from 'discord.js'; |
|||
import { decode } from 'html-entities'; |
|||
import axios from "axios"; |
|||
import { MessageEmbed } from "discord.js"; |
|||
import { decode } from "html-entities"; |
|||
|
|||
import { testingGuild } from '../helpers/env'; |
|||
import { testingGuild } from "../helpers/env"; |
|||
|
|||
export const name = 'messageCreate'; |
|||
export const name = "messageCreate"; |
|||
|
|||
export const once = false; |
|||
|
|||
export async function execute(message) { |
|||
if (message.author.bot || message.guild.id != testingGuild) return; |
|||
if (message.author.bot || message.guild.id != testingGuild) return; |
|||
|
|||
if (message.content.startsWith('!q')) { |
|||
const questionId = message.content.split(' ')[1]; |
|||
axios |
|||
.get(`https://scibowldb.com/api/questions/${questionId}`) |
|||
.then((res) => { |
|||
const data = res.data.question; |
|||
const tossupQuestion = data.tossup_question; |
|||
const tossupAnswer = data.tossup_answer; |
|||
let answers = tossupAnswer.split(' (ACCEPT: '); |
|||
if (answers.length > 1) { |
|||
answers[1] = answers[1].slice(0, answers[1].length - 1); // If there are multiple elements, it means there was an 'accept' and therefore a trailing ')' which should be removed
|
|||
answers = [answers[0], ...answers[1].split(new RegExp(' OR ', 'i'))]; // Use the first element plus the last element split by 'OR' case insensitive
|
|||
} |
|||
const dataEmbed = new MessageEmbed() |
|||
.setTitle('Data') |
|||
.setDescription(`\`\`\`json\n${JSON.stringify(data, null, 2)}\`\`\``); |
|||
message.reply({ |
|||
content: decode(tossupQuestion) + `\n\nAnswers: [${answers}]`, |
|||
embeds: [dataEmbed], |
|||
}); |
|||
}); |
|||
} |
|||
} |
|||
if (message.content.startsWith("!q")) { |
|||
const questionId = message.content.split(" ")[1]; |
|||
axios |
|||
.get(`https://scibowldb.com/api/questions/${questionId}`) |
|||
.then((res) => { |
|||
const data = res.data.question; |
|||
const tossupQuestion = data.tossup_question; |
|||
const tossupAnswer = data.tossup_answer; |
|||
let answers = tossupAnswer.split(" (ACCEPT: "); |
|||
if (answers.length > 1) { |
|||
answers[1] = answers[1].slice(0, answers[1].length - 1); // If there are multiple elements, it means there was an 'accept' and therefore a trailing ')' which should be removed
|
|||
answers = [answers[0], ...answers[1].split(new RegExp(" OR ", "i"))]; // Use the first element plus the last element split by 'OR' case insensitive
|
|||
} |
|||
const dataEmbed = new MessageEmbed() |
|||
.setTitle("Data") |
|||
.setDescription(`\`\`\`json\n${JSON.stringify(data, null, 2)}\`\`\``); |
|||
message.reply({ |
|||
content: decode(tossupQuestion) + `\n\nAnswers: [${answers}]`, |
|||
embeds: [dataEmbed], |
|||
}); |
|||
}); |
|||
} |
|||
} |
|||
|
@ -1,16 +1,17 @@ |
|||
import * as db from '../helpers/db'; |
|||
import { mongoUri } from '../helpers/env'; |
|||
import log from '../helpers/log'; |
|||
import * as db from "../helpers/db"; |
|||
import { mongoUri } from "../helpers/env"; |
|||
import log from "../helpers/log"; |
|||
|
|||
export const name = 'ready'; |
|||
export const name = "ready"; |
|||
|
|||
export const once = true; |
|||
|
|||
export async function execute(client) { |
|||
await db.connect(mongoUri); |
|||
log({ logger: 'status', content: `Logged in as ${client.user.tag}!`, level: 'info' }); |
|||
client.user.setActivity( |
|||
'for /help', |
|||
{ type: 'WATCHING' }, |
|||
); |
|||
await db.connect(mongoUri); |
|||
log({ |
|||
logger: "status", |
|||
content: `Logged in as ${client.user.tag}!`, |
|||
level: "info", |
|||
}); |
|||
client.user.setActivity("for /help", { type: "WATCHING" }); |
|||
} |
|||
|
@ -1,51 +1,67 @@ |
|||
import mongoose from 'mongoose'; |
|||
|
|||
import log from '../helpers/log'; |
|||
import userScore from '../models/userScore'; |
|||
|
|||
export async function updateScore(isCorrect: boolean, score: number, authorId: string) { |
|||
if (!isCorrect) { |
|||
return `Nice try! Your score is still ${score}.`; |
|||
} |
|||
else { |
|||
// TODO: Error handling
|
|||
const doc = await userScore.findOne({ |
|||
authorID: authorId, |
|||
}); |
|||
if (!doc) { |
|||
const newUserScore = new userScore({ |
|||
authorID: authorId, |
|||
score: score + 4, |
|||
}); |
|||
newUserScore.save(err => { |
|||
if (err) { |
|||
log({ logger: 'db', content: `Error creating new user ${authorId} for scoring`, level: 'error' }); |
|||
} |
|||
else { |
|||
log({ logger: 'db', content: `Successfully created user ${authorId} for scoring`, level: 'debug' }); |
|||
} |
|||
}); |
|||
} |
|||
else { |
|||
doc.score = doc.score + 4; |
|||
doc.save(); |
|||
} |
|||
|
|||
return `Great job! Your score is now ${score + 4}.`; |
|||
} |
|||
} |
|||
|
|||
export async function connect(mongoUri) { |
|||
mongoose |
|||
.connect(mongoUri, { |
|||
useUnifiedTopology: true, |
|||
useNewUrlParser: true, |
|||
}) |
|||
.then(() => log({ logger: 'db', content: `Connected to the database at ${mongoUri}!`, level: 'info' })) |
|||
.catch(err => log({ |
|||
logger: 'db', |
|||
content: `Failed to connect to the database at ${mongoUri}: ${err}`, |
|||
level: 'fatal', |
|||
})); |
|||
} |
|||
|
|||
import mongoose from "mongoose"; |
|||
|
|||
import log from "../helpers/log"; |
|||
import userScore from "../models/userScore"; |
|||
|
|||
export async function updateScore( |
|||
isCorrect: boolean, |
|||
score: number, |
|||
authorId: string |
|||
) { |
|||
if (!isCorrect) { |
|||
return `Nice try! Your score is still ${score}.`; |
|||
} else { |
|||
// TODO: Error handling
|
|||
const doc = await userScore.findOne({ |
|||
authorID: authorId, |
|||
}); |
|||
if (!doc) { |
|||
const newUserScore = new userScore({ |
|||
authorID: authorId, |
|||
score: score + 4, |
|||
}); |
|||
newUserScore.save((err) => { |
|||
if (err) { |
|||
log({ |
|||
logger: "db", |
|||
content: `Error creating new user ${authorId} for scoring`, |
|||
level: "error", |
|||
}); |
|||
} else { |
|||
log({ |
|||
logger: "db", |
|||
content: `Successfully created user ${authorId} for scoring`, |
|||
level: "debug", |
|||
}); |
|||
} |
|||
}); |
|||
} else { |
|||
doc.score = doc.score + 4; |
|||
doc.save(); |
|||
} |
|||
|
|||
return `Great job! Your score is now ${score + 4}.`; |
|||
} |
|||
} |
|||
|
|||
export async function connect(mongoUri) { |
|||
mongoose |
|||
.connect(mongoUri, { |
|||
useUnifiedTopology: true, |
|||
useNewUrlParser: true, |
|||
}) |
|||
.then(() => |
|||
log({ |
|||
logger: "db", |
|||
content: `Connected to the database at ${mongoUri}!`, |
|||
level: "info", |
|||
}) |
|||
) |
|||
.catch((err) => |
|||
log({ |
|||
logger: "db", |
|||
content: `Failed to connect to the database at ${mongoUri}: ${err}`, |
|||
level: "fatal", |
|||
}) |
|||
); |
|||
} |
|||
|
@ -1,6 +1,7 @@ |
|||
import 'dotenv/config'; |
|||
import "dotenv/config"; |
|||
|
|||
export const clientId = process.env.CLIENT_ID || ''; |
|||
export const testingGuild = process.env.TESTING_GUILD || ''; |
|||
export const token = process.env.TOKEN || ''; |
|||
export const mongoUri = process.env.MONGO_URI = 'mongodb://mongo:27017/AWESOME'; |
|||
export const clientId = process.env.CLIENT_ID || ""; |
|||
export const testingGuild = process.env.TESTING_GUILD || ""; |
|||
export const token = process.env.TOKEN || ""; |
|||
export const mongoUri = (process.env.MONGO_URI = |
|||
"mongodb://mongo:27017/AWESOME"); |
|||
|
@ -1,29 +1,29 @@ |
|||
import log4js from 'log4js'; |
|||
import log4js from "log4js"; |
|||
|
|||
export default function(config) { |
|||
const logger = log4js.getLogger(config.logger); |
|||
logger.level = 'debug'; |
|||
switch (config.level) { |
|||
case 'trace': |
|||
logger.trace(config.content); |
|||
break; |
|||
case 'debug': |
|||
logger.debug(config.content); |
|||
break; |
|||
case 'info': |
|||
logger.info(config.content); |
|||
break; |
|||
case 'warn': |
|||
logger.warn(config.content); |
|||
break; |
|||
case 'error': |
|||
logger.error(config.content); |
|||
break; |
|||
case 'fatal': |
|||
logger.fatal(config.content); |
|||
break; |
|||
default: |
|||
logger.debug(config.content); |
|||
break; |
|||
} |
|||
} |
|||
export default function (config) { |
|||
const logger = log4js.getLogger(config.logger); |
|||
logger.level = "debug"; |
|||
switch (config.level) { |
|||
case "trace": |
|||
logger.trace(config.content); |
|||
break; |
|||
case "debug": |
|||
logger.debug(config.content); |
|||
break; |
|||
case "info": |
|||
logger.info(config.content); |
|||
break; |
|||
case "warn": |
|||
logger.warn(config.content); |
|||
break; |
|||
case "error": |
|||
logger.error(config.content); |
|||
break; |
|||
case "fatal": |
|||
logger.fatal(config.content); |
|||
break; |
|||
default: |
|||
logger.debug(config.content); |
|||
break; |
|||
} |
|||
} |
|||
|
@ -1,87 +1,113 @@ |
|||
import { CommandInteraction, Message, MessageActionRow, MessageButton, MessageEmbed } from 'discord.js'; |
|||
import { |
|||
CommandInteraction, |
|||
Message, |
|||
MessageActionRow, |
|||
MessageButton, |
|||
MessageEmbed, |
|||
} from "discord.js"; |
|||
|
|||
export async function paginateMessage(message: Message, embeds: MessageEmbed[]) { |
|||
let index = 0; |
|||
export async function paginateMessage( |
|||
message: Message, |
|||
embeds: MessageEmbed[] |
|||
) { |
|||
let index = 0; |
|||
|
|||
const row = new MessageActionRow; |
|||
row.addComponents( |
|||
new MessageButton() |
|||
.setCustomId('paginator-left') |
|||
.setEmoji('868552005977788466') |
|||
.setStyle('SECONDARY'), |
|||
new MessageButton() |
|||
.setCustomId('paginator-right') |
|||
.setEmoji('868551772887711754') |
|||
.setStyle('SECONDARY') |
|||
); |
|||
const row = new MessageActionRow(); |
|||
row.addComponents( |
|||
new MessageButton() |
|||
.setCustomId("paginator-left") |
|||
.setEmoji("868552005977788466") |
|||
.setStyle("SECONDARY"), |
|||
new MessageButton() |
|||
.setCustomId("paginator-right") |
|||
.setEmoji("868551772887711754") |
|||
.setStyle("SECONDARY") |
|||
); |
|||
|
|||
await message.reply({ content: `Page 1 of ${embeds.length}:`, embeds: [embeds[index]], components: [row] }) |
|||
.then(async paginatorMessage => { |
|||
const filter = m => m.author.id === message.author.id; |
|||
await message |
|||
.reply({ |
|||
content: `Page 1 of ${embeds.length}:`, |
|||
embeds: [embeds[index]], |
|||
components: [row], |
|||
}) |
|||
.then(async (paginatorMessage) => { |
|||
const filter = (m) => m.author.id === message.author.id; |
|||
|
|||
const paginatorCollector = paginatorMessage.createMessageComponentCollector({ |
|||
componentType: 'BUTTON', |
|||
filter: filter, |
|||
}); |
|||
const paginatorCollector = |
|||
paginatorMessage.createMessageComponentCollector({ |
|||
componentType: "BUTTON", |
|||
filter: filter, |
|||
}); |
|||
|
|||
paginatorCollector.on('collect', async i => { |
|||
switch (i.customId) { |
|||
case 'paginator-left': |
|||
index--; |
|||
if (index < 0) index = embeds.length - 1; |
|||
break; |
|||
case 'paginator-right': |
|||
index++; |
|||
if (index > embeds.length - 1) index = 0; |
|||
break; |
|||
} |
|||
paginatorMessage.edit({ content: `Page ${index + 1} of ${embeds.length}:`, embeds: [embeds[index]] }); |
|||
}); |
|||
}); |
|||
paginatorCollector.on("collect", async (i) => { |
|||
switch (i.customId) { |
|||
case "paginator-left": |
|||
index--; |
|||
if (index < 0) index = embeds.length - 1; |
|||
break; |
|||
case "paginator-right": |
|||
index++; |
|||
if (index > embeds.length - 1) index = 0; |
|||
break; |
|||
} |
|||
paginatorMessage.edit({ |
|||
content: `Page ${index + 1} of ${embeds.length}:`, |
|||
embeds: [embeds[index]], |
|||
}); |
|||
}); |
|||
}); |
|||
} |
|||
|
|||
export async function paginateInteraction(interaction: CommandInteraction, embeds: MessageEmbed[]) { |
|||
let index = 0; |
|||
export async function paginateInteraction( |
|||
interaction: CommandInteraction, |
|||
embeds: MessageEmbed[] |
|||
) { |
|||
let index = 0; |
|||
|
|||
const row = new MessageActionRow; |
|||
row.addComponents( |
|||
new MessageButton() |
|||
.setCustomId('paginator-left') |
|||
.setEmoji('868552005977788466') |
|||
.setStyle('SECONDARY'), |
|||
new MessageButton() |
|||
.setCustomId('paginator-right') |
|||
.setEmoji('868551772887711754') |
|||
.setStyle('SECONDARY') |
|||
); |
|||
const row = new MessageActionRow(); |
|||
row.addComponents( |
|||
new MessageButton() |
|||
.setCustomId("paginator-left") |
|||
.setEmoji("868552005977788466") |
|||
.setStyle("SECONDARY"), |
|||
new MessageButton() |
|||
.setCustomId("paginator-right") |
|||
.setEmoji("868551772887711754") |
|||
.setStyle("SECONDARY") |
|||
); |
|||
|
|||
await interaction.followUp({ |
|||
content: `Page 1 of ${embeds.length}:`, |
|||
embeds: [embeds[index]], |
|||
components: [row], |
|||
fetchReply: true, |
|||
}) |
|||
.then(async p => { |
|||
const paginatorMessage = p as Message; |
|||
const filter = i => i.user.id === interaction.user.id; |
|||
await interaction |
|||
.followUp({ |
|||
content: `Page 1 of ${embeds.length}:`, |
|||
embeds: [embeds[index]], |
|||
components: [row], |
|||
fetchReply: true, |
|||
}) |
|||
.then(async (p) => { |
|||
const paginatorMessage = p as Message; |
|||
const filter = (i) => i.user.id === interaction.user.id; |
|||
|
|||
const paginatorCollector = paginatorMessage.createMessageComponentCollector({ |
|||
componentType: 'BUTTON', |
|||
filter: filter, |
|||
}); |
|||
const paginatorCollector = |
|||
paginatorMessage.createMessageComponentCollector({ |
|||
componentType: "BUTTON", |
|||
filter: filter, |
|||
}); |
|||
|
|||
paginatorCollector.on('collect', async i => { |
|||
switch (i.customId) { |
|||
case 'paginator-left': |
|||
index--; |
|||
if (index < 0) index = embeds.length - 1; |
|||
break; |
|||
case 'paginator-right': |
|||
index++; |
|||
if (index > embeds.length - 1) index = 0; |
|||
break; |
|||
} |
|||
await i.update({ content: `Page ${index + 1} of ${embeds.length}:`, embeds: [embeds[index]] }); |
|||
}); |
|||
}); |
|||
} |
|||
paginatorCollector.on("collect", async (i) => { |
|||
switch (i.customId) { |
|||
case "paginator-left": |
|||
index--; |
|||
if (index < 0) index = embeds.length - 1; |
|||
break; |
|||
case "paginator-right": |
|||
index++; |
|||
if (index > embeds.length - 1) index = 0; |
|||
break; |
|||
} |
|||
await i.update({ |
|||
content: `Page ${index + 1} of ${embeds.length}:`, |
|||
embeds: [embeds[index]], |
|||
}); |
|||
}); |
|||
}); |
|||
} |
|||
|
@ -1,38 +1,54 @@ |
|||
#!/usr/bin/env node |
|||
|
|||
import fs from 'node:fs'; |
|||
import { Client, Collection, Intents } from 'discord.js'; |
|||
import { token } from './helpers/env'; |
|||
import log from './helpers/log'; |
|||
import fs from "node:fs"; |
|||
import { Client, Collection, Intents } from "discord.js"; |
|||
import { token } from "./helpers/env"; |
|||
import log from "./helpers/log"; |
|||
|
|||
const client = new Client({ |
|||
intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES, Intents.FLAGS.GUILD_MESSAGE_REACTIONS, Intents.FLAGS.GUILD_MEMBERS, Intents.FLAGS.DIRECT_MESSAGES, Intents.FLAGS.DIRECT_MESSAGE_REACTIONS], |
|||
intents: [ |
|||
Intents.FLAGS.GUILDS, |
|||
Intents.FLAGS.GUILD_MESSAGES, |
|||
Intents.FLAGS.GUILD_MESSAGE_REACTIONS, |
|||
Intents.FLAGS.GUILD_MEMBERS, |
|||
Intents.FLAGS.DIRECT_MESSAGES, |
|||
Intents.FLAGS.DIRECT_MESSAGE_REACTIONS, |
|||
], |
|||
}); |
|||
|
|||
client['commands'] = new Collection(); |
|||
client["commands"] = new Collection(); |
|||
|
|||
const commandFiles = fs.readdirSync(`${__dirname}/commands`).filter(file => file.endsWith('.js')); |
|||
const eventFiles = fs.readdirSync(`${__dirname}/events`).filter(file => file.endsWith('.js')); |
|||
const commandFiles = fs |
|||
.readdirSync(`${__dirname}/commands`) |
|||
.filter((file) => file.endsWith(".js")); |
|||
const eventFiles = fs |
|||
.readdirSync(`${__dirname}/events`) |
|||
.filter((file) => file.endsWith(".js")); |
|||
|
|||
for (const file of commandFiles) { |
|||
import(`${__dirname}/commands/${file}`) |
|||
.then(command => { |
|||
client['commands'].set(command.data.name, command); |
|||
log({ logger: 'command', content: `Registered command ${file}!`, level: 'info' }); |
|||
}); |
|||
import(`${__dirname}/commands/${file}`).then((command) => { |
|||
client["commands"].set(command.data.name, command); |
|||
log({ |
|||
logger: "command", |
|||
content: `Registered command ${file}!`, |
|||
level: "info", |
|||
}); |
|||
}); |
|||
} |
|||
|
|||
for (const file of eventFiles) { |
|||
import(`${__dirname}/events/${file}`) |
|||
.then(event => { |
|||
if (event.once) { |
|||
client.once(event.name, (...args) => event.execute(...args)); |
|||
} |
|||
else { |
|||
client.on(event.name, (...args) => event.execute(...args)); |
|||
} |
|||
log({ logger: 'event', content: `Registered event ${file}!`, level: 'info' }); |
|||
}); |
|||
import(`${__dirname}/events/${file}`).then((event) => { |
|||
if (event.once) { |
|||
client.once(event.name, (...args) => event.execute(...args)); |
|||
} else { |
|||
client.on(event.name, (...args) => event.execute(...args)); |
|||
} |
|||
log({ |
|||
logger: "event", |
|||
content: `Registered event ${file}!`, |
|||
level: "info", |
|||
}); |
|||
}); |
|||
} |
|||
|
|||
client.login(token); |
|||
|
@ -1,22 +1,22 @@ |
|||
import mongoose from 'mongoose'; |
|||
import mongoose from "mongoose"; |
|||
|
|||
const generatedRoundSchema = new mongoose.Schema({ |
|||
htmlContent: { |
|||
type: String, |
|||
required: true, |
|||
}, |
|||
requestedBy: { |
|||
type: String, |
|||
required: true, |
|||
}, |
|||
authorTag: { |
|||
type: String, |
|||
required: true, |
|||
}, |
|||
timestamp: { |
|||
type: String, |
|||
required: true, |
|||
}, |
|||
htmlContent: { |
|||
type: String, |
|||
required: true, |
|||
}, |
|||
requestedBy: { |
|||
type: String, |
|||
required: true, |
|||
}, |
|||
authorTag: { |
|||
type: String, |
|||
required: true, |
|||
}, |
|||
timestamp: { |
|||
type: String, |
|||
required: true, |
|||
}, |
|||
}); |
|||
|
|||
export default mongoose.model('GeneratedRound', generatedRoundSchema); |
|||
export default mongoose.model("GeneratedRound", generatedRoundSchema); |
|||
|
@ -1,17 +1,17 @@ |
|||
import mongoose from 'mongoose'; |
|||
import mongoose from "mongoose"; |
|||
|
|||
const userConfigSchema = new mongoose.Schema({ |
|||
_id: String, |
|||
subjects: { |
|||
type: [String], |
|||
required: true, |
|||
default: null, |
|||
}, |
|||
gradeLevels: { |
|||
type: [String], |
|||
required: true, |
|||
default: null, |
|||
}, |
|||
_id: String, |
|||
subjects: { |
|||
type: [String], |
|||
required: true, |
|||
default: null, |
|||
}, |
|||
gradeLevels: { |
|||
type: [String], |
|||
required: true, |
|||
default: null, |
|||
}, |
|||
}); |
|||
|
|||
export default mongoose.model('UserConfig', userConfigSchema); |
|||
export default mongoose.model("UserConfig", userConfigSchema); |
|||
|
@ -1,14 +1,14 @@ |
|||
import mongoose from 'mongoose'; |
|||
import mongoose from "mongoose"; |
|||
|
|||
const userScoreSchema = new mongoose.Schema({ |
|||
authorID: { |
|||
type: String, |
|||
required: true, |
|||
}, |
|||
score: { |
|||
type: Number, |
|||
required: true, |
|||
}, |
|||
authorID: { |
|||
type: String, |
|||
required: true, |
|||
}, |
|||
score: { |
|||
type: Number, |
|||
required: true, |
|||
}, |
|||
}); |
|||
|
|||
export default mongoose.model('UserScore', userScoreSchema); |
|||
export default mongoose.model("UserScore", userScoreSchema); |
|||
|
Loading…
Reference in new issue