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

Codebase improvements

This commit is contained in:
toast-ts 2023-10-06 16:54:27 +11:00
parent b9e7cfc3d4
commit 673d2e0aee
24 changed files with 151 additions and 83 deletions

11
.pnp.cjs generated
View File

@ -36,6 +36,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["@types/node", "npm:20.8.2"],\ ["@types/node", "npm:20.8.2"],\
["@types/node-cron", "npm:3.0.9"],\ ["@types/node-cron", "npm:3.0.9"],\
["canvas", "npm:2.11.2"],\ ["canvas", "npm:2.11.2"],\
["chalk", "npm:5.3.0"],\
["discord-player", "virtual:20c353e2d6536e37339997f03975c6a660f4d296e664d291bd43620c6162cca8eb5ef90b0998dc9db75ff6862e5da587d0530bae26805f5fadc8f17aaa4ff794#npm:6.6.4"],\ ["discord-player", "virtual:20c353e2d6536e37339997f03975c6a660f4d296e664d291bd43620c6162cca8eb5ef90b0998dc9db75ff6862e5da587d0530bae26805f5fadc8f17aaa4ff794#npm:6.6.4"],\
["discord.js", "npm:14.13.0"],\ ["discord.js", "npm:14.13.0"],\
["libsodium-wrappers", "npm:0.7.13"],\ ["libsodium-wrappers", "npm:0.7.13"],\
@ -930,6 +931,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
"linkType": "HARD"\ "linkType": "HARD"\
}]\ }]\
]],\ ]],\
["chalk", [\
["npm:5.3.0", {\
"packageLocation": "./.yarn/cache/chalk-npm-5.3.0-d181999efb-623922e077.zip/node_modules/chalk/",\
"packageDependencies": [\
["chalk", "npm:5.3.0"]\
],\
"linkType": "HARD"\
}]\
]],\
["chownr", [\ ["chownr", [\
["npm:2.0.0", {\ ["npm:2.0.0", {\
"packageLocation": "./.yarn/cache/chownr-npm-2.0.0-638f1c9c61-c57cf9dd07.zip/node_modules/chownr/",\ "packageLocation": "./.yarn/cache/chownr-npm-2.0.0-638f1c9c61-c57cf9dd07.zip/node_modules/chownr/",\
@ -1051,6 +1061,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["@types/node", "npm:20.8.2"],\ ["@types/node", "npm:20.8.2"],\
["@types/node-cron", "npm:3.0.9"],\ ["@types/node-cron", "npm:3.0.9"],\
["canvas", "npm:2.11.2"],\ ["canvas", "npm:2.11.2"],\
["chalk", "npm:5.3.0"],\
["discord-player", "virtual:20c353e2d6536e37339997f03975c6a660f4d296e664d291bd43620c6162cca8eb5ef90b0998dc9db75ff6862e5da587d0530bae26805f5fadc8f17aaa4ff794#npm:6.6.4"],\ ["discord-player", "virtual:20c353e2d6536e37339997f03975c6a660f4d296e664d291bd43620c6162cca8eb5ef90b0998dc9db75ff6862e5da587d0530bae26805f5fadc8f17aaa4ff794#npm:6.6.4"],\
["discord.js", "npm:14.13.0"],\ ["discord.js", "npm:14.13.0"],\
["libsodium-wrappers", "npm:0.7.13"],\ ["libsodium-wrappers", "npm:0.7.13"],\

View File

@ -34,6 +34,7 @@
"@octokit/auth-token": "4.0.0", "@octokit/auth-token": "4.0.0",
"@octokit/rest": "20.0.2", "@octokit/rest": "20.0.2",
"canvas": "2.11.2", "canvas": "2.11.2",
"chalk": "5.3.0",
"discord-player": "6.6.4", "discord-player": "6.6.4",
"discord.js": "14.13.0", "discord.js": "14.13.0",
"libsodium-wrappers": "0.7.13", "libsodium-wrappers": "0.7.13",

View File

@ -88,26 +88,35 @@ export default class TClient extends Discord.Client {
} }
async init(){ async init(){
console.time('Startup'); console.time('Startup');
CacheServer.init(); await Promise.all([
DatabaseServer.init(); CacheServer.init(),
this.login((await TSClient.Token()).main); DatabaseServer.init(),
for (const file of readdirSync('dist/events')){ this.login((await TSClient.Token()).main)
const eventFile = await import(`./events/${file}`); ]);
this.on(file.replace('.js',''), async(...args)=>eventFile.default.run(this,...args))
} const eventFiles = await Promise.all(
for (const file of readdirSync('dist/commands')){ readdirSync('dist/events').map(file=>import(`./events/${file}`))
const command = await import(`./commands/${file}`); );
this.commands.set(command.default.data.name,{command, uses: 0}); eventFiles.forEach((eventFile, index)=>{
this.registry.push(command.default.data.toJSON()) const eventName = readdirSync('dist/events')[index].replace('.js', '');
} this.on(eventName, async(...args)=>eventFile.default.run(this, ...args));
for (const naming of Object.keys(this.config.MPStatsLocation)){ });
const commandFiles = await Promise.all(
readdirSync('dist/commands').map(file=>import(`./commands/${file}`))
);
commandFiles.forEach(commandFile=>{
const {default: command} = commandFile;
this.commands.set(command.data.name, {command, uses: 0});
this.registry.push(command.data.toJSON());
});
Object.keys(this.config.MPStatsLocation).forEach(naming=>{
this.MPServerCache[naming] = { this.MPServerCache[naming] = {
players: [], players: [],
status: null, status: null,
name: null name: null
} }
} });
} }
isStaff = (guildMember:Discord.GuildMember)=>this.config.mainServer.staffRoles.map((x: string)=>this.config.mainServer.roles[x]).some((x: string)=>guildMember.roles.cache.has(x));
youNeedRole = (interaction:Discord.CommandInteraction, role:string)=>interaction.reply(`This command is restricted to <@&${this.config.mainServer.roles[role]}>`);
} }

View File

@ -1,9 +1,10 @@
import Discord 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 MessageTool from '../helpers/MessageTool.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) && !client.config.whitelist.includes(interaction.member.id)) return client.youNeedRole(interaction, 'admin') if (!MessageTool.isStaff(interaction.member) && !client.config.whitelist.includes(interaction.member.id)) return MessageTool.youNeedRole(interaction, 'admin');
const word = interaction.options.getString('word'); const word = interaction.options.getString('word');
const wordExists = await client.bannedWords._content.findById(word); const wordExists = await client.bannedWords._content.findById(word);
({ ({

View File

@ -1,9 +1,10 @@
import Discord from 'discord.js'; import Discord from 'discord.js';
import TClient from '../client.js'; import TClient from '../client.js';
import FormatTime from '../helpers/FormatTime.js'; import FormatTime from '../helpers/FormatTime.js';
import MessageTool from '../helpers/MessageTool.js';
export default { export default {
run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){
if (!client.isStaff(interaction.member)) return client.youNeedRole(interaction, 'dcmod'); if (!MessageTool.isStaff(interaction.member)) return MessageTool.youNeedRole(interaction, 'dcmod');
const caseId = interaction.options.getInteger('id'); const caseId = interaction.options.getInteger('id');
({ ({
update: async()=>{ update: async()=>{
@ -18,8 +19,8 @@ export default {
const cancelledBy = punishment.expired ? await client.punishments._content.findOne({cancels:punishment.id}) : null; const cancelledBy = punishment.expired ? await client.punishments._content.findOne({cancels:punishment.id}) : null;
const cancels = punishment.cancels ? await client.punishments._content.findOne({_id:punishment.cancels}) : null; const cancels = punishment.cancels ? await client.punishments._content.findOne({_id:punishment.cancels}) : null;
const embed = new client.embed().setColor(client.config.embedColor).setTimestamp(punishment.time).setTitle(`${punishment.type[0].toUpperCase()+punishment.type.slice(1)} | Case #${punishment.id}`).addFields( const embed = new client.embed().setColor(client.config.embedColor).setTimestamp(punishment.time).setTitle(`${punishment.type[0].toUpperCase()+punishment.type.slice(1)} | Case #${punishment.id}`).addFields(
{name: '🔹 User', value: `<@${punishment.member}> \`${punishment.member}\``, inline: true}, {name: '🔹 User', value: `${MessageTool.formatMention(punishment.member, 'user')} \`${punishment.member}\``, inline: true},
{name: '🔹 Moderator', value: `<@${punishment.moderator}> \`${punishment.moderator}\``, inline: true}, {name: '🔹 Moderator', value: `${MessageTool.formatMention(punishment.moderator, 'user')} \`${punishment.moderator}\``, inline: true},
{name: '\u200b', value: '\u200b', inline: true}, {name: '\u200b', value: '\u200b', inline: true},
{name: '🔹 Reason', value: `\`${punishment.reason || 'Reason unspecified'}\``, inline: true}) {name: '🔹 Reason', value: `\`${punishment.reason || 'Reason unspecified'}\``, inline: true})
if (punishment.duration) embed.addFields({name: '🔹 Duration', value: `${FormatTime(punishment.duration, 100)}`}) if (punishment.duration) embed.addFields({name: '🔹 Duration', value: `${FormatTime(punishment.duration, 100)}`})
@ -35,7 +36,7 @@ export default {
const userPunishment = userPunishmentData.sort((a,b)=>a.time-b.time).map((punishment)=>{ const userPunishment = userPunishmentData.sort((a,b)=>a.time-b.time).map((punishment)=>{
return { return {
name: `${punishment.type[0].toUpperCase()+punishment.type.slice(1)} | Case #${punishment.id}`, name: `${punishment.type[0].toUpperCase()+punishment.type.slice(1)} | Case #${punishment.id}`,
value: `Reason: \`${punishment.reason}\`\n${punishment.duration ? `Duration: ${FormatTime(punishment.duration, 3)}\n` : ''}Moderator: <@${punishment.moderator}>${punishment.expired ? `\nOverwritten by Case #${punishments.find(x=>x.cancels===punishment._id)?._id}` : ''}${punishment.cancels ? `\nOverwrites Case #${punishment.cancels}` : ''}` value: `Reason: \`${punishment.reason}\`\n${punishment.duration ? `Duration: ${FormatTime(punishment.duration, 3)}\n` : ''}Moderator: ${MessageTool.formatMention(punishment.moderator, 'user')}${punishment.expired ? `\nOverwritten by Case #${punishments.find(x=>x.cancels===punishment._id)?._id}` : ''}${punishment.cancels ? `\nOverwrites Case #${punishment.cancels}` : ''}`
} }
}); });
if (!punishments || !userPunishment) return interaction.reply(`**${user.username}** has a clean record.`) if (!punishments || !userPunishment) return interaction.reply(`**${user.username}** has a clean record.`)

View File

@ -11,33 +11,48 @@ import fs from 'node:fs';
import util from 'node:util'; import util from 'node:util';
export default { export default {
run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>) { run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>) {
if (!client.config.whitelist.includes(interaction.user.id)) return client.youNeedRole(interaction, 'bottech'); if (!client.config.whitelist.includes(interaction.user.id)) return MessageTool.youNeedRole(interaction, 'bottech');
({ ({
eval: async()=>{ eval: async()=>{
if (!client.config.eval) return interaction.reply({content: 'Eval is currently disabled.', ephemeral: true}); if (!client.config.eval) return interaction.reply({content: 'Eval is currently disabled.', ephemeral: true});
const code = interaction.options.getString('code') as string; const code = interaction.options.getString('code') as string;
let consoleOutput:string = '';
const deleteEmbedBtn = new Discord.ButtonBuilder().setCustomId('deleteEmbed').setLabel('Delete').setStyle(Discord.ButtonStyle.Danger).setEmoji('🗑️');
const deleteEmbedRow = new Discord.ActionRowBuilder<Discord.ButtonBuilder>().addComponents(deleteEmbedBtn);
const deleteEmbedCollector = interaction.channel.createMessageComponentCollector({componentType: Discord.ComponentType.Button});
deleteEmbedCollector.on('collect', async i=>{
if (i.customId === 'deleteEmbed') deleteEmbedCollector.stop();
});
try { try {
const consoleLog = console.log;
console.log = (...args: any[])=>{
consoleLog(...args);
consoleOutput += util.formatWithOptions({depth: 2, colors: true}, ...args) + '\n';
}
const output = await eval(interaction.options.getBoolean('async') ? `(async()=>{${code}})()` : code); const output = await eval(interaction.options.getBoolean('async') ? `(async()=>{${code}})()` : code);
let outVal = output !== undefined ? output : 'No output';
if (outVal && outVal.includes && outVal.includes(client.token)) outVal = outVal.replace(client.token, '*'.repeat(8));
const embedFields:Discord.APIEmbedField[] = [
{name: 'Input', value: `\`\`\`js\n${code.slice(0,1020)}\n\`\`\``},
{name: 'Output', value: `**\`\`\`${UsernameHelper.stripName(outVal === 'string' ? String(outVal) : 'ansi\n'+util.formatWithOptions({depth: 2, colors: true}, '%O', outVal)).slice(0,1012)}\n\`\`\`**`}
];
if (consoleOutput) embedFields.push({name: 'Console', value: `**\`\`\`ansi\n${UsernameHelper.stripName(consoleOutput).slice(0,1008)}\n\`\`\`**`});
if (typeof output === 'object') { if (typeof output === 'object') {
const embed = new client.embed().setColor(client.config.embedColor).addFields( const embed = new client.embed().setColor(client.config.embedColor).addFields(embedFields);
{name: 'Input', value: `\`\`\`js\n${code.slice(0,1020)}\n\`\`\``}, interaction.reply({embeds: [embed], components: [deleteEmbedRow]}).catch(()=>(interaction.channel as Discord.TextChannel).send({embeds: [embed], components: [deleteEmbedRow]}));
{name: 'Output', value: `\`\`\`${UsernameHelper.stripName('ansi\n'+util.formatWithOptions({depth: 2, colors: true}, '%O', output)).slice(0,1016)}\n\`\`\``}
);
interaction.reply({embeds: [embed]}).catch(()=>(interaction.channel as Discord.TextChannel).send({embeds: [embed]}));
} else { } else {
const embed = new client.embed().setColor(client.config.embedColor).addFields( const embed = new client.embed().setColor(client.config.embedColor).addFields(embedFields);
{name: 'Input', value: `\`\`\`js\n${code.slice(0,1020)}\n\`\`\``}, interaction.reply({embeds: [embed], components: [deleteEmbedRow]}).catch(()=>(interaction.channel as Discord.TextChannel).send({embeds: [embed], components: [deleteEmbedRow]}));
{name: 'Output', value: `\`\`\`${UsernameHelper.stripName('\n' + String(output)).slice(0,1016)}\n\`\`\``}
);
interaction.reply({embeds: [embed]}).catch(()=>(interaction.channel as Discord.TextChannel).send({embeds: [embed]}));
} }
} catch (err) { } catch (err) {
const embed = new client.embed().setColor('#560000').addFields( const embed = new client.embed().setColor('#560000').addFields(
{name: 'Input', value: `\`\`\`js\n${code.slice(0, 1020)}\n\`\`\``}, {name: 'Input', value: `\`\`\`js\n${code.slice(0, 1020)}\n\`\`\``},
{name: 'Output', value: `\`\`\`\n${err}\`\`\``} {name: 'Output', value: `\`\`\`\n${err}\`\`\``}
); );
interaction.reply({embeds: [embed]}).catch(()=>(interaction.channel as Discord.TextChannel).send({embeds: [embed]})).then(()=>{ interaction.reply({embeds: [embed], components: [deleteEmbedRow]}).catch(()=>(interaction.channel as Discord.TextChannel).send({embeds: [embed], components: [deleteEmbedRow]})).then(()=>{
const filter = (x:Discord.Message)=>x.content.includes('console') && x.author.id === interaction.user.id const filter = (x:Discord.Message)=>x.content.includes('console') && x.author.id === interaction.user.id
const messagecollector = (interaction.channel as Discord.TextChannel).createMessageCollector({filter, max: 1, time: 60000}); const messagecollector = (interaction.channel as Discord.TextChannel).createMessageCollector({filter, max: 1, time: 60000});
messagecollector.on('collect', collected=>{ messagecollector.on('collect', collected=>{
@ -45,6 +60,8 @@ export default {
collected.reply(`\`\`\`\n${UsernameHelper.stripName(err.stack)}\n\`\`\``); collected.reply(`\`\`\`\n${UsernameHelper.stripName(err.stack)}\n\`\`\``);
}); });
}); });
} finally {
console.log = console.log;
} }
}, },
update: async()=>{ update: async()=>{

View File

@ -21,15 +21,15 @@ export default {
); );
const youCanGetRole = (role:string, roleEmoji:string)=>`You can get the ${MessageTool.formatMention(client.config.mainServer.roles[role], 'role')} role from <#802283932430106624> by clicking :${roleEmoji}: button on a webhook's message.`; const youCanGetRole = (role:string, roleEmoji:string)=>`You can get the ${MessageTool.formatMention(client.config.mainServer.roles[role], 'role')} role from <#802283932430106624> by clicking :${roleEmoji}: button on a webhook's message.`;
({ ({
srp: ()=>FAQStore.reply(null, interaction, null, '[Ballyspring](<https://www.farming-simulator.com/mod.php?mod_id=270745>) is the map that is used in Survival Roleplay S4.\n\n> __Note__\n> The map won\'t look closely like the one in SRP as it is privately edited version of the public map.', null, false), srp: ()=>FAQStore.reply(interaction, null, '[Ballyspring](<https://www.farming-simulator.com/mod.php?mod_id=270745>) is the map that is used in Survival Roleplay S4.\n\n> __Note__\n> The map won\'t look closely like the one in SRP as it is privately edited version of the public map.', null, false),
vtcR: ()=>interaction.reply(youCanGetRole('vtcmember', 'truck')+'\n*VTC skin can also be found in <#801975222609641472> as well.*'), vtcR: ()=>interaction.reply(youCanGetRole('vtcmember', 'truck')+'\n*VTC skin can also be found in <#801975222609641472> as well.*'),
mpR: ()=>interaction.reply(youCanGetRole('mpplayer', 'tractor')), mpR: ()=>interaction.reply(youCanGetRole('mpplayer', 'tractor')),
ytscam: ()=>FAQStore.reply(client, interaction, 'Scammers in YouTube comments section', 'If you ever see a comment mentioning a giveaway or anything else, **it\'s a scam!**\nYou should report it to YouTube and move on or ignore it.\nP.S: They\'re on every channel and not just Daggerwin.', CDN('YTScam'), true), ytscam: ()=>FAQStore.reply(interaction, 'Scammers in YouTube comments section', 'If you ever see a comment mentioning a giveaway or anything else, **it\'s a scam!**\nYou should report it to YouTube and move on or ignore it.\nP.S: They\'re on every channel and not just Daggerwin.', CDN('YTScam'), true),
steamscam: ()=>FAQStore.reply(client, interaction, 'Steam account report scam', 'If you received a DM about this, please report it to Discord Moderators or open a [ticket](https://discord.com/channels/468835415093411861/942173932339986472/1054128182468546631)', CDN('SteamScam'), true), steamscam: ()=>FAQStore.reply(interaction, 'Steam account report scam', 'If you received a DM about this, please report it to Discord Moderators or open a [ticket](https://discord.com/channels/468835415093411861/942173932339986472/1054128182468546631)', CDN('SteamScam'), true),
fsVerifyGame: ()=>FAQStore.reply(client, interaction, 'Verifying your game files', `You can verify your game files if you experience any issues with your game.\n${verifyFaq}`, CDN('Steam-Epic-VerifyGamesLocation'), true), fsVerifyGame: ()=>FAQStore.reply(interaction, 'Verifying your game files', `You can verify your game files if you experience any issues with your game.\n${verifyFaq}`, CDN('Steam-Epic-VerifyGamesLocation'), true),
fsShader: ()=>FAQStore.reply(client, interaction, 'Clearing your shader cache folder', 'If your game keeps crashing shortly after opening your game, then the shaders might be an issue.\nTo resolve this, you can go to `Documents/My Games/FarmingSimulator2022` and delete the folder called `shader_cache`', CDN('shader_cache-Location'), true), fsShader: ()=>FAQStore.reply(interaction, 'Clearing your shader cache folder', 'If your game keeps crashing shortly after opening your game, then the shaders might be an issue.\nTo resolve this, you can go to `Documents/My Games/FarmingSimulator2022` and delete the folder called `shader_cache`', CDN('shader_cache-Location'), true),
fsLogfile: ()=>FAQStore.reply(client, interaction, 'Uploading your log file', 'You can find `log.txt` in `Documents/My Games/FarmingSimulator2022` and upload it into <#596989522395398144> along with your issue, so people can assist you further and help you resolve.', CDN('log_txt-Location'), true), fsLogfile: ()=>FAQStore.reply(interaction, 'Uploading your log file', 'You can find `log.txt` in `Documents/My Games/FarmingSimulator2022` and upload it into <#596989522395398144> along with your issue, so people can assist you further and help you resolve.', CDN('log_txt-Location'), true),
fsDevConsole: ()=>FAQStore.reply(client, interaction, 'Enabling the development console', '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).', CDN('enableDevConsole'), true) fsDevConsole: ()=>FAQStore.reply(interaction, 'Enabling the development console', '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).', CDN('enableDevConsole'), true)
} as any)[interaction.options.getString('question', true)](); } as any)[interaction.options.getString('question', true)]();
}, },
data: new Discord.SlashCommandBuilder() data: new Discord.SlashCommandBuilder()

View File

@ -1,10 +1,10 @@
import Discord from 'discord.js'; import Discord from 'discord.js';
import TClient from '../client.js'; import TClient from '../client.js';
import MessageTool from '../helpers/MessageTool.js';
export default { export default {
async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){
if (client.config.mainServer.id === interaction.guildId) { if (client.config.mainServer.id === interaction.guildId) {
if (!interaction.member.roles.cache.has(client.config.mainServer.roles.mpmanager) && !interaction.member.roles.cache.has(client.config.mainServer.roles.bottech) && !interaction.member.roles.cache.has(client.config.mainServer.roles.admin)) return client.youNeedRole(interaction, 'mpmanager'); if (!interaction.member.roles.cache.has(client.config.mainServer.roles.mpmanager) && !interaction.member.roles.cache.has(client.config.mainServer.roles.bottech) && !interaction.member.roles.cache.has(client.config.mainServer.roles.admin)) return MessageTool.youNeedRole(interaction, 'mpmanager');
} }
const maintenanceMessage = interaction.options.getString('message'); const maintenanceMessage = interaction.options.getString('message');
const activePlayersChannel = '739084625862852715'; const activePlayersChannel = '739084625862852715';

View File

@ -18,7 +18,7 @@ export default {
async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){
if (client.uptime < 35000) return interaction.reply('I have just restarted, please wait for MPLoop to finish initializing.'); if (client.uptime < 35000) return interaction.reply('I have just restarted, please wait for MPLoop to finish initializing.');
const serverSelector = interaction.options.getString('server'); const serverSelector = interaction.options.getString('server');
if (['468835769092669461', '1149238561934151690'].includes(interaction.channelId) && !client.isStaff(interaction.member) && ['status', 'players'].includes(interaction.options.getSubcommand())) return interaction.reply('Please use <#739084625862852715> for `/mp status/players` commands to prevent clutter in this channel.').then(()=>setTimeout(()=>interaction.deleteReply(), 6000)); if (['468835769092669461', '1149238561934151690'].includes(interaction.channelId) && !MessageTool.isStaff(interaction.member) && ['status', 'players'].includes(interaction.options.getSubcommand())) return interaction.reply('Please use <#739084625862852715> for `/mp status/players` commands to prevent clutter in this channel.').then(()=>setTimeout(()=>interaction.deleteReply(), 6000));
const database = await client.MPServer.findInCache(interaction.guildId); const database = await client.MPServer.findInCache(interaction.guildId);
const endpoint = await fetch(database[serverSelector].ip+'/feed/dedicated-server-stats.json?code='+database[serverSelector].code, {signal: AbortSignal.timeout(7500),headers:{'User-Agent':'Daggerbot - MPdata/undici'}}).then(r=>r.json() as Promise<FSData>); const endpoint = await fetch(database[serverSelector].ip+'/feed/dedicated-server-stats.json?code='+database[serverSelector].code, {signal: AbortSignal.timeout(7500),headers:{'User-Agent':'Daggerbot - MPdata/undici'}}).then(r=>r.json() as Promise<FSData>);
@ -190,7 +190,7 @@ export default {
}, },
url: async()=>{ url: async()=>{
if (client.config.mainServer.id == interaction.guildId) { if (client.config.mainServer.id == interaction.guildId) {
if (!interaction.member.roles.cache.has(client.config.mainServer.roles.mpmanager) && !interaction.member.roles.cache.has(client.config.mainServer.roles.bottech) && !interaction.member.roles.cache.has(client.config.mainServer.roles.admin)) return client.youNeedRole(interaction, 'mpmanager'); if (!interaction.member.roles.cache.has(client.config.mainServer.roles.mpmanager) && !interaction.member.roles.cache.has(client.config.mainServer.roles.bottech) && !interaction.member.roles.cache.has(client.config.mainServer.roles.admin)) return MessageTool.youNeedRole(interaction, 'mpmanager');
} }
const address = interaction.options.getString('address'); const address = interaction.options.getString('address');
if (!address){ if (!address){

View File

@ -3,11 +3,11 @@ import TClient from '../client.js';
import TSClient from '../helpers/TSClient.js'; import TSClient from '../helpers/TSClient.js';
import {Player,useTimeline,useQueue} from 'discord-player'; import {Player,useTimeline,useQueue} from 'discord-player';
import {SpotifyExtractor} from '@discord-player/extractor'; import {SpotifyExtractor} from '@discord-player/extractor';
import MessageTool from '../helpers/MessageTool.js';
export default { export default {
async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){
if (!client.config.botSwitches.music && !client.config.whitelist.includes(interaction.user.id)) return interaction.reply({content:'Music module is currently disabled.',ephemeral:true}); if (!client.config.botSwitches.music && !client.config.whitelist.includes(interaction.user.id)) return interaction.reply({content:'Music module is currently disabled.',ephemeral:true});
if (!client.isStaff(interaction.member) && !client.config.whitelist.includes(interaction.member.id)) return interaction.reply('Music module is close to being completed, some parts may be incomplete or broken, so it has been restricted to staff for time-being.'); if (!MessageTool.isStaff(interaction.member) && !client.config.whitelist.includes(interaction.member.id)) return interaction.reply('Music module is close to being completed, some parts may be incomplete or broken, so it has been restricted to staff for time-being.');
const player = Player.singleton(client); const player = Player.singleton(client);
await player.extractors.register(SpotifyExtractor,{clientId: (await TSClient.Token()).spotify.client, clientSecret: (await TSClient.Token()).spotify.secret}); await player.extractors.register(SpotifyExtractor,{clientId: (await TSClient.Token()).spotify.client, clientSecret: (await TSClient.Token()).spotify.secret});
if (!interaction.member.voice.channel) return interaction.reply('Please join a voice channel first to use the command.'); if (!interaction.member.voice.channel) return interaction.reply('Please join a voice channel first to use the command.');

View File

@ -1,11 +1,11 @@
import Discord from 'discord.js'; import Discord from 'discord.js';
import TClient from '../client.js'; import TClient from '../client.js';
import {writeFileSync, existsSync, mkdirSync} from 'node:fs'; import {writeFileSync, existsSync, mkdirSync} from 'node:fs';
import MessageTool from '../helpers/MessageTool.js';
export default { export default {
async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){
if (client.config.mainServer.id === interaction.guildId) { if (client.config.mainServer.id === interaction.guildId) {
if (!interaction.member.roles.cache.has(client.config.mainServer.roles.mpmod) && !interaction.member.roles.cache.has(client.config.mainServer.roles.bottech)) return client.youNeedRole(interaction, 'mpmod'); if (!interaction.member.roles.cache.has(client.config.mainServer.roles.mpmod) && !interaction.member.roles.cache.has(client.config.mainServer.roles.bottech)) return MessageTool.youNeedRole(interaction, 'mpmod');
} }
const channelId = '1084864116776251463'; // #mp-announcements const channelId = '1084864116776251463'; // #mp-announcements
({ ({

View File

@ -1,9 +1,10 @@
import Discord from 'discord.js'; import Discord from 'discord.js';
import TClient from '../client.js'; import TClient from '../client.js';
import MessageTool from '../helpers/MessageTool.js';
export default { export default {
async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){
if (client.config.mainServer.id === interaction.guildId) { if (client.config.mainServer.id === interaction.guildId) {
if (!client.isStaff(interaction.member)) return client.youNeedRole(interaction, 'dcmod'); if (!MessageTool.isStaff(interaction.member)) return MessageTool.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})

View File

@ -30,11 +30,11 @@ export default {
const columns = ['Command name', 'Count']; const columns = ['Command name', 'Count'];
const includedCommands = client.commands.filter(x=>x.uses).sort((a,b)=>b.uses - a.uses); const includedCommands = client.commands.filter(x=>x.uses).sort((a,b)=>b.uses - a.uses);
if (includedCommands.size === 0) return interaction.reply(`No commands have been used yet.\nUptime: **${FormatTime(client.uptime, 3, {longNames: true, commas: true})}**`); if (includedCommands.size === 0) return interaction.reply(`No commands have been used yet.\nUptime: **${FormatTime(client.uptime, 3, {longNames: true, commas: true})}**`);
const nameLength = Math.max(...includedCommands.map(x=>x.command.default.data.name.length), columns[0].length) + 2; const nameLength = Math.max(...includedCommands.map(x=>x.command.data.name.length), columns[0].length) + 2;
const amountLength = Math.max(...includedCommands.map(x=>x.uses.toString().length), columns[1].length) + 1; const amountLength = Math.max(...includedCommands.map(x=>x.uses.toString().length), columns[1].length) + 1;
const rows = [`${columns[0] + ' '.repeat(nameLength - columns[0].length)}|${' '.repeat(amountLength - columns[1].length) + columns[1]}\n`, '-'.repeat(nameLength) + '-'.repeat(amountLength) + '\n']; const rows = [`${columns[0] + ' '.repeat(nameLength - columns[0].length)}|${' '.repeat(amountLength - columns[1].length) + columns[1]}\n`, '-'.repeat(nameLength) + '-'.repeat(amountLength) + '\n'];
includedCommands.forEach(command=>{ includedCommands.forEach(command=>{
const name = command.command.default.data.name; const name = command.command.data.name;
const count = command.uses.toString(); const count = command.uses.toString();
rows.push(`${name + ' '.repeat(nameLength - name.length)}${' '.repeat(amountLength - count.length) + count}\n`); rows.push(`${name + ' '.repeat(nameLength - name.length)}${' '.repeat(amountLength - count.length) + count}\n`);
}); });

View File

@ -10,7 +10,7 @@ export default {
const theirIdea = (await client.suggestion._content.findById(suggestionIDReply))?.idea; const theirIdea = (await client.suggestion._content.findById(suggestionIDReply))?.idea;
const timeFormatting = client.moment().format('DD/MM/YY h:mm A'); const timeFormatting = client.moment().format('DD/MM/YY h:mm A');
const stateChanged = 'Suggestion state has been successfully updated and DM is sent.'; const stateChanged = 'Suggestion state has been successfully updated and DM is sent.';
const dmFail = `Failed to send a DM to <@${userid}>, they possibly have it turned off or blocked me.\nSuggestion ID: **${suggestionIDReply}**`; const dmFail = `Failed to send a DM to ${MessageTool.formatMention(userid, 'user')}, they possibly have it turned off or blocked me.\nSuggestion ID: **${suggestionIDReply}**`;
({ ({
your: async()=>{ your: async()=>{
const webhook = await (await (client.channels.fetch(client.config.mainServer.channels.bot_suggestions) as Promise<Discord.TextChannel>)).fetchWebhooks().then(x => x.find(y => y.name === client.user.username)); const webhook = await (await (client.channels.fetch(client.config.mainServer.channels.bot_suggestions) as Promise<Discord.TextChannel>)).fetchWebhooks().then(x => x.find(y => y.name === client.user.username));
@ -36,7 +36,7 @@ export default {
}, },
approve: async()=>{ approve: async()=>{
if (client.config.mainServer.id === interaction.guildId) { if (client.config.mainServer.id === interaction.guildId) {
if (!interaction.member.roles.cache.has(client.config.mainServer.roles.bottech)) return client.youNeedRole(interaction, 'bottech'); if (!interaction.member.roles.cache.has(client.config.mainServer.roles.bottech)) return MessageTool.youNeedRole(interaction, 'bottech');
} }
if ((await client.suggestion._content.findById(suggestionIDReply)).state === 'Rejected') return interaction.reply({content: 'This suggestion\'s state is locked and cannot be modified.', ephemeral: true}); if ((await client.suggestion._content.findById(suggestionIDReply)).state === 'Rejected') return interaction.reply({content: 'This suggestion\'s state is locked and cannot be modified.', ephemeral: true});
(await client.users.fetch(userid)).send({embeds: [new client.embed() (await client.users.fetch(userid)).send({embeds: [new client.embed()
@ -51,7 +51,7 @@ export default {
}, },
reject: async()=>{ reject: async()=>{
if (client.config.mainServer.id === interaction.guildId) { if (client.config.mainServer.id === interaction.guildId) {
if (!interaction.member.roles.cache.has(client.config.mainServer.roles.bottech)) return client.youNeedRole(interaction, 'bottech'); if (!interaction.member.roles.cache.has(client.config.mainServer.roles.bottech)) return MessageTool.youNeedRole(interaction, 'bottech');
} }
if ((await client.suggestion._content.findById(suggestionIDReply)).state === 'Approved') return interaction.reply({content: 'This suggestion\'s state is locked and cannot be modified.', ephemeral: true}); if ((await client.suggestion._content.findById(suggestionIDReply)).state === 'Approved') return interaction.reply({content: 'This suggestion\'s state is locked and cannot be modified.', ephemeral: true});
(await client.users.fetch(userid)).send({embeds: [new client.embed() (await client.users.fetch(userid)).send({embeds: [new client.embed()

View File

@ -8,7 +8,7 @@ export default {
// If you question all those '?.', let me tell you: Discord.JS is fricking stupid and I am too stressed to find a solution for it. // If you question all those '?.', let me tell you: Discord.JS is fricking stupid and I am too stressed to find a solution for it.
}, },
async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){
if (interaction.options.getSubcommandGroup() === 'management' && !client.isStaff(interaction.member) && !client.config.whitelist.includes(interaction.member.id)) return client.youNeedRole(interaction, 'dcmod'); if (interaction.options.getSubcommandGroup() === 'management' && !MessageTool.isStaff(interaction.member) && !client.config.whitelist.includes(interaction.member.id)) return MessageTool.youNeedRole(interaction, 'dcmod');
const tagData = async()=>await client.tags._content.findOne({_id: interaction.options.getString('name')}); const tagData = async()=>await client.tags._content.findOne({_id: interaction.options.getString('name')});
const tagMeta = { const tagMeta = {
isEmbedTrue: async()=>(await tagData()).embedBool, isEmbedTrue: async()=>(await tagData()).embedBool,

View File

@ -1,10 +1,10 @@
import Discord from 'discord.js'; import Discord from 'discord.js';
import TClient from '../client.js'; import TClient from '../client.js';
import Logger from '../helpers/Logger.js'; import Logger from '../helpers/Logger.js';
import MessageTool from '../helpers/MessageTool.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 as Discord.GuildMember)) return client.youNeedRole(interaction, 'dcmod'); if (!MessageTool.isStaff(interaction.member as Discord.GuildMember)) return MessageTool.youNeedRole(interaction, 'dcmod');
const punishment = (await client.punishments._content.find({})).find(x=>x._id === interaction.options.getInteger('case_id', true)); const punishment = (await client.punishments._content.find({})).find(x=>x._id === interaction.options.getInteger('case_id', true));
if (!punishment) return interaction.reply({content: 'Invalid Case ID', ephemeral: true}); if (!punishment) return interaction.reply({content: 'Invalid Case ID', ephemeral: true});
if (punishment.expired) return interaction.reply('This case has been overwritten by another case.'); if (punishment.expired) return interaction.reply('This case has been overwritten by another case.');

View File

@ -11,17 +11,17 @@ export default {
if (!client.config.botSwitches.commands && !client.config.whitelist.includes(interaction.user.id)) return interaction.reply({content: `I am currently operating in development mode.\nPlease notify <@${client.config.whitelist[0]}> if this is a mistake.`, ephemeral: true}); if (!client.config.botSwitches.commands && !client.config.whitelist.includes(interaction.user.id)) return interaction.reply({content: `I am currently operating in development mode.\nPlease notify <@${client.config.whitelist[0]}> if this is a mistake.`, ephemeral: true});
if (commandFile){ if (commandFile){
try{ try{
commandFile.command.default.run(client, interaction); commandFile.command.run(client, interaction);
commandFile.command.default.autocomplete ? commandFile.command.default.autocomplete(interaction) : undefined; commandFile.command.autocomplete ? commandFile.command.autocomplete(interaction) : undefined;
commandFile.uses ? commandFile.uses++ : commandFile.uses = 1; commandFile.uses ? commandFile.uses++ : commandFile.uses = 1;
} catch (error){ } catch (error){
console.log(`An error occurred while running command "${interaction.commandName} ${interaction.options.getSubcommand(false) ?? ''}"`, error, error.stack); console.log(`An error occurred while running command "${interaction.commandName} ${interaction.options.getSubcommandGroup(false) ?? ''} ${interaction.options.getSubcommand(false) ?? ''}"`, error, error.stack);
return interaction.reply('An error occurred while executing that command.'); return interaction.reply('An error occurred while running that command.');
} }
} }
} else if (interaction.isAutocomplete()){ } else if (interaction.isAutocomplete()){
try { try {
await client.commands.get(interaction.commandName).command.default.autocomplete(client, interaction); await client.commands.get(interaction.commandName).command.autocomplete(client, interaction);
} catch (error){ } catch (error){
return console.log('An error occurred while running autocomplete:\n', error) return console.log('An error occurred while running autocomplete:\n', error)
} }
@ -45,6 +45,10 @@ export default {
interaction.member.roles.add(RoleID, 'Button Role'); interaction.member.roles.add(RoleID, 'Button Role');
interaction.reply({content: `You have been added to <@&${RoleID}>`, ephemeral: true}) interaction.reply({content: `You have been added to <@&${RoleID}>`, ephemeral: true})
} }
} else if (interaction.customId.includes('deleteEmbed')) {
if (!client.config.whitelist.includes(interaction.user.id)) return interaction.reply({content: '*Only whitelisted people can delete this embed.*', ephemeral: true});
interaction.message.edit({content: '*Deleted.*', embeds: [], components: []});
Logger.forwardToConsole('log', 'InteractionLog', `Embed has been deleted at ${interaction.message.url}`);
} else Logger.forwardToConsole('log', 'InteractionLog', `Button has been pressed at ${interaction.message.url}`); } else Logger.forwardToConsole('log', 'InteractionLog', `Button has been pressed at ${interaction.message.url}`);
} }
} }

View File

@ -4,11 +4,11 @@ import Response from '../funcs/ResponseModule.js';
import CmdTrigger from '../funcs/CmdModule.js'; import CmdTrigger from '../funcs/CmdModule.js';
import Logger from '../helpers/Logger.js'; import Logger from '../helpers/Logger.js';
import Automoderator from '../funcs/Automod.js'; import Automoderator from '../funcs/Automod.js';
import MessageTool from '../helpers/MessageTool.js';
export default { export default {
async run(client:TClient, message:Discord.Message){ async run(client:TClient, message:Discord.Message){
if (message.author.bot) return; if (message.author.bot) return;
if (!message.inGuild()) return (client.channels.resolve(client.config.mainServer.channels.logs) as Discord.TextChannel).send({content: `<:fish_unamused:1083675172407623711> <@${client.config.whitelist[0]}>\n**${message.author.username}** tried to send me a DM, their message is:\`\`\`${message.content}\`\`\``, allowedMentions: {parse: ['users']}}); if (!message.inGuild()) return (client.channels.resolve(client.config.mainServer.channels.logs) as Discord.TextChannel).send({content: `<:fish_unamused:1083675172407623711> ${MessageTool.formatMention(client.config.whitelist[0], 'user')}\n**${message.author.username}** tried to send me a DM, their message is:\`\`\`${message.content}\`\`\``, allowedMentions: {parse: ['users']}});
let automodded: boolean; let automodded: boolean;
if (client.config.botSwitches.automod && !message.member.roles.cache.has(client.config.mainServer.roles.admin) && message.guildId == client.config.mainServer.id){ if (client.config.botSwitches.automod && !message.member.roles.cache.has(client.config.mainServer.roles.admin) && message.guildId == client.config.mainServer.id){
@ -18,7 +18,7 @@ export default {
message.delete().catch(()=>Logger.forwardToConsole('log', 'AUTOMOD-BANNEDWORDS', automodFailReason)); message.delete().catch(()=>Logger.forwardToConsole('log', 'AUTOMOD-BANNEDWORDS', automodFailReason));
message.channel.send('That word isn\'t allowed here.').then(x=>setTimeout(()=>x.delete(), 10000)); message.channel.send('That word isn\'t allowed here.').then(x=>setTimeout(()=>x.delete(), 10000));
await Automoderator.repeatedMessages(client, message, 30000, 3, 'bw', '30m', 'Constant swearing'); await Automoderator.repeatedMessages(client, message, 30000, 3, 'bw', '30m', 'Constant swearing');
} else if (message.content.toLowerCase().includes('discord.gg/') && !client.isStaff(message.member as Discord.GuildMember)){ } else if (message.content.toLowerCase().includes('discord.gg/') && !MessageTool.isStaff(message.member as Discord.GuildMember)){
const url = message.content.split(' ').find(x=>x.includes('discord.gg/')); const url = message.content.split(' ').find(x=>x.includes('discord.gg/'));
const validInvite = await client.fetchInvite(url).catch(()=>undefined); const validInvite = await client.fetchInvite(url).catch(()=>undefined);
if (validInvite && validInvite.guild?.id !== client.config.mainServer.id){ if (validInvite && validInvite.guild?.id !== client.config.mainServer.id){
@ -60,14 +60,14 @@ export default {
CmdTrigger.TriggerTest(message, '!!_test-trigger'); CmdTrigger.TriggerTest(message, '!!_test-trigger');
if (message.type === 8 && message.channelId === GeneralChatID) message.channel.send({content: outgoingArrays.guildBoost[Math.floor(Math.random() * outgoingArrays.guildBoost.length)], allowedMentions: {parse: ['users']}}) if (message.type === 8 && message.channelId === GeneralChatID) message.channel.send({content: outgoingArrays.guildBoost[Math.floor(Math.random() * outgoingArrays.guildBoost.length)], allowedMentions: {parse: ['users']}})
if (message.mentions.members.has('309373272594579456') && !client.isStaff(message.member)) message.reply('Please don\'t tag Daggerwin, read rule 14 in <#468846117405196289>'); if (message.mentions.members.has('309373272594579456') && !MessageTool.isStaff(message.member)) message.reply('Please don\'t tag Daggerwin, read rule 14 in <#468846117405196289>');
if (message.mentions.members.has('215497515934416896') && !client.isStaff(message.member) && message.type != 19) message.reply('Please don\'t tag Monster unless it\'s important!'); if (message.mentions.members.has('215497515934416896') && !MessageTool.isStaff(message.member) && message.type != 19) message.reply('Please don\'t tag Monster unless it\'s important!');
if (incomingArrays.password.some(e=>message.content.toLowerCase().includes(e))) message.reply('Password and other details can be found in <#543494084363288637>'); if (incomingArrays.password.some(e=>message.content.toLowerCase().includes(e))) message.reply('Password and other details can be found in <#543494084363288637>');
if (incomingArrays.cantRead.some(e=>message.content.toLowerCase().includes(e))) message.reply('https://tenor.com/view/aristocats-george-pen-cap-meticulous-gif-5330931'); if (incomingArrays.cantRead.some(e=>message.content.toLowerCase().includes(e))) message.reply('https://tenor.com/view/aristocats-george-pen-cap-meticulous-gif-5330931');
if (message.content.toLowerCase().includes('is daggerbot working')) message.reply('https://tenor.com/view/i-still-feel-alive-living-existing-active-singing-gif-14630579'); if (message.content.toLowerCase().includes('is daggerbot working')) message.reply('https://tenor.com/view/i-still-feel-alive-living-existing-active-singing-gif-14630579');
if (incomingArrays.deadChat.some(e=>message.content.toLowerCase().includes(e))) message.reply('https://cdn.discordapp.com/attachments/925589318276382720/1011333656167579849/F57G5ZS.png'); if (incomingArrays.deadChat.some(e=>message.content.toLowerCase().includes(e))) message.reply('https://cdn.discordapp.com/attachments/925589318276382720/1011333656167579849/F57G5ZS.png');
if (Automoderator.scanMsg(message).includes('nawdic') && incomingArrays.theyBrokeIt.some(e=>Automoderator.scanMsg(message).includes(e)) && client.isStaff(message.member) && message.channelId !== '516344221452599306') message.reply({embeds: [new client.embed().setTitle('*Nawdic has done an oopsie*').setImage('https://c.tenor.com/JSj9ie_MD9kAAAAC/kopfsch%C3%BCtteln-an-kopf-fassen-oh-no.gif').setColor(client.config.embedColor)]}); if (Automoderator.scanMsg(message).includes('nawdic') && incomingArrays.theyBrokeIt.some(e=>Automoderator.scanMsg(message).includes(e)) && MessageTool.isStaff(message.member) && message.channelId !== '516344221452599306') message.reply({embeds: [new client.embed().setTitle('*Nawdic has done an oopsie*').setImage('https://c.tenor.com/JSj9ie_MD9kAAAAC/kopfsch%C3%BCtteln-an-kopf-fassen-oh-no.gif').setColor(client.config.embedColor)]});
if (Automoderator.scanMsg(message).includes('monster') && incomingArrays.theyBrokeIt.some(e=>Automoderator.scanMsg(message).includes(e)) && client.isStaff(message.member) && message.channelId !== '516344221452599306') message.reply({embeds: [new client.embed().setTitle('*Monster has broken something*').setImage('https://media.tenor.com/ZIzIjb_wvEoAAAAC/face-palm.gif').setColor(client.config.embedColor)]}); if (Automoderator.scanMsg(message).includes('monster') && incomingArrays.theyBrokeIt.some(e=>Automoderator.scanMsg(message).includes(e)) && MessageTool.isStaff(message.member) && message.channelId !== '516344221452599306') message.reply({embeds: [new client.embed().setTitle('*Monster has broken something*').setImage('https://media.tenor.com/ZIzIjb_wvEoAAAAC/face-palm.gif').setColor(client.config.embedColor)]});
} }
} }
} }

View File

@ -1,11 +1,12 @@
import Discord from 'discord.js'; import Discord from 'discord.js';
import TClient from '../client.js'; import TClient from '../client.js';
import MessageTool from '../helpers/MessageTool.js';
import {escapeCodeBlock} from 'discord.js'; import {escapeCodeBlock} from 'discord.js';
export default { export default {
async run(client:TClient, oldMsg:Discord.Message, newMsg:Discord.Message){ async run(client:TClient, oldMsg:Discord.Message, newMsg:Discord.Message){
if (!client.config.botSwitches.logs) return; if (!client.config.botSwitches.logs) return;
if (oldMsg.guild?.id != client.config.mainServer.id || oldMsg.author === null || oldMsg?.author.bot || oldMsg.partial || newMsg.partial || !newMsg.member || ['548032776830582794', '541677709487505408', '949380187668242483'].includes(newMsg.channelId)) return; if (oldMsg.guild?.id != client.config.mainServer.id || oldMsg.author === null || oldMsg?.author.bot || oldMsg.partial || newMsg.partial || !newMsg.member || ['548032776830582794', '541677709487505408', '949380187668242483'].includes(newMsg.channelId)) return;
if (await client.bannedWords._content.findOne({_id:newMsg.content.toLowerCase().replaceAll(/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?\n]/g, ' ').split(' ')}) && (!client.isStaff(newMsg.member))) newMsg.delete(); if (await client.bannedWords._content.findOne({_id:newMsg.content.toLowerCase().replaceAll(/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?\n]/g, ' ').split(' ')}) && (!MessageTool.isStaff(newMsg.member))) newMsg.delete();
if (newMsg.content === oldMsg.content) return; if (newMsg.content === oldMsg.content) return;
(client.channels.resolve(client.config.mainServer.channels.logs) as Discord.TextChannel).send({embeds: [new client.embed().setColor(client.config.embedColor).setTimestamp().setAuthor({name: `Author: ${oldMsg.author.username} (${oldMsg.author.id})`, iconURL: `${oldMsg.author.displayAvatarURL()}`}).setTitle('Message edited').setDescription(`<@${oldMsg.author.id}>\nOld content:\n\`\`\`\n${oldMsg.content.length < 1 ? '(Attachment)' : escapeCodeBlock(oldMsg.content.slice(0,2048))}\n\`\`\`\nNew content:\n\`\`\`\n${escapeCodeBlock(newMsg.content.slice(0,2048))}\`\`\`\nChannel: <#${oldMsg.channelId}>`)], components: [new Discord.ActionRowBuilder<Discord.ButtonBuilder>().addComponents(new Discord.ButtonBuilder().setStyle(5).setURL(`${oldMsg.url}`).setLabel('Jump to message'))]}); (client.channels.resolve(client.config.mainServer.channels.logs) as Discord.TextChannel).send({embeds: [new client.embed().setColor(client.config.embedColor).setTimestamp().setAuthor({name: `Author: ${oldMsg.author.username} (${oldMsg.author.id})`, iconURL: `${oldMsg.author.displayAvatarURL()}`}).setTitle('Message edited').setDescription(`<@${oldMsg.author.id}>\nOld content:\n\`\`\`\n${oldMsg.content.length < 1 ? '(Attachment)' : escapeCodeBlock(oldMsg.content.slice(0,2048))}\n\`\`\`\nNew content:\n\`\`\`\n${escapeCodeBlock(newMsg.content.slice(0,2048))}\`\`\`\nChannel: <#${oldMsg.channelId}>`)], components: [new Discord.ActionRowBuilder<Discord.ButtonBuilder>().addComponents(new Discord.ButtonBuilder().setStyle(5).setURL(`${oldMsg.url}`).setLabel('Jump to message'))]});
} }

View File

@ -1,8 +1,10 @@
import Discord from 'discord.js'; import Discord from 'discord.js';
import TClient from '../client.js'; import TClient from '../client.js';
import chalk from 'chalk';
export default { export default {
async run(client:TClient){ async run(client:TClient){
const botSwitches = Object.entries(client.config.botSwitches).map(([k, v])=>`${chalk.yellow(k)}${chalk.black(':')} ${v}`).join('\n').replace(/true/g, chalk.green('true')).replace(/false/g, chalk.red('false'));
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(()=>{ setInterval(()=>{
@ -19,7 +21,7 @@ export default {
} }
console.log(`${client.user.username} has logged into Discord API`); console.log(`${client.user.username} has logged into Discord API`);
console.log(client.config.botSwitches, client.config.whitelistedServers); console.log(client.config.botSwitches, client.config.whitelistedServers);
(client.channels.resolve(client.config.mainServer.channels.bot_status) as Discord.TextChannel).send({content: `${client.user.username} is active`, embeds:[new client.embed().setColor(client.config.embedColor).setDescription(`\`\`\`json\n${Object.entries(client.config.botSwitches).map(x=>`${x[0]}: ${x[1]}`).join('\n')}\`\`\``)]}); (client.channels.resolve(client.config.mainServer.channels.bot_status) as Discord.TextChannel).send({content: `**${client.user.username}** is active`, embeds:[new client.embed().setColor(client.config.embedColor).setDescription(`**\`\`\`ansi\n${botSwitches}\n\`\`\`**`)]});
console.timeEnd('Startup') console.timeEnd('Startup')
} }
} }

View File

@ -1,9 +1,9 @@
import Discord from 'discord.js'; import Discord from 'discord.js';
import TClient from '../client.js'; import TClient from '../client.js';
import Logger from '../helpers/Logger.js'; import Logger from '../helpers/Logger.js';
import MessageTool from '../helpers/MessageTool.js';
export default async(client:TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>, type: string)=>{ export default async(client:TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>, type: string)=>{
if (!client.isStaff(interaction.member as Discord.GuildMember)) return client.youNeedRole(interaction, 'dcmod'); if (!MessageTool.isStaff(interaction.member as Discord.GuildMember)) return MessageTool.youNeedRole(interaction, 'dcmod');
const time = interaction.options.getString('time') ?? undefined; const time = interaction.options.getString('time') ?? undefined;
const reason = interaction.options.getString('reason') ?? 'Reason unspecified'; const reason = interaction.options.getString('reason') ?? 'Reason unspecified';

View File

@ -1,10 +1,12 @@
import Discord from 'discord.js'; import Discord from 'discord.js';
import TClient from '../client.js';
import MessageTool from './MessageTool.js'; import MessageTool from './MessageTool.js';
import {Config} from 'src/typings/interfaces';
import {readFileSync} from 'node:fs';
const config:Config = JSON.parse(readFileSync('src/config.json', 'utf8'));
export default class FAQStore { export default class FAQStore {
protected static readonly errorMsg:string = 'Failed to send the message, please report to **Toast** if it continues.'; protected static readonly errorMsg:string = 'Failed to send the message, please report to **Toast** if it continues.';
static async reply(client:TClient|null, interaction:Discord.ChatInputCommandInteraction, title:string|null, message:string, image:string|null, useEmbed:boolean=false) { static async reply(interaction:Discord.ChatInputCommandInteraction, title:string|null, message:string, image:string|null, useEmbed:boolean=false) {
if (useEmbed) return interaction.reply({embeds: [MessageTool.embedStruct(client.config.embedColor, title, message, image)]}).catch(err=>interaction.reply(this.errorMsg+'\n'+err)) if (useEmbed) return interaction.reply({embeds: [MessageTool.embedStruct(config.embedColor, title, message, image)]}).catch(err=>interaction.reply(this.errorMsg+'\n'+err))
else return interaction.reply(message).catch(err=>interaction.reply(this.errorMsg+'\n'+err)) else return interaction.reply(message).catch(err=>interaction.reply(this.errorMsg+'\n'+err))
} }
} }

View File

@ -1,4 +1,8 @@
import Discord from 'discord.js'; import Discord from 'discord.js';
import {readFileSync} from 'node:fs';
import {Config} from 'src/typings/interfaces';
const config:Config = JSON.parse(readFileSync('src/config.json', 'utf8'));
type RoleKeys = keyof typeof config.mainServer.roles;
export default class MessageTool { export default class MessageTool {
static embedMusic(color:Discord.ColorResolvable, title:string, thumbnail?:string, footer?:string){ static embedMusic(color:Discord.ColorResolvable, title:string, thumbnail?:string, footer?:string){
@ -19,5 +23,11 @@ export default class MessageTool {
static formatMention(mention:string, type:'user'|'channel'|'role'){ static formatMention(mention:string, type:'user'|'channel'|'role'){
return `<@${type === 'role' ? '&' : type === 'channel' ? '#' : ''}${mention}>` return `<@${type === 'role' ? '&' : type === 'channel' ? '#' : ''}${mention}>`
} }
static isStaff(guildMember:Discord.GuildMember){
return config.mainServer.staffRoles.map((x:string)=>config.mainServer.roles[x]).some((x:string)=>guildMember.roles.cache.has(x));
}
static youNeedRole(interaction:Discord.CommandInteraction, role:RoleKeys){
return interaction.reply(`This command is restricted to ${this.formatMention(config.mainServer.roles[role], 'role')}`);
}
} }
// I want to come up with better name instead of calling this file "MessageTool", but I am super bad at naming things. // I want to come up with better name instead of calling this file "MessageTool", but I am super bad at naming things.

View File

@ -697,6 +697,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"chalk@npm:5.3.0":
version: 5.3.0
resolution: "chalk@npm:5.3.0"
checksum: 623922e077b7d1e9dedaea6f8b9e9352921f8ae3afe739132e0e00c275971bdd331268183b2628cf4ab1727c45ea1f28d7e24ac23ce1db1eb653c414ca8a5a80
languageName: node
linkType: hard
"chownr@npm:^2.0.0": "chownr@npm:^2.0.0":
version: 2.0.0 version: 2.0.0
resolution: "chownr@npm:2.0.0" resolution: "chownr@npm:2.0.0"
@ -800,13 +807,14 @@ __metadata:
"@types/node": 20.8.2 "@types/node": 20.8.2
"@types/node-cron": 3.0.9 "@types/node-cron": 3.0.9
canvas: 2.11.2 canvas: 2.11.2
chalk: 5.3.0
discord-player: 6.6.4 discord-player: 6.6.4
discord.js: 14.13.0 discord.js: 14.13.0
libsodium-wrappers: 0.7.13 libsodium-wrappers: 0.7.13
moment: 2.29.4 moment: 2.29.4
mongoose: 7.5.4 mongoose: 7.5.4
ms: 2.1.3 ms: 2.1.3
node-cron: ^3.0.2 node-cron: 3.0.2
prism-media: 1.3.5 prism-media: 1.3.5
redis: 4.6.10 redis: 4.6.10
systeminformation: 5.21.10 systeminformation: 5.21.10
@ -1744,7 +1752,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"node-cron@npm:^3.0.2": "node-cron@npm:3.0.2":
version: 3.0.2 version: 3.0.2
resolution: "node-cron@npm:3.0.2" resolution: "node-cron@npm:3.0.2"
dependencies: dependencies: