diff --git a/src/commands/contributors.ts b/src/commands/contributors.ts index 5a9977d..6200f3f 100644 --- a/src/commands/contributors.ts +++ b/src/commands/contributors.ts @@ -1,11 +1,12 @@ import Discord from 'discord.js'; import TClient from '../client.js'; +import MessageTool from '../helpers/MessageTool.js'; export default { run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ - interaction.reply({embeds: [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(MessageTool.concatMessage( '**Thanks to those below that contributed to/developed the bot!**', client.config.contribList.map(id=>{const member = interaction.guild.members.cache.get(id); return `${member?.user?.username ?? 'N/A'} <@${id}>`}).join('\n') - ].join('\n'))]}) + ))]}) }, data: new Discord.SlashCommandBuilder() .setName('contributors') diff --git a/src/commands/dev.ts b/src/commands/dev.ts index 61239f8..63ff9a0 100644 --- a/src/commands/dev.ts +++ b/src/commands/dev.ts @@ -2,6 +2,7 @@ import Discord from 'discord.js'; import {Octokit} from '@octokit/rest'; import {createTokenAuth} from '@octokit/auth-token'; import {exec} from 'node:child_process'; +import MessageTool from '../helpers/MessageTool.js'; import fs from 'node:fs'; import util from 'node:util'; import TClient from '../client.js'; @@ -92,13 +93,13 @@ export default { if (name) currentActivities[0].name = name; if (url) currentActivities[0].url = url; client.user.setPresence(client.config.botPresence); - interaction.reply([ + interaction.reply(MessageTool.concatMessage( 'Presence updated:', `Status: **${client.config.botPresence.status}**`, `Type: **${convertType(currentActivities[0].type)}**`, `Name: **${currentActivities[0].name}**`, `URL: \`${currentActivities[0].url}\`` - ].join('\n')) + )) }, statsgraph: ()=>{ client.statsGraph = -(interaction.options.getInteger('number', true)); diff --git a/src/commands/faq.ts b/src/commands/faq.ts index 5501a17..1778954 100644 --- a/src/commands/faq.ts +++ b/src/commands/faq.ts @@ -1,14 +1,9 @@ import Discord from 'discord.js'; import TClient from '../client.js'; +import MessageTool from '../helpers/MessageTool.js'; export default { run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ - function faqEmbed(color:Discord.ColorResolvable,title:string,description?:string|null,image?:string|null){ - const embed = new client.embed().setColor(color).setTitle(title); - if (description) embed.setDescription(description); - if (image) embed.setImage(image); - return embed - } // I am loving this fancy idea, pretty simplified! - const joinVerifyFaqDesc = [ + const verifyFaq = MessageTool.concatMessage( '```ansi', 'Steam (Top panel)', '1. Go to your game library and right click on Farming Simulator 22', @@ -21,17 +16,17 @@ export default { '2. Click on Manage and click on "Verify"', '3. Epic Launcher will scan your game installation directory and will re-download anything that is corrupted or tampered with.', '```' - ].join('\n'); + ); ({ srp: ()=>interaction.reply('[Ballyspring]() 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.'), vtcR: ()=>interaction.reply(`You can get the <@&${client.config.mainServer.roles.vtcmember}> role from <#802283932430106624> by clicking :truck: button on a webhook's message\n*VTC skin can also be found in <#801975222609641472> as well.*`), mpR: ()=>interaction.reply(`You can get the <@&${client.config.mainServer.roles.mpplayer}> role from <#802283932430106624> by clicking :tractor: button on webhook's message`), - ytscam: ()=>interaction.reply({embeds: [faqEmbed(client.config.embedColor, '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.', 'https://cdn.discordapp.com/attachments/1015195575693627442/1068078284996345916/image.png')]}), - steamscam: ()=>interaction.reply({embeds: [faqEmbed(client.config.embedColor, '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)', 'https://cdn.discordapp.com/attachments/1091300529696673792/1122266621088645130/image.png')]}), - fsVerifyGame: ()=>interaction.reply({embeds: [faqEmbed(client.config.embedColor, 'Verifying your game files', `You can verify your game files if you experience any issues with your game.\n${joinVerifyFaqDesc}`, 'https://cdn.discordapp.com/attachments/1015195575693627442/1138185771971526757/Steam-Epic-VerifyGamesLocation.png')]}), - fsShader: ()=>interaction.reply({embeds: [faqEmbed(client.config.embedColor, '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`', 'https://cdn.discordapp.com/attachments/1015195575693627442/1015195687970943016/unknown.png')]}), - fsLogfile: ()=>interaction.reply({embeds: [faqEmbed(client.config.embedColor, '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.', 'https://cdn.discordapp.com/attachments/1015195575693627442/1015195643528101958/unknown.png')]}), - fsDevConsole: ()=>interaction.reply({embeds: [faqEmbed(client.config.embedColor, 'Enabling the development console', 'Head over to `game.xml` in `Documents/My Games/FarmingSimulator2022` and find the section that mentions `false` inside development section, change it to `true` then you are good to go!\nFYI: The keybind to open console is \``\u200b\` (backtick).', 'https://cdn.discordapp.com/attachments/1015195575693627442/1097273921444790322/image.png')]}) + ytscam: ()=>interaction.reply({embeds: [MessageTool.embedStruct(client.config.embedColor, '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.', 'https://cdn.discordapp.com/attachments/1015195575693627442/1068078284996345916/image.png')]}), + steamscam: ()=>interaction.reply({embeds: [MessageTool.embedStruct(client.config.embedColor, '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)', 'https://cdn.discordapp.com/attachments/1091300529696673792/1122266621088645130/image.png')]}), + fsVerifyGame: ()=>interaction.reply({embeds: [MessageTool.embedStruct(client.config.embedColor, 'Verifying your game files', `You can verify your game files if you experience any issues with your game.\n${verifyFaq}`, 'https://cdn.discordapp.com/attachments/1015195575693627442/1138185771971526757/Steam-Epic-VerifyGamesLocation.png')]}), + fsShader: ()=>interaction.reply({embeds: [MessageTool.embedStruct(client.config.embedColor, '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`', 'https://cdn.discordapp.com/attachments/1015195575693627442/1015195687970943016/unknown.png')]}), + fsLogfile: ()=>interaction.reply({embeds: [MessageTool.embedStruct(client.config.embedColor, '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.', 'https://cdn.discordapp.com/attachments/1015195575693627442/1015195643528101958/unknown.png')]}), + fsDevConsole: ()=>interaction.reply({embeds: [MessageTool.embedStruct(client.config.embedColor, 'Enabling the development console', 'Head over to `game.xml` in `Documents/My Games/FarmingSimulator2022` and find the section that mentions `false` inside development section, change it to `true` then you are good to go!\nFYI: The keybind to open console is \``\u200b\` (backtick).', 'https://cdn.discordapp.com/attachments/1015195575693627442/1097273921444790322/image.png')]}) } as any)[interaction.options.getString('question', true)](); }, data: new Discord.SlashCommandBuilder() diff --git a/src/commands/inviteinfo.ts b/src/commands/inviteinfo.ts index 6052a45..a6f3a69 100644 --- a/src/commands/inviteinfo.ts +++ b/src/commands/inviteinfo.ts @@ -1,16 +1,17 @@ import Discord from 'discord.js'; import TClient from '../client.js'; +import MessageTool from '../helpers/MessageTool.js'; export default { 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 interaction.reply({embeds:[new client.embed() - .setColor(client.config.embedColor).setURL(`https://discord.gg/${inviteData.code}`).setTitle(inviteData.guild.name).setDescription([ + .setColor(client.config.embedColor).setURL(`https://discord.gg/${inviteData.code}`).setTitle(inviteData.guild.name).setDescription(MessageTool.concatMessage( `ID: \`${inviteData.guild.id}\``, `Description: \`\`\`${inviteData.guild.description != null ? inviteData.guild.description : 'No description set.'}`, `\`\`\`Total server boosts: \`${inviteData.guild.premiumSubscriptionCount}\``, `Total members: \`${inviteData.presenceCount}\`**/**\`${inviteData.memberCount}\``, `Channel: \`#${inviteData.channel.name}\``, - ].join('\n')).setThumbnail(inviteData.guild.iconURL({size:1024,extension:'webp'})).setImage(inviteData.guild.bannerURL({size:2048,extension:'webp'})) + )).setThumbnail(inviteData.guild.iconURL({size:1024,extension:'webp'})).setImage(inviteData.guild.bannerURL({size:2048,extension:'webp'})) ]})).catch((err:Discord.DiscordAPIError)=>interaction.reply(err.message)); }, data: new Discord.SlashCommandBuilder() diff --git a/src/commands/mp.ts b/src/commands/mp.ts index 3827c72..b15cd35 100644 --- a/src/commands/mp.ts +++ b/src/commands/mp.ts @@ -2,6 +2,7 @@ import Discord from 'discord.js'; import TClient from '../client.js'; import path from 'node:path'; import canvas from 'canvas'; +import MessageTool from '../helpers/MessageTool.js'; import {readFileSync} from 'node:fs'; import {FSData} from 'src/typings/interfaces.js'; @@ -178,7 +179,7 @@ export default { info: async()=>{ if (!endpoint) return console.log('Endpoint failed - info') if (endpoint.server.name.length < 1) embed.setFooter({text: 'Server is currently offline.'}) - interaction.reply({embeds: [embed.setColor(client.config.embedColor).setDescription([ + interaction.reply({embeds: [embed.setColor(client.config.embedColor).setDescription(MessageTool.concatMessage( `**Server name**: \`${endpoint?.server.name.length === 0 ? '\u200b' : endpoint.server.name}\``, '**Password:** `mf4700`', '**Crossplay server**', @@ -186,7 +187,7 @@ export default { `**Mods:** [Click here](${database[serverSelector].ip}/mods.html) **|** [Direct Download](${database[serverSelector].ip}/all_mods_download?onlyActive=true)`, '**Filters:** [Click here](https://discord.com/channels/468835415093411861/468835769092669461/926581585938120724)', 'Please see <#543494084363288637> for additional information.' - ].join('\n'))]}); + ))]}); }, /* url: async()=>{ if (client.config.mainServer.id == interaction.guildId) { diff --git a/src/commands/statistics.ts b/src/commands/statistics.ts index da55283..192738a 100644 --- a/src/commands/statistics.ts +++ b/src/commands/statistics.ts @@ -1,5 +1,6 @@ import Discord from 'discord.js'; import pkg from 'typescript'; +import MessageTool from '../helpers/MessageTool.js'; import si from 'systeminformation'; import TClient from '../client.js'; import os from 'node:os'; @@ -15,7 +16,7 @@ export default { const columns = ['Command name', 'Count']; 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: **${client.formatTime(client.uptime as number, 3, {longNames: true, commas: true})}**`); + if (includedCommands.size === 0) return interaction.reply(`No commands have been used yet.\nUptime: **${client.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 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']; @@ -25,10 +26,10 @@ export default { rows.push(`${name + ' '.repeat(nameLength - name.length)}${' '.repeat(amountLength - count.length) + count}\n`); }); const embed = new client.embed().setColor(client.config.embedColor).setTitle('Statistics: Command Usage') - .setDescription([ + .setDescription(MessageTool.concatMessage( 'List of commands that have been used in this session, ordered by amount of use. Table contains command name and amount of uses.', `Total amount of commands used in this session: ${client.commands.filter(x=>x.uses).map(x=>x.uses).reduce((a,b)=>a+b, 0)}` - ].join('\n')) + )); if (rows.join('').length > 1024){ let fieldValue = ''; rows.forEach(row=>{ @@ -40,20 +41,20 @@ export default { embed.addFields({name: '\u200b', value: `\`\`\`\n${fieldValue}\`\`\``}); } else embed.addFields({name: '\u200b', value: `\`\`\`\n${rows.join('')}\`\`\``}); embed.addFields( - {name: '> __Dependencies__', value: [ + {name: '> __Dependencies__', value: MessageTool.concatMessage( `**TypeScript:** ${pkg.version}`, `**NodeJS:** ${process.version}`, `**DiscordJS:** ${Discord.version}`, `**Yarn:** ${packageJson.packageManager.slice(5)}` - ].join('\n')}, - {name: '> __Host__', value: [ + )}, + {name: '> __Host__', value: MessageTool.concatMessage( `**Operating System:** ${osInfo.distro + ' ' + osInfo.release}`, `**CPU:** ${cpu.manufacturer} ${cpu.brand}`, `**Memory:** ${client.formatBytes(ram.used)}/${client.formatBytes(ram.total)}`, `**Process:** ${client.formatBytes(process.memoryUsage().heapUsed)}/${client.formatBytes(process.memoryUsage().heapTotal)}`, `**Load Usage:**\nUser: ${currentLoad.currentLoadUser.toFixed(1)}%\nSystem: ${currentLoad.currentLoadSystem.toFixed(1)}%`, `**Uptime:**\nHost: ${client.formatTime((os.uptime()*1000), 2, {longNames: true, commas: true})}\nBot: ${client.formatTime(client.uptime, 2, {commas: true, longNames: true})}` - ].join('\n')} + )} ); waitForData.edit({content:null,embeds:[embed]}).then(x=>x.edit({embeds:[new client.embed(x.embeds[0].data).setFooter({text: `Load time: ${client.formatTime(x.createdTimestamp - interaction.createdTimestamp, 2, {longNames: true, commas: true})}`})]})) }, diff --git a/src/commands/suggest.ts b/src/commands/suggest.ts index a2d163c..f8395ec 100644 --- a/src/commands/suggest.ts +++ b/src/commands/suggest.ts @@ -1,5 +1,6 @@ import Discord from 'discord.js'; import TClient from '../client.js'; +import MessageTool from '../helpers/MessageTool.js'; export default { async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>){ const replyInDM = interaction.options.getString('message'); @@ -20,10 +21,10 @@ export default { .setTitle(`Suggestion ID: ${suggestionID}`) .setAuthor({name: interaction.user.username, iconURL: interaction.user.avatarURL({size: 256})}) .setFooter({text: `Timestamp: ${timeFormatting}`}) - .setDescription([ + .setDescription(MessageTool.concatMessage( '> **Suggestion:**', suggestionText - ].join('\n')); + )); if (suggestionImage) notifEmbed.setImage(suggestionImage.url); webhook.send({embeds: [notifEmbed], username: `${client.user.username} Notification`, avatarURL: client.user.avatarURL({size: 256})} ).catch(e=>{ diff --git a/src/commands/tag.ts b/src/commands/tag.ts index 44adb8c..77d7663 100644 --- a/src/commands/tag.ts +++ b/src/commands/tag.ts @@ -1,5 +1,6 @@ import Discord from 'discord.js'; import TClient from '../client.js'; +import MessageTool from '../helpers/MessageTool.js'; export default { async autocomplete(client: TClient, interaction: Discord.AutocompleteInteraction){ const array = (await client.tags?._content.find())?.map(x=>x._id).filter(c=>c.startsWith(interaction.options.getFocused())); @@ -22,13 +23,13 @@ export default { const targetMember = interaction.options.getMember('target_user'); if (targetMember) targetField = `*This tag is for <@${targetMember.id}>*`; const embedTemplate = new client.embed().setColor(client.config.embedColor).setTitle(await tagMeta.title()).setDescription(await tagMeta.message()).setFooter({text: `Tag creator: ${await tagMeta.creatorName()}`}); - const messageTemplate = [ + const messageTemplate = MessageTool.concatMessage( targetField ? targetField : '', `**${await tagMeta.title()}**`, await tagMeta.message(), '', `Tag creator: **${await tagMeta.creatorName()}**` - ].join('\n'); + ); if (await tagMeta.isEmbedTrue()) return interaction.reply({content: targetField ? targetField : null, embeds: [embedTemplate], allowedMentions:{parse:['users']}}); else return interaction.reply({content: messageTemplate, allowedMentions:{parse:['users']}}) }, diff --git a/src/events/guildMemberAdd.ts b/src/events/guildMemberAdd.ts index c643738..6e6362d 100644 --- a/src/events/guildMemberAdd.ts +++ b/src/events/guildMemberAdd.ts @@ -1,5 +1,6 @@ import Discord from 'discord.js'; import TClient from '../client.js'; +import MessageTool from '../helpers/MessageTool.js'; export default { async run(client:TClient, member:Discord.GuildMember){ if (member.partial || member.guild?.id != client.config.mainServer.id) return; @@ -27,10 +28,10 @@ export default { {name: '🔹 Invite Data:', value: usedInvite ? `Invite: \`${usedInvite.code}\`\nCreated by: **${usedInvite.inviter?.username}**\nChannel: **#${usedInvite.channel.name}**` : 'No invite data could be fetched.'} )]}); if (await client.punishments._content.findOne({'member': member.user.id, type: 'mute', expired: undefined})){ - (client.channels.resolve(client.config.mainServer.channels.dcmod_chat) as Discord.TextChannel).send({embeds: [new client.embed().setColor(client.config.embedColorYellow).setTitle('Case evasion detected').setDescription([ + (client.channels.resolve(client.config.mainServer.channels.dcmod_chat) as Discord.TextChannel).send({embeds: [new client.embed().setColor(client.config.embedColorYellow).setTitle('Case evasion detected').setDescription(MessageTool.concatMessage( `**${member.user.username}** (\`${member.user.id}\`) has been detected for case evasion.`, 'Timeout has been automatically added. (25 days)' - ].join('\n')).setTimestamp()]}); + )).setTimestamp()]}); await client.punishments.addPunishment('mute', {time: '25d'}, client.user.id, '[AUTOMOD] Case evasion', member.user, member) } } diff --git a/src/helpers/MessageTool.ts b/src/helpers/MessageTool.ts new file mode 100644 index 0000000..6c1400b --- /dev/null +++ b/src/helpers/MessageTool.ts @@ -0,0 +1,14 @@ +import Discord from 'discord.js'; + +export default class MessageTool { + static embedStruct(color:Discord.ColorResolvable, title:string, description?:string|null, image?:string|null){ + const embed = new Discord.EmbedBuilder().setColor(color).setTitle(title); + if (description) embed.setDescription(description); + if (image) embed.setImage(image); + return embed + } + static concatMessage(...messages:string[]){ + return messages.join('\n') + } +} +// I want to come up with better name instead of calling this file "MessageTool", but I am super bad at naming things.