"use strict"; // Require the necessary discord.js classes const { Client, Events, GatewayIntentBits, REST, Routes, Collection, FLAGS, MessageMentionOptions, codeBlock, SlashCommandBuilder, blockQuote } = require('discord.js'); const Discord = require('discord.js'); const { clientId, guildId, token } = require('./key.json'); let fs = require('node:fs'); let path = require('node:path'); global.madlibState = { gameChannel: undefined, storyTitle:undefined, currentStory: undefined, storyIterate: 0, storyReplaceContent: [], storyLength: undefined, numberOfStories: undefined}; //export {madlibState}; //Get number of stories const madlib = require("./madlibs/stories.json"); global.madlibState.numberOfStories = Object.keys(madlib.stories).length; // 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'); const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.cjs')); 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 { await command.execute(interaction, client); } 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"); const { start } = require('node:repl'); function arrayRotate(arr, reverse, amount) { for (let i = 0; i < amount; i++) { if (reverse) arr.unshift(arr.pop()); else arr.push(arr.shift()); return arr; } } function matchAbbr(abbrTarget) { console.log("Looking for: " + abbrTarget); for (var abbr in abbreviationKey.target_phrases) { if (abbreviationKey.target_phrases[abbr] == abbrTarget) { //console.log("abbrTarget: " + typeof (abbrTarget)); //console.log("abbr: " + typeof (abbr)); return abbr; } else { //console.log("abbrTarget: " + typeof (abbrTarget)); //console.log("abbr: " + typeof (abbr)); } } return ""; } function replyMessage(message, correctedMessage, abbrsUsed) { var plural = ""; if (abbrsUsed == 1) { plural = "an acronym"; } else { plural = abbrsUsed + " acronyms" } var replyString = "Your message contains " + plural + "! Let me fix that for you: \n"+ " \|\|btw I was written by Caleb Fontenot\|\| \n \n" + blockQuote(correctedMessage); var stringLength = replyString.length; if (stringLength > 2000) { replyString = "Sorry, I detected " + plural + ", but the resultant response was " + stringLength + " characters long, and Discord only allows a maximum of 2000." } message.reply({ content: replyString, allowedMentions: { repliedUser: false } }); } client.on('messageCreate', message => { 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); } checkMessage(message, false); }); client.on('messageUpdate', (undefined, newMessage) => { checkMessage(newMessage, false); }); 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; } global.checkMessage = function checkMessage(message, runFromGlobal) { 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}`); } //console.log(message.author); var matchMessageArray = message.content.toLowerCase().split(/\W/g); // /[\‘\’\' ,!?\"@#$%^&*().;:|]+/ console.log(matchMessageArray); let correctedMessage = message.content; let matchDetected = false; let abbrsUsed = 0; for (let i = 0; i < matchMessageArray.length; ++i) { let rebuildMessageArray = []; //console.log("Corrected Message: " + correctedMessage); if (abbreviationKey.target_phrases[matchMessageArray[i]] !== undefined) { checkIfGirlfriend(message); if (!runFromGlobal) { if (checkIfExempt(message)) { return; } } matchDetected = true; abbrsUsed++; //Return key let phrase = abbreviationKey.target_phrases[matchMessageArray[i]]; let abbr = matchAbbr(phrase); //abbreviationKey.target_phrases[phrase]; //console.log(typeof(abbr)); console.log("Found abbreviation: " + abbr); console.log("Phrase that matches used acronym: " + phrase); if (abbr !== "") { // 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); } else { message.reply("Detected abbreviation, but regex matching broke. Caleb is working on this..."); return; } //https://gitea.calebfontenot.com/CCF_100/NoMoreAcronyms/issues/1 //Insert phrase into string arrayRotate(rebuildMessageArray, true, 1); rebuildMessageArray.unshift("`" + phrase + "`"); arrayRotate(rebuildMessageArray, true, 2); console.log(rebuildMessageArray); // Build into string and set to variable! correctedMessage = "" // clear old message. for (let j = 0; j < rebuildMessageArray.length; j++) { correctedMessage += rebuildMessageArray[j]; } console.log(correctedMessage); //break; } } if (matchDetected) { replyMessage(message, correctedMessage, abbrsUsed); } } function checkIfGirlfriend(message) { if (message.author.id == "698360641731166238") { message.react('☺️'); message.react('❤️'); } } 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; } function checkInsult(message) { 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('🇺'); } } } } // 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; let storyTitle; console.log(selectedStory); if (selectedStory == 0) { //Pick random story: storyTitle = Object.keys(madlib.stories)[Math.trunc(Math.random() * storyCount)]; } else { storyTitle = Object.keys(madlib.stories)[selectedStory - 1]; } 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); let aAn; let vowelArray = ["a", "e", "i", "o", "u"]; aAn = "a "; for (let i = 0; i < vowelArray.length; ++i) { if (phrase[iteration].toLowerCase().charAt(0) == (vowelArray[i].charAt(0))) { aAn = "an "; } } channel.send("Give me " + aAn + phrase[iteration] + ":\n(" + (phrase.length - iteration) + " words remain)"); } /* * 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}; }