Updated gaydar and refactor

This commit is contained in:
Ryahn 2025-05-12 15:08:23 -05:00
parent ddd5972f72
commit bc39fe3f7a
10 changed files with 318 additions and 104 deletions

BIN
assets/gaydar.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -1,5 +1,7 @@
const fs = require("fs");
const path = require("path");
const Embed = require("../functions/embed") const Embed = require("../functions/embed")
// const { } = require('revolt.js') const Uploader = require("revolt-uploader");
module.exports = { module.exports = {
config: { config: {
@ -8,33 +10,90 @@ module.exports = {
cooldown: 5000, cooldown: 5000,
available: true, available: true,
permissions: [], permissions: [],
roles: [],
dm: false,
aliases: ['gd'] aliases: ['gd']
}, },
run: async (client, message, args, db) => { run: async (client, message, args, db) => {
try {
function randomInteger(min, max) { function randomInteger(min, max) {
min = Math.ceil(min); min = Math.ceil(min);
max = Math.floor(max); max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min; return Math.floor(Math.random() * (max - min + 1)) + min;
} }
const member = await (client.servers.get(message.server.id) || await client.servers.fetch(message.server.id))?.fetchMember(message.mentionIds[0]).then((user) => { let targetUser;
return console.log();
// Check if there's a mentioned user
if (message.mentionIds && message.mentionIds.length > 0) {
try {
const server = await client.servers.fetch(message.server.id);
const member = await server.fetchMember(message.mentionIds[0]);
if (!member || !member.id || !member.id.user) {
throw new Error("Invalid member structure");
}
// Fetch the user using the user ID from the member object
targetUser = await client.users.fetch(member.id.user);
if (!targetUser || !targetUser.username) {
throw new Error("Could not fetch user information");
}
} catch (fetchError) {
console.error("Fetch error details:", fetchError.message);
return message.reply({
embeds: [new Embed()
.setDescription("Could not find the mentioned user.")
.setColor(`#FF0000`)]
}, false);
}
} else {
// Use the command author if no user is mentioned
targetUser = message.author;
}
if (!targetUser) {
return message.reply({
embeds: [new Embed()
.setDescription("Could not determine the target user.")
.setColor(`#FF0000`)]
}, false);
}
const amount = randomInteger(1, 100);
const imagePath = path.join(__dirname, "../assets/gaydar.jpg");
// Check if file exists
if (!fs.existsSync(imagePath)) {
return message.reply({
embeds: [new Embed()
.setDescription("Error: Required image file not found.")
.setColor(`#FF0000`)]
}, false);
}
// Upload the image as an attachment
const attachment = await client.Uploader.uploadFile(imagePath, "gaydar.jpg");
// Send the message with the attachment
await message.channel.sendMessage({
content: `#### ${targetUser.username} is ${amount}% gay.`,
attachments: [attachment]
}); });
// const target = member.user.username;
// return console.log(member)
// let amount = randomInteger(1, 100);
// const embed = { } catch (error) {
// description: `#### ${target} is ${amount}% gay.`, console.log(`${Date(Date.now().toString()).slice(0, 25)}`);
// colour: "#ff8080", console.log("User: " + message.author.username + ` [${message.authorId}] ` + " | Command: gaydar | Args: " + (args?.join(" ") || "NONE"));
// image: 'https://overlord.lordainz.xyz/f/gaydar.jpg' console.log(error.message);
// }
// await message.channel.sendMessage({ content: "", embeds: [embed] }).catch(err => { return message.reply({
// console.log(`${Date(Date.now().toString()).slice(0, 25)}`); embeds: [new Embed()
// console.log("User: " + message.author.username + ` [${message.authorId}] ` + " | Command: gardar | Args: " + (args?.join(" ") || "NONE")) .setDescription("An error occurred while processing the command.")
// console.log(err.message); .setColor(`#FF0000`)]
// return; }, false);
// }); }
}, },
}; };

View File

@ -3,8 +3,6 @@ const Collector = require("../functions/messageCollector");
const EditCollector = require("../functions/messageEdit"); const EditCollector = require("../functions/messageEdit");
const CommandDB = require('../models/commands'); const CommandDB = require('../models/commands');
const { isJson } = require('../functions/randomStr'); const { isJson } = require('../functions/randomStr');
const logger = require('../functions/logger');
const audit = require('../functions/audit');
module.exports = async (client, message) => { module.exports = async (client, message) => {
// Early return checks // Early return checks

View File

@ -1,12 +1,50 @@
const { readdirSync } = require("fs") const { readdirSync } = require("fs")
const { join } = require("path")
const color = require("../functions/colorCodes") const color = require("../functions/colorCodes")
module.exports = (client) => {
const commands = readdirSync(`./commands/`).filter(d => d.endsWith('.js'));
for (let file of commands) {
let pull = require(`../commands/${file}`);
client.commands.set(pull.config.name, pull);
if (pull.config.aliases) pull.config.aliases.forEach(a => client.aliases.set(a, pull.config.name));
};
console.log(color("%", `%b[Command_Handler]%7 :: Loaded %e${client.commands.size} %7commands`)); /**
* Loads and registers all command files from the commands directory
* @param {Object} client - The Discord client instance
* @returns {Promise<void>}
*/
module.exports = async (client) => {
try {
const commandsPath = join(__dirname, "..", "commands")
const commandFiles = readdirSync(commandsPath).filter(file => file.endsWith(".js"))
let loadedCommands = 0
let failedCommands = 0
for (const file of commandFiles) {
try {
const command = require(join(commandsPath, file))
// Validate command structure
if (!command.config?.name) {
console.error(color("%", `%r[Command_Handler]%7 :: Command in ${file} is missing required config.name property`))
failedCommands++
continue
}
// Register command and aliases
client.commands.set(command.config.name, command)
if (command.config.aliases?.length) {
command.config.aliases.forEach(alias => client.aliases.set(alias, command.config.name))
}
loadedCommands++
} catch (error) {
console.error(color("%", `%r[Command_Handler]%7 :: Failed to load command ${file}: ${error.message}`))
failedCommands++
}
}
console.log(color("%", `%b[Command_Handler]%7 :: Successfully loaded %e${loadedCommands}%7 commands`))
if (failedCommands > 0) {
console.warn(color("%", `%y[Command_Handler]%7 :: Failed to load %r${failedCommands}%7 commands`))
}
} catch (error) {
console.error(color("%", `%r[Command_Handler]%7 :: Critical error: ${error.message}`))
throw error // Re-throw to handle at higher level
}
} }

View File

@ -1,11 +1,24 @@
const { connect } = require("mongoose").set('strictQuery', true); const { connect } = require("mongoose").set('strictQuery', true);
const color = require("../functions/colorCodes") const color = require("../functions/colorCodes")
const fs = require('fs');
const path = require('path');
module.exports = class DatabaseHandler { module.exports = class DatabaseHandler {
constructor(connectionString) { constructor(connectionString) {
this.cache = new Map(); this.cache = new Map();
this.guildModel = require('../models/guilds');
this.connectionString = connectionString; this.connectionString = connectionString;
this.models = {};
this.initializeModels();
}
initializeModels() {
const modelsPath = path.join(__dirname, '../models');
const modelFiles = fs.readdirSync(modelsPath).filter(file => file.endsWith('.js'));
for (const file of modelFiles) {
const modelName = path.parse(file).name;
this.models[modelName] = require(path.join(modelsPath, file));
}
} }
cacheSweeper(client) { cacheSweeper(client) {
@ -46,17 +59,17 @@ module.exports = class DatabaseHandler {
} }
async fetchGuild(guildId, createIfNotFound = false) { async fetchGuild(guildId, createIfNotFound = false) {
const fetched = await this.guildModel.findOne({ id: guildId }); const fetched = await this.models.guilds.findOne({ id: guildId });
if (fetched) return fetched; if (fetched) return fetched;
if (!fetched && createIfNotFound) { if (!fetched && createIfNotFound) {
await this.guildModel.create({ await this.models.guilds.create({
id: guildId, id: guildId,
language: 'en_EN', language: 'en_EN',
botJoined: Date.now() / 1000 | 0, botJoined: Date.now() / 1000 | 0,
}); });
return this.guildModel.findOne({ id: guildId }); return this.models.guilds.findOne({ id: guildId });
} return null; } return null;
} }
@ -78,7 +91,7 @@ module.exports = class DatabaseHandler {
async deleteGuild(guildId, onlyCache = false) { async deleteGuild(guildId, onlyCache = false) {
if (this.cache.has(guildId)) this.cache.delete(guildId); if (this.cache.has(guildId)) this.cache.delete(guildId);
return !onlyCache ? this.guildModel.deleteMany({ id: guildId }) : true; return !onlyCache ? this.models.guilds.deleteMany({ id: guildId }) : true;
} }
async updateGuild(guildId, data = {}, createIfNotFound = false) { async updateGuild(guildId, data = {}, createIfNotFound = false) {
@ -91,13 +104,13 @@ module.exports = class DatabaseHandler {
this.cache.set(guildId, data); this.cache.set(guildId, data);
return this.guildModel.updateOne({ return this.models.guilds.updateOne({
id: guildId, id: guildId,
}, data); }, data);
} return null; } return null;
} }
async getAll() { async getAll() {
return this.guildModel.find(); return this.models.guilds.find();
} }
}; };

View File

@ -1,12 +1,44 @@
const { readdirSync } = require("fs") const { readdirSync } = require("fs")
const path = require("path")
const color = require("../functions/colorCodes") const color = require("../functions/colorCodes")
module.exports = (client) => {
const events = readdirSync(`./events/`).filter(d => d.endsWith('.js'));
for (let file of events) {
let evt = require(`../events/${file}`);
client.event.set(file.split(".")[0], evt.bind(null, client));
client.on(file.split('.')[0], evt.bind(null, client));
};
console.log(color("%", `%b[Event_Handler]%7 :: Loaded %e${client.event.size} %7events`)); /**
}; * Loads and registers all event handlers for the client
* @param {Object} client - The Discord client instance
* @returns {Promise<void>}
*/
module.exports = async (client) => {
try {
const eventsPath = path.join(__dirname, "..", "events")
const eventFiles = readdirSync(eventsPath)
.filter(file => file.endsWith(".js"))
const loadedEvents = await Promise.all(
eventFiles.map(async (file) => {
try {
const eventName = path.parse(file).name
const event = require(path.join(eventsPath, file))
// Register the event
client.event.set(eventName, event.bind(null, client))
client.on(eventName, event.bind(null, client))
return eventName
} catch (error) {
console.error(color("%", `%r[Event_Handler]%7 :: Failed to load event %e${file}%7: ${error.message}`))
return null
}
})
)
const successfulEvents = loadedEvents.filter(Boolean)
console.log(color("%", `%b[Event_Handler]%7 :: Successfully loaded %e${successfulEvents.length}%7 events`))
if (successfulEvents.length < eventFiles.length) {
console.warn(color("%", `%y[Event_Handler]%7 :: %r${eventFiles.length - successfulEvents.length}%7 events failed to load`))
}
} catch (error) {
console.error(color("%", `%r[Event_Handler]%7 :: Critical error: ${error.message}`))
throw error // Re-throw to handle it in the main application
}
}

View File

@ -1,11 +1,40 @@
const { readdirSync } = require("fs") const { readdirSync } = require("fs")
const { join } = require("path")
const logger = require("../functions/logger") const logger = require("../functions/logger")
module.exports = (client) => {
const functions = readdirSync(`./functions`).filter(d => d.endsWith('.js'));
for (let file of functions) {
let evt = require(`../functions/${file}`);
client.functions.set(file.split(".")[0], evt);
};
logger.event('Function_Handler', `Loaded ${client.functions.size} functions`); /**
* Loads and registers all function modules from the functions directory
* @param {Object} client - The client instance
* @returns {Promise<void>}
*/
module.exports = async (client) => {
try {
if (!client || !client.functions) {
throw new Error('Invalid client object or missing functions collection');
}
const functionsDir = join(__dirname, '..', 'functions');
const functions = readdirSync(functionsDir)
.filter(file => file.endsWith('.js') && file !== 'logger.js');
const loadedFunctions = await Promise.all(
functions.map(async (file) => {
try {
const functionName = file.split('.')[0];
const functionModule = require(join(functionsDir, file));
client.functions.set(functionName, functionModule);
return functionName;
} catch (error) {
logger.error('Function_Handler', `Failed to load function ${file}: ${error.message}`);
return null;
}
})
);
const successfulLoads = loadedFunctions.filter(Boolean).length;
logger.event('Function_Handler', `Successfully loaded ${successfulLoads}/${functions.length} functions`);
} catch (error) {
logger.error('Function_Handler', `Failed to initialize function handler: ${error.message}`);
throw error;
}
}; };

125
index.js
View File

@ -2,57 +2,102 @@ const { Client } = require("revolt.js");
const { Collection } = require('@discordjs/collection'); const { Collection } = require('@discordjs/collection');
const { token, mongoDB, api } = require("./botconfig.json"); const { token, mongoDB, api } = require("./botconfig.json");
const logger = require('./functions/logger'); const logger = require('./functions/logger');
const checkPolls = require('./functions/checkPolls') const checkPolls = require('./functions/checkPolls');
const color = require("./functions/colorCodes"); const color = require("./functions/colorCodes");
const client = new Client({ baseURL: api });
const Uploader = require("revolt-uploader"); const Uploader = require("revolt-uploader");
const fetch = require("wumpfetch");
const TranslationHandler = require('./handlers/translation'); const TranslationHandler = require('./handlers/translation');
const DatabaseHandler = require('./handlers/database'); const DatabaseHandler = require('./handlers/database');
client.Uploader = new Uploader(client); class Bot {
client.config = require("./config"); constructor(config) {
client.translate = new TranslationHandler(); this.config = config;
client.logger = require('./functions/logger'); this.client = new Client({ baseURL: config.api });
client.botConfig = require("./botconfig.json"); this.initializeCore();
this.initializeCollections();
this.setupErrorHandling();
}
client.database = new DatabaseHandler(mongoDB); initializeCore() {
client.database.connectToDatabase(); this.client.Uploader = new Uploader(this.client);
client.database.cacheSweeper(client); this.client.config = require("./config");
client.database.guildSweeper(client); this.client.translate = new TranslationHandler();
this.client.logger = logger;
this.client.botConfig = this.config;
}
["reactions", "paginate", "timeout", "polls", "used", "messageCollector", "messageEdit"].forEach(x => client[x] = new Map()); initializeCollections() {
["aliases", "commands", "event", "functions"].forEach(x => client[x] = new Collection()); const collections = ["aliases", "commands", "event", "functions"];
["command", "event", "function"].forEach(x => require(`./handlers/${x}`)(client)); const maps = ["reactions", "paginate", "timeout", "polls", "used", "messageCollector", "messageEdit"];
client.once("ready", async () => { collections.forEach(x => this.client[x] = new Collection());
logger.success('Bot Ready', `${client.user.username} is ready`); maps.forEach(x => this.client[x] = new Map());
}
//client.database.connectToDatabase(); async initializeDatabase() {
//client.database.cacheSweeper(client); try {
//client.database.guildSweeper(client); const db = new DatabaseHandler(this.config.mongoDB);
await db.connectToDatabase();
await checkPolls(client); this.client.database = db;
this.client.models = db.models;
}); db.cacheSweeper(this.client);
db.guildSweeper(this.client);
logger.success('Database', 'Successfully connected to database');
} catch (error) {
logger.error('Database Error', error);
throw error;
}
}
process.on("unhandledRejection", (reason, p) => { setupErrorHandling() {
console.log(color("%", "%4[Error_Handling] :: Unhandled Rejection/Catch%c")); const errorTypes = {
console.log(reason); "unhandledRejection": "Unhandled Rejection/Catch",
console.log(p) "uncaughtException": "Uncaught Exception/Catch",
}); "uncaughtExceptionMonitor": "Uncaught Exception/Catch (MONITOR)"
process.on("uncaughtException", (err, origin) => { };
console.log(color("%", "%4[Error_Handling] :: Uncaught Exception/Catch%c"));
console.log(err);
console.log(origin)
});
process.on("uncaughtExceptionMonitor", (err, origin) => {
console.log(color("%", "%4[Error_Handling] :: Uncaught Exception/Catch (MONITOR)%c"));
console.log(err);
console.log(origin)
});
client.loginBot(token); Object.entries(errorTypes).forEach(([event, message]) => {
process.on(event, (error, origin) => {
logger.error('Error Handling', `${message}: ${error.message}`);
console.log(color("%", `%4[Error_Handling] :: ${message}%c`));
console.log(error);
if (origin) console.log(origin);
});
});
}
async initializeHandlers() {
try {
["command", "event", "function"].forEach(x => require(`./handlers/${x}`)(this.client));
logger.success('Handlers', 'Successfully initialized all handlers');
} catch (error) {
logger.error('Handler Error', error);
throw error;
}
}
setupEventListeners() {
this.client.once("ready", async () => {
logger.success('Bot Ready', `${this.client.user.username} is ready`);
await checkPolls(this.client);
});
}
async start() {
try {
await this.initializeDatabase();
await this.initializeHandlers();
this.setupEventListeners();
await this.client.loginBot(this.config.token);
} catch (error) {
logger.error('Startup Error', error);
process.exit(1);
}
}
}
// Start the bot
const bot = new Bot({ token, mongoDB, api });
bot.start();

10
package-lock.json generated
View File

@ -16,7 +16,7 @@
"mongoose": "^7.2.0", "mongoose": "^7.2.0",
"nanoid": "3.3.4", "nanoid": "3.3.4",
"node-fetch-commonjs": "^3.3.2", "node-fetch-commonjs": "^3.3.2",
"revolt-uploader": "^1.1.1", "revolt-uploader": "^1.1.5",
"revolt.js": "npm:revolt.js-update@^7.0.0-beta.9", "revolt.js": "npm:revolt.js-update@^7.0.0-beta.9",
"screen": "^0.2.10", "screen": "^0.2.10",
"wumpfetch": "^0.3.1" "wumpfetch": "^0.3.1"
@ -1227,10 +1227,10 @@
} }
}, },
"node_modules/revolt-uploader": { "node_modules/revolt-uploader": {
"version": "1.1.4", "version": "1.1.6",
"resolved": "https://registry.npmjs.org/revolt-uploader/-/revolt-uploader-1.1.4.tgz", "resolved": "https://registry.npmjs.org/revolt-uploader/-/revolt-uploader-1.1.6.tgz",
"integrity": "sha512-hnUCc1grg6Yq1J2q0HcsbfbWCvHIR6hPHzk3/75EjWEjP7bPYwAAVsHOwwtfdMtwMUPN9EAmBj3NvU4t+o1JJw==", "integrity": "sha512-teMUhz/QJDqx/sXJFFReur8kR/KUSl2A5dYy9hLY/KLLgpaZw+el4bV+TgFb0vPtpM4hg7mLn44gLiuBR7kD7g==",
"license": "ISC", "license": "MIT",
"dependencies": { "dependencies": {
"form-data": "^4.0.0", "form-data": "^4.0.0",
"node-fetch": "^2.6.7" "node-fetch": "^2.6.7"

View File

@ -15,7 +15,7 @@
"mongoose": "^7.2.0", "mongoose": "^7.2.0",
"nanoid": "3.3.4", "nanoid": "3.3.4",
"node-fetch-commonjs": "^3.3.2", "node-fetch-commonjs": "^3.3.2",
"revolt-uploader": "^1.1.1", "revolt-uploader": "^1.1.5",
"revolt.js": "npm:revolt.js-update@^7.0.0-beta.9", "revolt.js": "npm:revolt.js-update@^7.0.0-beta.9",
"screen": "^0.2.10", "screen": "^0.2.10",
"wumpfetch": "^0.3.1" "wumpfetch": "^0.3.1"