From a06090eca727690339ef4b8d6b2859d3ec9f69ce Mon Sep 17 00:00:00 2001 From: AnxietyisReal <96593068+AnxietyisReal@users.noreply.github.com> Date: Tue, 23 May 2023 15:14:17 +1000 Subject: [PATCH] Bot improvements --- src/MPLoop.ts | 6 +++--- src/client.ts | 10 +++++----- src/commands/ban.ts | 10 +++++----- src/commands/bannedWords.ts | 15 +++++++-------- src/commands/bonk.ts | 8 ++++---- src/commands/case.ts | 20 ++++++++++---------- src/commands/contributors.ts | 4 ++-- src/commands/dev.ts | 28 ++++++++++++++-------------- src/commands/faq.ts | 6 +++--- src/commands/kick.ts | 8 ++++---- src/commands/mp.ts | 20 ++++++++++---------- src/commands/mute.ts | 10 +++++----- src/commands/ping.ts | 4 ++-- src/commands/purge.ts | 12 +++++++----- src/commands/randomcolor.ts | 4 ++-- src/commands/rank.ts | 16 ++++++++-------- src/commands/roleinfo.ts | 6 +++--- src/commands/softban.ts | 8 ++++---- src/commands/statistics.ts | 6 +++--- src/commands/suggest.ts | 22 +++++++++++----------- src/commands/unpunish.ts | 8 ++++---- src/commands/warn.ts | 11 +++++------ src/commands/whois.ts | 12 ++++++------ src/events/guildBanAdd.ts | 4 ++-- src/events/guildBanRemove.ts | 2 +- src/events/guildMemberAdd.ts | 8 ++++---- src/events/guildMemberRemove.ts | 1 + src/events/guildMemberUpdate.ts | 6 +++--- src/events/inviteCreate.ts | 2 +- src/events/messageDelete.ts | 2 +- src/events/messageDeleteBulk.ts | 8 +++----- src/index.ts | 16 +++++++++------- 32 files changed, 152 insertions(+), 151 deletions(-) diff --git a/src/MPLoop.ts b/src/MPLoop.ts index 2a5a101..9438b42 100644 --- a/src/MPLoop.ts +++ b/src/MPLoop.ts @@ -1,6 +1,6 @@ import Discord from 'discord.js'; import TClient from './client'; -import fs from 'node:fs'; +import {writeFileSync, readFileSync} from 'node:fs'; import {FSPlayer, FSData, FSCareerSavegame} from './typings/interfaces'; export default async(client:TClient,Channel:string,Message:string,ServerName:string)=>{ @@ -112,9 +112,9 @@ export default async(client:TClient,Channel:string,Message:string,ServerName:str if (!isServerOnline){ playerLog(); - const Database:Array = JSON.parse(fs.readFileSync('src/database/MPPlayerData.json',{encoding:'utf8',flag:'r+'})); + const Database:Array = JSON.parse(readFileSync('src/database/MPPlayerData.json',{encoding:'utf8',flag:'r+'})); Database.push(DSS.data.slots?.used); - fs.writeFileSync('src/database/MPPlayerData.json', JSON.stringify(Database)); + writeFileSync('src/database/MPPlayerData.json', JSON.stringify(Database)); client.MPServerCache.players = playersOnServer } } diff --git a/src/client.ts b/src/client.ts index fbd8625..598ab7d 100644 --- a/src/client.ts +++ b/src/client.ts @@ -1,5 +1,5 @@ import Discord, {Client, WebhookClient, GatewayIntentBits, Partials} from 'discord.js'; -import fs from 'node:fs'; +import {readFileSync, readdirSync} from 'node:fs'; import {exec} from 'node:child_process'; import mongoose from 'mongoose'; import {formatTimeOpt, Tokens, Config, repeatedMessages, MPServerCache} from './typings/interfaces'; @@ -16,10 +16,10 @@ import tokens from './tokens.json' assert { type: 'json'}; let importconfig:Config try{ - importconfig = JSON.parse(fs.readFileSync('src/DB-Beta.config.json', {encoding:'utf8'})); + importconfig = JSON.parse(readFileSync('src/DB-Beta.config.json', {encoding:'utf8'})); console.log('Using development config :: Daggerbot Beta') } catch(e){ - importconfig = JSON.parse(fs.readFileSync('src/config.json', {encoding:'utf8'})) + importconfig = JSON.parse(readFileSync('src/config.json', {encoding:'utf8'})) console.log('Using production config') } @@ -101,11 +101,11 @@ export default class TClient extends Client { family: 4 }).then(()=>console.log(this.logTime(), 'Successfully connected to MongoDB')).catch(err=>{console.error(this.logTime(), `Failed to connect to MongoDB\n${err.reason}`); exec('pm2 stop Daggerbot')}) this.login(this.tokens.main); - for await (const file of fs.readdirSync('dist/events')){ + for await (const file of readdirSync('dist/events')){ const eventFile = await import(`./events/${file}`); this.on(file.replace('.js',''), async(...args)=>eventFile.default.run(this,...args)) }; - for await (const file of fs.readdirSync('dist/commands')){ + for await (const file of readdirSync('dist/commands')){ const command = await import(`./commands/${file}`); this.commands.set(command.default.data.name,{command, uses: 0}); this.registry.push(command.default.data.toJSON()) diff --git a/src/commands/ban.ts b/src/commands/ban.ts index 530b345..f0d091f 100644 --- a/src/commands/ban.ts +++ b/src/commands/ban.ts @@ -1,20 +1,20 @@ -import Discord,{SlashCommandBuilder} from 'discord.js'; +import Discord from 'discord.js'; import TClient from '../client.js'; export default { run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ client.punish(interaction, 'ban'); }, - data: new SlashCommandBuilder() + data: new Discord.SlashCommandBuilder() .setName('ban') .setDescription('Ban a member from the server') - .addUserOption(opt=>opt + .addUserOption(x=>x .setName('member') .setDescription('Which member to ban?') .setRequired(true)) - .addStringOption(opt=>opt + .addStringOption(x=>x .setName('time') .setDescription('How long the ban will be?')) - .addStringOption(opt=>opt + .addStringOption(x=>x .setName('reason') .setDescription('Reason for the ban')) } \ No newline at end of file diff --git a/src/commands/bannedWords.ts b/src/commands/bannedWords.ts index 6e3a582..b9bddec 100644 --- a/src/commands/bannedWords.ts +++ b/src/commands/bannedWords.ts @@ -1,7 +1,6 @@ -import Discord,{SlashCommandBuilder} from 'discord.js'; +import Discord from 'discord.js'; import TClient from '../client.js'; import {writeFileSync} from 'node:fs'; -import path from 'node:path'; export default { async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ if (!client.isStaff(interaction.member) && !client.config.whitelist.includes(interaction.member.id)) return client.youNeedRole(interaction, 'admin') @@ -25,23 +24,23 @@ export default { } } as any)[interaction.options.getSubcommand()](); }, - data: new SlashCommandBuilder() + data: new Discord.SlashCommandBuilder() .setName('bannedwords') .setDescription('description placeholder') - .addSubcommand(opt=>opt + .addSubcommand(x=>x .setName('view') .setDescription('View the list of currently banned words')) - .addSubcommand(opt=>opt + .addSubcommand(x=>x .setName('add') .setDescription('Add the word to the list') - .addStringOption(optt=>optt + .addStringOption(x=>x .setName('word') .setDescription('Add the specific word to automod\'s bannedWords database') .setRequired(true))) - .addSubcommand(opt=>opt + .addSubcommand(x=>x .setName('remove') .setDescription('Remove the word from the list') - .addStringOption(optt=>optt + .addStringOption(x=>x .setName('word') .setDescription('Remove the specific word from automod\'s bannedWords list') .setRequired(true))) diff --git a/src/commands/bonk.ts b/src/commands/bonk.ts index bee42cd..d4d3de5 100644 --- a/src/commands/bonk.ts +++ b/src/commands/bonk.ts @@ -1,4 +1,4 @@ -import Discord,{SlashCommandBuilder} from 'discord.js'; +import Discord from 'discord.js'; import TClient from '../client.js'; export default { async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ @@ -15,14 +15,14 @@ export default { .setFooter({text: `Bonk count for ${member.user.tag}: ${await client.bonkCount._content.findById(member.id).then(b=>b.value.toLocaleString('en-US'))}`}) ]}) }, - data: new SlashCommandBuilder() + data: new Discord.SlashCommandBuilder() .setName('bonk') .setDescription('Bonk a member') - .addUserOption(opt=>opt + .addUserOption(x=>x .setName('member') .setDescription('Which member to bonk?') .setRequired(true)) - .addStringOption(opt=>opt + .addStringOption(x=>x .setName('reason') .setDescription('Reason for the bonk')) } diff --git a/src/commands/case.ts b/src/commands/case.ts index 20a2432..73125fa 100644 --- a/src/commands/case.ts +++ b/src/commands/case.ts @@ -1,4 +1,4 @@ -import Discord,{SlashCommandBuilder} from "discord.js"; +import Discord from "discord.js"; import TClient from '../client.js'; export default { run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ @@ -43,34 +43,34 @@ export default { } } as any)[interaction.options.getSubcommand()](); }, - data: new SlashCommandBuilder() + data: new Discord.SlashCommandBuilder() .setName('case') .setDescription('Retrieve case information or user\'s punishment history') - .addSubcommand(opt=>opt + .addSubcommand(x=>x .setName('view') .setDescription('View a multiple or single case') - .addIntegerOption((optt)=>optt + .addIntegerOption(x=>x .setName('id') .setDescription('Case ID') .setRequired(true))) - .addSubcommand(opt=>opt + .addSubcommand(x=>x .setName('member') .setDescription('View member\'s punishment history') - .addUserOption(optt=>optt + .addUserOption(x=>x .setName('user') .setDescription('Which user do you want to view their punishment history?') .setRequired(true)) - .addIntegerOption(optt=>optt + .addIntegerOption(x=>x .setName('page') .setDescription('Select the page number'))) - .addSubcommand(opt=>opt + .addSubcommand(x=>x .setName('update') .setDescription('Update the case with new reason') - .addIntegerOption(optt=>optt + .addIntegerOption(x=>x .setName('id') .setDescription('Case ID to be updated') .setRequired(true)) - .addStringOption(optt=>optt + .addStringOption(x=>x .setName('reason') .setDescription('New reason for the case') .setRequired(true))) diff --git a/src/commands/contributors.ts b/src/commands/contributors.ts index e96f242..5a9977d 100644 --- a/src/commands/contributors.ts +++ b/src/commands/contributors.ts @@ -1,4 +1,4 @@ -import Discord,{SlashCommandBuilder} from 'discord.js'; +import Discord from 'discord.js'; import TClient from '../client.js'; export default { run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ @@ -7,7 +7,7 @@ export default { client.config.contribList.map(id=>{const member = interaction.guild.members.cache.get(id); return `${member?.user?.username ?? 'N/A'} <@${id}>`}).join('\n') ].join('\n'))]}) }, - data: new SlashCommandBuilder() + data: new Discord.SlashCommandBuilder() .setName('contributors') .setDescription('List of people who contributed to the bot') } \ No newline at end of file diff --git a/src/commands/dev.ts b/src/commands/dev.ts index dde63ed..f883d6c 100644 --- a/src/commands/dev.ts +++ b/src/commands/dev.ts @@ -1,4 +1,4 @@ -import Discord,{SlashCommandBuilder} from 'discord.js'; +import Discord from 'discord.js'; import {Octokit} from '@octokit/rest'; import {createTokenAuth} from '@octokit/auth-token'; import {exec} from 'node:child_process'; @@ -130,36 +130,36 @@ export default { } } as any)[interaction.options.getSubcommand()](); }, - data: new SlashCommandBuilder() + data: new Discord.SlashCommandBuilder() .setName('dev') .setDescription('Developer commands') - .addSubcommand(optt=>optt + .addSubcommand(x=>x .setName('eval') .setDescription('Execute the code to the bot') - .addStringOption((opt)=>opt + .addStringOption(x=>x .setName('code') .setDescription('Execute your code') .setRequired(true))) - .addSubcommand(optt=>optt + .addSubcommand(x=>x .setName('logs') .setDescription('Retrieve the logs from host and sends it to dev server')) - .addSubcommand(optt=>optt + .addSubcommand(x=>x .setName('restart') .setDescription('Restart the bot for technical reasons')) - .addSubcommand(optt=>optt + .addSubcommand(x=>x .setName('update') .setDescription('Pull from repository and restart')) - .addSubcommand(optt=>optt + .addSubcommand(x=>x .setName('statsgraph') .setDescription('Edit the number of data points to pull') - .addIntegerOption(hiTae=>hiTae + .addIntegerOption(x=>x .setName('number') .setDescription('Number of data points to pull') .setRequired(true))) - .addSubcommand(optt=>optt + .addSubcommand(x=>x .setName('presence') .setDescription('Update the bot\'s presence') - .addIntegerOption(hiTae=>hiTae + .addIntegerOption(x=>x .setName('type') .setDescription('Set an activity type') .addChoices( @@ -169,13 +169,13 @@ export default { {name: 'Watching', value: Discord.ActivityType.Watching}, {name: 'Competing in', value: Discord.ActivityType.Competing} )) - .addStringOption(hiAgain=>hiAgain + .addStringOption(x=>x .setName('name') .setDescription('Set a message for the activity status')) - .addStringOption(hiAgainx2=>hiAgainx2 + .addStringOption(x=>x .setName('url') .setDescription('Set an url for streaming status')) - .addStringOption(hiAgainx3=>hiAgainx3 + .addStringOption(x=>x .setName('status') .setDescription('Set a status indicator for the bot') .setChoices( diff --git a/src/commands/faq.ts b/src/commands/faq.ts index b5c8245..c9aa261 100644 --- a/src/commands/faq.ts +++ b/src/commands/faq.ts @@ -1,4 +1,4 @@ -import Discord,{SlashCommandBuilder} from 'discord.js'; +import Discord from 'discord.js'; import TClient from '../client.js'; export default { run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ @@ -12,10 +12,10 @@ export default { fsDevConsole: ()=>interaction.reply({embeds: [new client.embed().setColor(client.config.embedColor).setTitle('Enabling the development console').setDescription('Head over to `game.xml` in `Documents/My Games/FarmingSimulator2022` and find the section that mentions `false` inside development section, change it to `true` then you are good to go!\nFYI: The keybind to open console is \``\u200b\` (backtick).').setImage('https://cdn.discordapp.com/attachments/1015195575693627442/1097273921444790322/image.png')]}) } as any)[interaction.options.getString('question', true)](); }, - data: new SlashCommandBuilder() + data: new Discord.SlashCommandBuilder() .setName('faq') .setDescription('List of questions, e.g; log file for FS, YT Scams and etc.') - .addStringOption(opt=>opt + .addStringOption(x=>x .setName('question') .setDescription('What question do you want answered?') .setRequired(true) diff --git a/src/commands/kick.ts b/src/commands/kick.ts index eb990b3..35dce7e 100644 --- a/src/commands/kick.ts +++ b/src/commands/kick.ts @@ -1,17 +1,17 @@ -import Discord,{SlashCommandBuilder} from 'discord.js'; +import Discord from 'discord.js'; import TClient from '../client.js'; export default { run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ client.punish(interaction, 'kick'); }, - data: new SlashCommandBuilder() + data: new Discord.SlashCommandBuilder() .setName('kick') .setDescription('Boot a member from the server') - .addUserOption(opt=>opt + .addUserOption(x=>x .setName('member') .setDescription('Which member to kick?') .setRequired(true)) - .addStringOption(opt=>opt + .addStringOption(x=>x .setName('reason') .setDescription('Reason for the kick')) } \ No newline at end of file diff --git a/src/commands/mp.ts b/src/commands/mp.ts index aeb1c25..f6d871b 100644 --- a/src/commands/mp.ts +++ b/src/commands/mp.ts @@ -1,8 +1,8 @@ -import Discord,{SlashCommandBuilder} from 'discord.js'; +import Discord from 'discord.js'; import TClient from '../client.js'; import path from 'node:path'; import canvas from 'canvas'; -import fs from 'node:fs'; +import {readFileSync} from 'node:fs'; async function MPdata(client:TClient, interaction:Discord.ChatInputCommandInteraction, embed: Discord.EmbedBuilder) { let FSserver; @@ -94,7 +94,7 @@ export default { }, players: async()=>{ const embed1 = new client.embed(); - const data = JSON.parse(fs.readFileSync(path.join('src/database/MPPlayerData.json'), {encoding: 'utf8'})).slice(client.statsGraph) + const data = JSON.parse(readFileSync(path.join('src/database/MPPlayerData.json'), {encoding: 'utf8'})).slice(client.statsGraph) // handle negative days data.forEach((change: number, i: number) => { if (change < 0) data[i] = data[i - 1] || data[i + 1] || 0; @@ -259,25 +259,25 @@ export default { }*/ } as any)[interaction.options.getSubcommand()](); }, - data: new SlashCommandBuilder() + data: new Discord.SlashCommandBuilder() .setName('mp') .setDescription('Display MP status and other things') - .addSubcommand(opt=>opt + .addSubcommand(x=>x .setName('status') .setDescription('Check server status and details')) - .addSubcommand(opt=>opt + .addSubcommand(x=>x .setName('players') .setDescription('Check who\'s playing on the server')) - .addSubcommand(opt=>opt + .addSubcommand(x=>x .setName('info') .setDescription('Provides you with server information such as filters and so on')) - .addSubcommand(opt=>opt + .addSubcommand(x=>x .setName('url') .setDescription('View the URL for this server\'s FSMP server or update the URL') - .addStringOption(opt=>opt + .addStringOption(x=>x .setName('address') .setDescription('Insert a \'dedicated-server-stats\' URL')))/* - .addSubcommand(opt=>opt + .addSubcommand(x=>x .setName('series') .setDescription('Step-by-step on joining Daggerwin\'s MP series'))*/ } diff --git a/src/commands/mute.ts b/src/commands/mute.ts index d44c35a..aa7f5a3 100644 --- a/src/commands/mute.ts +++ b/src/commands/mute.ts @@ -1,20 +1,20 @@ -import Discord,{SlashCommandBuilder} from 'discord.js'; +import Discord from 'discord.js'; import TClient from '../client.js'; export default { run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ client.punish(interaction, 'mute'); }, - data: new SlashCommandBuilder() + data: new Discord.SlashCommandBuilder() .setName('mute') .setDescription('Mute a member') - .addUserOption(opt=>opt + .addUserOption(x=>x .setName('member') .setDescription('Which member to mute?') .setRequired(true)) - .addStringOption(opt=>opt + .addStringOption(x=>x .setName('time') .setDescription('Mute duration')) - .addStringOption(opt=>opt + .addStringOption(x=>x .setName('reason') .setDescription('Reason for the mute')) } \ No newline at end of file diff --git a/src/commands/ping.ts b/src/commands/ping.ts index ef9f876..dd1082d 100644 --- a/src/commands/ping.ts +++ b/src/commands/ping.ts @@ -1,4 +1,4 @@ -import Discord,{SlashCommandBuilder} from 'discord.js'; +import Discord from 'discord.js'; import TClient from '../client.js'; export default { async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ @@ -6,7 +6,7 @@ export default { const time = msg.createdTimestamp - interaction.createdTimestamp; msg.edit(`Websocket: \`${client.formatTime(client.ws.ping, 3, {longNames: false, commas: true})}\`\nBot: \`${client.formatTime(time, 3, {longNames: false, commas: true})}\``) }, - data: new SlashCommandBuilder() + data: new Discord.SlashCommandBuilder() .setName('ping') .setDescription('Check bot\'s latency') } \ No newline at end of file diff --git a/src/commands/purge.ts b/src/commands/purge.ts index f49eaa3..defc0f9 100644 --- a/src/commands/purge.ts +++ b/src/commands/purge.ts @@ -1,8 +1,10 @@ -import Discord,{SlashCommandBuilder} from 'discord.js'; +import Discord from 'discord.js'; import TClient from '../client.js'; export default { async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ - if (!client.isStaff(interaction.member)) return client.youNeedRole(interaction, 'dcmod'); + if (client.config.mainServer.id === interaction.guildId) { + if (!client.isStaff(interaction.member)) return client.youNeedRole(interaction, 'dcmod'); + } const amount = interaction.options.getInteger('amount') as number; if (amount > 100) return interaction.reply({content: 'Discord API limits purging up to 100 messages.', ephemeral: true}) const user = interaction.options.getUser('user'); @@ -22,14 +24,14 @@ export default { } await interaction.reply({content: `Successfully purged ${amount} messages.`, ephemeral: true}) }, - data: new SlashCommandBuilder() + data: new Discord.SlashCommandBuilder() .setName('purge') .setDescription('Purge the amount of messages in this channel') - .addIntegerOption(opt=>opt + .addIntegerOption(x=>x .setName('amount') .setDescription('Amount of messages to be obliterated') .setRequired(true)) - .addUserOption(opt=>opt + .addUserOption(x=>x .setName('user') .setDescription('Which user to have their messages obliterated?')) } \ No newline at end of file diff --git a/src/commands/randomcolor.ts b/src/commands/randomcolor.ts index 9e11ab7..15f08e3 100644 --- a/src/commands/randomcolor.ts +++ b/src/commands/randomcolor.ts @@ -1,4 +1,4 @@ -import Discord,{SlashCommandBuilder} from 'discord.js'; +import Discord from 'discord.js'; import TClient from '../client.js'; export default { run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ @@ -6,7 +6,7 @@ export default { embed.addFields({name: 'Hex code', value: `#${embed.data.color.toString(16).toUpperCase()}`}); interaction.reply({embeds: [embed]}); }, - data: new SlashCommandBuilder() + data: new Discord.SlashCommandBuilder() .setName('randomcolor') .setDescription('Generate a random hex code') } \ No newline at end of file diff --git a/src/commands/rank.ts b/src/commands/rank.ts index ccda1c1..ca90753 100644 --- a/src/commands/rank.ts +++ b/src/commands/rank.ts @@ -1,7 +1,7 @@ -import Discord,{SlashCommandBuilder} from 'discord.js'; +import Discord from 'discord.js'; import TClient from '../client.js'; import path from 'node:path'; -import fs from 'node:fs'; +import {readFileSync} from 'node:fs'; import canvas from 'canvas'; export default { async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ @@ -11,7 +11,7 @@ export default { view: async()=>{ // fetch user or user interaction sender const member = interaction.options.getMember("member") ?? interaction.member as Discord.GuildMember; - if (member.user.bot) return interaction.reply('Bots don\'t level up, try viewing non-bots instead.') + if (member.user.bot) return interaction.reply('Bots don\'t level up, try viewing the rank data from the users instead.'); // information about users progress on level roles const userData = await client.userLevels._content.findById(member.user.id); @@ -31,7 +31,7 @@ export default { const timeActive = Math.floor((Date.now() - client.config.LRSstart)/1000/60/60/24); const dailyMsgsPath = path.join('./src/database/dailyMsgs.json'); - const data = JSON.parse(fs.readFileSync(dailyMsgsPath, 'utf8')).map((x: Array, i: number, a: any) => { + const data = JSON.parse(readFileSync(dailyMsgsPath, 'utf8')).map((x: Array, i: number, a: any) => { const yesterday = a[i - 1] || []; return x[1] - (yesterday[1] || x[1]); }).slice(1).slice(-60); @@ -159,16 +159,16 @@ export default { } } as any)[interaction.options.getSubcommand()](); }, - data: new SlashCommandBuilder() + data: new Discord.SlashCommandBuilder() .setName('rank') .setDescription('Level system') - .addSubcommand(optt=>optt + .addSubcommand(x=>x .setName('view') .setDescription('View your rank or someone else\'s rank') - .addUserOption(opt=>opt + .addUserOption(x=>x .setName('member') .setDescription('Which member do you want to view?'))) - .addSubcommand(optt=>optt + .addSubcommand(x=>x .setName('leaderboard') .setDescription('View top 10 users on leaderboard')) } \ No newline at end of file diff --git a/src/commands/roleinfo.ts b/src/commands/roleinfo.ts index 503fd0b..5b97ba1 100644 --- a/src/commands/roleinfo.ts +++ b/src/commands/roleinfo.ts @@ -1,4 +1,4 @@ -import Discord,{SlashCommandBuilder} from 'discord.js'; +import Discord from 'discord.js'; import TClient from '../client.js'; export default { run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ @@ -13,10 +13,10 @@ export default { {name: '🔹 Permissions', value: `${permissions.includes('Administrator') ? ['Administrator'] : permissions.join(', ') || 'None'}`, inline: true} )]}) }, - data: new SlashCommandBuilder() + data: new Discord.SlashCommandBuilder() .setName('roleinfo') .setDescription('View information about the selected role') - .addRoleOption(opt=>opt + .addRoleOption(x=>x .setName('role') .setDescription('Role name to view information') .setRequired(true)) diff --git a/src/commands/softban.ts b/src/commands/softban.ts index e39d5b0..eb4e23a 100644 --- a/src/commands/softban.ts +++ b/src/commands/softban.ts @@ -1,17 +1,17 @@ -import Discord,{SlashCommandBuilder} from 'discord.js'; +import Discord from 'discord.js'; import TClient from '../client.js'; export default { run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ client.punish(interaction, 'softban'); }, - data: new SlashCommandBuilder() + data: new Discord.SlashCommandBuilder() .setName('softban') .setDescription('Softban a member from the server') - .addUserOption(opt=>opt + .addUserOption(x=>x .setName('member') .setDescription('Which member to softban?') .setRequired(true)) - .addStringOption(opt=>opt + .addStringOption(x=>x .setName('reason') .setDescription('Reason for the softban')) } \ No newline at end of file diff --git a/src/commands/statistics.ts b/src/commands/statistics.ts index 1f8ab7e..f094092 100644 --- a/src/commands/statistics.ts +++ b/src/commands/statistics.ts @@ -1,4 +1,4 @@ -import Discord,{SlashCommandBuilder,version} from 'discord.js'; +import Discord from 'discord.js'; import pkg from 'typescript'; import si from 'systeminformation'; import TClient from '../client.js'; @@ -49,7 +49,7 @@ export default { {name: '> __Dependencies__', value: [ `**TypeScript:** ${pkg.version}`, `**NodeJS:** ${process.version}`, - `**DiscordJS:** ${version}`, + `**DiscordJS:** ${Discord.version}`, `**Axios:** ${client.axios.VERSION}` ].join('\n')}, {name: '> __Host__', value: [ @@ -63,7 +63,7 @@ export default { ); interaction.reply({embeds: [embed], fetchReply: true}).then(x=>x.edit({embeds: [new client.embed(x.embeds[0].data).setFooter({text: `Load time: ${client.formatTime(x.createdTimestamp - interaction.createdTimestamp, 2, {longNames: true, commas: true})}`})]})) }, - data: new SlashCommandBuilder() + data: new Discord.SlashCommandBuilder() .setName('statistics') .setDescription('See a list of commands ordered by their usage or host stats') } \ No newline at end of file diff --git a/src/commands/suggest.ts b/src/commands/suggest.ts index e7679c7..be442dd 100644 --- a/src/commands/suggest.ts +++ b/src/commands/suggest.ts @@ -1,4 +1,4 @@ -import Discord,{SlashCommandBuilder} from 'discord.js'; +import Discord from 'discord.js'; import TClient,{WClient} from '../client.js'; export default { async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ @@ -64,39 +64,39 @@ export default { } } as any)[interaction.options.getSubcommand()](); }, - data: new SlashCommandBuilder() + data: new Discord.SlashCommandBuilder() .setName('suggest') .setDescription('Want to suggest ideas/thoughts to bot techs? Suggest it here') - .addSubcommand(opt=>opt + .addSubcommand(x=>x .setName('your') .setDescription('What do you want to suggest?') - .addStringOption(s=>s + .addStringOption(x=>x .setName('suggestion') .setDescription('Suggest something to bot techs. (You will be DM\'d by bot if your idea was approved/rejected)') .setMaxLength(1024) .setRequired(true)) - .addAttachmentOption(i=>i + .addAttachmentOption(x=>x .setName('image') .setDescription('If your idea seems complicated or prefer to show what your idea may look like then attach the image.'))) - .addSubcommand(opt=>opt + .addSubcommand(x=>x .setName('approve') .setDescription('[Bot Tech] Approve the suggestion sent by the user') - .addStringOption(id=>id + .addStringOption(x=>x .setName('id') .setDescription('User\'s suggestion ID') .setRequired(true)) - .addStringOption(m=>m + .addStringOption(x=>x .setName('message') .setDescription('(Optional) Include a message with your approval') .setMaxLength(256))) - .addSubcommand(opt=>opt + .addSubcommand(x=>x .setName('reject') .setDescription('[Bot Tech] Reject the suggestion sent by the user') - .addStringOption(id=>id + .addStringOption(x=>x .setName('id') .setDescription('User\'s suggestion ID') .setRequired(true)) - .addStringOption(m=>m + .addStringOption(x=>x .setName('message') .setDescription('(Optional) Include a message with your rejection') .setMaxLength(256))) diff --git a/src/commands/unpunish.ts b/src/commands/unpunish.ts index 5f50065..46b7de2 100644 --- a/src/commands/unpunish.ts +++ b/src/commands/unpunish.ts @@ -1,4 +1,4 @@ -import Discord,{SlashCommandBuilder} from 'discord.js'; +import Discord from 'discord.js'; import TClient from '../client.js'; export default { async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ @@ -11,14 +11,14 @@ export default { console.log(client.logTime(), `[UnpunishmentLog] Case #${interaction.options.getInteger('case_id')} was used in /${interaction.commandName} for ${reason}`); (client.channels.cache.get(client.config.mainServer.channels.punishment_log) as Discord.TextChannel).send({embeds:[new client.embed().setColor(client.config.embedColor).setTitle('Unpunishment Log').setDescription(`Case #${interaction.options.getInteger('case_id')} was used in \`/${interaction.commandName}\` for \`${reason}\``).setTimestamp()]}); }, - data: new SlashCommandBuilder() + data: new Discord.SlashCommandBuilder() .setName('unpunish') .setDescription('Remove the active punishment from a member') - .addIntegerOption(opt=>opt + .addIntegerOption(x=>x .setName('case_id') .setDescription('Case ID of the punishment to be overwritten') .setRequired(true)) - .addStringOption(opt=>opt + .addStringOption(x=>x .setName('reason') .setDescription('Reason for removing the punishment')) } \ No newline at end of file diff --git a/src/commands/warn.ts b/src/commands/warn.ts index b0b56d2..39db46a 100644 --- a/src/commands/warn.ts +++ b/src/commands/warn.ts @@ -1,18 +1,17 @@ -import Discord,{SlashCommandBuilder} from 'discord.js'; +import Discord from 'discord.js'; import TClient from '../client.js'; export default { run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ client.punish(interaction, 'warn'); }, - data: new SlashCommandBuilder() + data: new Discord.SlashCommandBuilder() .setName('warn') .setDescription('Warn a member') - .addUserOption(opt=>opt + .addUserOption(x=>x .setName('member') .setDescription('Which member to warn?') .setRequired(true)) - .addStringOption(opt=>opt + .addStringOption(x=>x .setName('reason') - .setDescription('Reason for the warning') - .setRequired(false)) + .setDescription('Reason for the warning')) } \ No newline at end of file diff --git a/src/commands/whois.ts b/src/commands/whois.ts index 8bbdb50..f5d9687 100644 --- a/src/commands/whois.ts +++ b/src/commands/whois.ts @@ -1,4 +1,4 @@ -import Discord,{GuildMember, SlashCommandBuilder} from 'discord.js'; +import Discord from 'discord.js'; import TClient from '../client.js'; function convert(status?:Discord.ClientPresenceStatus){ @@ -12,8 +12,8 @@ function convert(status?:Discord.ClientPresenceStatus){ export default { async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ - const member = interaction.options.getMember('member') as GuildMember; - if (member == null){ + const member = interaction.options.getMember('member') as Discord.GuildMember; + if (member === null){ const user = interaction.options.getUser('member') as Discord.User; const embed = new client.embed() .setColor(client.config.embedColor) @@ -44,16 +44,16 @@ export default { {name: `🔹 Roles: ${member.roles.cache.size - 1}`, value: member.roles.cache.size > 1 ? member.roles.cache.filter(x=>x.id !== interaction.guild.roles.everyone.id).sort((a,b)=>b.position - a.position).map(x=>x).join(member.roles.cache.size > 4 ? ' ' : '\n').slice(0,1024) : 'No roles'} ) if (member.premiumSinceTimestamp !== null) embed.addFields({name: '🔹 Server Boosting since', value: `\n`, inline: true}) - if (!presence) embed.addFields({name: `🔹 Status: Unavailable to retrieve`, value: '\u200b'}) + if (!presence) embed.addFields({name: `🔹 Status: Unavailable to be fetched`, value: '\u200b'}) if (member.presence) embed.addFields({name: `🔹 Status: ${member.presence.status}`, value: `${member.presence.status === 'offline' ? '⚫' : `Desktop: ${convert(presence.desktop)}\nWeb: ${convert(presence.web)}\nMobile: ${convert(presence.mobile)}`}`, inline: true}) embedArray.push(embed) interaction.reply({embeds: embedArray}) } }, - data: new SlashCommandBuilder() + data: new Discord.SlashCommandBuilder() .setName('whois') .setDescription('View your own or someone else\'s information') - .addUserOption(opt=>opt + .addUserOption(x=>x .setName('member') .setDescription('Member or user to view their information') .setRequired(true)) diff --git a/src/events/guildBanAdd.ts b/src/events/guildBanAdd.ts index d0ab9ca..243fb36 100644 --- a/src/events/guildBanAdd.ts +++ b/src/events/guildBanAdd.ts @@ -7,8 +7,8 @@ export default { const banLog = fetchBanlog.entries.first(); if (!banLog) return console.log(`${member.user.tag} was banned from ${member.guild.name} but no audit log for this user.`) const {executor, target, reason } = banLog; - if (target.id == member.user.id) (client.channels.resolve(client.config.mainServer.channels.logs) as Discord.TextChannel).send({embeds: [ - new client.embed().setColor(client.config.embedColorRed).setTimestamp().setThumbnail(member.user.displayAvatarURL({size: 2048})).setTitle(`Member Banned: ${target.tag}`).setDescription(`🔹 **User**\n<@${target.id}>\n\`${target.id}\``).addFields( + if (target.id === member.user.id) (client.channels.resolve(client.config.mainServer.channels.logs) as Discord.TextChannel).send({embeds: [ + new client.embed().setColor(client.config.embedColorRed).setTimestamp().setThumbnail(member.user.displayAvatarURL({size: 2048})).setTitle(`Member Banned: ${target.tag}`).setDescription(`🔹 **User**\n<@${target.id}>\n\`${target.id}\``).setFooter({text:'Rank data has been wiped.'}).addFields( {name: '🔹 Moderator', value: `<@${executor.id}>\n\`${executor.id}\``}, {name: '🔹 Reason', value: `${reason == null ? 'Reason unspecified': reason}`} )]}); diff --git a/src/events/guildBanRemove.ts b/src/events/guildBanRemove.ts index 7c42866..9475423 100644 --- a/src/events/guildBanRemove.ts +++ b/src/events/guildBanRemove.ts @@ -7,7 +7,7 @@ export default { const unbanLog = fetchUnbanlog.entries.first(); if (!unbanLog) return console.log(`${member.user.tag} was unbanned from ${member.guild.name} but no audit log for this user.`) const { executor, target, reason } = unbanLog; - if (target.id == member.user.id) (client.channels.resolve(client.config.mainServer.channels.logs) as Discord.TextChannel).send({embeds: [ + if (target.id === member.user.id) (client.channels.resolve(client.config.mainServer.channels.logs) as Discord.TextChannel).send({embeds: [ new client.embed().setColor(client.config.embedColorGreen).setTimestamp().setThumbnail(member.user.displayAvatarURL({size: 2048})).setTitle(`Member Unbanned: ${target.tag}`).setDescription(`🔹 **User**\n<@${target.id}>\n\`${target.id}\``).addFields( {name: '🔹 Moderator', value: `<@${executor.id}>\n\`${executor.id}\``}, {name: '🔹 Reason', value: `${reason == null ? 'Reason unspecified.': reason}`} diff --git a/src/events/guildMemberAdd.ts b/src/events/guildMemberAdd.ts index b07bee5..121d095 100644 --- a/src/events/guildMemberAdd.ts +++ b/src/events/guildMemberAdd.ts @@ -4,7 +4,7 @@ export default { async run(client:TClient, member:Discord.GuildMember){ if (member.partial || member.guild?.id != client.config.mainServer.id) return; const index = member.guild.memberCount; - const suffix = ((index)=>{ + const suffix = (index=>{ const numbers = index.toString().split('').reverse(); // eg 1850 --> [0,5,8,1] if (numbers[1] === '1') return 'th'; // this is some -teen else { @@ -17,13 +17,13 @@ export default { (client.channels.resolve(client.config.mainServer.channels.welcome) as Discord.TextChannel).send({embeds: [new client.embed().setColor(client.config.embedColor).setThumbnail(member.user.displayAvatarURL({size: 2048}) || member.user.defaultAvatarURL).setTitle(`Welcome to Daggerwin, ${member.user.tag}!`).setFooter({text: `${index}${suffix} member`})]}) if (!client.config.botSwitches.logs) return; const newInvites = await member.guild.invites.fetch(); - const usedInvite = newInvites.find((inv:any)=>client.invites.get(inv.code)?.uses < inv.uses); - newInvites.forEach((inv:any)=>client.invites.set(inv.code,{uses: inv.uses, creator: inv.inviter.id})); + const usedInvite = newInvites.find((inv:Discord.Invite)=>client.invites.get(inv.code)?.uses < inv.uses); + newInvites.forEach((inv:Discord.Invite)=>client.invites.set(inv.code,{uses: inv.uses, creator: inv.inviterId, channel: inv.channel.name})); (client.channels.resolve(client.config.mainServer.channels.logs) as Discord.TextChannel).send({embeds: [ new client.embed().setColor(client.config.embedColorGreen).setTimestamp().setThumbnail(member.user.displayAvatarURL({size: 2048})).setTitle(`Member Joined: ${member.user.tag}`).setDescription(`<@${member.user.id}>\n\`${member.user.id}\``).setFooter({text: `Total members: ${index}${suffix}`}).addFields( {name: '🔹 Account Creation Date', value: `\n`}, - {name: '🔹 Invite Data:', value: usedInvite ? `Invite: \`${usedInvite.code}\`\nCreated by: **${usedInvite.inviter?.tag}**` : 'No invite data could be found.'} + {name: '🔹 Invite Data:', value: usedInvite ? `Invite: \`${usedInvite.code}\`\nCreated by: **${usedInvite.inviter?.tag}**\nChannel: **#${usedInvite.channel.name}**` : 'No invite data could be fetched.'} )]}) } } diff --git a/src/events/guildMemberRemove.ts b/src/events/guildMemberRemove.ts index 2838c6f..007be45 100644 --- a/src/events/guildMemberRemove.ts +++ b/src/events/guildMemberRemove.ts @@ -4,6 +4,7 @@ export default { async run(client:TClient, member:Discord.GuildMember){ if (!client.config.botSwitches.logs) return; if (!member.joinedTimestamp || member.guild?.id != client.config.mainServer.id) return; + if (client.guilds.cache.get(client.config.mainServer.id).bans.cache.has(member.id)) return await client.userLevels._content.findByIdAndDelete(member.id); const levelData = await client.userLevels._content.findById(member.id); const embed = new client.embed().setColor(client.config.embedColorRed).setTimestamp().setThumbnail(member.user.displayAvatarURL({size: 2048}) as string).setTitle(`Member Left: ${member.user.tag}`).setDescription(`<@${member.user.id}>\n\`${member.user.id}\``).addFields( {name: '🔹 Account Creation Date', value: `\n`}, diff --git a/src/events/guildMemberUpdate.ts b/src/events/guildMemberUpdate.ts index fb3b6e9..3fbf051 100644 --- a/src/events/guildMemberUpdate.ts +++ b/src/events/guildMemberUpdate.ts @@ -4,7 +4,7 @@ export default { run(client:TClient, oldMember:Discord.GuildMember, newMember:Discord.GuildMember){ if (oldMember.guild.id != client.config.mainServer.id) return; if (!client.config.botSwitches.logs) return; - const channel = (client.channels.resolve(client.config.mainServer.channels.logs) as Discord.TextChannel) + const channel = (client.channels.resolve(client.config.mainServer.channels.logs) as Discord.TextChannel); if (oldMember.nickname != newMember.nickname){ const embed = new client.embed().setColor(client.config.embedColor).setTimestamp().setThumbnail(newMember.user.displayAvatarURL({size: 2048})).setTitle(`Nickname updated: ${newMember.user.tag}`).setDescription(`<@${newMember.user.id}>\n\`${newMember.user.id}\``) oldMember.nickname == null ? '' : embed.addFields({name: '🔹 Old nickname', value: `\`\`\`${oldMember.nickname}\`\`\``}) @@ -16,8 +16,8 @@ export default { const oldRoles = oldMember.roles.cache.map((x,i)=>i).filter(x=>!newMember.roles.cache.map((x,i)=>i).some(y=>y==x)); if (newRoles.length == 0 && oldRoles.length == 0) return; const embed = new client.embed().setColor(client.config.embedColor).setThumbnail(newMember.user.displayAvatarURL({size: 2048})).setTitle(`Role updated: ${newMember.user.tag}`).setDescription(`<@${newMember.user.id}>\n\`${newMember.user.id}\``) - if (newRoles.length != 0) embed.addFields({name: '🔹 Role added', value: newRoles.map((x)=>`<@&${x}>`).join(' ')}); - if (oldRoles.length != 0) embed.addFields({name: '🔹 Role removed', value: oldRoles.map((x)=>`<@&${x}>`).join(' ')}); + if (newRoles.length != 0) embed.addFields({name: newRoles.length > 1 ? '🔹 Roles added' : '🔹 Role added', value: newRoles.map(x=>`<@&${x}>`).join(' ')}); + if (oldRoles.length != 0) embed.addFields({name: oldRoles.length > 1 ? '🔹 Roles removed' : '🔹 Role removed', value: oldRoles.map(x=>`<@&${x}>`).join(' ')}); channel.send({embeds: [embed]}) } } diff --git a/src/events/inviteCreate.ts b/src/events/inviteCreate.ts index 1e1ceda..aff3e8f 100644 --- a/src/events/inviteCreate.ts +++ b/src/events/inviteCreate.ts @@ -4,6 +4,6 @@ export default { async run(client:TClient, invite: Discord.Invite){ if (!invite.guild) return; const newInvites = await (invite.guild as Discord.Guild).invites.fetch(); - newInvites.forEach(inv=>client.invites.set(inv.code,{uses: inv.code, creator: inv.inviterId})) + newInvites.forEach(inv=>client.invites.set(inv.code,{uses: inv.code, creator: inv.inviterId, channel: inv.channel.name})) } } diff --git a/src/events/messageDelete.ts b/src/events/messageDelete.ts index 00e043a..c32b081 100644 --- a/src/events/messageDelete.ts +++ b/src/events/messageDelete.ts @@ -14,7 +14,7 @@ export default { { name: 'Sent at', value: `\n` } ) const attachments: Array = []; - msg.attachments.forEach((x) => attachments.push(x.url)); + msg.attachments.forEach(x=>attachments.push(x.url)); channel.send({embeds: [embed], files: attachments}) } } diff --git a/src/events/messageDeleteBulk.ts b/src/events/messageDeleteBulk.ts index 8620485..010d85e 100644 --- a/src/events/messageDeleteBulk.ts +++ b/src/events/messageDeleteBulk.ts @@ -1,10 +1,8 @@ import Discord from 'discord.js'; import TClient from '../client.js'; export default { - run(client:TClient, messages:Discord.Collection>){ - if (!client.config.botSwitches.logs) return; - if (client.config.mainServer.id != '468835415093411861') return; - const channel = client.channels.resolve(client.config.mainServer.channels.logs) as Discord.TextChannel; - channel.send({embeds: [new client.embed().setColor(client.config.embedColorRed).setTimestamp().setTitle(`${messages.size} messages were purged`).setDescription(`\`\`\`${messages.map((msgs)=>`${msgs.author?.username}: ${msgs.content}`).reverse().join('\n').slice(0,3900)}\`\`\``).addFields({name: 'Channel', value: `<#${messages.first().channel.id}>`})]}) + run(client:TClient, messages:Discord.Collection>, channel:Discord.GuildTextBasedChannel){ + if (!client.config.botSwitches.logs || channel.guildId != client.config.mainServer.id) return; + (client.channels.resolve(client.config.mainServer.channels.logs) as Discord.TextChannel).send({embeds: [new client.embed().setColor(client.config.embedColorRed).setTimestamp().setTitle(`${messages.size} messages were purged`).setDescription(`\`\`\`${messages.map(msgs=>`${msgs.author?.username}: ${msgs.content}`).reverse().join('\n').slice(0,3900)}\`\`\``).addFields({name: 'Channel', value: `<#${messages.first().channel.id}>`})]}) } } diff --git a/src/index.ts b/src/index.ts index 780517a..cbe92af 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,13 +3,15 @@ import TClient from './client.js'; const client = new TClient; client.init(); import MPLoop from './MPLoop.js'; -import fs from 'node:fs'; +import {writeFileSync, readFileSync} from 'node:fs'; client.on('ready', async()=>{ - setInterval(()=>client.user.setPresence(client.config.botPresence), 300000); await client.guilds.fetch(client.config.mainServer.id).then(async guild=>{ await guild.members.fetch(); - setInterval(()=>guild.invites.fetch().then(invites=>invites.forEach(inv=>client.invites.set(inv.code, {uses: inv.uses, creator: inv.inviterId}))),300000) + setInterval(()=>{ + client.user.setPresence(client.config.botPresence); + guild.invites.fetch().then(invites=>invites.forEach(inv=>client.invites.set(inv.code, {uses: inv.uses, creator: inv.inviterId, channel: inv.channel.name}))) + },300000) }); if (client.config.botSwitches.registerCommands){ client.config.whitelistedServers.forEach(guildId=>(client.guilds.cache.get(guildId) as Discord.Guild).commands.set(client.registry).catch((e:Error)=>{ @@ -46,22 +48,22 @@ setInterval(async()=>{ setInterval(async()=>{ const now = Date.now(); const lrsStart = client.config.LRSstart; - + const punishments = await client.punishments._content.find({}); punishments.filter(x=>x.endTime && x.endTime<= now && !x.expired).forEach(async punishment=>{ console.log(client.logTime(), `${punishment.member}\'s ${punishment.type} should expire now`); const unpunishResult = await client.punishments.removePunishment(punishment._id, client.user.id, 'Time\'s up!'); console.log(client.logTime(), unpunishResult); }); - + const formattedDate = Math.floor((now - lrsStart)/1000/60/60/24); - const dailyMsgs = JSON.parse(fs.readFileSync('./src/database/dailyMsgs.json', {encoding: 'utf8'})) + const dailyMsgs = JSON.parse(readFileSync('./src/database/dailyMsgs.json', {encoding: 'utf8'})) if (!dailyMsgs.some((x:Array)=>x[0] === formattedDate)){ let total = (await client.userLevels._content.find({})).reduce((a,b)=>a + b.messages, 0); // sum of all users const yesterday = dailyMsgs.find((x:Array)=>x[0] === formattedDate - 1); if (total < yesterday) total = yesterday // messages went down. dailyMsgs.push([formattedDate, total]); - fs.writeFileSync('./src/database/dailyMsgs.json', JSON.stringify(dailyMsgs)) + writeFileSync('./src/database/dailyMsgs.json', JSON.stringify(dailyMsgs)) console.log(client.logTime(), `Pushed [${formattedDate}, ${total}] to dailyMsgs`); client.guilds.cache.get(client.config.mainServer.id).commands.fetch().then((commands)=>(client.channels.resolve(client.config.mainServer.channels.logs) as Discord.TextChannel).send(`:pencil: Pushed \`[${formattedDate}, ${total}]\` to x.name == 'rank').id}>`)) }