Initial commit

This commit is contained in:
VetheonGames 2024-02-28 13:03:31 -07:00
parent 3556ea77fd
commit 03c6ad4fac
11 changed files with 578 additions and 0 deletions

338
package-lock.json generated Normal file
View File

@ -0,0 +1,338 @@
{
"name": "speaker-bot",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "speaker-bot",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"@discordjs/builders": "^1.7.0",
"@discordjs/rest": "^2.2.0",
"discord-api-types": "^0.37.71",
"discord.js": "^14.14.1",
"dotenv": "^16.4.5",
"fast-deep-equal": "^3.1.3",
"js-yaml": "^4.1.0",
"lodash": "^4.17.21",
"lodash.snakecase": "^4.1.1",
"magic-bytes.js": "^1.8.0",
"ts-mixer": "^6.0.4",
"tslib": "^2.6.2",
"undici": "^5.27.2",
"undici-types": "^5.26.5",
"ws": "^8.14.2"
}
},
"node_modules/@discordjs/builders": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.7.0.tgz",
"integrity": "sha512-GDtbKMkg433cOZur8Dv6c25EHxduNIBsxeHrsRoIM8+AwmEZ8r0tEpckx/sHwTLwQPOF3e2JWloZh9ofCaMfAw==",
"dependencies": {
"@discordjs/formatters": "^0.3.3",
"@discordjs/util": "^1.0.2",
"@sapphire/shapeshift": "^3.9.3",
"discord-api-types": "0.37.61",
"fast-deep-equal": "^3.1.3",
"ts-mixer": "^6.0.3",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.11.0"
}
},
"node_modules/@discordjs/builders/node_modules/discord-api-types": {
"version": "0.37.61",
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.61.tgz",
"integrity": "sha512-o/dXNFfhBpYHpQFdT6FWzeO7pKc838QeeZ9d91CfVAtpr5XLK4B/zYxQbYgPdoMiTDvJfzcsLW5naXgmHGDNXw=="
},
"node_modules/@discordjs/collection": {
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.5.3.tgz",
"integrity": "sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ==",
"engines": {
"node": ">=16.11.0"
}
},
"node_modules/@discordjs/formatters": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.3.3.tgz",
"integrity": "sha512-wTcI1Q5cps1eSGhl6+6AzzZkBBlVrBdc9IUhJbijRgVjCNIIIZPgqnUj3ntFODsHrdbGU8BEG9XmDQmgEEYn3w==",
"dependencies": {
"discord-api-types": "0.37.61"
},
"engines": {
"node": ">=16.11.0"
}
},
"node_modules/@discordjs/formatters/node_modules/discord-api-types": {
"version": "0.37.61",
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.61.tgz",
"integrity": "sha512-o/dXNFfhBpYHpQFdT6FWzeO7pKc838QeeZ9d91CfVAtpr5XLK4B/zYxQbYgPdoMiTDvJfzcsLW5naXgmHGDNXw=="
},
"node_modules/@discordjs/rest": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.2.0.tgz",
"integrity": "sha512-nXm9wT8oqrYFRMEqTXQx9DUTeEtXUDMmnUKIhZn6O2EeDY9VCdwj23XCPq7fkqMPKdF7ldAfeVKyxxFdbZl59A==",
"dependencies": {
"@discordjs/collection": "^2.0.0",
"@discordjs/util": "^1.0.2",
"@sapphire/async-queue": "^1.5.0",
"@sapphire/snowflake": "^3.5.1",
"@vladfrangu/async_event_emitter": "^2.2.2",
"discord-api-types": "0.37.61",
"magic-bytes.js": "^1.5.0",
"tslib": "^2.6.2",
"undici": "5.27.2"
},
"engines": {
"node": ">=16.11.0"
}
},
"node_modules/@discordjs/rest/node_modules/@discordjs/collection": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.0.0.tgz",
"integrity": "sha512-YTWIXLrf5FsrLMycpMM9Q6vnZoR/lN2AWX23/Cuo8uOOtS8eHB2dyQaaGnaF8aZPYnttf2bkLMcXn/j6JUOi3w==",
"engines": {
"node": ">=18"
}
},
"node_modules/@discordjs/rest/node_modules/discord-api-types": {
"version": "0.37.61",
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.61.tgz",
"integrity": "sha512-o/dXNFfhBpYHpQFdT6FWzeO7pKc838QeeZ9d91CfVAtpr5XLK4B/zYxQbYgPdoMiTDvJfzcsLW5naXgmHGDNXw=="
},
"node_modules/@discordjs/util": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.0.2.tgz",
"integrity": "sha512-IRNbimrmfb75GMNEjyznqM1tkI7HrZOf14njX7tCAAUetyZM1Pr8hX/EK2lxBCOgWDRmigbp24fD1hdMfQK5lw==",
"engines": {
"node": ">=16.11.0"
}
},
"node_modules/@discordjs/ws": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.0.2.tgz",
"integrity": "sha512-+XI82Rm2hKnFwAySXEep4A7Kfoowt6weO6381jgW+wVdTpMS/56qCvoXyFRY0slcv7c/U8My2PwIB2/wEaAh7Q==",
"dependencies": {
"@discordjs/collection": "^2.0.0",
"@discordjs/rest": "^2.1.0",
"@discordjs/util": "^1.0.2",
"@sapphire/async-queue": "^1.5.0",
"@types/ws": "^8.5.9",
"@vladfrangu/async_event_emitter": "^2.2.2",
"discord-api-types": "0.37.61",
"tslib": "^2.6.2",
"ws": "^8.14.2"
},
"engines": {
"node": ">=16.11.0"
}
},
"node_modules/@discordjs/ws/node_modules/@discordjs/collection": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.0.0.tgz",
"integrity": "sha512-YTWIXLrf5FsrLMycpMM9Q6vnZoR/lN2AWX23/Cuo8uOOtS8eHB2dyQaaGnaF8aZPYnttf2bkLMcXn/j6JUOi3w==",
"engines": {
"node": ">=18"
}
},
"node_modules/@discordjs/ws/node_modules/discord-api-types": {
"version": "0.37.61",
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.61.tgz",
"integrity": "sha512-o/dXNFfhBpYHpQFdT6FWzeO7pKc838QeeZ9d91CfVAtpr5XLK4B/zYxQbYgPdoMiTDvJfzcsLW5naXgmHGDNXw=="
},
"node_modules/@fastify/busboy": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz",
"integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==",
"engines": {
"node": ">=14"
}
},
"node_modules/@sapphire/async-queue": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.2.tgz",
"integrity": "sha512-7X7FFAA4DngXUl95+hYbUF19bp1LGiffjJtu7ygrZrbdCSsdDDBaSjB7Akw0ZbOu6k0xpXyljnJ6/RZUvLfRdg==",
"engines": {
"node": ">=v14.0.0",
"npm": ">=7.0.0"
}
},
"node_modules/@sapphire/shapeshift": {
"version": "3.9.6",
"resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.9.6.tgz",
"integrity": "sha512-4+Na/fxu2SEepZRb9z0dbsVh59QtwPuBg/UVaDib3av7ZY14b14+z09z6QVn0P6Dv6eOU2NDTsjIi0mbtgP56g==",
"dependencies": {
"fast-deep-equal": "^3.1.3",
"lodash": "^4.17.21"
},
"engines": {
"node": ">=v18"
}
},
"node_modules/@sapphire/snowflake": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.5.1.tgz",
"integrity": "sha512-BxcYGzgEsdlG0dKAyOm0ehLGm2CafIrfQTZGWgkfKYbj+pNNsorZ7EotuZukc2MT70E0UbppVbtpBrqpzVzjNA==",
"engines": {
"node": ">=v14.0.0",
"npm": ">=7.0.0"
}
},
"node_modules/@types/node": {
"version": "20.11.22",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.22.tgz",
"integrity": "sha512-/G+IxWxma6V3E+pqK1tSl2Fo1kl41pK1yeCyDsgkF9WlVAme4j5ISYM2zR11bgLFJGLN5sVK40T4RJNuiZbEjA==",
"dependencies": {
"undici-types": "~5.26.4"
}
},
"node_modules/@types/ws": {
"version": "8.5.9",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.9.tgz",
"integrity": "sha512-jbdrY0a8lxfdTp/+r7Z4CkycbOFN8WX+IOchLJr3juT/xzbJ8URyTVSJ/hvNdadTgM1mnedb47n+Y31GsFnQlg==",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@vladfrangu/async_event_emitter": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/@vladfrangu/async_event_emitter/-/async_event_emitter-2.2.4.tgz",
"integrity": "sha512-ButUPz9E9cXMLgvAW8aLAKKJJsPu1dY1/l/E8xzLFuysowXygs6GBcyunK9rnGC4zTsnIc2mQo71rGw9U+Ykug==",
"engines": {
"node": ">=v14.0.0",
"npm": ">=7.0.0"
}
},
"node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
"node_modules/discord-api-types": {
"version": "0.37.71",
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.71.tgz",
"integrity": "sha512-oYDVWoiQdblr9DpwOgpi5d78dVhPcoN9YZCCqYZf2T0v9+iICs7k2bYGumoHuYMtaIitpp5aQNs+2guVkgjbOA=="
},
"node_modules/discord.js": {
"version": "14.14.1",
"resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.14.1.tgz",
"integrity": "sha512-/hUVzkIerxKHyRKopJy5xejp4MYKDPTszAnpYxzVVv4qJYf+Tkt+jnT2N29PIPschicaEEpXwF2ARrTYHYwQ5w==",
"dependencies": {
"@discordjs/builders": "^1.7.0",
"@discordjs/collection": "1.5.3",
"@discordjs/formatters": "^0.3.3",
"@discordjs/rest": "^2.1.0",
"@discordjs/util": "^1.0.2",
"@discordjs/ws": "^1.0.2",
"@sapphire/snowflake": "3.5.1",
"@types/ws": "8.5.9",
"discord-api-types": "0.37.61",
"fast-deep-equal": "3.1.3",
"lodash.snakecase": "4.1.1",
"tslib": "2.6.2",
"undici": "5.27.2",
"ws": "8.14.2"
},
"engines": {
"node": ">=16.11.0"
}
},
"node_modules/discord.js/node_modules/discord-api-types": {
"version": "0.37.61",
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.61.tgz",
"integrity": "sha512-o/dXNFfhBpYHpQFdT6FWzeO7pKc838QeeZ9d91CfVAtpr5XLK4B/zYxQbYgPdoMiTDvJfzcsLW5naXgmHGDNXw=="
},
"node_modules/dotenv": {
"version": "16.4.5",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
"integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://dotenvx.com"
}
},
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
"node_modules/js-yaml": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"dependencies": {
"argparse": "^2.0.1"
},
"bin": {
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"node_modules/lodash.snakecase": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz",
"integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw=="
},
"node_modules/magic-bytes.js": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.8.0.tgz",
"integrity": "sha512-lyWpfvNGVb5lu8YUAbER0+UMBTdR63w2mcSUlhhBTyVbxJvjgqwyAf3AZD6MprgK0uHuBoWXSDAMWLupX83o3Q=="
},
"node_modules/ts-mixer": {
"version": "6.0.4",
"resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.4.tgz",
"integrity": "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA=="
},
"node_modules/tslib": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
},
"node_modules/undici": {
"version": "5.27.2",
"resolved": "https://registry.npmjs.org/undici/-/undici-5.27.2.tgz",
"integrity": "sha512-iS857PdOEy/y3wlM3yRp+6SNQQ6xU0mmZcwRSriqk+et/cwWAtwmIGf6WkoDN2EK/AMdCO/dfXzIwi+rFMrjjQ==",
"dependencies": {
"@fastify/busboy": "^2.0.0"
},
"engines": {
"node": ">=14.0"
}
},
"node_modules/undici-types": {
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
},
"node_modules/ws": {
"version": "8.14.2",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz",
"integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
}
}
}

31
package.json Normal file
View File

@ -0,0 +1,31 @@
{
"name": "speaker-bot",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module",
"dependencies": {
"@discordjs/builders": "^1.7.0",
"@discordjs/rest": "^2.2.0",
"discord-api-types": "^0.37.71",
"discord.js": "^14.14.1",
"dotenv": "^16.4.5",
"fast-deep-equal": "^3.1.3",
"js-yaml": "^4.1.0",
"lodash": "^4.17.21",
"lodash.snakecase": "^4.1.1",
"magic-bytes.js": "^1.8.0",
"ts-mixer": "^6.0.4",
"tslib": "^2.6.2",
"undici": "^5.27.2",
"undici-types": "^5.26.5",
"ws": "^8.14.2"
},
"scripts": {
"start": "node src/index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}

33
phrases.yml Normal file
View File

@ -0,0 +1,33 @@
phrases:
- trigger: ".*(I).*(motion|proposal).*(speaker).*"
response: "A motion has been recognized. Please state your motion clearly for the house's consideration."
- trigger: ".*(point).*(order).*(speaker).*"
response: "A Point of Order has been recognized. I ask the current speaker to pause. Please state your point, member."
- trigger: ".*(request).*(speak|address).*(speaker).*"
response: "A request to speak has been acknowledged. Please wait for recognition before proceeding."
- trigger: ".*(information).*(request).*(speaker).*"
response: "A Request for Information has been noted. What information do you seek, member?"
- trigger: ".*(call).*(question).*(speaker).*"
response: "A Call to Question has been noted. We will proceed to vote on the current motion shortly."
- trigger: ".*(second).*(motion).*(speaker).*"
response: "The motion has been seconded. Discussion will now commence."
- trigger: ".*(adjourn).*(request|motion).*(speaker).*"
response: "A motion to adjourn has been recognized. Please stand by for the vote."
- trigger: ".*(roll).*(call).*(vote).*(speaker).*"
response: "A Roll Call Vote has been requested. Members will now vote on the motion in order."
- trigger: ".*(unanimous).*(consent).*(speaker).*"
response: "Unanimous Consent has been requested. Is there any objection?"
- trigger: ".*(quorum).*(call).*(speaker).*"
response: "A Quorum Call has been initiated. Members, please indicate your presence."
- trigger: ".*(point).*(privilege).*(speaker).*"
response: "A Point of Privilege is raised. Please state the nature of your privilege, member."

View File

@ -0,0 +1,42 @@
import { config } from 'dotenv';
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import { SlashCommandBuilder } from '@discordjs/builders';
import { REST } from '@discordjs/rest';
import { Routes } from 'discord-api-types/v9';
// Load environment variables from .env file
config();
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const commands = [];
const commandsPath = path.join(__dirname, 'commands');
const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js') && file !== 'deploy-commands.js');
for (const file of commandFiles) {
const filePath = path.join(commandsPath, file);
import(filePath).then((command) => {
if (command.data instanceof SlashCommandBuilder) {
commands.push(command.data.toJSON());
}
});
}
const rest = new REST({ version: '9' }).setToken(process.env.DISCORD_TOKEN);
// Due to the asynchronous nature of dynamic imports, we need to ensure all commands are loaded before proceeding
const waitForCommandsToLoad = async () => {
while (commands.length < commandFiles.length) {
await new Promise(resolve => setTimeout(resolve, 100));
}
// Once all commands are loaded, proceed to register them
rest.put(Routes.applicationGuildCommands(process.env.CLIENT_ID, process.env.GUILD_ID), { body: commands })
.then(() => console.log('Successfully registered application commands.'))
.catch(console.error);
};
waitForCommandsToLoad();

48
src/commands/help.js Normal file
View File

@ -0,0 +1,48 @@
import { SlashCommandBuilder } from '@discordjs/builders';
import { MessageEmbed } from 'discord.js';
// Define the command data using SlashCommandBuilder
export const data = new SlashCommandBuilder()
.setName('help')
.setDescription('List all my commands or info about a specific command.')
.addStringOption(option =>
option.setName('command')
.setDescription('The command to get help for')
.setRequired(false));
// The execute function now needs to be exported separately and aligned with how commands are dynamically loaded.
export async function execute(interaction) {
const commands = interaction.client.commands.cache;
if (!interaction.options.getString('command')) {
// Generate a list of all commands if no specific command is asked
const commandList = Array.from(commands.values()).map(cmd => cmd.data.name).join(', ');
const embed = new MessageEmbed()
.setTitle('Available Commands')
.setDescription(commandList)
.setColor('#0099ff')
.setFooter('Use /help [command name] to get detailed information about a specific command.');
await interaction.reply({ embeds: [embed], ephemeral: true });
} else {
// Provide detailed help for a specific command
const name = interaction.options.getString('command');
const command = commands.get(name);
if (!command) {
await interaction.reply({ content: `No information found for command: ${name}`, ephemeral: true });
return;
}
const embed = new MessageEmbed()
.setTitle(`Command: ${command.data.name}`)
.setDescription(command.data.description || 'No description available.')
.setColor('#0099ff');
// Assuming 'usage' and 'examples' are properties you might add to your command objects for detailed help
if (command.usage) embed.addField('Usage', command.usage);
if (command.examples) embed.addField('Examples', command.examples.join('\n'));
await interaction.reply({ embeds: [embed], ephemeral: true });
}
}

View File

@ -0,0 +1,27 @@
import { MessageEmbed } from 'discord.js';
import { loadPhrases } from '../utils/phrasesLoader.js';
export const name = 'listphrases'; // Ensure this matches the command name you registered with Discord.
export const description = 'Lists all phrases the bot is listening for.';
export async function execute(interaction) {
if (!interaction.isCommand() || interaction.commandName !== 'listphrases') return;
const phrases = loadPhrases();
const embed = new MessageEmbed()
.setTitle('Phrases I Listen For')
.setColor('#0099ff');
// Limiting embed size due to Discord's embed limits
const maxFields = 25;
phrases.slice(0, maxFields).forEach(({ trigger, response }) => {
embed.addField(`Trigger: ${trigger}`, `Response: ${response}`, false);
});
if (phrases.length > maxFields) {
embed.setFooter('Only showing the first 25 phrases due to embed limits.');
}
await interaction.reply({ embeds: [embed] });
}

View File

@ -0,0 +1,20 @@
import { loadPhrases } from '../utils/phrasesLoader.js';
export const name = 'messageCreate';
export function execute(message) {
if (message.author.bot) return;
checkForPhrases(message);
}
function checkForPhrases(message) {
const phrases = loadPhrases();
phrases.forEach(({ trigger, response }) => {
const regex = new RegExp(trigger, 'i');
if (regex.test(message.content)) {
message.reply(response);
}
});
}

9
src/events/ready.js Normal file
View File

@ -0,0 +1,9 @@
// events/ready.js
import { logger } from '../utils/logger.js'; // Adjust the path as necessary
export const name = 'ready';
export const once = true;
export function execute(client) {
logger(client, 'Speaker Bot is online!');
// The 'client' parameter is now passed to the execute function automatically by discord.js event handling
}

17
src/utils/logger.js Normal file
View File

@ -0,0 +1,17 @@
function sendLogToDiscord(client, message, isError = false) {
const channelId = process.env.LOG_CHANNEL_ID; // Ensure this is set in your .env
const channel = client.channels.cache.get(channelId);
if (channel) {
channel.send(`${isError ? 'ERROR: ' : ''}${message}`);
} else {
console.error('Log channel not found.');
}
}
export function logger(client, message, level = 'info') {
console.log(message); // Log to console for all messages
if (level === 'error') {
// Send only error messages to a dedicated Discord channel
sendLogToDiscord(client, message, true);
}
}

View File

@ -0,0 +1,13 @@
import fs from 'fs';
import yaml from 'js-yaml';
export function loadPhrases() {
try {
const fileContents = fs.readFileSync('./phrases.yml', 'utf8');
const config = yaml.load(fileContents);
return config.phrases;
} catch (error) {
console.error('Error loading phrases from YAML file:', error);
return [];
}
}