This repository has been archived by the owner on Jun 3, 2023. It is now read-only.
generated from Mirasaki/discord.js-bot-template
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #25 from Mirasaki/rank-command
Stats command
- Loading branch information
Showing
6 changed files
with
274 additions
and
104 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
const logger = require('@mirasaki/logger'); | ||
const { stripIndents } = require('common-tags/lib'); | ||
const { fetchPlayerDetails } = require('../../modules/cftClient'); | ||
const { colorResolver, titleCase } = require('../../util'); | ||
|
||
const { DEBUG_STAT_COMMAND_DATA } = process.env; | ||
|
||
module.exports = { | ||
data: { | ||
description: 'Display information for a specific player', | ||
options: [ | ||
{ | ||
type: 3, // STRING, | ||
name: 'cftoolsid', | ||
description: 'The player\'s CFTools Cloud ID', | ||
required: true | ||
} | ||
] | ||
}, | ||
|
||
config: { | ||
cooldown: { | ||
usages: 10, | ||
duration: 60 | ||
} | ||
}, | ||
|
||
// eslint-disable-next-line sonarjs/cognitive-complexity | ||
run: async ({ client, interaction }) => { | ||
// Destructuring and assignments | ||
const { options, member } = interaction; | ||
const { emojis } = client.container; | ||
const cftoolsId = options.getString('cftoolsid'); | ||
|
||
// Deferring our reply and fetching from API | ||
await interaction.deferReply(); | ||
let data; | ||
try { | ||
data = await fetchPlayerDetails(cftoolsId); | ||
} catch (err) { | ||
interaction.editReply({ | ||
content: `${emojis.error} ${member}, encountered an error while fetching data, please try again later.` | ||
}); | ||
return; | ||
} | ||
|
||
// Invalid ID or no access granted | ||
if (data.status === false) { | ||
interaction.editReply({ | ||
content: `${emojis.error} ${member}, either the ID you provided is invalid or that player isn't currently known to the client. This command has been cancelled.` | ||
}); | ||
return; | ||
} | ||
|
||
// Data is delivered as on object with ID key parameters | ||
const stats = data[cftoolsId]; | ||
|
||
// Detailed, conditional debug logging | ||
if (DEBUG_STAT_COMMAND_DATA === 'true') { | ||
logger.startLog('STAT COMMAND DATA'); | ||
console.dir(stats, { depth: Infinity }); | ||
logger.endLog('STAT COMMAND DATA'); | ||
} | ||
|
||
// Assigning our stat variables | ||
const { omega, game } = stats; | ||
const { general } = game; | ||
const hoursPlayed = Math.round(omega.playtime / 60 / 60); | ||
const remainingMinutesPlayed = Math.round(omega.playtime % 60); | ||
const playSessions = omega.sessions; | ||
const averagePlaytimePerSession = Math.round( | ||
((hoursPlayed * 60) | ||
+ remainingMinutesPlayed) | ||
/ playSessions | ||
); | ||
const [ | ||
day, month, date, year, time, timezone | ||
] = `${new Date(stats.updated_at)}`.split(' '); | ||
let favoriteWeaponName; | ||
const highestKills = Object.entries(general.weapons).reduce((acc, [weaponName, weaponStats]) => { | ||
const weaponKillsIsLower = acc > weaponStats.kills; | ||
if (!weaponKillsIsLower) favoriteWeaponName = weaponName; | ||
return weaponKillsIsLower ? acc : weaponStats.kills; | ||
}, 0); | ||
// const favoriteWeapon = Object.entries(general.weapons).find(([name]) => name === favoriteWeaponName); | ||
const cleanedWeaponName = titleCase(favoriteWeaponName.replace(/_/g, ' ')); | ||
|
||
// Reversing the name history array so the latest used name is the first item | ||
omega.name_history.reverse(); | ||
|
||
// Returning our detailed player information | ||
interaction.editReply({ | ||
embeds: [ | ||
{ | ||
color: colorResolver(), | ||
title: `Stats for ${omega.name_history[0] || 'Survivor'}`, | ||
description: stripIndents` | ||
Survivor has played for ${hoursPlayed} hours and ${remainingMinutesPlayed} minutes over ${playSessions} total sessions. | ||
Bringing them to an average of ${averagePlaytimePerSession} minutes per session. | ||
**Name History:** **\`${omega.name_history.slice(0, 10).join('`**, **`')}\`** | ||
**Deaths:** ${general.deaths || 0} | ||
**Hits:** ${general.hits || 0} | ||
**KDRatio:** ${general.kdratio || 0} | ||
**Kills:** ${general.kills || 0} | ||
**Longest Kill:** ${general.longest_kill || 0} m | ||
**Longest Shot:** ${general.longest_shot || 0} m | ||
**Suicides:** ${general.suicides || 0} | ||
**Favorite Weapon:** ${cleanedWeaponName || 'Knife'} with ${highestKills || 0} kills | ||
`, | ||
footer: { | ||
text: `Last action: ${time} | ${day} ${month} ${date} ${year} ${time} (${timezone})` | ||
} | ||
} | ||
] | ||
}); | ||
} | ||
}; | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,98 @@ | ||
const statsCommand = require('./stats'); | ||
const { stripIndents } = require('common-tags'); | ||
const { version } = require('discord.js'); | ||
const { colorResolver } = require('../../util'); | ||
|
||
const discordVersion = version.indexOf('dev') < 0 ? version : version.slice(0, version.indexOf('dev') + 3); | ||
const discordVersionDocLink = `https://discord.js.org/#/docs/discord.js/v${discordVersion.split('.')[0]}/general/welcome`; | ||
const nodeVersionDocLink = `https://nodejs.org/docs/latest-${process.version.split('.')[0]}.x/api/#`; | ||
|
||
// Spread all the data from our /stats command but overwrite the name | ||
module.exports = { | ||
...statsCommand, | ||
data: { | ||
...statsCommand.data, | ||
name: 'ping' | ||
name: 'ping', | ||
description: 'Display latency & bot stats' | ||
}, | ||
|
||
config: { | ||
globalCmd: true | ||
}, | ||
|
||
run: async ({ client, interaction }) => { | ||
// Calculating our API latency | ||
const latency = Math.round(client.ws.ping); | ||
const sent = await interaction.reply({ | ||
content: 'Pinging...', | ||
fetchReply: true | ||
}); | ||
const fcLatency = sent.createdTimestamp - interaction.createdTimestamp; | ||
|
||
// Utility function for getting appropriate status emojis | ||
const getMsEmoji = (ms) => { | ||
let emoji = undefined; | ||
for (const [key, value] of Object.entries({ | ||
250: '🟢', | ||
500: '🟡', | ||
1000: '🟠' | ||
})) if (ms <= key) { | ||
emoji = value; | ||
break; | ||
} | ||
return (emoji ??= '🔴'); | ||
}; | ||
|
||
// Replying to the interaction with our embed data | ||
interaction.editReply({ | ||
content: '\u200b', | ||
embeds: [ | ||
{ | ||
color: colorResolver(), | ||
author: { | ||
name: `${client.user.tag}`, | ||
iconURL: client.user.displayAvatarURL() | ||
}, | ||
fields: [ | ||
{ | ||
name: 'Latency', | ||
value: stripIndents` | ||
${getMsEmoji(latency)} **API Latency:** ${latency} ms | ||
${getMsEmoji(fcLatency)} **Full Circle Latency:** ${fcLatency} ms | ||
`, | ||
inline: true | ||
}, | ||
{ | ||
name: 'Memory', | ||
value: stripIndents` | ||
💾 **Memory Usage:** ${(process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2)} MB | ||
♻️ **Cache Size:** ${(process.memoryUsage().external / 1024 / 1024).toFixed(2)} MB | ||
`, | ||
inline: true | ||
}, | ||
{ | ||
name: 'Uptime', | ||
value: stripIndents`**📊 I've been online for ${parseInt((client.uptime / (1000 * 60 * 60 * 24)) % 60, 10)} days, ${parseInt((client.uptime / (1000 * 60 * 60)) % 24, 10)} hours, ${parseInt((client.uptime / (1000 * 60)) % 60, 10)} minutes and ${parseInt((client.uptime / 1000) % 60, 10)}.${parseInt((client.uptime % 1000) / 100, 10)} seconds!**`, | ||
inline: false | ||
}, | ||
{ | ||
name: 'System', | ||
value: stripIndents` | ||
⚙️ **Discord.js Version:** [v${discordVersion}](${discordVersionDocLink}) | ||
⚙️ **Node Version:** [${process.version}](${nodeVersionDocLink}) | ||
`, | ||
inline: true | ||
}, | ||
{ | ||
name: 'Stats', | ||
value: stripIndents` | ||
👪 **Servers:** ${client.guilds.cache.size.toLocaleString('en-US')} | ||
🙋 **Users:** ${client.guilds.cache.reduce((previousValue, currentValue) => previousValue += currentValue.memberCount, 0).toLocaleString('en-US')} | ||
`, | ||
inline: true | ||
} | ||
], | ||
footer: { | ||
text: 'Made with ❤️ by Mirasaki#0001 • Open to collaborate • me@mirasaki.dev' | ||
} | ||
} | ||
] | ||
}); | ||
} | ||
}; |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.