const fs = require('fs'); const sqlite3 = require('sqlite3').verbose(); const request = require("request"); const config = require("./config.js"); const packageInfo = require("./package.json"); const terminal = require("terminal-kit").terminal; const apiHelper = require("./helpers/api.js"); const { queryMulti } = require("./helpers/helper.js"); const { Client, GatewayIntentBits, Partials, Collection, ActivityType, Routes, REST, EmbedBuilder } = require('discord.js'); const mysql = require('mysql'); const clientOptions = { intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMembers, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent, GatewayIntentBits.GuildPresences], partials: [Partials.Channel] }; const client = new Client(clientOptions); let databaseConnection; // Open SQLite Database databaseConnection = new sqlite3.Database(config.sqlite.dbPath, sqlite3.OPEN_READWRITE, (err) => { if (err) { console.error("Error opening database", err.message); } else { console.log("Connected to the SQLite database."); // Ensure a table exists databaseConnection.run(`CREATE TABLE IF NOT EXISTS tableName ( id INTEGER PRIMARY KEY AUTOINCREMENT, column1 TEXT, column2 TEXT )`, [], function(err) { if (err) { console.error("Error creating table", err.message); } }); } }); function handleDisconnect() { const mysqlConfig = { "port": config.mysql.port, "charset": 'utf8mb4', host: config.mysql.host, "user": config.mysql.user, "password": config.mysql.password, "database": config.mysql.database }; databaseConnection = mysql.createConnection(mysqlConfig); databaseConnection.connect(function (connectionError) { if (connectionError) { console.log("error when connecting to db:", connectionError); setTimeout(handleDisconnect, 0x7d0); } else { require("./helpers/ready.js")(databaseConnection); console.log("Connected to database!"); } }); databaseConnection.on("error", function (dbError) { console.log("db error", dbError); if (dbError.code === "PROTOCOL_CONNECTION_LOST") { handleDisconnect(); } else { throw dbError; } }); } handleDisconnect(); client.login(config.bot_token).then(() => { console.log("Successfully logged in."); checkLicense(); }).catch((error) => { console.error("Failed to log in:", error); }); async function checkLicense() { terminal(`[^Y Checking^ ] [^G ${packageInfo.description} Checking license^ ].\n`); const headers = { "Content-Type": "application/json" }; const requestData = { "license": config.licenseKey, domain: config.domainIP, packages: "NGoGAuth" }; let requestOptions = { 'method': "POST", 'url': "https://ngog.net/api/v1/licenses/public/validate", 'headers': headers, 'body': JSON.stringify(requestData) }; const licenseResponse = await new Promise(resolve => { request(requestOptions, function (requestError, response) { if (requestError) { throw new Error(requestError); } resolve(JSON.parse(response.body)); }); }); if (licenseResponse.success) { client.login(config.bot_token); terminal(`[^G AUTHORIZED^ ][^B V${packageInfo.version}^ ] [^G ${packageInfo.description} ${licenseResponse.message}^ ]\n`); } else { terminal(`[^R UNAUTHORIZED^ ] ${licenseResponse.errors}.\n\n^+Activating Bot:^-\n^K Join our support server: https://discord.gg/TB8WN3fbFM \n^-`); } } client.on('ready', () => { client.user.setStatus("Online"); client.commands = new Collection(); readCommands(); updateActivity(); terminal(`[^B INFO^ ] [^GLogged in as ${client.user.tag}^ ]\n`); }); async function readCommands() { let commandData = []; fs.readdirSync("./slash-commands").forEach(fileName => { let commandModule = require("./slash-commands/" + fileName); client.commands.set(commandModule.data.name, commandModule); commandData.push(commandModule.data.toJSON()); }); require("./helpers/cron.js")(client); require("./helpers/interaction.js")(client, databaseConnection); require("./helpers/createTicket.js")(client, databaseConnection); const restOptions = { version: 0xa }; const requestBody = { "body": commandData }; await new REST(restOptions).setToken(config.bot_token).put(Routes.applicationGuildCommands(client.user.id, config.guild_id), requestBody); } client.on("guildMemberUpdate", async (newMember, oldMember) => { if (newMember.partial) { try { newMember.fetch(); } catch (error) { return console.error("Something went wrong: ", error); } } if (newMember.guild.id !== config.guild_id) { return; } let roleChangeLog = ''; let newRoles = Array.from(newMember.roles.cache.keys()); let oldRoles = Array.from(oldMember.roles.cache.keys()); let packageRoles = config.package_roles.map(roleData => roleData.roleID); packageRoles.push(config.api_role_id); let addedRoles = newRoles.filter(roleID => !oldRoles.includes(roleID) && packageRoles.includes(roleID)); let removedRoles = oldRoles.filter(roleID => !newRoles.includes(roleID) && packageRoles.includes(roleID)); if (removedRoles.length) { roleChangeLog = "<@&" + removedRoles.join("> <@&") + "> removed from " + newMember; } else if (addedRoles.length) { roleChangeLog = "<@&" + addedRoles.join("> <@&") + "> added to " + newMember; } if (!roleChangeLog.length) { return; } const logDetails = { 'name': "User Role Updated" }; let logEmbed = new EmbedBuilder().setTimestamp().setColor("Random").setDescription(roleChangeLog).setAuthor(logDetails); let notificationChannel = await newMember.guild.channels.fetch(config.notification_channelID)["catch"](_ => {}); if (!notificationChannel) { return; } const messageOptions = { "embeds": [logEmbed] }; return notificationChannel.send(messageOptions)["catch"](_ => {}); }); client.on("interactionCreate", async interaction => { let { options } = interaction; if (!interaction.isAutocomplete()) { return; } if (interaction.commandName == "remove-question") { let searchQuery = options.getFocused(true); let questions = await queryMulti(databaseConnection, "SELECT * FROM questions WHERE guildID='" + interaction.guildId + "'"); if (!questions) { questions = []; } let filteredQuestions = questions.filter(questionData => { return questionData.question?.["toLowerCase"]()["startsWith"](searchQuery.value.toLowerCase()); }); return interaction.respond(filteredQuestions.map(questionData => ({ 'name': questionData.question, 'value': questionData.id }))); } else { if (interaction.commandName == "remove-ticket-option" || interaction.commandName == "create-question") { let searchQuery = options.getFocused(true); let optionsData = await queryMulti(databaseConnection, "SELECT * FROM options WHERE guildID='" + interaction.guildId + "'"); if (!optionsData) { optionsData = []; } let filteredOptions = optionsData.filter(optionData => { return optionData.name?.["toLowerCase"]()["startsWith"](searchQuery.value.toLowerCase()); }); return interaction.respond(filteredOptions.map(optionData => ({ 'name': optionData.name, 'value': optionData.id }))); } } }); client.on("error", async error => { console.log("Discord error '" + error.code + "' (" + error.message + ').', error); }); async function updateActivity() { setTimeout(updateActivity, 300000); let userCount = (await apiHelper.getAllUsers()).length; let activeOrdersCount = (await apiHelper.getActiveOrders()).length; const activityDetails = { "name": "Users: " + userCount + " / Orders: " + activeOrdersCount, "type": ActivityType.Playing }; const activityOptions = { activities: [activityDetails] }; client.user.setPresence(activityOptions); }