1
0
mirror of https://github.com/toast-ts/Daggerbot-TS.git synced 2024-11-18 00:31:00 -05:00

Good morning pals!

This commit is contained in:
toast-ts 2024-02-18 05:54:55 +11:00
parent baf717efb4
commit 659cb4808e
9 changed files with 39 additions and 64 deletions

View File

@ -52,9 +52,11 @@ export default class TClient extends Discord.Client {
Discord.GatewayIntentBits.GuildModeration, Discord.GatewayIntentBits.GuildInvites, Discord.GatewayIntentBits.GuildModeration, Discord.GatewayIntentBits.GuildInvites,
Discord.GatewayIntentBits.GuildPresences, Discord.GatewayIntentBits.MessageContent, Discord.GatewayIntentBits.GuildPresences, Discord.GatewayIntentBits.MessageContent,
Discord.GatewayIntentBits.GuildMessages, Discord.GatewayIntentBits.DirectMessages Discord.GatewayIntentBits.GuildMessages, Discord.GatewayIntentBits.DirectMessages
], partials: [ ],
Discord.Partials.Channel, Discord.Partials.Message partials: [
], allowedMentions: {users:[], roles:[]} Discord.Partials.Message
],
allowedMentions: {users:[], roles:[]}
}) })
this.config = ConfigHelper.loadConfig() as Config; this.config = ConfigHelper.loadConfig() as Config;
this.setMaxListeners(50); this.setMaxListeners(50);

View File

@ -3,7 +3,7 @@ import TClient from '../client.js';
import MessageTool from '../helpers/MessageTool.js'; import MessageTool from '../helpers/MessageTool.js';
export default class InviteInfo { export default class InviteInfo {
static async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ static async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){
await client.fetchInvite(interaction.options.getString('code',true).replace(/(https:\/\/|discord.gg\/)/g,'')).then(async inviteData=> await client.fetchInvite(interaction.options.getString('code',true).replace(/(https:\/\/)/g,'')).then(async inviteData=>
await interaction.reply({embeds:[new client.embed() await interaction.reply({embeds:[new client.embed()
.setColor(client.config.embedColor).setURL(`https://discord.gg/${inviteData.code}`).setTitle(inviteData.guild.name).setDescription(MessageTool.concatMessage( .setColor(client.config.embedColor).setURL(`https://discord.gg/${inviteData.code}`).setTitle(inviteData.guild.name).setDescription(MessageTool.concatMessage(
`ID: \`${inviteData.guild.id}\``, `ID: \`${inviteData.guild.id}\``,

View File

@ -120,16 +120,12 @@ export default class MP {
const reason = interaction.options.getString('reason'); const reason = interaction.options.getString('reason');
const channel = interaction.guild.channels.cache.get(channels.activePlayers) as Discord.TextChannel; const channel = interaction.guild.channels.cache.get(channels.activePlayers) as Discord.TextChannel;
const embed = new client.embed().setColor(client.config.embedColor).setAuthor({name: interaction.member.displayName, iconURL: interaction.member.displayAvatarURL({size:1024})}).setTimestamp(); const embed = new client.embed().setColor(client.config.embedColor).setAuthor({name: interaction.member.displayName, iconURL: interaction.member.displayAvatarURL({size:1024})}).setTimestamp();
const isLocked = channel.permissionsFor(interaction.guildId).has('SendMessages');
const titleAction = isLocked ? '🔒 Locked' : '🔓 Unlocked';
if (channel.permissionsFor(interaction.guildId).has('SendMessages')) { channel.permissionOverwrites.edit(interaction.guildId, {SendMessages: !isLocked}, {type: 0, reason: `${isLocked ? 'Locked' : 'Unlocked'} by ${interaction.member.displayName}`});
channel.permissionOverwrites.edit(interaction.guildId, {SendMessages: false}, {type: 0, reason: `Locked by ${interaction.member.displayName}`}); channel.send({embeds: [embed.setTitle(titleAction).setDescription(`**Reason:**\n${reason}`)]});
channel.send({embeds: [embed.setTitle('🔒 Locked').setDescription(`**Reason:**\n${reason}`)]}); interaction.reply({content: `${MessageTool.formatMention(channels.activePlayers, 'channel')} ${isLocked ? 'locked' : 'unlocked'} successfully`, ephemeral: true});
interaction.reply({content: `${MessageTool.formatMention(channels.activePlayers, 'channel')} locked successfully`, ephemeral: true});
} else {
channel.permissionOverwrites.edit(interaction.guildId, {SendMessages: true}, {type: 0, reason: `Unlocked by ${interaction.member.displayName}`});
channel.send({embeds: [embed.setTitle('🔓 Unlocked').setDescription(`**Reason:**\n${reason}`)]});
interaction.reply({content: `${MessageTool.formatMention(channels.activePlayers, 'channel')} unlocked successfully`, ephemeral: true});
}
}, },
start: async()=>{ start: async()=>{
if (client.config.dcServer.id === interaction.guildId) { if (client.config.dcServer.id === interaction.guildId) {

View File

@ -28,22 +28,23 @@ export default class Statistics {
const nameLen = Math.max(...cmdUses.map(x=>x.command.data.name.length), col[0].length) + 2; const nameLen = Math.max(...cmdUses.map(x=>x.command.data.name.length), col[0].length) + 2;
const usesLen = Math.max(...cmdUses.map(x=>x.uses.toString().length), col[1].length) + 1; const usesLen = Math.max(...cmdUses.map(x=>x.uses.toString().length), col[1].length) + 1;
const rows = [`${col[0] + ' '.repeat(nameLen-col[0].length)}|${' '.repeat(usesLen-col[1].length) + col[1]}\n`, '-'.repeat(nameLen) + '-'.repeat(usesLen) + '\n']; const rows = [`${col[0].padEnd(nameLen)}${col[1].padStart(usesLen)}\n`, '.repeat(nameLen + usesLen) + '\n'];
cmdUses.forEach(cmd=>{ cmdUses.forEach(cmd=>{
const name = cmd.command.data.name; const name = cmd.command.data.name;
const uses = cmd.uses.toString(); const uses = cmd.uses.toString();
rows.push(`${name+' '.repeat(nameLen-name.length)}${' '.repeat(usesLen-uses.length)+uses}\n`); rows.push(`${name.padEnd(nameLen)}${uses.padStart(usesLen)}\n`);
}); });
if (rows.join('').length > 1024) {
const fieldChunks = [];
let field = ''; let field = '';
rows.forEach(r=>{ rows.forEach(r=>{
if (field.length+r.length > 1024) { if (field.length+r.length > 1024) {
embed.addFields({name: '\u200b', value: `\`\`\`\n${field}\`\`\``}); fieldChunks.push(field);
field = r; field = r;
} } else field += r;
}); });
embed.addFields({name: '\u200b', value: `\`\`\`\n${field}\`\`\``}); fieldChunks.push(field);
} else embed.addFields({name: '\u200b', value: `\`\`\`\n${rows.join('')}\`\`\``}); fieldChunks.forEach(field=>embed.addFields({name: '\u200b', value: `\`\`\`\n${field}\`\`\``}));
const pkg = JSON.parse(readFileSync('package.json', 'utf8')); const pkg = JSON.parse(readFileSync('package.json', 'utf8'));
embed.addFields( embed.addFields(

View File

@ -3,7 +3,7 @@ import TClient from '../client.js';
import Logger from '../helpers/Logger.js'; import Logger from '../helpers/Logger.js';
import {disabledChannels} from '../index.js'; import {disabledChannels} from '../index.js';
export default class MessageDelete { export default class MessageDelete {
static run(client:TClient, msg:Discord.Message){ static run(client:TClient, msg:Discord.Message|Discord.PartialMessage){
if (!client.config.botSwitches.logs) return; if (!client.config.botSwitches.logs) return;
if (msg.guild?.id != client.config.dcServer.id || msg.partial || msg.author.bot || disabledChannels.includes(msg.channelId)) return; if (msg.guild?.id != client.config.dcServer.id || msg.partial || msg.author.bot || disabledChannels.includes(msg.channelId)) return;
if (Discord.DiscordAPIError.name === '10008') return Logger.console('log', 'MsgDelete', 'Caught an unexpected error returned by Discord API. (Unknown Message)'); if (Discord.DiscordAPIError.name === '10008') return Logger.console('log', 'MsgDelete', 'Caught an unexpected error returned by Discord API. (Unknown Message)');

View File

@ -1,7 +1,7 @@
import Discord from 'discord.js'; import Discord from 'discord.js';
import TClient from '../client.js'; import TClient from '../client.js';
export default class MessageDeleteBulk { export default class MessageDeleteBulk {
static run(client:TClient, messages:Discord.Collection<string, Discord.Message<boolean>>, channel:Discord.GuildTextBasedChannel){ static run(client:TClient, messages:Discord.Collection<string, Discord.Message<boolean>|Discord.PartialMessage>, channel:Discord.GuildTextBasedChannel){
if (!client.config.botSwitches.logs || channel.guildId != client.config.dcServer.id) return; if (!client.config.botSwitches.logs || channel.guildId != client.config.dcServer.id) return;
if (messages.some(msg=>{ if (messages.some(msg=>{
msg.author?.username === undefined ?? null; msg.author?.username === undefined ?? null;

View File

@ -3,9 +3,9 @@ import TClient from '../client.js';
import MessageTool from '../helpers/MessageTool.js'; import MessageTool from '../helpers/MessageTool.js';
import {disabledChannels, rawSwitches} from '../index.js'; import {disabledChannels, rawSwitches} from '../index.js';
export default class MessageUpdate { export default class MessageUpdate {
static async run(client:TClient, oldMsg:Discord.Message, newMsg:Discord.Message){ static async run(client:TClient, oldMsg:Discord.Message|Discord.PartialMessage, newMsg:Discord.Message){
if (!client.config.botSwitches.logs) return; if (!client.config.botSwitches.logs) return;
if (oldMsg.guild?.id != client.config.dcServer.id || oldMsg.author === null || oldMsg?.author.bot || oldMsg.partial || newMsg.partial || !newMsg.member || disabledChannels.includes(newMsg.channelId)) return; if (oldMsg.guild?.id != client.config.dcServer.id || oldMsg.author === null || oldMsg?.author.bot || newMsg.partial || !newMsg.member || disabledChannels.includes(newMsg.channelId)) return;
if (await client.prohibitedWords.findWord(newMsg.content.toLowerCase().replaceAll(/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?\n?0-9]|[]|ing\b/g, '').split(' ').join('')) && (!MessageTool.isStaff(newMsg.member))) newMsg.delete(); if (await client.prohibitedWords.findWord(newMsg.content.toLowerCase().replaceAll(/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?\n?0-9]|[]|ing\b/g, '').split(' ').join('')) && (!MessageTool.isStaff(newMsg.member))) newMsg.delete();
if (!rawSwitches.MESSAGE_UPDATE || (rawSwitches.MESSAGE_UPDATE && newMsg.content !== oldMsg.content)) { if (!rawSwitches.MESSAGE_UPDATE || (rawSwitches.MESSAGE_UPDATE && newMsg.content !== oldMsg.content)) {
rawSwitches.MESSAGE_UPDATE = true; rawSwitches.MESSAGE_UPDATE = true;

View File

@ -1,18 +1,17 @@
import Discord from 'discord.js'; import Discord from 'discord.js';
import ConfigHelper from './ConfigHelper.js'; import ConfigHelper from './ConfigHelper.js';
const config = ConfigHelper.readConfig(); const config = ConfigHelper.readConfig();
type RoleKeys = keyof typeof config.dcServer.roles;
export default class MessageTool { export default class MessageTool {
static embedStruct(color:Discord.ColorResolvable, title:string, description?:string|null, image?:string|null) { public static embedStruct(color:Discord.ColorResolvable, title:string, description?:string|null, image?:string|null) {
const embed = new Discord.EmbedBuilder().setColor(color).setTitle(title); const embed = new Discord.EmbedBuilder().setColor(color).setTitle(title);
if (description) embed.setDescription(description); if (description) embed.setDescription(description);
if (image) embed.setImage(image); if (image) embed.setImage(image);
return embed return embed
} }
static concatMessage =(...messages:string[])=>messages.join('\n'); public static concatMessage =(...messages:string[])=>messages.join('\n');
static formatMention =(mention:string, type:'user'|'channel'|'role')=>`<${type === 'role' ? '@&' : type === 'channel' ? '#' : '@'}${mention}>`; public static formatMention =(mention:string, type:'user'|'channel'|'role')=>`<${type === 'role' ? '@&' : type === 'channel' ? '#' : '@'}${mention}>`;
static isStaff =(guildMember:Discord.GuildMember)=>config.dcServer.staffRoles.map((x:string)=>config.dcServer.roles[x]).some((x:string)=>guildMember.roles.cache.has(x)); public static isStaff =(guildMember:Discord.GuildMember)=>config.dcServer.staffRoles.map((x:string)=>config.dcServer.roles[x]).some((x:string)=>guildMember.roles.cache.has(x));
static youNeedRole =(interaction:Discord.CommandInteraction, role:RoleKeys)=>interaction.reply(`You do not have ${this.formatMention(config.dcServer.roles[role], 'role')} role to use this command.`); public static youNeedRole =(interaction:Discord.CommandInteraction, role:keyof typeof config.dcServer.roles)=>interaction.reply(`You do not have ${this.formatMention(config.dcServer.roles[role], 'role')} role to use this command.`);
static isModerator =(guildMember:Discord.GuildMember)=>config.dcServer.staffRoles.filter((x:string)=>/^admin|^dcmod/.test(x)).map((x:string)=>config.dcServer.roles[x]).some((x:string)=>guildMember.roles.cache.has(x)); public static isModerator =(guildMember:Discord.GuildMember)=>config.dcServer.staffRoles.filter((x:string)=>/^admin|^dcmod/.test(x)).map((x:string)=>config.dcServer.roles[x]).some((x:string)=>guildMember.roles.cache.has(x));
} }

View File

@ -9,27 +9,13 @@ import MPModule, {refreshTimerSecs} from './modules/MPModule.js';
import UsernameHelper from './helpers/UsernameHelper.js'; import UsernameHelper from './helpers/UsernameHelper.js';
import {Punishment, RawGatewayPacket, RawMessageDelete, RawMessageUpdate} from 'src/interfaces'; import {Punishment, RawGatewayPacket, RawMessageDelete, RawMessageUpdate} from 'src/interfaces';
import {readFileSync} from 'node:fs'; import {readFileSync} from 'node:fs';
import {execSync} from 'node:child_process';
export const disabledChannels = ['548032776830582794', '541677709487505408', '949380187668242483']; export const disabledChannels = ['548032776830582794', '541677709487505408', '949380187668242483'];
// Error handler // Error handler
function _(error:Error, type:string) { function _(error:Error, type:string) {
if (JSON.parse(readFileSync('src/errorBlocklist.json', 'utf8')).includes(error.message)) return; if (JSON.parse(readFileSync('src/errorBlocklist.json', 'utf8')).includes(error.message)) return;
console.error(error); console.error(error);
(client.channels.resolve(client.config.dcServer.channels.errors) as Discord.TextChannel | null)?.send({embeds: [new client.embed().setColor('#560000').setTitle('Error caught!').setFooter({text: `Error type: ${type}`}).setDescription(`**Error:**\n\`\`\`${error.message}\`\`\`**Stack:**\n\`\`\`${`${UsernameHelper(error.stack)}`.slice(0, 2500)}\`\`\``)]}) (client.channels.resolve(client.config.dcServer.channels.errors) as Discord.TextChannel | null)?.send({embeds: [new client.embed().setColor('#560000').setTitle('Error caught!').setFooter({text: `Error type: ${type}`}).setDescription(`**Error:**\n\`\`\`${error.message}\`\`\`**Stack:**\n\`\`\`${`${UsernameHelper(error.stack)}`.slice(0, 2500)}\`\`\``)]});
if (error.message.includes('could not fdatasync file')) {
client.users.createDM(client.config.whitelist[1]).then(u=>u.send({
embeds: [new client.embed()
.setColor(client.config.embedColorYellow)
.setTitle('Database error')
.setDescription('I couldn\'t write to the database due to filesystem issues, shutting down...')
.setFields({name: 'Error message', value: `\`\`\`${error.message}\`\`\``})
.setFooter({text: `Error type: ${type}`})
]
}));
setTimeout(()=>execSync('pm2 stop 0', {shell: 'bash'}), 5500);
}
} }
process.on('unhandledRejection', (error: Error)=>_(error, 'unhandledRejection')); process.on('unhandledRejection', (error: Error)=>_(error, 'unhandledRejection'));
process.on('uncaughtException', (error: Error)=>_(error, 'uncaughtException')); process.on('uncaughtException', (error: Error)=>_(error, 'uncaughtException'));
@ -106,24 +92,15 @@ client.on('raw', async (packet:RawGatewayPacket<RawMessageUpdate>)=>{
if (typeof packet.d.content === 'undefined') return; if (typeof packet.d.content === 'undefined') return;
const channel = client.channels.cache.get(packet.d.channel_id) as Discord.TextBasedChannel; const channel = client.channels.cache.get(packet.d.channel_id) as Discord.TextBasedChannel;
const old_message = await channel.messages.fetch(packet.d.id); const message = await channel.messages.fetch(packet.d.id);
const new_message = await channel.messages.fetch(packet.d.id);
client.emit('messageUpdate', old_message, new_message); client.emit('messageUpdate', message, message);
}); });
client.on('raw', async (packet:RawGatewayPacket<RawMessageDelete>)=>{ client.on('raw', async (packet:RawGatewayPacket<RawMessageDelete>)=>{
if (rawSwitches[packet.t]) return; if (rawSwitches[packet.t]) return;
if (packet.t !== 'MESSAGE_DELETE' || packet.d.guild_id != client.config.dcServer.id || disabledChannels.includes(packet.d.channel_id)) return; if (packet.t !== 'MESSAGE_DELETE' || packet.d.guild_id != client.config.dcServer.id || disabledChannels.includes(packet.d.channel_id)) return;
(client.channels.resolve(client.config.dcServer.channels.logs) as Discord.TextChannel).send({
embeds: [new client.embed() Logger.console('log', 'RawEvent:Del', `Message was deleted in #${(client.channels.resolve(packet.d.channel_id) as Discord.TextChannel).name}`);
.setColor(client.config.embedColorRed)
.setTitle('Message deleted')
.addFields(
{name: 'This was received over raw API event', value: '\u200b'},
{name: 'Channel', value: `<#${packet.d.channel_id}>`},
).setTimestamp()
]
});
rawSwitches[packet.t] = true; rawSwitches[packet.t] = true;
}); });