2023-04-06 15:54:44 +07:00
"use strict" ;
2023-03-31 00:34:58 +07:00
// Require the necessary discord.js classes
2023-04-10 23:57:08 +07:00
const { Client , Events , GatewayIntentBits , REST , Routes , Collection , FLAGS , MessageMentionOptions , codeBlock , SlashCommandBuilder , blockQuote } = require ( 'discord.js' ) ;
2023-03-31 00:34:58 +07:00
const Discord = require ( 'discord.js' ) ;
const { clientId , guildId , token } = require ( './key.json' ) ;
2023-04-04 21:03:27 +07:00
let fs = require ( 'node:fs' ) ;
let path = require ( 'node:path' ) ;
2023-04-06 16:28:29 +07:00
global . madlibState = { gameChannel : undefined , storyTitle : undefined , currentStory : undefined , storyIterate : 0 , storyReplaceContent : [ ] , storyLength : undefined , numberOfStories : undefined } ;
2023-04-06 15:54:44 +07:00
//export {madlibState};
2023-04-06 16:28:29 +07:00
//Get number of stories
const madlib = require ( "./madlibs/stories.json" ) ;
global . madlibState . numberOfStories = Object . keys ( madlib . stories ) . length ;
2023-03-31 00:34:58 +07:00
// Create a new client instance
const client = new Discord . Client ( {
intents : [
GatewayIntentBits . Guilds ,
GatewayIntentBits . GuildMessages ,
GatewayIntentBits . MessageContent ,
GatewayIntentBits . GuildMembers ,
] ,
} ) ;
// When the client is ready, run this code (only once)
// We use 'c' for the event parameter to keep it separate from the already defined 'client'
client . once ( Events . ClientReady , c => {
console . log ( ` Ready! Logged in as ${ c . user . tag } ` ) ;
} ) ;
// Log in to Discord with your client's token
client . login ( token ) ;
// Retrieve commands
client . commands = new Collection ( ) ;
const commandsPath = path . join ( _ _dirname , 'commands' ) ;
2023-04-05 00:49:38 +07:00
const commandFiles = fs . readdirSync ( commandsPath ) . filter ( file => file . endsWith ( '.cjs' ) ) ;
2023-03-31 00:34:58 +07:00
for ( const file of commandFiles ) {
const filePath = path . join ( commandsPath , file ) ;
const command = require ( filePath ) ;
// Set a new item in the Collection with the key as the command name and the value as the exported module
if ( 'data' in command && 'execute' in command ) {
client . commands . set ( command . data . name , command ) ;
} else {
console . log ( ` [WARNING] The command at ${ filePath } is missing a required "data" or "execute" property. ` ) ;
}
}
client . on ( Events . InteractionCreate , async interaction => {
if ( ! interaction . isChatInputCommand ( ) ) return ;
const command = interaction . client . commands . get ( interaction . commandName ) ;
if ( ! command ) {
console . error ( ` No command matching ${ interaction . commandName } was found. ` ) ;
return ;
}
try {
2023-04-04 17:19:28 +07:00
await command . execute ( interaction , client ) ;
2023-03-31 00:34:58 +07:00
} catch ( error ) {
console . error ( error ) ;
if ( interaction . replied || interaction . deferred ) {
await interaction . followUp ( { content : 'There was an error while executing this command!' , ephemeral : true } ) ;
} else {
await interaction . reply ( { content : 'There was an error while executing this command!' , ephemeral : true } ) ;
}
}
} ) ;
// My code
var abbreviationKey = require ( "./abbreviation_key.json" ) ;
2023-04-06 15:54:44 +07:00
const { start } = require ( 'node:repl' ) ;
2023-03-31 12:10:42 +07:00
function arrayRotate ( arr , reverse , amount ) {
2023-04-06 15:54:44 +07:00
for ( let i = 0 ; i < amount ; i ++ ) {
2023-03-31 13:20:24 +07:00
if ( reverse ) arr . unshift ( arr . pop ( ) ) ;
else arr . push ( arr . shift ( ) ) ;
return arr ;
2023-03-31 12:10:42 +07:00
}
2023-03-31 00:34:58 +07:00
}
2023-03-31 12:10:42 +07:00
function matchAbbr ( abbrTarget ) {
2023-03-31 12:29:46 +07:00
console . log ( "Looking for: " + abbrTarget ) ;
2023-03-31 12:10:42 +07:00
for ( var abbr in abbreviationKey . target _phrases ) {
2023-03-31 12:46:02 +07:00
if ( abbreviationKey . target _phrases [ abbr ] == abbrTarget ) {
2023-03-31 21:39:39 +07:00
//console.log("abbrTarget: " + typeof (abbrTarget));
//console.log("abbr: " + typeof (abbr));
2023-03-31 12:10:42 +07:00
return abbr ;
} else {
2023-03-31 21:39:39 +07:00
//console.log("abbrTarget: " + typeof (abbrTarget));
//console.log("abbr: " + typeof (abbr));
2023-03-31 12:10:42 +07:00
}
}
2023-03-31 13:20:24 +07:00
return "" ;
2023-03-31 12:10:42 +07:00
}
2023-03-31 00:34:58 +07:00
2023-04-01 12:15:12 +07:00
function replyMessage ( message , correctedMessage , abbrsUsed ) {
var plural = "" ;
if ( abbrsUsed == 1 ) {
plural = "an acronym" ;
} else {
plural = abbrsUsed + " acronyms"
}
2023-04-10 23:57:08 +07:00
var replyString = "Your message contains " + plural + "! Let me fix that for you: \n" + " \|\|btw I was written by Caleb Fontenot\|\| \n \n" + blockQuote ( correctedMessage ) ;
2023-04-04 18:01:12 +07:00
var stringLength = replyString . length ;
2023-04-04 16:28:07 +07:00
if ( stringLength > 2000 ) {
2023-04-04 16:28:53 +07:00
replyString = "Sorry, I detected " + plural + ", but the resultant response was " + stringLength + " characters long, and Discord only allows a maximum of 2000."
2023-04-04 16:28:07 +07:00
}
2023-04-06 15:54:44 +07:00
message . reply ( { content : replyString , allowedMentions : { repliedUser : false } } ) ;
2023-03-31 12:10:42 +07:00
}
2023-03-31 00:34:58 +07:00
client . on ( 'messageCreate' , message => {
2023-04-06 15:54:44 +07:00
if ( global . madlibState . gameChannel == message . channel . id && message . author . id != "1091120267851485215" ) { // Pass message to madlib game handler if message was sent in the active game channel.
madlibNextMessage ( message . content , client ) ;
}
2023-04-09 22:39:21 +07:00
checkMessage ( message , false ) ;
2023-04-01 18:41:35 +07:00
} ) ;
2023-04-01 18:44:08 +07:00
client . on ( 'messageUpdate' , ( undefined , newMessage ) => {
2023-04-09 22:39:21 +07:00
checkMessage ( newMessage , false ) ;
2023-04-09 22:16:44 +07:00
2023-04-01 18:41:35 +07:00
} ) ;
2023-04-10 23:57:08 +07:00
function getMatchingPhrase ( inputString , targetCharacter ) {
const words = inputString . split ( /\s+/ ) ;
let matchingPhrase = null ;
for ( let i = 0 ; i < words . length ; i ++ ) {
const word = words [ i ] ;
if ( word . includes ( targetCharacter ) ) {
matchingPhrase = abbreviationKey . target _phrases [ word ] ;
if ( matchingPhrase ) {
break ;
}
}
}
return matchingPhrase ;
}
2023-04-09 22:39:52 +07:00
global . checkMessage = function checkMessage ( message , runFromGlobal ) {
2023-04-09 22:39:21 +07:00
if ( ! runFromGlobal ) {
checkInsult ( message ) ;
if ( message . content == "<@1091120267851485215>, what are your pronouns?" ) {
message . reply ( { content : "My pronouns are she/her ☺️" , allowedMentions : { repliedUser : false } } )
}
if ( message . author . id == "1091120267851485215" ) {
return ;
}
console . log ( ` ${ message . author . tag } in # ${ message . channel . name } sent: ${ message . content } ` ) ;
2023-04-04 19:56:47 +07:00
}
2023-04-02 15:40:04 +07:00
//console.log(message.author);
2023-04-10 23:57:08 +07:00
var matchMessageArray = message . content . toLowerCase ( ) . split ( /\W/g ) ;
// /[\‘ \’ \' ,!?\"@#$%^&*().;:|]+/
2023-03-31 12:10:42 +07:00
console . log ( matchMessageArray ) ;
2023-03-31 21:24:57 +07:00
let correctedMessage = message . content ;
let matchDetected = false ;
2023-04-05 00:49:38 +07:00
let abbrsUsed = 0 ;
2023-03-31 12:10:42 +07:00
for ( let i = 0 ; i < matchMessageArray . length ; ++ i ) {
2023-04-05 00:49:38 +07:00
let rebuildMessageArray = [ ] ;
2023-03-31 21:47:23 +07:00
//console.log("Corrected Message: " + correctedMessage);
2023-04-02 15:40:04 +07:00
2023-04-02 15:37:01 +07:00
if ( abbreviationKey . target _phrases [ matchMessageArray [ i ] ] !== undefined ) {
2023-04-04 13:05:18 +07:00
checkIfGirlfriend ( message ) ;
2023-04-09 22:51:04 +07:00
if ( ! runFromGlobal ) {
if ( checkIfExempt ( message ) ) {
return ;
}
2023-04-02 15:37:01 +07:00
}
2023-03-31 21:24:57 +07:00
matchDetected = true ;
2023-04-01 12:15:12 +07:00
abbrsUsed ++ ;
2023-03-31 12:10:42 +07:00
//Return key
2023-04-05 00:49:38 +07:00
let phrase = abbreviationKey . target _phrases [ matchMessageArray [ i ] ] ;
let abbr = matchAbbr ( phrase ) ; //abbreviationKey.target_phrases[phrase];
2023-04-01 15:37:35 +07:00
//console.log(typeof(abbr));
2023-03-31 12:10:42 +07:00
console . log ( "Found abbreviation: " + abbr ) ;
console . log ( "Phrase that matches used acronym: " + phrase ) ;
2023-03-31 12:33:50 +07:00
if ( abbr !== "" ) {
2023-04-10 23:57:08 +07:00
// let regex = new RegExp(`^(.*?)${ '\\b' + abbr + '\\b'}`, 'i');
let regex = new RegExp ( ` ^((?:.*? \n )*?.*?) ${ '\\b' + abbr + '\\b' } ` , 'i' ) ;
rebuildMessageArray = correctedMessage . split ( regex ) ;
console . log ( "rebuildMessageArray: " , rebuildMessageArray ) ;
2023-03-31 12:33:50 +07:00
} else {
message . reply ( "Detected abbreviation, but regex matching broke. Caleb is working on this..." ) ;
2023-04-04 12:59:58 +07:00
return ;
2023-03-31 12:33:50 +07:00
}
2023-04-04 12:26:22 +07:00
//https://gitea.calebfontenot.com/CCF_100/NoMoreAcronyms/issues/1
2023-04-10 23:57:08 +07:00
//Insert phrase into string
2023-03-31 12:10:42 +07:00
arrayRotate ( rebuildMessageArray , true , 1 ) ;
2023-04-03 18:01:47 +07:00
rebuildMessageArray . unshift ( "`" + phrase + "`" ) ;
2023-03-31 12:10:42 +07:00
arrayRotate ( rebuildMessageArray , true , 2 ) ;
console . log ( rebuildMessageArray ) ;
// Build into string and set to variable!
2023-04-10 23:57:08 +07:00
correctedMessage = "" // clear old message.
2023-03-31 12:10:42 +07:00
for ( let j = 0 ; j < rebuildMessageArray . length ; j ++ ) {
correctedMessage += rebuildMessageArray [ j ] ;
}
console . log ( correctedMessage ) ;
2023-04-02 15:40:04 +07:00
2023-03-31 12:10:42 +07:00
//break;
2023-03-31 00:34:58 +07:00
}
}
2023-03-31 21:24:57 +07:00
if ( matchDetected ) {
2023-04-01 12:15:12 +07:00
replyMessage ( message , correctedMessage , abbrsUsed ) ;
2023-03-31 21:24:57 +07:00
}
2023-04-02 15:40:04 +07:00
2023-04-02 18:56:10 +07:00
}
2023-04-04 13:05:18 +07:00
function checkIfGirlfriend ( message ) {
if ( message . author . id == "698360641731166238" ) {
message . react ( '☺️' ) ;
message . react ( '❤️' ) ;
}
}
2023-04-04 12:59:58 +07:00
function checkIfExempt ( message ) {
console . log ( "Has role? " + message . member . roles . cache . some ( role => role . name == "Exempt from NoMoreAcronyms" ) ) ;
if ( ! message . author . bot ) {
if ( message . member . roles . cache . some ( role => role . name == "Exempt from NoMoreAcronyms" ) ) {
if ( ! message . member . roles . cache . some ( role => role . name == "NoReactions" ) ) {
message . react ( '🇵' ) ;
message . react ( '🇴' ) ;
message . react ( '🇬' ) ;
return true ;
}
return true ;
}
}
return false ;
}
2023-04-02 18:56:10 +07:00
function checkInsult ( message ) {
2023-04-02 19:18:10 +07:00
if ( ! message . author . bot ) {
if ( ! message . member . roles . cache . some ( role => role . name == "Exempt from NoMoreAcronyms" ) ) {
if ( message . content . includes ( "bot" , "annoying" ) ) {
message . react ( '🇳' ) ;
message . react ( '🇴' ) ;
message . react ( '❌' ) ;
message . react ( '🇺' ) ;
}
2023-04-02 19:02:58 +07:00
}
2023-04-02 18:56:10 +07:00
}
2023-04-06 15:54:44 +07:00
}
// Madlib game logic
// Setup story
function startMadlib ( selectedStory ) {
// Load story
const madlib = require ( "./madlibs/stories.json" ) ;
console . log ( "Madlib story count: " + Object . keys ( madlib . stories ) . length ) ;
let storyCount = Object . keys ( madlib . stories ) . length ;
2023-04-06 18:02:20 +07:00
let storyTitle ;
console . log ( selectedStory ) ;
if ( selectedStory == 0 ) {
2023-04-06 15:54:44 +07:00
//Pick random story:
2023-04-06 18:02:20 +07:00
storyTitle = Object . keys ( madlib . stories ) [ Math . trunc ( Math . random ( ) * storyCount ) ] ;
2023-04-06 15:54:44 +07:00
} else {
2023-04-06 18:02:20 +07:00
storyTitle = Object . keys ( madlib . stories ) [ selectedStory - 1 ] ;
2023-04-06 15:54:44 +07:00
}
console . log ( "Current story: " + storyTitle ) ;
let currentStory = madlib . stories [ storyTitle ] ;
let storyLength = currentStory . match ( /<([^>]+)>/g ) . length ;
// Update global variables with states.
global . madlibState . storyTitle = storyTitle ;
global . madlibState . currentStory = currentStory ;
global . madlibState . storyLength = storyLength ;
//Print story title
const channel = client . channels . cache . get ( madlibState . gameChannel ) ;
channel . send ( "Current story: " + storyTitle ) ;
}
/ *
* This function sends a prompt for the next keyword for the madlib story .
* /
global . madlibNextPrompt = function madlibNextPrompt ( client , iteration , selectedStory ) {
console . log ( "Next prompt requested" ) ;
if ( global . madlibState . currentStory == undefined ) {
startMadlib ( selectedStory ) ;
}
let currentStory = global . madlibState . currentStory ;
//Find all <> in the string and return it.
let phrase = currentStory . match ( /(?<=<)[^>]+(?=>)/g ) ;
//remove every other element in array, so we only have the prompts
console . log ( phrase ) ;
// Send a message in the gameChannel with the next prompt.
const channel = client . channels . cache . get ( madlibState . gameChannel ) ;
2023-04-06 18:02:20 +07:00
let aAn ;
2023-04-07 10:58:19 +07:00
let vowelArray = [ "a" , "e" , "i" , "o" , "u" ] ;
aAn = "a " ;
for ( let i = 0 ; i < vowelArray . length ; ++ i ) {
2023-04-07 10:59:40 +07:00
if ( phrase [ iteration ] . toLowerCase ( ) . charAt ( 0 ) == ( vowelArray [ i ] . charAt ( 0 ) ) ) {
2023-04-07 10:58:19 +07:00
aAn = "an " ;
}
2023-04-06 18:02:20 +07:00
}
channel . send ( "Give me " + aAn + phrase [ iteration ] + ":\n(" + ( phrase . length - iteration ) + " words remain)" ) ;
2023-04-06 15:54:44 +07:00
}
/ *
* This function is executed when a player is sending a new message .
* /
global . madlibNextMessage = function madlibNextMessage ( promptAnswerString , client ) {
global . madlibState . storyIterate ++ ;
//Process message
console . log ( "Processing next message..." ) ;
console . log ( "Player responded with: \"" + promptAnswerString + "\"" ) ;
global . madlibState . storyReplaceContent . push ( "`" + promptAnswerString + "`" ) ;
console . log ( madlibState . storyReplaceContent ) ;
// Check how many times we've iterated, and if we're not done collecting content for the story, continue
if ( global . madlibState . storyIterate < global . madlibState . storyLength ) {
global . madlibNextPrompt ( client , global . madlibState . storyIterate , undefined ) ;
} else { //Story content has been obtained! Now we just need to build the story and return it.
endMadlib ( ) ;
}
}
function endMadlib ( ) {
// Build story string, send the message, and set all of the madlibState variables to their defaults.
let currentStory = global . madlibState . currentStory ;
let storyReplaceContent = global . madlibState . storyReplaceContent ;
for ( let i = 0 ; i < storyReplaceContent . length ; ++ i ) {
currentStory = currentStory . replace ( /<([^>]+)>/ , storyReplaceContent [ i ] ) ;
}
console . log ( currentStory ) ;
const channel = client . channels . cache . get ( madlibState . gameChannel ) ;
channel . send ( "Story is complete! \n" + currentStory ) ;
//Reset madlibState.
global . madlibState = { gameChannel : undefined , storyTitle : undefined , currentStory : undefined , storyIterate : 0 , storyReplaceContent : [ ] , storyLength : undefined } ;
2023-04-01 18:41:35 +07:00
}