@ -1,31 +1,37 @@
import { SlashCommandBuilder } from '@discordjs/builders' ;
import { MessageEmbed , MessageActionRow , MessageButton , CommandInteraction , Message } from 'discord.js' ;
import { SlashCommandBuilder } from "@discordjs/builders" ;
import {
MessageEmbed ,
MessageActionRow ,
MessageButton ,
CommandInteraction ,
Message ,
} from "discord.js" ;
import { decode } from 'html-entities' ;
import axios from 'axios' ;
import { decode } from "html-entities" ;
import axios from "axios" ;
import userScore from '../models/userScore' ;
import userConfig from '../models/userConfig' ;
import userScore from "../models/userScore" ;
import userConfig from "../models/userConfig" ;
import log from '../helpers/log.js' ;
import { updateScore } from '../helpers/db.js' ;
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 = > {
. setName ( "train" )
. setDescription ( "Sends a training question to be answered" )
. addStringOption ( ( option ) = > {
option
. setName ( 'subject' )
. setDescription ( 'Optional subject to be used as a filter' )
. 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' } ,
{ 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 ;
@ -34,153 +40,188 @@ export const data = new SlashCommandBuilder()
export async function execute ( interaction : CommandInteraction ) {
await interaction . deferReply ( ) ;
const subject = interaction . options . get ( 'subject' ) ? interaction . options . get ( 'subject' ) ? . value : null ;
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 ) = > {
. then ( ( obj : { score : number } , err : unknown ) = > {
if ( ! obj ) {
score = 0 ;
const firstTimeEmbed = new MessageEmbed ( )
. setAuthor ( {
name : interaction.client.user?.tag ? interaction . client . user ? . tag : '' ,
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' )
. 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 ) {
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' } ) ;
} 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 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 ) ;
categoryArray = configCategories
? configCategories . subjects || allCategories
: allCategories ;
break ;
case 'astro' :
case 'astronomy' :
categoryArray = [ 'ASTRONOMY' ] ;
case "astro" :
case "astronomy" :
categoryArray = [ "ASTRONOMY" ] ;
break ;
case 'bio' :
case 'biology' :
categoryArray = [ 'BIOLOGY' ] ;
case "bio" :
case "biology" :
categoryArray = [ "BIOLOGY" ] ;
break ;
case 'ess' :
case 'earth science' :
case 'es' :
categoryArray = [ 'EARTH SCIENCE' ] ;
case "ess" :
case "earth science" :
case "es" :
categoryArray = [ "EARTH SCIENCE" ] ;
break ;
case 'chem' :
case 'chemistry' :
categoryArray = [ 'CHEMISTRY' ] ;
case "chem" :
case "chemistry" :
categoryArray = [ "CHEMISTRY" ] ;
break ;
case 'phys' :
case 'physics' :
categoryArray = [ 'PHYSICS' ] ;
case "phys" :
case "physics" :
categoryArray = [ "PHYSICS" ] ;
break ;
case 'math' :
categoryArray = [ 'MATH' ] ;
case "math" :
categoryArray = [ "MATH" ] ;
break ;
case 'energy' :
categoryArray = [ 'ENERGY' ] ;
case "energy" :
categoryArray = [ "ENERGY" ] ;
break ;
default :
interaction . followUp ( {
embeds : [ new MessageEmbed ( )
. setDescription ( '<:red_x:816791117671825409> Not a valid subject!' )
. setColor ( '#ffffff' ) ] ,
embeds : [
new MessageEmbed ( )
. setDescription ( "<:red_x:816791117671825409> Not a valid subject!" )
. setColor ( "#ffffff" ) ,
] ,
} ) ;
return ;
}
axios
. post ( 'https://scibowldb.com/api/questions/random' , { categories : categoryArray } )
. 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: ' ) ;
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
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 = > {
interaction
. followUp ( { content : decode ( tossupQuestion ) , fetchReply : true } )
. then ( ( q ) = > {
const questionMessage = q as Message ;
const sourceButton = new MessageActionRow ( )
. addComponents (
const sourceButton = new MessageActionRow ( ) . addComponents (
new MessageButton ( )
. setURL ( questionData . uri )
. setLabel ( 'Source' )
. setStyle ( 'LINK' ) ,
. setLabel ( "Source" )
. setStyle ( "LINK" )
) ;
switch ( tossupFormat ) {
case 'Short Answer' : {
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 ( {
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 = > {
. then ( ( collected ) = > {
const answerMsg = collected . first ( ) ;
if ( answerMsg ? . author . id === interaction . client . user ? . id ) return ;
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' ;
let predicted = "" ;
if (
answerMsg ? . content . toLowerCase ( ) ===
tossupAnswer . toLowerCase ( ) ||
answers . includes ( answerMsg ? . content . toUpperCase ( ) )
) {
predicted = "correct" ;
} else {
predicted = "incorrect" ;
}
if ( predicted === 'correct' ) {
if ( predicted === "correct" ) {
updateScore ( true , score , authorId ) . then ( ( msgToReply ) = >
answerMsg ? . reply ( msgToReply ) ,
answerMsg ? . reply ( msgToReply )
) ;
}
else {
} else {
const overrideEmbed = new MessageEmbed ( )
. setAuthor ( {
name : answerMsg?.author.tag ? answerMsg . author . tag : '' ,
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' )
. 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 (
const overrideButton = new MessageActionRow ( ) . addComponents (
new MessageButton ( )
. setCustomId ( 'override' )
. setEmoji ( '<:override:955265585086857236>' )
. setStyle ( 'SECONDARY' ) ,
. setCustomId ( "override" )
. setEmoji ( "<:override:955265585086857236>" )
. setStyle ( "SECONDARY" )
) ;
answerMsg ? . channel . send ( {
answerMsg ? . channel
. send ( {
embeds : [ overrideEmbed ] ,
components : [ overrideButton ] ,
} )
. then ( overrideMsg = > {
const overrideFilter = i = > {
. then ( ( overrideMsg ) = > {
const overrideFilter = ( i ) = > {
return (
[ 'override' ] . includes ( i . customId ) &&
[ "override" ] . includes ( i . customId ) &&
i . user . id === answerMsg . author . id
) ;
} ;
@ -188,64 +229,80 @@ export async function execute(interaction: CommandInteraction) {
. awaitMessageComponent ( {
filter : overrideFilter ,
} )
. then ( i = > {
updateScore ( true , score , authorId ) . then ( async msgToReply = > {
. then ( ( i ) = > {
updateScore ( true , score , authorId ) . then (
async ( msgToReply ) = > {
await i . reply ( msgToReply ) ;
overrideMsg . edit ( { components : [ ] } ) ;
} ) ;
} ) . catch ( err = > log ( {
logger : 'train' ,
}
) ;
} )
. catch ( ( err ) = >
log ( {
logger : "train" ,
content : ` Failed to override score: ${ err } ` ,
level : 'error' ,
} ) ) ;
} ) . catch ( err = > log ( {
logger : 'train' ,
level : "error" ,
} )
) ;
} )
. catch ( ( err ) = >
log ( {
logger : "train" ,
content : ` Failed to send override message: ${ err } ` ,
level : 'error' ,
} ) ) ;
level : "error" ,
} )
) ;
}
interaction . editReply ( { components : [ sourceButton ] } ) ;
} ) . catch ( err = > log ( { logger : 'train' , content : ` ${ err } ` , level : 'error' } ) ) ;
} )
. catch ( ( err ) = >
log ( { logger : "train" , content : ` ${ err } ` , level : "error" } )
) ;
break ;
}
case 'Multiple Choice' : {
const choices = new MessageActionRow ( )
. addComponents (
case "Multiple Choice" : {
const choices = new MessageActionRow ( ) . addComponents (
new MessageButton ( )
. setCustomId ( 'w' )
. setLabel ( 'W' )
. setStyle ( 'SECONDARY' ) ,
. setCustomId ( "w" )
. setLabel ( "W" )
. setStyle ( "SECONDARY" ) ,
new MessageButton ( )
. setCustomId ( 'x' )
. setLabel ( 'X' )
. setStyle ( 'SECONDARY' ) ,
. setCustomId ( "x" )
. setLabel ( "X" )
. setStyle ( "SECONDARY" ) ,
new MessageButton ( )
. setCustomId ( 'y' )
. setLabel ( 'Y' )
. setStyle ( 'SECONDARY' ) ,
. setCustomId ( "y" )
. setLabel ( "Y" )
. setStyle ( "SECONDARY" ) ,
new MessageButton ( )
. setCustomId ( 'z' )
. setLabel ( 'Z' )
. setStyle ( 'SECONDARY' ) ,
. 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 ) {
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 ) ,
mcChoice . reply ( msgToReply )
) ;
}
else {
} 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' )
. addField ( "Correct answer" , ` \` ${ tossupAnswer } \` ` )
. setDescription (
` It seems your answer ${ mcChoice . customId . toUpperCase ( ) } was incorrect. `
)
. setColor ( "#ffffff" )
. setTimestamp ( ) ;
mcChoice . reply ( { embeds : [ incorrectEmbed ] } ) ;
}
@ -254,6 +311,12 @@ export async function execute(interaction: CommandInteraction) {
break ;
}
}
} ) . catch ( err = > log ( { logger : 'train' , content : ` ${ err } ` , level : 'error' } ) ) ;
} ) . catch ( err = > log ( { logger : 'train' , content : ` ${ err } ` , level : 'error' } ) ) ;
} )
. catch ( ( err ) = >
log ( { logger : "train" , content : ` ${ err } ` , level : "error" } )
) ;
} )
. catch ( ( err ) = >
log ( { logger : "train" , content : ` ${ err } ` , level : "error" } )
) ;
}