diff --git a/src/client.ts b/src/client.ts index 1cc7b39..65c7400 100644 --- a/src/client.ts +++ b/src/client.ts @@ -7,7 +7,16 @@ import MPDB from './models/MPServer'; import axios from 'axios'; import moment from 'moment'; import tokens from './tokens.json'; -import config from './config.json'; + +let importconfig:Config +try{ + importconfig = require('./DB-Beta.config.json') + console.log('Using development config : Daggerbot Beta') +} catch(e){ + importconfig = require('./config.json') + console.log('Using production config') +} + export class TClient extends Client { invites: Map; commands: Discord.Collection; @@ -46,7 +55,7 @@ export class TClient extends Client { this.invites = new Map(); this.commands = new Discord.Collection(); this.registry = []; - this.config = config as Config; + this.config = importconfig as Config; this.tokens = tokens as Tokens; this.YTCache = { 'UCQ8k8yTDLITldfWYKDs3xFg': undefined, // Daggerwin diff --git a/src/commands/botlog.ts b/src/commands/botlog.ts deleted file mode 100644 index 8394b44..0000000 --- a/src/commands/botlog.ts +++ /dev/null @@ -1,13 +0,0 @@ -import Discord,{SlashCommandBuilder} from 'discord.js'; -import { TClient } from 'src/client'; -export default { - async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ - if (!client.config.eval.whitelist.includes(interaction.user.id)) return client.youNeedRole(interaction, 'bottech'); - (client.channels.resolve(client.config.mainServer.channels.console) as Discord.TextChannel).send({content: `Uploaded the current console dump as of `, files: ['../../.pm2/logs/Daggerbot-out-0.log', '../../.pm2/logs/Daggerbot-error-0.log']}) - await interaction.reply('It has been uploaded to dev server.') - }, - data: new SlashCommandBuilder() - .setName('botlog') - .setDescription('Retrieves the log from host and sends it to development server.') - .setDMPermission(false) -} diff --git a/src/commands/dev.ts b/src/commands/dev.ts new file mode 100644 index 0000000..4459d2a --- /dev/null +++ b/src/commands/dev.ts @@ -0,0 +1,102 @@ +import Discord,{SlashCommandBuilder} from 'discord.js'; +import { TClient } from 'src/client'; +import * as util from 'node:util'; +import {exec} from 'node:child_process'; +const removeUsername = (text: string)=>{ + let matchesLeft = true; + const array = text.split('\\'); + while (matchesLeft){ + let usersIndex = array.indexOf('Users'); + if (usersIndex<1) matchesLeft = false; + else { + let usernameIndex = usersIndex+1; + if(array[usernameIndex].length == 0) usernameIndex += 1; + array[usernameIndex] = '*'.repeat(array[usernameIndex].length); + array[usersIndex] = 'Us\u200bers'; + } + } return array.join('\\'); +}; +export default { + async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>) { + if (!client.config.eval.whitelist.includes(interaction.user.id)) return client.youNeedRole(interaction, 'bottech'); + switch (interaction.options.getSubcommand()){ + case 'eval': + if (!client.config.eval.allowed) return interaction.reply({content: 'Eval is disabled.', ephemeral: true}); + const code = interaction.options.getString('code') as string; + let output = 'error'; + let error = false; + try { + output = await eval(code); + } catch (err: any) { + error = true + const embed = new client.embed().setColor('#ff0000').setTitle('__Eval__').addFields( + {name: 'Input', value: `\`\`\`js\n${code.slice(0, 1010)}\n\`\`\``}, + {name: 'Output', value: `\`\`\`\n${err}\`\`\``} + ) + interaction.reply({embeds: [embed]}).catch(()=>(interaction.channel as Discord.TextChannel).send({embeds: [embed]})).then(errorEmbedMessage=>{ + const filter = (x:any)=>x.content === 'stack' && x.author.id === interaction.user.id + const messagecollector = (interaction.channel as Discord.TextChannel).createMessageCollector({filter, max: 1, time: 60000}); + messagecollector.on('collect', collected=>{ + collected.reply({content: `\`\`\`\n${removeUsername(err.stack)}\n\`\`\``, allowedMentions: {repliedUser: false}}); + }); + }); + } + if (error) return; + if (typeof output == 'object') { + output = 'js\n'+util.formatWithOptions({depth: 1}, '%O', output) + } else { + output = '\n' + String(output); + } + [client.tokens.token_main,client.tokens.token_beta,client.tokens.token_toast,client.tokens.token_tae].forEach((x)=>{ + const regexp = new RegExp(x as string,'g'); + output = output.replace(regexp, ':noblank: No token?'); + }) + const embed = new client.embed().setColor(client.config.embedColor).setTitle('__Eval__').addFields( + {name: 'Input', value: `\`\`\`js\n${code.slice(0,1010)}\n\`\`\``}, + {name: 'Output', value: `\`\`\`${removeUsername(output).slice(0,1016)}\n\`\`\``} + ); + interaction.reply({embeds: [embed]}).catch(()=>(interaction.channel as Discord.TextChannel).send({embeds: [embed]})); + break + case 'logs': + interaction.deferReply(); + (client.channels.resolve(client.config.mainServer.channels.console) as Discord.TextChannel).send({content: `Uploaded the current console dump as of `, files: [`${process.env.pm2_home}/logs/Daggerbot-out-0.log`, `${process.env.pm2_home}/logs/Daggerbot-error-0.log`]}).then(()=>interaction.editReply('It has been uploaded to dev server.')).catch((e:Error)=>interaction.editReply(`\`${e.message}\``)) + break + case 'restart': + client.userLevels.forceSave(); + interaction.reply(`Uptime before restarting: **${client.formatTime(client.uptime as number, 3, {commas: true, longNames: true})}**`).then(()=>exec('pm2 restart Daggerbot')) + break + case 'update': + const clarkson = await interaction.reply({content: 'Pulling from repository...', fetchReply: true}); + exec('git pull',(err:Error,stdout)=>{ + if (err){ + clarkson.edit(`\`\`\`${removeUsername(err.message)}\`\`\``) + } else if (stdout.includes('Already up to date')){ + clarkson.edit('Bot is already up to date with the repository, did you forgor to push the changes? :skull:') + } else { + setTimeout(()=>{clarkson.edit(`Uptime before restarting: **${client.formatTime(client.uptime as number, 3, {commas: true, longNames: true})}**`).then(()=>exec('pm2 restart Daggerbot'))},650) + } + }); + break + } + }, + data: new SlashCommandBuilder() + .setName('dev') + .setDescription('Developer commands') + .setDMPermission(false) + .addSubcommand((optt)=>optt + .setName('eval') + .setDescription('Execute the code to the bot') + .addStringOption((opt)=>opt + .setName('code') + .setDescription('Execute your code') + .setRequired(true))) + .addSubcommand((optt)=>optt + .setName('logs') + .setDescription('Retrieve the logs from host and sends it to dev server')) + .addSubcommand((optt)=>optt + .setName('restart') + .setDescription('Restart the bot for technical reasons')) + .addSubcommand((optt)=>optt + .setName('update') + .setDescription('Pull from repository and restart')) +} diff --git a/src/commands/eval.ts b/src/commands/eval.ts deleted file mode 100644 index a25904f..0000000 --- a/src/commands/eval.ts +++ /dev/null @@ -1,65 +0,0 @@ -import Discord,{SlashCommandBuilder} from 'discord.js'; -import { TClient } from 'src/client'; -import * as util from 'node:util'; -const removeUsername = (text: string)=>{ - let matchesLeft = true; - const array = text.split('\\'); - while (matchesLeft){ - let usersIndex = array.indexOf('Users'); - if (usersIndex<1) matchesLeft = false; - else { - let usernameIndex = usersIndex+1; - if(array[usernameIndex].length == 0) usernameIndex += 1; - array[usernameIndex] = '*'.repeat(array[usernameIndex].length); - array[usersIndex] = 'Us\u200bers'; - } - } return array.join('\\'); -}; -export default { - async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>) { - if (!client.config.eval.allowed) return interaction.reply({content: 'Eval is disabled.', ephemeral: true}); - if (!client.config.eval.whitelist.includes(interaction.user.id)) return interaction.reply({content: 'You\'re not allowed to use this command.', ephemeral: true}); - const code = interaction.options.getString('code') as string; - let output = 'error'; - let error = false; - try { - output = await eval(code); - } catch (err: any) { - error = true - const embed = new client.embed().setColor('#ff0000').setTitle('__Eval__').addFields( - {name: 'Input', value: `\`\`\`js\n${code.slice(0, 1010)}\n\`\`\``}, - {name: 'Output', value: `\`\`\`\n${err}\`\`\``} - ) - interaction.reply({embeds: [embed]}).catch(()=>(interaction.channel as Discord.TextChannel).send({embeds: [embed]})).then(errorEmbedMessage=>{ - const filter = (x:any)=>x.content === 'stack' && x.author.id === interaction.user.id - const messagecollector = (interaction.channel as Discord.TextChannel).createMessageCollector({filter, max: 1, time: 60000}); - messagecollector.on('collect', collected=>{ - collected.reply({content: `\`\`\`\n${removeUsername(err.stack)}\n\`\`\``, allowedMentions: {repliedUser: false}}); - }); - }); - } - if (error) return; - if (typeof output == 'object') { - output = 'js\n'+util.formatWithOptions({depth: 1}, '%O', output) - } else { - output = '\n' + String(output); - } - [client.tokens.token_main,client.tokens.token_beta,client.tokens.token_toast,client.tokens.token_tae].forEach((x)=>{ - const regexp = new RegExp(x as string,'g'); - output = output.replace(regexp, 'TOKEN_LEAK'); - }) - const embed = new client.embed().setColor(client.config.embedColor).setTitle('__Eval__').addFields( - {name: 'Input', value: `\`\`\`js\n${code.slice(0,1010)}\n\`\`\``}, - {name: 'Output', value: `\`\`\`${removeUsername(output).slice(0,1016)}\n\`\`\``} - ); - interaction.reply({embeds: [embed]}).catch(()=>(interaction.channel as Discord.TextChannel).send({embeds: [embed]})) - }, - data: new SlashCommandBuilder() - .setName('eval') - .setDescription('Run code for debugging purposes') - .setDMPermission(false) - .addStringOption((opt)=>opt - .setName('code') - .setDescription('Execute your code') - .setRequired(true)) -} \ No newline at end of file diff --git a/src/commands/restart.ts b/src/commands/restart.ts deleted file mode 100644 index 52178a5..0000000 --- a/src/commands/restart.ts +++ /dev/null @@ -1,13 +0,0 @@ -import Discord,{SlashCommandBuilder} from 'discord.js'; -import { TClient } from 'src/client'; -export default { - async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ - if (!client.config.eval.whitelist.includes(interaction.user.id)) return client.youNeedRole(interaction, 'bottech'); - client.userLevels.forceSave(); - interaction.reply(`Uptime before restarting: **${client.formatTime(client.uptime as number, 3, {commas: true, longNames: true})}**`).then(()=>require('node:child_process').exec('pm2 restart Daggerbot')) - }, - data: new SlashCommandBuilder() - .setName('restart') - .setDescription('Restart the bot for technical reasons') - .setDMPermission(false) -} \ No newline at end of file diff --git a/src/commands/update.ts b/src/commands/update.ts deleted file mode 100644 index 8cbef34..0000000 --- a/src/commands/update.ts +++ /dev/null @@ -1,24 +0,0 @@ -import Discord,{SlashCommandBuilder} from 'discord.js'; -import { TClient } from 'src/client'; -import { exec } from 'node:child_process'; -export default { - async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ - if (!client.config.eval.whitelist.includes(interaction.user.id)) return client.youNeedRole(interaction, 'bottech'); - const msg = await interaction.reply({content: 'Pulling from repository...', fetchReply: true}) - exec( - 'git pull',(err:Error,stdout)=>{ - if (err){ - msg.edit(`Pull failed:\n\`\`\`${err.message}\`\`\``) - } else if (stdout.includes('Already up to date')){ - msg.edit(`Pull aborted:\nUp to date with the repository`) - } else { - setTimeout(()=>{msg.edit(`Uptime before restarting: **${client.formatTime(client.uptime as number, 3, {commas: true, longNames: true})}**`).then(()=>require('node:child_process').exec('pm2 restart Daggerbot'))},1000) - } - } - ) - }, - data: new SlashCommandBuilder() - .setName('update') - .setDescription('Pull from repository and restart') - .setDMPermission(false) -} \ No newline at end of file