1
0
mirror of https://github.com/toast-ts/Daggerbot-TS.git synced 2024-11-17 04:10:59 -05:00

Bot improvements

This commit is contained in:
AnxietyisReal 2023-05-23 15:14:17 +10:00
parent 650933bcf0
commit 4c3f913a44
32 changed files with 152 additions and 151 deletions

View File

@ -1,6 +1,6 @@
import Discord from 'discord.js'; import Discord from 'discord.js';
import TClient from './client'; import TClient from './client';
import fs from 'node:fs'; import {writeFileSync, readFileSync} from 'node:fs';
import {FSPlayer, FSData, FSCareerSavegame} from './typings/interfaces'; import {FSPlayer, FSData, FSCareerSavegame} from './typings/interfaces';
export default async(client:TClient,Channel:string,Message:string,ServerName:string)=>{ 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){ if (!isServerOnline){
playerLog(); playerLog();
const Database:Array<number> = JSON.parse(fs.readFileSync('src/database/MPPlayerData.json',{encoding:'utf8',flag:'r+'})); const Database:Array<number> = JSON.parse(readFileSync('src/database/MPPlayerData.json',{encoding:'utf8',flag:'r+'}));
Database.push(DSS.data.slots?.used); 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 client.MPServerCache.players = playersOnServer
} }
} }

View File

@ -1,5 +1,5 @@
import Discord, {Client, WebhookClient, GatewayIntentBits, Partials} from 'discord.js'; 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 {exec} from 'node:child_process';
import mongoose from 'mongoose'; import mongoose from 'mongoose';
import {formatTimeOpt, Tokens, Config, repeatedMessages, MPServerCache} from './typings/interfaces'; import {formatTimeOpt, Tokens, Config, repeatedMessages, MPServerCache} from './typings/interfaces';
@ -16,10 +16,10 @@ import tokens from './tokens.json' assert { type: 'json'};
let importconfig:Config let importconfig:Config
try{ 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') console.log('Using development config :: Daggerbot Beta')
} catch(e){ } 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') console.log('Using production config')
} }
@ -101,11 +101,11 @@ export default class TClient extends Client {
family: 4 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')}) }).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); 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}`); const eventFile = await import(`./events/${file}`);
this.on(file.replace('.js',''), async(...args)=>eventFile.default.run(this,...args)) 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}`); const command = await import(`./commands/${file}`);
this.commands.set(command.default.data.name,{command, uses: 0}); this.commands.set(command.default.data.name,{command, uses: 0});
this.registry.push(command.default.data.toJSON()) this.registry.push(command.default.data.toJSON())

View File

@ -1,20 +1,20 @@
import Discord,{SlashCommandBuilder} from 'discord.js'; import Discord from 'discord.js';
import TClient from '../client.js'; import TClient from '../client.js';
export default { export default {
run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){
client.punish(interaction, 'ban'); client.punish(interaction, 'ban');
}, },
data: new SlashCommandBuilder() data: new Discord.SlashCommandBuilder()
.setName('ban') .setName('ban')
.setDescription('Ban a member from the server') .setDescription('Ban a member from the server')
.addUserOption(opt=>opt .addUserOption(x=>x
.setName('member') .setName('member')
.setDescription('Which member to ban?') .setDescription('Which member to ban?')
.setRequired(true)) .setRequired(true))
.addStringOption(opt=>opt .addStringOption(x=>x
.setName('time') .setName('time')
.setDescription('How long the ban will be?')) .setDescription('How long the ban will be?'))
.addStringOption(opt=>opt .addStringOption(x=>x
.setName('reason') .setName('reason')
.setDescription('Reason for the ban')) .setDescription('Reason for the ban'))
} }

View File

@ -1,7 +1,6 @@
import Discord,{SlashCommandBuilder} from 'discord.js'; import Discord from 'discord.js';
import TClient from '../client.js'; import TClient from '../client.js';
import {writeFileSync} from 'node:fs'; import {writeFileSync} from 'node:fs';
import path from 'node:path';
export default { export default {
async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ 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') 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()](); } as any)[interaction.options.getSubcommand()]();
}, },
data: new SlashCommandBuilder() data: new Discord.SlashCommandBuilder()
.setName('bannedwords') .setName('bannedwords')
.setDescription('description placeholder') .setDescription('description placeholder')
.addSubcommand(opt=>opt .addSubcommand(x=>x
.setName('view') .setName('view')
.setDescription('View the list of currently banned words')) .setDescription('View the list of currently banned words'))
.addSubcommand(opt=>opt .addSubcommand(x=>x
.setName('add') .setName('add')
.setDescription('Add the word to the list') .setDescription('Add the word to the list')
.addStringOption(optt=>optt .addStringOption(x=>x
.setName('word') .setName('word')
.setDescription('Add the specific word to automod\'s bannedWords database') .setDescription('Add the specific word to automod\'s bannedWords database')
.setRequired(true))) .setRequired(true)))
.addSubcommand(opt=>opt .addSubcommand(x=>x
.setName('remove') .setName('remove')
.setDescription('Remove the word from the list') .setDescription('Remove the word from the list')
.addStringOption(optt=>optt .addStringOption(x=>x
.setName('word') .setName('word')
.setDescription('Remove the specific word from automod\'s bannedWords list') .setDescription('Remove the specific word from automod\'s bannedWords list')
.setRequired(true))) .setRequired(true)))

View File

@ -1,4 +1,4 @@
import Discord,{SlashCommandBuilder} from 'discord.js'; import Discord from 'discord.js';
import TClient from '../client.js'; import TClient from '../client.js';
export default { export default {
async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ 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'))}`}) .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') .setName('bonk')
.setDescription('Bonk a member') .setDescription('Bonk a member')
.addUserOption(opt=>opt .addUserOption(x=>x
.setName('member') .setName('member')
.setDescription('Which member to bonk?') .setDescription('Which member to bonk?')
.setRequired(true)) .setRequired(true))
.addStringOption(opt=>opt .addStringOption(x=>x
.setName('reason') .setName('reason')
.setDescription('Reason for the bonk')) .setDescription('Reason for the bonk'))
} }

View File

@ -1,4 +1,4 @@
import Discord,{SlashCommandBuilder} from "discord.js"; import Discord from "discord.js";
import TClient from '../client.js'; import TClient from '../client.js';
export default { export default {
run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){
@ -43,34 +43,34 @@ export default {
} }
} as any)[interaction.options.getSubcommand()](); } as any)[interaction.options.getSubcommand()]();
}, },
data: new SlashCommandBuilder() data: new Discord.SlashCommandBuilder()
.setName('case') .setName('case')
.setDescription('Retrieve case information or user\'s punishment history') .setDescription('Retrieve case information or user\'s punishment history')
.addSubcommand(opt=>opt .addSubcommand(x=>x
.setName('view') .setName('view')
.setDescription('View a multiple or single case') .setDescription('View a multiple or single case')
.addIntegerOption((optt)=>optt .addIntegerOption(x=>x
.setName('id') .setName('id')
.setDescription('Case ID') .setDescription('Case ID')
.setRequired(true))) .setRequired(true)))
.addSubcommand(opt=>opt .addSubcommand(x=>x
.setName('member') .setName('member')
.setDescription('View member\'s punishment history') .setDescription('View member\'s punishment history')
.addUserOption(optt=>optt .addUserOption(x=>x
.setName('user') .setName('user')
.setDescription('Which user do you want to view their punishment history?') .setDescription('Which user do you want to view their punishment history?')
.setRequired(true)) .setRequired(true))
.addIntegerOption(optt=>optt .addIntegerOption(x=>x
.setName('page') .setName('page')
.setDescription('Select the page number'))) .setDescription('Select the page number')))
.addSubcommand(opt=>opt .addSubcommand(x=>x
.setName('update') .setName('update')
.setDescription('Update the case with new reason') .setDescription('Update the case with new reason')
.addIntegerOption(optt=>optt .addIntegerOption(x=>x
.setName('id') .setName('id')
.setDescription('Case ID to be updated') .setDescription('Case ID to be updated')
.setRequired(true)) .setRequired(true))
.addStringOption(optt=>optt .addStringOption(x=>x
.setName('reason') .setName('reason')
.setDescription('New reason for the case') .setDescription('New reason for the case')
.setRequired(true))) .setRequired(true)))

View File

@ -1,4 +1,4 @@
import Discord,{SlashCommandBuilder} from 'discord.js'; import Discord from 'discord.js';
import TClient from '../client.js'; import TClient from '../client.js';
export default { export default {
run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ 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') client.config.contribList.map(id=>{const member = interaction.guild.members.cache.get(id); return `${member?.user?.username ?? 'N/A'} <@${id}>`}).join('\n')
].join('\n'))]}) ].join('\n'))]})
}, },
data: new SlashCommandBuilder() data: new Discord.SlashCommandBuilder()
.setName('contributors') .setName('contributors')
.setDescription('List of people who contributed to the bot') .setDescription('List of people who contributed to the bot')
} }

View File

@ -1,4 +1,4 @@
import Discord,{SlashCommandBuilder} from 'discord.js'; import Discord from 'discord.js';
import {Octokit} from '@octokit/rest'; import {Octokit} from '@octokit/rest';
import {createTokenAuth} from '@octokit/auth-token'; import {createTokenAuth} from '@octokit/auth-token';
import {exec} from 'node:child_process'; import {exec} from 'node:child_process';
@ -130,36 +130,36 @@ export default {
} }
} as any)[interaction.options.getSubcommand()](); } as any)[interaction.options.getSubcommand()]();
}, },
data: new SlashCommandBuilder() data: new Discord.SlashCommandBuilder()
.setName('dev') .setName('dev')
.setDescription('Developer commands') .setDescription('Developer commands')
.addSubcommand(optt=>optt .addSubcommand(x=>x
.setName('eval') .setName('eval')
.setDescription('Execute the code to the bot') .setDescription('Execute the code to the bot')
.addStringOption((opt)=>opt .addStringOption(x=>x
.setName('code') .setName('code')
.setDescription('Execute your code') .setDescription('Execute your code')
.setRequired(true))) .setRequired(true)))
.addSubcommand(optt=>optt .addSubcommand(x=>x
.setName('logs') .setName('logs')
.setDescription('Retrieve the logs from host and sends it to dev server')) .setDescription('Retrieve the logs from host and sends it to dev server'))
.addSubcommand(optt=>optt .addSubcommand(x=>x
.setName('restart') .setName('restart')
.setDescription('Restart the bot for technical reasons')) .setDescription('Restart the bot for technical reasons'))
.addSubcommand(optt=>optt .addSubcommand(x=>x
.setName('update') .setName('update')
.setDescription('Pull from repository and restart')) .setDescription('Pull from repository and restart'))
.addSubcommand(optt=>optt .addSubcommand(x=>x
.setName('statsgraph') .setName('statsgraph')
.setDescription('Edit the number of data points to pull') .setDescription('Edit the number of data points to pull')
.addIntegerOption(hiTae=>hiTae .addIntegerOption(x=>x
.setName('number') .setName('number')
.setDescription('Number of data points to pull') .setDescription('Number of data points to pull')
.setRequired(true))) .setRequired(true)))
.addSubcommand(optt=>optt .addSubcommand(x=>x
.setName('presence') .setName('presence')
.setDescription('Update the bot\'s presence') .setDescription('Update the bot\'s presence')
.addIntegerOption(hiTae=>hiTae .addIntegerOption(x=>x
.setName('type') .setName('type')
.setDescription('Set an activity type') .setDescription('Set an activity type')
.addChoices( .addChoices(
@ -169,13 +169,13 @@ export default {
{name: 'Watching', value: Discord.ActivityType.Watching}, {name: 'Watching', value: Discord.ActivityType.Watching},
{name: 'Competing in', value: Discord.ActivityType.Competing} {name: 'Competing in', value: Discord.ActivityType.Competing}
)) ))
.addStringOption(hiAgain=>hiAgain .addStringOption(x=>x
.setName('name') .setName('name')
.setDescription('Set a message for the activity status')) .setDescription('Set a message for the activity status'))
.addStringOption(hiAgainx2=>hiAgainx2 .addStringOption(x=>x
.setName('url') .setName('url')
.setDescription('Set an url for streaming status')) .setDescription('Set an url for streaming status'))
.addStringOption(hiAgainx3=>hiAgainx3 .addStringOption(x=>x
.setName('status') .setName('status')
.setDescription('Set a status indicator for the bot') .setDescription('Set a status indicator for the bot')
.setChoices( .setChoices(

View File

@ -1,4 +1,4 @@
import Discord,{SlashCommandBuilder} from 'discord.js'; import Discord from 'discord.js';
import TClient from '../client.js'; import TClient from '../client.js';
export default { export default {
run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ 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 `<controls>false</controls>` 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')]}) 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 `<controls>false</controls>` 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)](); } as any)[interaction.options.getString('question', true)]();
}, },
data: new SlashCommandBuilder() data: new Discord.SlashCommandBuilder()
.setName('faq') .setName('faq')
.setDescription('List of questions, e.g; log file for FS, YT Scams and etc.') .setDescription('List of questions, e.g; log file for FS, YT Scams and etc.')
.addStringOption(opt=>opt .addStringOption(x=>x
.setName('question') .setName('question')
.setDescription('What question do you want answered?') .setDescription('What question do you want answered?')
.setRequired(true) .setRequired(true)

View File

@ -1,17 +1,17 @@
import Discord,{SlashCommandBuilder} from 'discord.js'; import Discord from 'discord.js';
import TClient from '../client.js'; import TClient from '../client.js';
export default { export default {
run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){
client.punish(interaction, 'kick'); client.punish(interaction, 'kick');
}, },
data: new SlashCommandBuilder() data: new Discord.SlashCommandBuilder()
.setName('kick') .setName('kick')
.setDescription('Boot a member from the server') .setDescription('Boot a member from the server')
.addUserOption(opt=>opt .addUserOption(x=>x
.setName('member') .setName('member')
.setDescription('Which member to kick?') .setDescription('Which member to kick?')
.setRequired(true)) .setRequired(true))
.addStringOption(opt=>opt .addStringOption(x=>x
.setName('reason') .setName('reason')
.setDescription('Reason for the kick')) .setDescription('Reason for the kick'))
} }

View File

@ -1,8 +1,8 @@
import Discord,{SlashCommandBuilder} from 'discord.js'; import Discord from 'discord.js';
import TClient from '../client.js'; import TClient from '../client.js';
import path from 'node:path'; import path from 'node:path';
import canvas from 'canvas'; 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) { async function MPdata(client:TClient, interaction:Discord.ChatInputCommandInteraction, embed: Discord.EmbedBuilder) {
let FSserver; let FSserver;
@ -94,7 +94,7 @@ export default {
}, },
players: async()=>{ players: async()=>{
const embed1 = new client.embed(); 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 // handle negative days
data.forEach((change: number, i: number) => { data.forEach((change: number, i: number) => {
if (change < 0) data[i] = data[i - 1] || data[i + 1] || 0; if (change < 0) data[i] = data[i - 1] || data[i + 1] || 0;
@ -259,25 +259,25 @@ export default {
}*/ }*/
} as any)[interaction.options.getSubcommand()](); } as any)[interaction.options.getSubcommand()]();
}, },
data: new SlashCommandBuilder() data: new Discord.SlashCommandBuilder()
.setName('mp') .setName('mp')
.setDescription('Display MP status and other things') .setDescription('Display MP status and other things')
.addSubcommand(opt=>opt .addSubcommand(x=>x
.setName('status') .setName('status')
.setDescription('Check server status and details')) .setDescription('Check server status and details'))
.addSubcommand(opt=>opt .addSubcommand(x=>x
.setName('players') .setName('players')
.setDescription('Check who\'s playing on the server')) .setDescription('Check who\'s playing on the server'))
.addSubcommand(opt=>opt .addSubcommand(x=>x
.setName('info') .setName('info')
.setDescription('Provides you with server information such as filters and so on')) .setDescription('Provides you with server information such as filters and so on'))
.addSubcommand(opt=>opt .addSubcommand(x=>x
.setName('url') .setName('url')
.setDescription('View the URL for this server\'s FSMP server or update the URL') .setDescription('View the URL for this server\'s FSMP server or update the URL')
.addStringOption(opt=>opt .addStringOption(x=>x
.setName('address') .setName('address')
.setDescription('Insert a \'dedicated-server-stats\' URL')))/* .setDescription('Insert a \'dedicated-server-stats\' URL')))/*
.addSubcommand(opt=>opt .addSubcommand(x=>x
.setName('series') .setName('series')
.setDescription('Step-by-step on joining Daggerwin\'s MP series'))*/ .setDescription('Step-by-step on joining Daggerwin\'s MP series'))*/
} }

View File

@ -1,20 +1,20 @@
import Discord,{SlashCommandBuilder} from 'discord.js'; import Discord from 'discord.js';
import TClient from '../client.js'; import TClient from '../client.js';
export default { export default {
run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){
client.punish(interaction, 'mute'); client.punish(interaction, 'mute');
}, },
data: new SlashCommandBuilder() data: new Discord.SlashCommandBuilder()
.setName('mute') .setName('mute')
.setDescription('Mute a member') .setDescription('Mute a member')
.addUserOption(opt=>opt .addUserOption(x=>x
.setName('member') .setName('member')
.setDescription('Which member to mute?') .setDescription('Which member to mute?')
.setRequired(true)) .setRequired(true))
.addStringOption(opt=>opt .addStringOption(x=>x
.setName('time') .setName('time')
.setDescription('Mute duration')) .setDescription('Mute duration'))
.addStringOption(opt=>opt .addStringOption(x=>x
.setName('reason') .setName('reason')
.setDescription('Reason for the mute')) .setDescription('Reason for the mute'))
} }

View File

@ -1,4 +1,4 @@
import Discord,{SlashCommandBuilder} from 'discord.js'; import Discord from 'discord.js';
import TClient from '../client.js'; import TClient from '../client.js';
export default { export default {
async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){
@ -6,7 +6,7 @@ export default {
const time = msg.createdTimestamp - interaction.createdTimestamp; 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})}\``) 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') .setName('ping')
.setDescription('Check bot\'s latency') .setDescription('Check bot\'s latency')
} }

View File

@ -1,8 +1,10 @@
import Discord,{SlashCommandBuilder} from 'discord.js'; import Discord from 'discord.js';
import TClient from '../client.js'; import TClient from '../client.js';
export default { export default {
async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ 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; 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}) if (amount > 100) return interaction.reply({content: 'Discord API limits purging up to 100 messages.', ephemeral: true})
const user = interaction.options.getUser('user'); const user = interaction.options.getUser('user');
@ -22,14 +24,14 @@ export default {
} }
await interaction.reply({content: `Successfully purged ${amount} messages.`, ephemeral: true}) await interaction.reply({content: `Successfully purged ${amount} messages.`, ephemeral: true})
}, },
data: new SlashCommandBuilder() data: new Discord.SlashCommandBuilder()
.setName('purge') .setName('purge')
.setDescription('Purge the amount of messages in this channel') .setDescription('Purge the amount of messages in this channel')
.addIntegerOption(opt=>opt .addIntegerOption(x=>x
.setName('amount') .setName('amount')
.setDescription('Amount of messages to be obliterated') .setDescription('Amount of messages to be obliterated')
.setRequired(true)) .setRequired(true))
.addUserOption(opt=>opt .addUserOption(x=>x
.setName('user') .setName('user')
.setDescription('Which user to have their messages obliterated?')) .setDescription('Which user to have their messages obliterated?'))
} }

View File

@ -1,4 +1,4 @@
import Discord,{SlashCommandBuilder} from 'discord.js'; import Discord from 'discord.js';
import TClient from '../client.js'; import TClient from '../client.js';
export default { export default {
run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ 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()}`}); embed.addFields({name: 'Hex code', value: `#${embed.data.color.toString(16).toUpperCase()}`});
interaction.reply({embeds: [embed]}); interaction.reply({embeds: [embed]});
}, },
data: new SlashCommandBuilder() data: new Discord.SlashCommandBuilder()
.setName('randomcolor') .setName('randomcolor')
.setDescription('Generate a random hex code') .setDescription('Generate a random hex code')
} }

View File

@ -1,7 +1,7 @@
import Discord,{SlashCommandBuilder} from 'discord.js'; import Discord from 'discord.js';
import TClient from '../client.js'; import TClient from '../client.js';
import path from 'node:path'; import path from 'node:path';
import fs from 'node:fs'; import {readFileSync} from 'node:fs';
import canvas from 'canvas'; import canvas from 'canvas';
export default { export default {
async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){
@ -11,7 +11,7 @@ export default {
view: async()=>{ view: async()=>{
// fetch user or user interaction sender // fetch user or user interaction sender
const member = interaction.options.getMember("member") ?? interaction.member as Discord.GuildMember; 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 // information about users progress on level roles
const userData = await client.userLevels._content.findById(member.user.id); 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 timeActive = Math.floor((Date.now() - client.config.LRSstart)/1000/60/60/24);
const dailyMsgsPath = path.join('./src/database/dailyMsgs.json'); const dailyMsgsPath = path.join('./src/database/dailyMsgs.json');
const data = JSON.parse(fs.readFileSync(dailyMsgsPath, 'utf8')).map((x: Array<number>, i: number, a: any) => { const data = JSON.parse(readFileSync(dailyMsgsPath, 'utf8')).map((x: Array<number>, i: number, a: any) => {
const yesterday = a[i - 1] || []; const yesterday = a[i - 1] || [];
return x[1] - (yesterday[1] || x[1]); return x[1] - (yesterday[1] || x[1]);
}).slice(1).slice(-60); }).slice(1).slice(-60);
@ -159,16 +159,16 @@ export default {
} }
} as any)[interaction.options.getSubcommand()](); } as any)[interaction.options.getSubcommand()]();
}, },
data: new SlashCommandBuilder() data: new Discord.SlashCommandBuilder()
.setName('rank') .setName('rank')
.setDescription('Level system') .setDescription('Level system')
.addSubcommand(optt=>optt .addSubcommand(x=>x
.setName('view') .setName('view')
.setDescription('View your rank or someone else\'s rank') .setDescription('View your rank or someone else\'s rank')
.addUserOption(opt=>opt .addUserOption(x=>x
.setName('member') .setName('member')
.setDescription('Which member do you want to view?'))) .setDescription('Which member do you want to view?')))
.addSubcommand(optt=>optt .addSubcommand(x=>x
.setName('leaderboard') .setName('leaderboard')
.setDescription('View top 10 users on leaderboard')) .setDescription('View top 10 users on leaderboard'))
} }

View File

@ -1,4 +1,4 @@
import Discord,{SlashCommandBuilder} from 'discord.js'; import Discord from 'discord.js';
import TClient from '../client.js'; import TClient from '../client.js';
export default { export default {
run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ 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} {name: '🔹 Permissions', value: `${permissions.includes('Administrator') ? ['Administrator'] : permissions.join(', ') || 'None'}`, inline: true}
)]}) )]})
}, },
data: new SlashCommandBuilder() data: new Discord.SlashCommandBuilder()
.setName('roleinfo') .setName('roleinfo')
.setDescription('View information about the selected role') .setDescription('View information about the selected role')
.addRoleOption(opt=>opt .addRoleOption(x=>x
.setName('role') .setName('role')
.setDescription('Role name to view information') .setDescription('Role name to view information')
.setRequired(true)) .setRequired(true))

View File

@ -1,17 +1,17 @@
import Discord,{SlashCommandBuilder} from 'discord.js'; import Discord from 'discord.js';
import TClient from '../client.js'; import TClient from '../client.js';
export default { export default {
run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){
client.punish(interaction, 'softban'); client.punish(interaction, 'softban');
}, },
data: new SlashCommandBuilder() data: new Discord.SlashCommandBuilder()
.setName('softban') .setName('softban')
.setDescription('Softban a member from the server') .setDescription('Softban a member from the server')
.addUserOption(opt=>opt .addUserOption(x=>x
.setName('member') .setName('member')
.setDescription('Which member to softban?') .setDescription('Which member to softban?')
.setRequired(true)) .setRequired(true))
.addStringOption(opt=>opt .addStringOption(x=>x
.setName('reason') .setName('reason')
.setDescription('Reason for the softban')) .setDescription('Reason for the softban'))
} }

View File

@ -1,4 +1,4 @@
import Discord,{SlashCommandBuilder,version} from 'discord.js'; import Discord from 'discord.js';
import pkg from 'typescript'; import pkg from 'typescript';
import si from 'systeminformation'; import si from 'systeminformation';
import TClient from '../client.js'; import TClient from '../client.js';
@ -49,7 +49,7 @@ export default {
{name: '> __Dependencies__', value: [ {name: '> __Dependencies__', value: [
`**TypeScript:** ${pkg.version}`, `**TypeScript:** ${pkg.version}`,
`**NodeJS:** ${process.version}`, `**NodeJS:** ${process.version}`,
`**DiscordJS:** ${version}`, `**DiscordJS:** ${Discord.version}`,
`**Axios:** ${client.axios.VERSION}` `**Axios:** ${client.axios.VERSION}`
].join('\n')}, ].join('\n')},
{name: '> __Host__', value: [ {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})}`})]})) 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') .setName('statistics')
.setDescription('See a list of commands ordered by their usage or host stats') .setDescription('See a list of commands ordered by their usage or host stats')
} }

View File

@ -1,4 +1,4 @@
import Discord,{SlashCommandBuilder} from 'discord.js'; import Discord from 'discord.js';
import TClient,{WClient} from '../client.js'; import TClient,{WClient} from '../client.js';
export default { export default {
async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){
@ -64,39 +64,39 @@ export default {
} }
} as any)[interaction.options.getSubcommand()](); } as any)[interaction.options.getSubcommand()]();
}, },
data: new SlashCommandBuilder() data: new Discord.SlashCommandBuilder()
.setName('suggest') .setName('suggest')
.setDescription('Want to suggest ideas/thoughts to bot techs? Suggest it here') .setDescription('Want to suggest ideas/thoughts to bot techs? Suggest it here')
.addSubcommand(opt=>opt .addSubcommand(x=>x
.setName('your') .setName('your')
.setDescription('What do you want to suggest?') .setDescription('What do you want to suggest?')
.addStringOption(s=>s .addStringOption(x=>x
.setName('suggestion') .setName('suggestion')
.setDescription('Suggest something to bot techs. (You will be DM\'d by bot if your idea was approved/rejected)') .setDescription('Suggest something to bot techs. (You will be DM\'d by bot if your idea was approved/rejected)')
.setMaxLength(1024) .setMaxLength(1024)
.setRequired(true)) .setRequired(true))
.addAttachmentOption(i=>i .addAttachmentOption(x=>x
.setName('image') .setName('image')
.setDescription('If your idea seems complicated or prefer to show what your idea may look like then attach the 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') .setName('approve')
.setDescription('[Bot Tech] Approve the suggestion sent by the user') .setDescription('[Bot Tech] Approve the suggestion sent by the user')
.addStringOption(id=>id .addStringOption(x=>x
.setName('id') .setName('id')
.setDescription('User\'s suggestion ID') .setDescription('User\'s suggestion ID')
.setRequired(true)) .setRequired(true))
.addStringOption(m=>m .addStringOption(x=>x
.setName('message') .setName('message')
.setDescription('(Optional) Include a message with your approval') .setDescription('(Optional) Include a message with your approval')
.setMaxLength(256))) .setMaxLength(256)))
.addSubcommand(opt=>opt .addSubcommand(x=>x
.setName('reject') .setName('reject')
.setDescription('[Bot Tech] Reject the suggestion sent by the user') .setDescription('[Bot Tech] Reject the suggestion sent by the user')
.addStringOption(id=>id .addStringOption(x=>x
.setName('id') .setName('id')
.setDescription('User\'s suggestion ID') .setDescription('User\'s suggestion ID')
.setRequired(true)) .setRequired(true))
.addStringOption(m=>m .addStringOption(x=>x
.setName('message') .setName('message')
.setDescription('(Optional) Include a message with your rejection') .setDescription('(Optional) Include a message with your rejection')
.setMaxLength(256))) .setMaxLength(256)))

View File

@ -1,4 +1,4 @@
import Discord,{SlashCommandBuilder} from 'discord.js'; import Discord from 'discord.js';
import TClient from '../client.js'; import TClient from '../client.js';
export default { export default {
async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ 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}`); 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()]}); (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') .setName('unpunish')
.setDescription('Remove the active punishment from a member') .setDescription('Remove the active punishment from a member')
.addIntegerOption(opt=>opt .addIntegerOption(x=>x
.setName('case_id') .setName('case_id')
.setDescription('Case ID of the punishment to be overwritten') .setDescription('Case ID of the punishment to be overwritten')
.setRequired(true)) .setRequired(true))
.addStringOption(opt=>opt .addStringOption(x=>x
.setName('reason') .setName('reason')
.setDescription('Reason for removing the punishment')) .setDescription('Reason for removing the punishment'))
} }

View File

@ -1,18 +1,17 @@
import Discord,{SlashCommandBuilder} from 'discord.js'; import Discord from 'discord.js';
import TClient from '../client.js'; import TClient from '../client.js';
export default { export default {
run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){
client.punish(interaction, 'warn'); client.punish(interaction, 'warn');
}, },
data: new SlashCommandBuilder() data: new Discord.SlashCommandBuilder()
.setName('warn') .setName('warn')
.setDescription('Warn a member') .setDescription('Warn a member')
.addUserOption(opt=>opt .addUserOption(x=>x
.setName('member') .setName('member')
.setDescription('Which member to warn?') .setDescription('Which member to warn?')
.setRequired(true)) .setRequired(true))
.addStringOption(opt=>opt .addStringOption(x=>x
.setName('reason') .setName('reason')
.setDescription('Reason for the warning') .setDescription('Reason for the warning'))
.setRequired(false))
} }

View File

@ -1,4 +1,4 @@
import Discord,{GuildMember, SlashCommandBuilder} from 'discord.js'; import Discord from 'discord.js';
import TClient from '../client.js'; import TClient from '../client.js';
function convert(status?:Discord.ClientPresenceStatus){ function convert(status?:Discord.ClientPresenceStatus){
@ -12,8 +12,8 @@ function convert(status?:Discord.ClientPresenceStatus){
export default { export default {
async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){
const member = interaction.options.getMember('member') as GuildMember; const member = interaction.options.getMember('member') as Discord.GuildMember;
if (member == null){ if (member === null){
const user = interaction.options.getUser('member') as Discord.User; const user = interaction.options.getUser('member') as Discord.User;
const embed = new client.embed() const embed = new client.embed()
.setColor(client.config.embedColor) .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'} {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: `<t:${Math.round(member.premiumSinceTimestamp/1000)}>\n<t:${Math.round(member.premiumSinceTimestamp/1000)}:R>`, inline: true}) if (member.premiumSinceTimestamp !== null) embed.addFields({name: '🔹 Server Boosting since', value: `<t:${Math.round(member.premiumSinceTimestamp/1000)}>\n<t:${Math.round(member.premiumSinceTimestamp/1000)}:R>`, 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}) 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) embedArray.push(embed)
interaction.reply({embeds: embedArray}) interaction.reply({embeds: embedArray})
} }
}, },
data: new SlashCommandBuilder() data: new Discord.SlashCommandBuilder()
.setName('whois') .setName('whois')
.setDescription('View your own or someone else\'s information') .setDescription('View your own or someone else\'s information')
.addUserOption(opt=>opt .addUserOption(x=>x
.setName('member') .setName('member')
.setDescription('Member or user to view their information') .setDescription('Member or user to view their information')
.setRequired(true)) .setRequired(true))

View File

@ -7,8 +7,8 @@ export default {
const banLog = fetchBanlog.entries.first(); 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.`) 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; const {executor, target, reason } = banLog;
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.embedColorRed).setTimestamp().setThumbnail(member.user.displayAvatarURL({size: 2048})).setTitle(`Member Banned: ${target.tag}`).setDescription(`🔹 **User**\n<@${target.id}>\n\`${target.id}\``).addFields( 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: '🔹 Moderator', value: `<@${executor.id}>\n\`${executor.id}\``},
{name: '🔹 Reason', value: `${reason == null ? 'Reason unspecified': reason}`} {name: '🔹 Reason', value: `${reason == null ? 'Reason unspecified': reason}`}
)]}); )]});

View File

@ -7,7 +7,7 @@ export default {
const unbanLog = fetchUnbanlog.entries.first(); 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.`) 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; 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( 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: '🔹 Moderator', value: `<@${executor.id}>\n\`${executor.id}\``},
{name: '🔹 Reason', value: `${reason == null ? 'Reason unspecified.': reason}`} {name: '🔹 Reason', value: `${reason == null ? 'Reason unspecified.': reason}`}

View File

@ -4,7 +4,7 @@ export default {
async run(client:TClient, member:Discord.GuildMember){ async run(client:TClient, member:Discord.GuildMember){
if (member.partial || member.guild?.id != client.config.mainServer.id) return; if (member.partial || member.guild?.id != client.config.mainServer.id) return;
const index = member.guild.memberCount; const index = member.guild.memberCount;
const suffix = ((index)=>{ const suffix = (index=>{
const numbers = index.toString().split('').reverse(); // eg 1850 --> [0,5,8,1] const numbers = index.toString().split('').reverse(); // eg 1850 --> [0,5,8,1]
if (numbers[1] === '1') return 'th'; // this is some -teen if (numbers[1] === '1') return 'th'; // this is some -teen
else { 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`})]}) (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; if (!client.config.botSwitches.logs) return;
const newInvites = await member.guild.invites.fetch(); const newInvites = await member.guild.invites.fetch();
const usedInvite = newInvites.find((inv:any)=>client.invites.get(inv.code)?.uses < inv.uses); const usedInvite = newInvites.find((inv:Discord.Invite)=>client.invites.get(inv.code)?.uses < inv.uses);
newInvites.forEach((inv:any)=>client.invites.set(inv.code,{uses: inv.uses, creator: inv.inviter.id})); 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: [ (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( 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: `<t:${Math.round(member.user.createdTimestamp/1000)}>\n<t:${Math.round(member.user.createdTimestamp/1000)}:R>`}, {name: '🔹 Account Creation Date', value: `<t:${Math.round(member.user.createdTimestamp/1000)}>\n<t:${Math.round(member.user.createdTimestamp/1000)}:R>`},
{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.'}
)]}) )]})
} }
} }

View File

@ -4,6 +4,7 @@ export default {
async run(client:TClient, member:Discord.GuildMember){ async run(client:TClient, member:Discord.GuildMember){
if (!client.config.botSwitches.logs) return; if (!client.config.botSwitches.logs) return;
if (!member.joinedTimestamp || member.guild?.id != client.config.mainServer.id) 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 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( 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: `<t:${Math.round(member.user.createdTimestamp/1000)}>\n<t:${Math.round(member.user.createdTimestamp/1000)}:R>`}, {name: '🔹 Account Creation Date', value: `<t:${Math.round(member.user.createdTimestamp/1000)}>\n<t:${Math.round(member.user.createdTimestamp/1000)}:R>`},

View File

@ -4,7 +4,7 @@ export default {
run(client:TClient, oldMember:Discord.GuildMember, newMember:Discord.GuildMember){ run(client:TClient, oldMember:Discord.GuildMember, newMember:Discord.GuildMember){
if (oldMember.guild.id != client.config.mainServer.id) return; if (oldMember.guild.id != client.config.mainServer.id) return;
if (!client.config.botSwitches.logs) 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){ 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}\``) 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}\`\`\``}) 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)); 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; 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}\``) 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 (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: '🔹 Role removed', value: oldRoles.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]}) channel.send({embeds: [embed]})
} }
} }

View File

@ -4,6 +4,6 @@ export default {
async run(client:TClient, invite: Discord.Invite){ async run(client:TClient, invite: Discord.Invite){
if (!invite.guild) return; if (!invite.guild) return;
const newInvites = await (invite.guild as Discord.Guild).invites.fetch(); 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}))
} }
} }

View File

@ -14,7 +14,7 @@ export default {
{ name: 'Sent at', value: `<t:${Math.round(msg.createdTimestamp/1000)}>\n<t:${Math.round(msg.createdTimestamp/1000)}:R>` } { name: 'Sent at', value: `<t:${Math.round(msg.createdTimestamp/1000)}>\n<t:${Math.round(msg.createdTimestamp/1000)}:R>` }
) )
const attachments: Array<string> = []; const attachments: Array<string> = [];
msg.attachments.forEach((x) => attachments.push(x.url)); msg.attachments.forEach(x=>attachments.push(x.url));
channel.send({embeds: [embed], files: attachments}) channel.send({embeds: [embed], files: attachments})
} }
} }

View File

@ -1,10 +1,8 @@
import Discord from 'discord.js'; import Discord from 'discord.js';
import TClient from '../client.js'; import TClient from '../client.js';
export default { export default {
run(client:TClient, messages:Discord.Collection<string, Discord.Message<boolean>>){ run(client:TClient, messages:Discord.Collection<string, Discord.Message<boolean>>, channel:Discord.GuildTextBasedChannel){
if (!client.config.botSwitches.logs) return; if (!client.config.botSwitches.logs || channel.guildId != client.config.mainServer.id) return;
if (client.config.mainServer.id != '468835415093411861') 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}>`})]})
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}>`})]})
} }
} }

View File

@ -3,13 +3,15 @@ import TClient from './client.js';
const client = new TClient; const client = new TClient;
client.init(); client.init();
import MPLoop from './MPLoop.js'; import MPLoop from './MPLoop.js';
import fs from 'node:fs'; import {writeFileSync, readFileSync} from 'node:fs';
client.on('ready', async()=>{ client.on('ready', async()=>{
setInterval(()=>client.user.setPresence(client.config.botPresence), 300000);
await client.guilds.fetch(client.config.mainServer.id).then(async guild=>{ await client.guilds.fetch(client.config.mainServer.id).then(async guild=>{
await guild.members.fetch(); 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){ 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)=>{ 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()=>{ setInterval(async()=>{
const now = Date.now(); const now = Date.now();
const lrsStart = client.config.LRSstart; const lrsStart = client.config.LRSstart;
const punishments = await client.punishments._content.find({}); const punishments = await client.punishments._content.find({});
punishments.filter(x=>x.endTime && x.endTime<= now && !x.expired).forEach(async punishment=>{ 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`); 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!'); const unpunishResult = await client.punishments.removePunishment(punishment._id, client.user.id, 'Time\'s up!');
console.log(client.logTime(), unpunishResult); console.log(client.logTime(), unpunishResult);
}); });
const formattedDate = Math.floor((now - lrsStart)/1000/60/60/24); 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<number>)=>x[0] === formattedDate)){ if (!dailyMsgs.some((x:Array<number>)=>x[0] === formattedDate)){
let total = (await client.userLevels._content.find({})).reduce((a,b)=>a + b.messages, 0); // sum of all users let total = (await client.userLevels._content.find({})).reduce((a,b)=>a + b.messages, 0); // sum of all users
const yesterday = dailyMsgs.find((x:Array<number>)=>x[0] === formattedDate - 1); const yesterday = dailyMsgs.find((x:Array<number>)=>x[0] === formattedDate - 1);
if (total < yesterday) total = yesterday // messages went down. if (total < yesterday) total = yesterday // messages went down.
dailyMsgs.push([formattedDate, total]); 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`); 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 </rank leaderboard:${commands.find(x=>x.name == 'rank').id}>`)) 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 </rank leaderboard:${commands.find(x=>x.name == 'rank').id}>`))
} }