From e3c768e95a6531a1d6e8962c7d5a89e69e972102 Mon Sep 17 00:00:00 2001 From: toast-ts <96593068+toast-ts@users.noreply.github.com> Date: Mon, 13 Feb 2023 18:37:23 +1100 Subject: [PATCH] I'm blaming someone if all else fails. --- src/commands/contributors.ts | 5 +- src/commands/mp.ts | 18 +-- src/commands/rank.ts | 263 +++++++++++++++----------------- src/commands/roleinfo.ts | 8 +- src/commands/whois.ts | 10 +- src/config.json | 2 +- src/events/guildBanAdd.ts | 11 +- src/events/guildBanRemove.ts | 11 +- src/events/guildMemberAdd.ts | 18 +-- src/events/guildMemberRemove.ts | 10 +- src/events/guildMemberUpdate.ts | 8 +- src/events/interactionCreate.ts | 30 ++-- src/events/messageCreate.ts | 20 +-- src/events/messageDelete.ts | 11 +- src/events/messageDeleteBulk.ts | 3 +- src/events/messageUpdate.ts | 17 +-- src/index.ts | 67 ++++---- 17 files changed, 220 insertions(+), 292 deletions(-) diff --git a/src/commands/contributors.ts b/src/commands/contributors.ts index ca837cb..4893f32 100644 --- a/src/commands/contributors.ts +++ b/src/commands/contributors.ts @@ -2,7 +2,7 @@ import Discord,{SlashCommandBuilder} from 'discord.js'; import TClient from 'src/client'; export default { async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ - const embed = new client.embed().setColor(client.config.embedColor).setTitle('Daggerbot contributors').setDescription([ + interaction.reply({embeds: [new client.embed().setColor(client.config.embedColor).setTitle('Daggerbot contributors').setDescription([ '**Thanks to those below that contributed to the bot!**', 'Toast <@190407856527376384>', 'TÆMBØ <@615761944154210305>', @@ -12,8 +12,7 @@ export default { 'Hitchhiker <@506022868157595648>', 'RedRover92 <@633345781780185099>', 'Nawdic <@178941218510602240>' - ].join('\n')) - interaction.reply({embeds: [embed]}) + ].join('\n'))]}) }, data: new SlashCommandBuilder() .setName('contributors') diff --git a/src/commands/mp.ts b/src/commands/mp.ts index 0d37d08..562109f 100644 --- a/src/commands/mp.ts +++ b/src/commands/mp.ts @@ -1,7 +1,8 @@ import Discord,{EmbedBuilder, SlashCommandBuilder} from 'discord.js'; -import TClient from 'src/client'; import MPDB from '../models/MPServer'; +import TClient from 'src/client'; import path from 'node:path'; +import canvas from 'canvas'; import fs from 'node:fs'; async function MPdata(client:TClient, interaction:Discord.ChatInputCommandInteraction, embed: EmbedBuilder) { @@ -127,8 +128,7 @@ export default { const first_graph_top = 16; const second_graph_top = 16; const textSize = 40; - - const canvas = require('canvas'); + const img = canvas.createCanvas(1500, 750); const ctx = img.getContext('2d'); @@ -188,10 +188,10 @@ export default { function colorAtPlayercount(playercount: number) { if (playercount === first_graph_top) { - return client.config.embedColorRed; + return client.config.embedColorRed as string; } else if (playercount > 9) { - return client.config.embedColorYellow; - } else {return client.config.embedColorGreen;} + return client.config.embedColorYellow as string; + } else {return client.config.embedColorGreen as string} } let lastCoords: Array = []; data.forEach((curPC: number /* current player count */, i: number) => { @@ -204,21 +204,21 @@ export default { const prvColor = colorAtPlayercount(prvPC); // color at last point if (curColor !== prvColor && !isNaN(prvPC) && lastCoords.length > 0) { // gradient should be used when the color between now and last point is not the same // gradient from now to last point - const grd = ctx.createLinearGradient(...lastCoords, x, y); + const grd = ctx.createLinearGradient(lastCoords[0], lastCoords[1], x, y); grd.addColorStop(0, colorAtPlayercount(prvPC)); // prev color at the beginning grd.addColorStop(1, colorAtPlayercount(curPC)); // cur color at the end // special case: playercount rises or falls rapidly accross all colors (eg. straight from red to green) if (curColor !== client.config.embedColorYellow && prvColor !== client.config.embedColorYellow) { const yellowY = getYCoordinate(10); // y coordinate at which line should be yellow const stop = (yellowY - lastCoords[1]) / (y - lastCoords[1]); // between 0 and 1, where is yellowY between y and nextPointCoords[1] ? - grd.addColorStop(stop, client.config.embedColorYellow); // add a yellow stop to the gradient + grd.addColorStop(stop, client.config.embedColorYellow as string); // add a yellow stop to the gradient } ctx.strokeStyle = grd; } else { ctx.strokeStyle = colorAtPlayercount(curPC); } ctx.beginPath(); - if (lastCoords.length > 0) ctx.moveTo(...lastCoords); + if (lastCoords.length > 0) ctx.moveTo(lastCoords[0], lastCoords[1]); // if the line being drawn is horizontal, make it go until it has to go down if (y === lastCoords[1]) { let newX = x; diff --git a/src/commands/rank.ts b/src/commands/rank.ts index 77a08c7..b4e7ae3 100644 --- a/src/commands/rank.ts +++ b/src/commands/rank.ts @@ -1,169 +1,160 @@ import Discord,{SlashCommandBuilder} from 'discord.js'; +import {UserLevels} from 'src/typings/interfaces'; import TClient from 'src/client'; -import { UserLevels } from 'src/typings/interfaces'; import path from 'node:path'; import fs from 'node:fs'; +import canvas from 'canvas'; export default { async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ if (interaction.guildId !== client.config.mainServer.id) return interaction.reply({content: 'This command doesn\'t work in this server.', ephemeral: true}); ({ - view: ()=>{ - // fetch user or user interaction sender - const member = interaction.options.getMember("member") ?? interaction.member as Discord.GuildMember; - if (member.user.bot) return interaction.reply('Bots don\'t level up, try viewing non-bots instead.') - const embed = new client.embed().setColor(member.displayColor) - // information about users progress on level roles - const information = client.userLevels._content[member.user.id]; + view: ()=>{ + // fetch user or user interaction sender + const member = interaction.options.getMember("member") ?? interaction.member as Discord.GuildMember; + if (member.user.bot) return interaction.reply('Bots don\'t level up, try viewing non-bots instead.') + // information about users progress on level roles + const information = client.userLevels._content[member.user.id]; - const pronounBool = (you: string, they: string) => { // takes 2 words and chooses which to use based on if user did this command on themself - if (interaction.user.id === member.user.id) return you || true; - else return they || false; - }; - if (!information) { - return interaction.reply(`${pronounBool('You', 'They')} currently don't have a level, send some messages to level up.`) - } + const pronounBool = (you: string, they: string) => { // takes 2 words and chooses which to use based on if user did this command on themself + if (interaction.user.id === member.user.id) return you || true; + else return they || false; + }; + if (!information) return interaction.reply(`${pronounBool('You', 'They')} currently don't have a level, send some messages to level up.`) - const index = Object.entries(client.userLevels._content).sort((a, b) => b[1].messages - a[1].messages).map(x => x[0]).indexOf(member.id) + 1; - const memberDifference = information.messages - client.userLevels.algorithm(information.level); - const levelDifference = client.userLevels.algorithm(information.level+1) - client.userLevels.algorithm(information.level); + const index = Object.entries(client.userLevels._content).sort((a, b) => b[1].messages - a[1].messages).map(x => x[0]).indexOf(member.id) + 1; + const memberDifference = information.messages - client.userLevels.algorithm(information.level); + const levelDifference = client.userLevels.algorithm(information.level+1) - client.userLevels.algorithm(information.level); + interaction.reply({embeds: [new client.embed().setColor(member.displayColor).setTitle(`Level: **${information.level}**\nRank: **${index ? '#' + index : 'last'}**\nProgress: **${information.messages - client.userLevels.algorithm(information.level)}/${client.userLevels.algorithm(information.level+1) - client.userLevels.algorithm(information.level)} (${(memberDifference/levelDifference*100).toFixed(2)}%)**\nTotal: **${information.messages}**`).setThumbnail(member.user.avatarURL({ extension: 'png', size: 256}) || member.user.defaultAvatarURL)]}) + }, + leaderboard: ()=>{ + const messageCountsTotal = Object.values(client.userLevels._content).reduce((a, b) => a + b.messages, 0); + const timeActive = Math.floor((Date.now() - client.config.LRSstart)/1000/60/60/24); - embed.setThumbnail(member.user.avatarURL({ extension: 'png', size: 256}) || member.user.defaultAvatarURL) - embed.setAuthor({name: `Ranking for ${member.user.tag}`}) - embed.setTitle(`Level: **${information.level}**\nRank: **${index ? '#' + index : 'last'}**\nProgress: **${information.messages - client.userLevels.algorithm(information.level)}/${client.userLevels.algorithm(information.level+1) - client.userLevels.algorithm(information.level)} (${(memberDifference/levelDifference*100).toFixed(2)}%)**\nTotal: **${information.messages}**`); - interaction.reply({embeds: [embed]}) - }, - leaderboard: ()=>{ - const messageCountsTotal = Object.values(client.userLevels._content).reduce((a, b) => a + b.messages, 0); - const timeActive = Math.floor((Date.now() - client.config.LRSstart)/1000/60/60/24); + const dailyMsgsPath = path.join(__dirname, '../database/dailyMsgs.json'); + const data = JSON.parse(fs.readFileSync(dailyMsgsPath, {encoding: 'utf8'})).map((x: Array, i: number, a: any) => { + const yesterday = a[i - 1] || []; + return x[1] - (yesterday[1] || x[1]); + }).slice(1).slice(-60); - const dailyMsgsPath = path.join(__dirname, '../database/dailyMsgs.json'); - const data = JSON.parse(fs.readFileSync(dailyMsgsPath, {encoding: 'utf8'})).map((x: Array, i: number, a: any) => { - const yesterday = a[i - 1] || []; - return x[1] - (yesterday[1] || x[1]); - }).slice(1).slice(-60); + // handle negative days + data.forEach((change: number, i: number) => { + if (change < 0) data[i] = data[i - 1] || data[i + 1] || 0; + }); - // handle negative days - data.forEach((change: number, i: number) => { - if (change < 0) data[i] = data[i - 1] || data[i + 1] || 0; - }); + const maxValue = Math.max(...data); + const maxValueArr = maxValue.toString().split(''); - const maxValue = Math.max(...data); - const maxValueArr = maxValue.toString().split(''); + const first_graph_top = Math.ceil(maxValue * 10 ** (-maxValueArr.length + 1)) * 10 ** (maxValueArr.length - 1); + const second_graph_top = Math.ceil(maxValue * 10 ** (-maxValueArr.length + 2)) * 10 ** (maxValueArr.length - 2); + const textSize = 32; - const first_graph_top = Math.ceil(maxValue * 10 ** (-maxValueArr.length + 1)) * 10 ** (maxValueArr.length - 1); - const second_graph_top = Math.ceil(maxValue * 10 ** (-maxValueArr.length + 2)) * 10 ** (maxValueArr.length - 2); + const img = canvas.createCanvas(950, 450); + const ctx = img.getContext('2d'); - const textSize = 32; + const graphOrigin = [10, 50]; + const graphSize = [700, 360]; + const nodeWidth = graphSize[0] / (data.length - 1); + ctx.fillStyle = '#36393f'; + ctx.fillRect(0, 0, img.width, img.height); - const canvas = require('canvas'); - const img = canvas.createCanvas(950, 450); - const ctx = img.getContext('2d'); + // grey horizontal lines + ctx.lineWidth = 3; - const graphOrigin = [10, 50]; - const graphSize = [700, 360]; - const nodeWidth = graphSize[0] / (data.length - 1); - ctx.fillStyle = '#36393f'; - ctx.fillRect(0, 0, img.width, img.height); + let interval_candidates = []; + for (let i = 4; i < 10; i++) { + const interval = first_graph_top / i; + if (Number.isInteger(interval)) { + let intervalString = interval.toString(); + const reference_number = i * Math.max(intervalString.split('').filter(x => x === '0').length / intervalString.length, 0.3) * (['1', '2', '4', '5', '6', '8'].includes(intervalString[0]) ? 1.5 : 0.67) + interval_candidates.push([interval, i, reference_number]); + } + } + const chosen_interval = interval_candidates.sort((a, b) => b[2] - a[2])[0]; + let previousY: Array = []; - // grey horizontal lines - ctx.lineWidth = 3; + ctx.strokeStyle = '#202225'; + for (let i = 0; i <= chosen_interval[1]; i++) { + const y = graphOrigin[1] + graphSize[1] - (i * (chosen_interval[0] / second_graph_top) * graphSize[1]); + if (y < graphOrigin[1]) continue; + const even = ((i + 1) % 2) === 0; + if (even) ctx.strokeStyle = '#2c2f33'; + ctx.beginPath(); + ctx.lineTo(graphOrigin[0], y); + ctx.lineTo(graphOrigin[0] + graphSize[0], y); + ctx.stroke(); + ctx.closePath(); + if (even) ctx.strokeStyle = '#202225'; + previousY = [y, i * chosen_interval[0]]; + } - let interval_candidates = []; - for (let i = 4; i < 10; i++) { - const interval = first_graph_top / i; - if (Number.isInteger(interval)) { - let intervalString = interval.toString(); - const reference_number = i * Math.max(intervalString.split('').filter(x => x === '0').length / intervalString.length, 0.3) * (['1', '2', '4', '5', '6', '8'].includes(intervalString[0]) ? 1.5 : 0.67) - interval_candidates.push([interval, i, reference_number]); - } - } - const chosen_interval = interval_candidates.sort((a, b) => b[2] - a[2])[0]; + // 30d mark + ctx.setLineDash([8, 16]); + ctx.beginPath(); + const lastMonthStart = graphOrigin[0] + (nodeWidth * (data.length - 30)); + ctx.lineTo(lastMonthStart, graphOrigin[1]); + ctx.lineTo(lastMonthStart, graphOrigin[1] + graphSize[1]); + ctx.stroke(); + ctx.closePath(); + ctx.setLineDash([]); - let previousY: Array = []; + // draw points + ctx.strokeStyle = client.config.embedColor as string; + ctx.fillStyle = client.config.embedColor as string; + ctx.lineWidth = 3; - ctx.strokeStyle = '#202225'; - for (let i = 0; i <= chosen_interval[1]; i++) { - const y = graphOrigin[1] + graphSize[1] - (i * (chosen_interval[0] / second_graph_top) * graphSize[1]); - if (y < graphOrigin[1]) continue; - const even = ((i + 1) % 2) === 0; - if (even) ctx.strokeStyle = '#2c2f33'; - ctx.beginPath(); - ctx.lineTo(graphOrigin[0], y); - ctx.lineTo(graphOrigin[0] + graphSize[0], y); - ctx.stroke(); - ctx.closePath(); - if (even) ctx.strokeStyle = '#202225'; - previousY = [y, i * chosen_interval[0]]; - } + function getYCoordinate(value: number) { + return ((1 - (value / second_graph_top)) * graphSize[1]) + graphOrigin[1]; + } - // 30d mark - ctx.setLineDash([8, 16]); - ctx.beginPath(); - const lastMonthStart = graphOrigin[0] + (nodeWidth * (data.length - 30)); - ctx.lineTo(lastMonthStart, graphOrigin[1]); - ctx.lineTo(lastMonthStart, graphOrigin[1] + graphSize[1]); - ctx.stroke(); - ctx.closePath(); - ctx.setLineDash([]); + let lastCoords: Array = []; + data.forEach((val: number, i: number) => { + ctx.beginPath(); + if (lastCoords) ctx.moveTo(lastCoords[0], lastCoords[1]); + if (val < 0) val = 0; + const x = i * nodeWidth + graphOrigin[0]; + const y = getYCoordinate(val); + ctx.lineTo(x, y); + lastCoords = [x, y]; + ctx.stroke(); + ctx.closePath(); - // draw points - ctx.strokeStyle = client.config.embedColor; - ctx.fillStyle = client.config.embedColor; - ctx.lineWidth = 3; + // ball + ctx.beginPath(); + ctx.arc(x, y, ctx.lineWidth * 1.2, 0, 2 * Math.PI) + ctx.closePath(); + ctx.fill(); + }); - function getYCoordinate(value: number) { - return ((1 - (value / second_graph_top)) * graphSize[1]) + graphOrigin[1]; - } + // draw text + ctx.font = '400 ' + textSize + 'px sans-serif'; + ctx.fillStyle = 'white'; - let lastCoords: Array = []; - data.forEach((val: number, i: number) => { - ctx.beginPath(); - if (lastCoords) ctx.moveTo(...lastCoords); - if (val < 0) val = 0; - const x = i * nodeWidth + graphOrigin[0]; - const y = getYCoordinate(val); - ctx.lineTo(x, y); - lastCoords = [x, y]; - ctx.stroke(); - ctx.closePath(); + // highest value + const maxx = graphOrigin[0] + graphSize[0] + textSize; + const maxy = previousY[0] + (textSize / 3); + ctx.fillText(previousY[1].toLocaleString('en-US'), maxx, maxy); - // ball - ctx.beginPath(); - ctx.arc(x, y, ctx.lineWidth * 1.2, 0, 2 * Math.PI) - ctx.closePath(); - ctx.fill(); - }); + // lowest value + const lowx = graphOrigin[0] + graphSize[0] + textSize; + const lowy = graphOrigin[1] + graphSize[1] + (textSize / 3); + ctx.fillText('0 msgs/day', lowx, lowy); - // draw text - ctx.font = '400 ' + textSize + 'px sans-serif'; - ctx.fillStyle = 'white'; + // 30d + ctx.fillText('30d ago', lastMonthStart, graphOrigin[1] - (textSize / 3)); - // highest value - const maxx = graphOrigin[0] + graphSize[0] + textSize; - const maxy = previousY[0] + (textSize / 3); - ctx.fillText(previousY[1].toLocaleString('en-US'), maxx, maxy); + // time -> + const tx = graphOrigin[0] + (textSize / 2); + const ty = graphOrigin[1] + graphSize[1] + (textSize); + ctx.fillText('time ->', tx, ty); - // lowest value - const lowx = graphOrigin[0] + graphSize[0] + textSize; - const lowy = graphOrigin[1] + graphSize[1] + (textSize / 3); - ctx.fillText('0 msgs/day', lowx, lowy); - - // 30d - ctx.fillText('30d ago', lastMonthStart, graphOrigin[1] - (textSize / 3)); - - // time -> - const tx = graphOrigin[0] + (textSize / 2); - const ty = graphOrigin[1] + graphSize[1] + (textSize); - ctx.fillText('time ->', tx, ty); - - const yeahok = new client.attachmentBuilder(img.toBuffer(), {name: 'dailymsgs.png'}) - const embed = new client.embed().setTitle('Ranking leaderboard') - .setDescription(`Level System was created **${timeActive}** days ago. Since then, a total of **${messageCountsTotal.toLocaleString('en-US')}** messages have been sent in this server.\nGraph updates daily @ `) - .addFields({name: 'Top users by messages sent:', value: Object.entries(client.userLevels._content).sort((a, b) => b[1].messages - a[1].messages).slice(0, 10).map((x, i) => `\`${i + 1}.\` <@${x[0]}>: ${x[1].messages.toLocaleString('en-US')}`).join('\n')}) - .setImage('attachment://dailymsgs.png').setColor(client.config.embedColor) - interaction.reply({embeds: [embed], files: [yeahok]}) - } - } as any)[interaction.options.getSubcommand()](); + const yeahok = new client.attachmentBuilder(img.toBuffer(), {name: 'dailymsgs.png'}) + const embed = new client.embed().setTitle('Ranking leaderboard') + .setDescription(`Level System was created **${timeActive}** days ago. Since then, a total of **${messageCountsTotal.toLocaleString('en-US')}** messages have been sent in this server.\nGraph updates daily @ `) + .addFields({name: 'Top users by messages sent:', value: Object.entries(client.userLevels._content).sort((a, b) => b[1].messages - a[1].messages).slice(0, 10).map((x, i) => `\`${i + 1}.\` <@${x[0]}>: ${x[1].messages.toLocaleString('en-US')}`).join('\n')}) + .setImage('attachment://dailymsgs.png').setColor(client.config.embedColor) + interaction.reply({embeds: [embed], files: [yeahok]}) + } + } as any)[interaction.options.getSubcommand()](); }, data: new SlashCommandBuilder() .setName('rank') diff --git a/src/commands/roleinfo.ts b/src/commands/roleinfo.ts index 7112319..3b4ae35 100644 --- a/src/commands/roleinfo.ts +++ b/src/commands/roleinfo.ts @@ -3,17 +3,15 @@ import TClient from 'src/client'; export default { async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ const role = interaction.options.getRole('role') as Discord.Role; - const keyPerms = ['Administrator', 'KickMembers', 'BanMembers', 'ManageChannels', 'ManageGuild', 'ViewAuditLog', 'ManageMessages', 'MentionEveryone', 'UseExternalEmojis', 'ManageRoles', 'Manage EmojiandStickers', 'ModerateMembers'] const permissions = role.permissions.toArray(); const Role = role.members.map((e:Discord.GuildMember)=>`**${e.user.tag}**`).join('\n') || ''; - const embed = new client.embed().setColor(role.color || '#fefefe').setThumbnail(role?.iconURL()).setTitle(`Role Info: ${role.name}`).addFields( + interaction.reply({embeds: [new client.embed().setColor(role.color || '#fefefe').setThumbnail(role?.iconURL()).setTitle(`Role Info: ${role.name}`).addFields( {name: '🔹 ID', value: `\`${role.id}\``, inline: true}, {name: '🔹 Color', value: `\`${role.hexColor}\``, inline: true}, {name: '🔹 Creation Date', value: `\n`, inline: true}, {name: '🔹 Misc', value: `Hoist: \`${role.hoist}\`\nMentionable: \`${role.mentionable}\`\nPosition: \`${role.position}\` from bottom\nMembers: \`${role.members.size}\`\n${role.members.size < 21 ? Role : ''}`, inline: true}, - {name: '🔹 Permissions', value: (permissions.includes('Administrator') ? ['Administrator'] : permissions.filter((x:string)=>keyPerms.includes(x))).map((x:string)=>{return x.split('_').map((y,i)=>y).join(' ')}).join(', ') || 'None', inline: true} - ) - interaction.reply({embeds: [embed]}) + {name: '🔹 Permissions', value: `${permissions.includes('Administrator') ? ['Administrator'] : permissions.join(', ') || 'None'}`, inline: true} + )]}) }, data: new SlashCommandBuilder() .setName('roleinfo') diff --git a/src/commands/whois.ts b/src/commands/whois.ts index 58f338f..51023e7 100644 --- a/src/commands/whois.ts +++ b/src/commands/whois.ts @@ -36,7 +36,7 @@ export default { } else if (member.user.id == interaction.guild.ownerId) { title = ':crown: Server Owner' }; - const embed0 = new client.embed() + const embed = new client.embed() .setColor(member.displayColor || client.config.embedColor) .setURL(`https://discord.com/users/${member.user.id}`) .setThumbnail(member.user.avatarURL({size:2048}) || member.user.defaultAvatarURL) @@ -48,10 +48,10 @@ export default { {name: '🔹 Server Join Date', value: `\n`}, {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) embed0.addFields({name: '🔹 Server Boosting since', value: `\n`, inline: true}) - if (!presence) embed0.addFields({name: `🔹 Status: Unavailable to retrieve`, value: '\u200b'}) - if (member.presence) embed0.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(embed0) + if (member.premiumSinceTimestamp !== null) embed.addFields({name: '🔹 Server Boosting since', value: `\n`, inline: true}) + if (!presence) embed.addFields({name: `🔹 Status: Unavailable to retrieve`, value: '\u200b'}) + if (member.presence) embed.addFields({name: `🔹 Status: ${member.presence.status}`, value: `${member.presence.status === 'offline' ? '⚫' : `Desktop: ${convert(presence.desktop)}\nWeb: ${convert(presence.web)}\nMobile: ${convert(presence.mobile)}`}`, inline: true}) + embedArray.push(embed) interaction.reply({embeds: embedArray}) } }, diff --git a/src/config.json b/src/config.json index 4c113c1..dd1fd51 100644 --- a/src/config.json +++ b/src/config.json @@ -20,7 +20,7 @@ }, "botPresence": { "activities": [ - {"name": "the rainy month go by", "url": "https://www.youtube.com/watch?v=8UVNT4wvIGY", "type": 3} + {"name": "Survival Roleplay S3", "url": "https://www.youtube.com/watch?v=wHKEpN5WKvY", "type": 1} ], "status": "idle" }, diff --git a/src/events/guildBanAdd.ts b/src/events/guildBanAdd.ts index 71f8fd0..eff1eeb 100644 --- a/src/events/guildBanAdd.ts +++ b/src/events/guildBanAdd.ts @@ -3,19 +3,16 @@ import TClient from '../client'; export default { async run(client:TClient, member:Discord.GuildMember){ if (member.guild?.id != client.config.mainServer.id) return; - const fetchBanlog = await member.guild.fetchAuditLogs({ - limit: 1, - type: AuditLogEvent.MemberBanAdd - }) + const fetchBanlog = await member.guild.fetchAuditLogs({limit: 1, type: AuditLogEvent.MemberBanAdd}) const banLog = fetchBanlog.entries.first(); if (!banLog) return console.log(`${member.user.tag} was banned from ${member.guild.name} but no audit log for this user.`) const {executor, target, reason } = banLog; if (target.id == member.user.id) { - const embed = 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( + (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( {name: '🔹 Moderator', value: `<@${executor.id}>\n\`${executor.id}\``}, {name: '🔹 Reason', value: `${reason == null ? 'Reason unspecified': reason}`} - ); - (client.channels.resolve(client.config.mainServer.channels.logs) as Discord.TextChannel).send({embeds: [embed]}) + )]}) } else { console.log(`${target.tag} was banned from ${member.guild.name} but no audit log could be fetched.`) } diff --git a/src/events/guildBanRemove.ts b/src/events/guildBanRemove.ts index 25ee584..beb8132 100644 --- a/src/events/guildBanRemove.ts +++ b/src/events/guildBanRemove.ts @@ -3,19 +3,16 @@ import TClient from '../client'; export default { async run(client:TClient, member:Discord.GuildMember){ if (member.guild?.id != client.config.mainServer.id) return; - const fetchUnbanlog = await member.guild.fetchAuditLogs({ - limit: 1, - type: AuditLogEvent.MemberBanRemove - }) + const fetchUnbanlog = await member.guild.fetchAuditLogs({limit: 1, type: AuditLogEvent.MemberBanRemove}) const unbanLog = fetchUnbanlog.entries.first(); if (!unbanLog) return console.log(`${member.user.tag} was unbanned from ${member.guild.name} but no audit log for this user.`) const { executor, target, reason } = unbanLog; if (target.id == member.user.id) { - const embed = 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( + (client.channels.resolve(client.config.mainServer.channels.logs) as Discord.TextChannel).send({embeds: [ + new client.embed().setColor(client.config.embedColorGreen).setTimestamp().setThumbnail(member.user.displayAvatarURL({size: 2048})).setTitle(`Member Unbanned: ${target.tag}`).setDescription(`🔹 **User**\n<@${target.id}>\n\`${target.id}\``).addFields( {name: '🔹 Moderator', value: `<@${executor.id}>\n\`${executor.id}\``}, {name: '🔹 Reason', value: `${reason == null ? 'Reason unspecified.': reason}`} - ); - (client.channels.resolve(client.config.mainServer.channels.logs) as Discord.TextChannel).send({embeds: [embed]}) + )]}) } else { console.log(`${target.tag} was unbanned from ${member.guild.name} but no audit log could be fetched.`) } diff --git a/src/events/guildMemberAdd.ts b/src/events/guildMemberAdd.ts index ae07aac..1fac5d8 100644 --- a/src/events/guildMemberAdd.ts +++ b/src/events/guildMemberAdd.ts @@ -2,10 +2,7 @@ import Discord from 'discord.js'; import TClient from '../client'; export default { 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 suffix = ((index)=>{ const numbers = index.toString().split('').reverse(); // eg 1850 --> [0,5,8,1] @@ -19,19 +16,16 @@ export default { } })(index); - const embed0: Discord.EmbedBuilder = 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: [embed0]}) - + (client.channels.resolve(client.config.mainServer.channels.welcome) as Discord.TextChannel).send({embeds: [new client.embed().setColor(client.config.embedColor).setThumbnail(member.user.displayAvatarURL({size: 2048}) || member.user.defaultAvatarURL).setTitle(`Welcome to Daggerwin, ${member.user.tag}!`).setFooter({text: `${index}${suffix} member`})]}) if (!client.config.botSwitches.logs) return; - const oldInvites = client.invites; const newInvites = await member.guild.invites.fetch(); - const usedInvite = newInvites.find((inv:any)=>oldInvites.get(inv.code)?.uses < inv.uses); + const usedInvite = newInvites.find((inv:any)=>client.invites.get(inv.code)?.uses < inv.uses); newInvites.forEach((inv:any)=>client.invites.set(inv.code,{uses: inv.uses, creator: inv.inviter.id})); - const embed1 = 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( + (client.channels.resolve(client.config.mainServer.channels.logs) as Discord.TextChannel).send({embeds: [ + new client.embed().setColor(client.config.embedColorGreen).setTimestamp().setThumbnail(member.user.displayAvatarURL({size: 2048})).setTitle(`Member Joined: ${member.user.tag}`).setDescription(`<@${member.user.id}>\n\`${member.user.id}\``).setFooter({text: `Total members: ${index}${suffix}`}).addFields( {name: '🔹 Account Creation Date', value: `\n`}, {name: '🔹 Invite Data:', value: usedInvite ? `Invite: \`${usedInvite.code}\`\nCreated by: **${usedInvite.inviter?.tag}**` : 'No invite data could be found.'} - ); - (client.channels.resolve(client.config.mainServer.channels.logs) as Discord.TextChannel).send({embeds: [embed1]}) + )]}) } } diff --git a/src/events/guildMemberRemove.ts b/src/events/guildMemberRemove.ts index e8cf3b6..d62f1b2 100644 --- a/src/events/guildMemberRemove.ts +++ b/src/events/guildMemberRemove.ts @@ -3,17 +3,13 @@ import TClient from '../client'; export default { async run(client:TClient, member:Discord.GuildMember){ if (!client.config.botSwitches.logs) return; - if ( - !member.joinedTimestamp - || member.guild?.id != client.config.mainServer.id - ) return; - 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( + if (!member.joinedTimestamp || member.guild?.id != client.config.mainServer.id) return; + (client.channels.resolve(client.config.mainServer.channels.logs) as Discord.TextChannel).send({embeds: [new client.embed().setColor(client.config.embedColorRed).setTimestamp().setThumbnail(member.user.displayAvatarURL({size: 2048}) as string).setTitle(`Member Left: ${member.user.tag}`).setDescription(`<@${member.user.id}>\n\`${member.user.id}\``).addFields( {name: '🔹 Account Creation Date', value: `\n`}, {name: '🔹 Server Join Date', value: `\n`}, {name: `🔹 Roles: ${member.roles.cache.size - 1}`, value: `${member.roles.cache.size > 1 ? member.roles.cache.filter((x)=>x.id !== member.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'}`, inline: true}, {name: '🔹 Level messages', value: `${client.userLevels._content[member.user.id]?.messages.toLocaleString('en-US') || 0}`, inline: true} - ); - (client.channels.resolve(client.config.mainServer.channels.logs) as Discord.TextChannel).send({embeds: [embed]}); + )]}); delete client.userLevels._content[member.user.id]; } } diff --git a/src/events/guildMemberUpdate.ts b/src/events/guildMemberUpdate.ts index a5a5755..6b90acb 100644 --- a/src/events/guildMemberUpdate.ts +++ b/src/events/guildMemberUpdate.ts @@ -16,12 +16,8 @@ export default { const oldRoles = oldMember.roles.cache.map((x,i)=>i).filter(x=>!newMember.roles.cache.map((x,i)=>i).some(y=>y==x)); if (newRoles.length == 0 && oldRoles.length == 0) return; const embed = new client.embed().setColor(client.config.embedColor).setThumbnail(newMember.user.displayAvatarURL({size: 2048})).setTitle(`Role updated: ${newMember.user.tag}`).setDescription(`<@${newMember.user.id}>\n\`${newMember.user.id}\``) - if (newRoles.length != 0){ - embed.addFields({name: '🔹 Role added', value: newRoles.map((x)=>`<@&${x}>`).join(' ')}) - } - if (oldRoles.length != 0){ - embed.addFields({name: '🔹 Role removed', value: oldRoles.map((x)=>`<@&${x}>`).join(' ')}) - } + if (newRoles.length != 0) embed.addFields({name: '🔹 Role added', value: newRoles.map((x)=>`<@&${x}>`).join(' ')}); + if (oldRoles.length != 0) embed.addFields({name: '🔹 Role removed', value: oldRoles.map((x)=>`<@&${x}>`).join(' ')}); channel.send({embeds: [embed]}) } } \ No newline at end of file diff --git a/src/events/interactionCreate.ts b/src/events/interactionCreate.ts index 3f512d9..5600194 100644 --- a/src/events/interactionCreate.ts +++ b/src/events/interactionCreate.ts @@ -1,21 +1,21 @@ import Discord from 'discord.js'; import TClient from '../client'; export default { - async run(client:TClient, interaction:Discord.BaseInteraction){ - if (!interaction.inGuild() || !interaction.inCachedGuild()) return; - if (interaction.isChatInputCommand()){ - const commandFile = client.commands.get(interaction.commandName); - console.log(`[${client.moment().format('DD/MM/YY HH:mm:ss')}] ${interaction.user.tag} used /${interaction.commandName} ${interaction.options.getSubcommand(false) ?? ''} in #${interaction.channel.name}`); - if (!client.config.botSwitches.commands && !client.config.eval.whitelist.includes(interaction.user.id)) return interaction.reply({content: 'Bot is currently being run in development mode.', ephemeral: true}); - if (commandFile){ - try{ - commandFile.default.run(client, interaction); - commandFile.uses ? commandFile.uses++ : commandFile.uses = 1; - } catch (error){ - console.log(`An error occured while running command "${commandFile.name}"`, error, error.stack); - return interaction.reply('An error occured while executing that command.'); - } - } + async run(client:TClient, interaction:Discord.BaseInteraction){ + if (!interaction.inGuild() || !interaction.inCachedGuild()) return; + if (interaction.isChatInputCommand()){ + const commandFile = client.commands.get(interaction.commandName); + console.log(`[${client.moment().format('DD/MM/YY HH:mm:ss')}] ${interaction.user.tag} used /${interaction.commandName} ${interaction.options.getSubcommand(false) ?? ''} in #${interaction.channel.name}`); + if (!client.config.botSwitches.commands && !client.config.eval.whitelist.includes(interaction.user.id)) return interaction.reply({content: 'Bot is currently being run in development mode.', ephemeral: true}); + if (commandFile){ + try{ + commandFile.default.run(client, interaction); + commandFile.uses ? commandFile.uses++ : commandFile.uses = 1; + } catch (error){ + console.log(`An error occured while running command "${commandFile.name}"`, error, error.stack); + return interaction.reply('An error occured while executing that command.'); } + } } + } } \ No newline at end of file diff --git a/src/events/messageCreate.ts b/src/events/messageCreate.ts index 7c9bdb0..4af6bb5 100644 --- a/src/events/messageCreate.ts +++ b/src/events/messageCreate.ts @@ -2,10 +2,7 @@ import Discord, { ChannelType } from 'discord.js'; import TClient from '../client'; export default { async run(client:TClient, message:Discord.Message){ - if ( - message.author.bot - || message.channel.type === ChannelType.DM - ) return; + if (message.author.bot || message.channel.type === ChannelType.DM) return; const msgarr = message.content.toLowerCase().split(' '); let automodded: boolean; @@ -19,9 +16,7 @@ export default { if (client.bannedWords._content.some((x)=>msgarr.includes(x)) && !message.member.roles.cache.has(client.config.mainServer.roles.dcmod) && message.guildId == client.config.mainServer.id && !Whitelist.includes(message.channelId) && client.config.botSwitches.automod){ automodded = true; - message.delete().catch((err)=>{ - console.log('bannedWords automod; msg got possibly deleted by another bot.') - }) + message.delete().catch(err=>console.log('bannedWords automod; msg got possibly deleted by another bot.')) message.channel.send('That word is banned here.').then((x)=>setTimeout(()=>x.delete(), 5000)); if (client.repeatedMessages[message.author.id]){ // add this message to the list @@ -58,20 +53,15 @@ export default { } if (message.content.toLowerCase().includes('discord.gg/') && !message.member.roles.cache.has(client.config.mainServer.roles.dcmod) && message.guildId == client.config.mainServer.id && !Whitelist.includes(message.channelId)) { automodded = true; - message.delete().catch((err)=>{ - console.log('advertisement automod; msg got possibly deleted by another bot.') - }) + message.delete().catch(err=>console.log('advertisement automod; msg got possibly deleted by another bot.')) message.channel.send('Advertising other Discord servers is not allowed.').then(x=>setTimeout(()=>x.delete(), 10000)) if (client.repeatedMessages[message.author.id]){ client.repeatedMessages[message.author.id].set(message.createdTimestamp,{cont:1,ch:message.channelId}); clearTimeout(client.repeatedMessages[message.author.id].to); client.repeatedMessages[message.author.id].to = setTimeout(onTimeout, 60000); - const threshold = 60000; - client.repeatedMessages[message.author.id] = client.repeatedMessages[message.author.id].filter((x:any, i:number)=> i >= Date.now() - threshold) - const spammedMessage = client.repeatedMessages[message.author.id]?.find((x:any)=>{ return client.repeatedMessages[message.author.id].filter((y:any)=>x.cont === y.cont).size >= 4; }); @@ -83,7 +73,6 @@ export default { }else{ client.repeatedMessages[message.author.id] = new client.collection(); client.repeatedMessages[message.author.id].set(message.createdTimestamp, {cont: 1, ch: message.channelId}); - client.repeatedMessages[message.author.id].to = setTimeout(onTimeout, 60000); } } @@ -154,8 +143,7 @@ export default { message.reply('https://cdn.discordapp.com/attachments/925589318276382720/1011333656167579849/F57G5ZS.png') } if (message.content.toLowerCase().includes('nawdic') && NawdicBrokeIt.some(e=>message.content.toLowerCase().includes(e)) && message.channelId !== '516344221452599306'){ - const embed = 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) - message.reply({embeds: [embed]}) + 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 (MorningArray.some(e=>message.content.toLowerCase().startsWith(e)) && message.channelId == '468835415093411863'){ message.reply(`${MorningPhrases[Math.floor(Math.random()*MorningPhrases.length)]}`) diff --git a/src/events/messageDelete.ts b/src/events/messageDelete.ts index e6b47d1..5fe9186 100644 --- a/src/events/messageDelete.ts +++ b/src/events/messageDelete.ts @@ -4,15 +4,8 @@ export default { async run(client:TClient, msg:Discord.Message){ if (!client.config.botSwitches.logs) return; const channel = client.channels.resolve(client.config.mainServer.channels.logs) as Discord.TextChannel; - const disabledChannels = [ - '548032776830582794', '541677709487505408' - ] - if ( - msg.guild?.id != client.config.mainServer.id - || msg.partial - || msg.author.bot - || disabledChannels.includes(msg.channelId) - ) return; + const disabledChannels = ['548032776830582794', '541677709487505408'] + if (msg.guild?.id != client.config.mainServer.id || msg.partial || msg.author.bot || disabledChannels.includes(msg.channelId)) return; const embed = new client.embed().setColor(client.config.embedColorRed).setTimestamp().setAuthor({name: `Author: ${msg.author.tag} (${msg.author.id})`, iconURL: `${msg.author.displayAvatarURL()}`}).setTitle('Message deleted').setDescription(`<@${msg.author.id}>\n\`${msg.author.id}\``); if (msg.content.length != 0) embed.addFields({name: 'Content', value: `\`\`\`\n${msg.content.slice(0,1000)}\n\`\`\``}); embed.addFields( diff --git a/src/events/messageDeleteBulk.ts b/src/events/messageDeleteBulk.ts index c43cd72..a3c37b9 100644 --- a/src/events/messageDeleteBulk.ts +++ b/src/events/messageDeleteBulk.ts @@ -5,7 +5,6 @@ export default { if (!client.config.botSwitches.logs) return; if (client.config.mainServer.id != '468835415093411861') return; const channel = client.channels.resolve(client.config.mainServer.channels.logs) as Discord.TextChannel; - const embed = new client.embed().setColor(client.config.embedColorRed).setTimestamp().setTitle(`${messages.size} messages were purged`).setDescription(`\`\`\`${messages.map((msgs)=>`${msgs.member.displayName}: ${msgs.content}`).reverse().join('\n').slice(0,3900)}\`\`\``).addFields({name: 'Channel', value: `<#${messages.first().channel.id}>`}); - channel.send({embeds: [embed]}) + channel.send({embeds: [new client.embed().setColor(client.config.embedColorRed).setTimestamp().setTitle(`${messages.size} messages were purged`).setDescription(`\`\`\`${messages.map((msgs)=>`${msgs.member.displayName}: ${msgs.content}`).reverse().join('\n').slice(0,3900)}\`\`\``).addFields({name: 'Channel', value: `<#${messages.first().channel.id}>`})]}) } } \ No newline at end of file diff --git a/src/events/messageUpdate.ts b/src/events/messageUpdate.ts index d1d5f19..14d4fdf 100644 --- a/src/events/messageUpdate.ts +++ b/src/events/messageUpdate.ts @@ -3,22 +3,11 @@ import TClient from '../client'; export default { async run(client:TClient, oldMsg:Discord.Message, newMsg:Discord.Message){ if (!client.config.botSwitches.logs) return; - const disabledChannels = [ - '548032776830582794', '541677709487505408' - ] - if ( - oldMsg.guild?.id != client.config.mainServer.id - || oldMsg.author == null - || oldMsg?.author.bot - || oldMsg.partial - || newMsg.partial - || !newMsg.member - || disabledChannels.includes(newMsg.channelId) - ) return; + const disabledChannels = ['548032776830582794', '541677709487505408'] + if (oldMsg.guild?.id != client.config.mainServer.id || oldMsg.author == null || oldMsg?.author.bot || oldMsg.partial || newMsg.partial || !newMsg.member || disabledChannels.includes(newMsg.channelId)) return; const msgarr = newMsg.content.toLowerCase().split(' '); if (client.bannedWords._content.some((word:string)=>msgarr.includes(word)) && (!client.isStaff(newMsg.member))) newMsg.delete(); if (newMsg.content === oldMsg.content) return; - const embed = new client.embed().setColor(client.config.embedColor).setTimestamp().setAuthor({name: `Author: ${oldMsg.author.tag} (${oldMsg.author.id})`, iconURL: `${oldMsg.author.displayAvatarURL()}`}).setTitle('Message edited').setDescription(`<@${oldMsg.author.id}>\nOld content:\n\`\`\`\n${oldMsg.content}\n\`\`\`\nNew content:\n\`\`\`\n${newMsg.content}\`\`\`\nChannel: <#${oldMsg.channelId}>`); - (client.channels.resolve(client.config.mainServer.channels.logs) as Discord.TextChannel).send({embeds: [embed], components: [new ActionRowBuilder().addComponents(new 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.tag} (${oldMsg.author.id})`, iconURL: `${oldMsg.author.displayAvatarURL()}`}).setTitle('Message edited').setDescription(`<@${oldMsg.author.id}>\nOld content:\n\`\`\`\n${oldMsg.content}\n\`\`\`\nNew content:\n\`\`\`\n${newMsg.content}\`\`\`\nChannel: <#${oldMsg.channelId}>`)], components: [new ActionRowBuilder().addComponents(new ButtonBuilder().setStyle(5).setURL(`${oldMsg.url}`).setLabel('Jump to message'))]}); } } diff --git a/src/index.ts b/src/index.ts index abe9aad..2bfdf58 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,36 +7,27 @@ import MPDB from './models/MPServer'; import {Punishment, UserLevels, FSData, FSCareerSavegame} from './typings/interfaces'; client.on('ready', async()=>{ - client.guilds.cache.forEach(async(e)=>{await e.members.fetch()}); - setInterval(async()=>{ - client.user.setPresence(client.config.botPresence); - }, 300000); - if (client.config.botSwitches.registerCommands){ - client.config.whitelistedServers.forEach((guildId)=>(client.guilds.cache.get(guildId) as Discord.Guild).commands.set(client.registry).catch((e:Error)=>{ - console.log(`Couldn't register slash commands for ${guildId} because`, e.stack); - (client.channels.resolve(client.config.mainServer.channels.errors) as Discord.TextChannel).send(`Cannot register slash commands for **${client.guilds.cache.get(guildId).name}** (\`${guildId}\`):\n\`\`\`${e.message}\`\`\``) - })); - }; - - setInterval(()=>{ - const guild = client.guilds.cache.get(client.config.mainServer.id) as Discord.Guild; - guild.invites.fetch().then((invs)=>{ - invs.forEach(async(inv)=>{ - client.invites.set(inv.code, {uses: inv.uses, creator: inv.inviterId}) - }) - }) - }, 500000); - console.log(`${client.user.tag} has logged into Discord API and now ready for operation`); - console.log(client.config.botSwitches); - console.log(client.config.whitelistedServers); - (client.channels.resolve(client.config.mainServer.channels.bot_status) as Discord.TextChannel).send(`${client.user.username} is active\n\`\`\`json\n${Object.entries(client.config.botSwitches).map((hi)=>`${hi[0]}: ${hi[1]}`).join('\n')}\`\`\``); + setInterval(()=>client.user.setPresence(client.config.botPresence), 300000); + await client.guilds.fetch(client.config.mainServer.id).then(async guild=>{ + await guild.members.fetch(); + setInterval(()=>guild.invites.fetch().then(invites=>invites.forEach(inv=>client.invites.set(inv.code, {uses: inv.uses, creator: inv.inviterId}))),300000) + }); + 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)=>{ + console.log(`Couldn't register slash commands for ${guildId} because`, e.stack); + (client.channels.resolve(client.config.mainServer.channels.errors) as Discord.TextChannel).send(`Cannot register slash commands for **${client.guilds.cache.get(guildId).name}** (\`${guildId}\`):\n\`\`\`${e.message}\`\`\``) + })) + }; + console.log(`${client.user.tag} has logged into Discord API`); + console.log(client.config.botSwitches, client.config.whitelistedServers); + (client.channels.resolve(client.config.mainServer.channels.bot_status) as Discord.TextChannel).send(`${client.user.username} is active\n\`\`\`json\n${Object.entries(client.config.botSwitches).map((hi)=>`${hi[0]}: ${hi[1]}`).join('\n')}\`\`\``); }) // Handle errors function DZ(error:Error, location:string){// Yes, I may have shiternet but I don't need to wake up to like a hundred messages or so. - if (['getaddrinfo ENOTFOUND discord.com'].includes(error.message)) return; - console.log(error); - (client.channels.resolve(client.config.mainServer.channels.errors) as Discord.TextChannel).send({embeds: [new client.embed().setColor('#420420').setTitle('Error caught!').setFooter({text: location}).setDescription(`**Error:** \`${error.message}\`\n\n**Stack:** \`${`${error.stack}`.slice(0, 2500)}\``)]}) + if (['getaddrinfo ENOTFOUND discord.com'].includes(error.message)) return; + console.log(error); + (client.channels.resolve(client.config.mainServer.channels.errors) as Discord.TextChannel).send({embeds: [new client.embed().setColor('#420420').setTitle('Error caught!').setFooter({text: location}).setDescription(`**Error:** \`${error.message}\`\n\n**Stack:** \`${`${error.stack}`.slice(0, 2500)}\``)]}) } process.on('unhandledRejection', async(error: Error)=>DZ(error, 'unhandledRejection')); process.on('uncaughtException', async(error: Error)=>DZ(error, 'uncaughtException')); @@ -45,19 +36,19 @@ client.on('error', async(error: Error)=>DZ(error, 'client-error')); // Daggerwin MP loop setInterval(async()=>{ - if (!client.config.botSwitches.mpstats) return; - const msg = await (client.channels.resolve('543494084363288637') as Discord.TextChannel).messages.fetch('1023699243183112192') - const embed = new client.embed(); - let Players = []; - let error; + if (!client.config.botSwitches.mpstats) return; + const msg = await (client.channels.resolve('543494084363288637') as Discord.TextChannel).messages.fetch('1023699243183112192') + const embed = new client.embed(); + let Players = []; + let error; - // Connect to DB to retrieve the Gameserver info to fetch data. - MPDB.sync(); - const ServerURL = MPDB.findOne({where: {serverId: client.config.mainServer.id}}) - const DBURL = (await ServerURL).ip - const DBCode = (await ServerURL).code - const verifyURL = DBURL.match(/http/); - const completedURL_DSS = DBURL + '/feed/dedicated-server-stats.json?code=' + DBCode + // Connect to DB to retrieve the Gameserver info to fetch data. + MPDB.sync(); + const ServerURL = MPDB.findOne({where: {serverId: client.config.mainServer.id}}) + const DBURL = (await ServerURL).ip + const DBCode = (await ServerURL).code + const verifyURL = DBURL.match(/http/); + const completedURL_DSS = DBURL + '/feed/dedicated-server-stats.json?code=' + DBCode const completedURL_CSG = DBURL + '/feed/dedicated-server-savegame.html?code=' + DBCode + '&file=careerSavegame' const FSdss = { data: {} as FSData,