453 lines
15 KiB
JavaScript
453 lines
15 KiB
JavaScript
const { SlashCommandBuilder, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, MessageFlags, AttachmentBuilder } = require('discord.js')
|
|
const { mClient } = require('../../../index')
|
|
require('dotenv').config()
|
|
|
|
function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }
|
|
|
|
const asset_path = './assets/Command_Nuts/'
|
|
|
|
async function nutsGive(interaction) {
|
|
async function tradeWindow(buttonID1, buttonID2) {
|
|
const embed = new EmbedBuilder()
|
|
.setTitle('Gib Nuss!')
|
|
.setDescription(`Willst du wirklich **${amount}** Nüsse an <@${to.id}> senden?`)
|
|
.addFields(
|
|
{ name: `Your Current Balance`, value: `${yourBalance.nuts} (**-${amount}**)`, inline: true },
|
|
{ name: `Your New Balance`, value: `${yourBalance.nuts - amount}`, inline: true },
|
|
{ name: '\u200B', value: '\u200B' },
|
|
{ name: `Their Current Balance`, value: `${theirBalance.nuts} (**+${amount}**)`, inline: true },
|
|
{ name: `Their New Balance`, value: `${theirBalance.nuts + amount}`, inline: true }
|
|
)
|
|
.setThumbnail('attachment://nuts_main.png')
|
|
|
|
const row = new ActionRowBuilder()
|
|
.addComponents(
|
|
new ButtonBuilder()
|
|
.setLabel('✔')
|
|
.setCustomId(buttonID1)
|
|
.setStyle(ButtonStyle.Success)
|
|
)
|
|
.addComponents(
|
|
new ButtonBuilder()
|
|
.setLabel('✖')
|
|
.setCustomId(buttonID2)
|
|
.setStyle(ButtonStyle.Danger)
|
|
)
|
|
|
|
await interaction.reply({
|
|
embeds: [embed],
|
|
components: [row],
|
|
flags: MessageFlags.Ephemeral
|
|
})
|
|
}
|
|
|
|
const from = interaction.user
|
|
const to = await interaction.options.getUser('target')
|
|
var amount = await interaction.options.getNumber('amount')
|
|
|
|
const db = mClient.db(process.env.M_DB)
|
|
const nutsColl = db.collection('items_nuts')
|
|
const yourBalance = await nutsColl.findOne({ userID: from.id })
|
|
const theirBalance = await nutsColl.findOne({ userID: to.id })
|
|
|
|
if (amount <= 0) {
|
|
amount = yourBalance.nuts
|
|
return tradeWindow('nuts_give_fake', 'abort')
|
|
}
|
|
|
|
if (yourBalance.nuts < amount) {
|
|
return await interaction.reply({
|
|
content: 'Du kannst nicht mehr geben als du hast!',
|
|
flags: MessageFlags.Ephemeral
|
|
})
|
|
}
|
|
|
|
return tradeWindow('nuts_give_confirm', 'abort')
|
|
}
|
|
|
|
async function nutsCheck(interaction) {
|
|
let target = interaction.options.getUser('target')
|
|
let addressing
|
|
|
|
if (!target) {
|
|
target = interaction.user
|
|
addressing = `Du hast`
|
|
}
|
|
|
|
if (!target.globalName) {
|
|
addressing = `${target.username} hat`
|
|
} else {
|
|
addressing = `${target.globalName} hat`
|
|
}
|
|
|
|
const db = mClient.db(process.env.M_DB)
|
|
const nutsColl = db.collection('items_nuts')
|
|
const nutsData = await nutsColl.findOne({ userID: target.id })
|
|
|
|
let content
|
|
if (!nutsData) {
|
|
content = `${addressing} noch keine Nüsse gesammelt :(`
|
|
} else {
|
|
content = `${addressing} bereits **${nutsData.nuts}** Nüsse gesammelt!`
|
|
}
|
|
|
|
let title = 'Zähle Nüsse'
|
|
const embed = new EmbedBuilder()
|
|
|
|
for (let i = 0; i < 4; i++) {
|
|
embed.setTitle(title)
|
|
await interaction.editReply({
|
|
embeds: [embed]
|
|
})
|
|
title = title + ' .'
|
|
await delay(500);
|
|
}
|
|
|
|
embed
|
|
.setTitle(content)
|
|
.setThumbnail('attachment://nuts_main.png')
|
|
|
|
await interaction.editReply({
|
|
embeds: [embed],
|
|
files: [`${asset_path}nuts_main.png`]
|
|
})
|
|
}
|
|
|
|
async function nutsLeaderboard(interaction) {
|
|
const row = new ActionRowBuilder()
|
|
.addComponents(
|
|
new ButtonBuilder()
|
|
.setLabel('◄')
|
|
.setStyle(ButtonStyle.Primary)
|
|
.setCustomId('nuts_leaderboard_left')
|
|
)
|
|
.addComponents(
|
|
new ButtonBuilder()
|
|
.setLabel('🧑')
|
|
.setStyle(ButtonStyle.Primary)
|
|
.setCustomId('nuts_leaderboard_self')
|
|
)
|
|
.addComponents(
|
|
new ButtonBuilder()
|
|
.setLabel('►')
|
|
.setStyle(ButtonStyle.Primary)
|
|
.setCustomId('nuts_leaderboard_right')
|
|
)
|
|
|
|
const db = mClient.db(process.env.M_DB)
|
|
const nutsColl = db.collection('items_nuts')
|
|
let skip = 0
|
|
|
|
const nutsData = await nutsColl.find({ nuts: { $gt: 0 } }).sort({ nuts: -1 }).skip(skip).limit(5).toArray()
|
|
|
|
let fields
|
|
let placements = skip + 1
|
|
|
|
nutsData.forEach((data) => {
|
|
fields = (fields ? fields : '') + (`${placements}. <@${data.userID}> : ${data.nuts} Nuts\r\n`)
|
|
placements++
|
|
})
|
|
|
|
const embed = new EmbedBuilder()
|
|
.setTitle('Nuts Leaderboard')
|
|
.setThumbnail('attachment://nuts_main.png')
|
|
.setDescription(fields.toString())
|
|
.setColor('#5865F2')
|
|
.setFooter({ text: 'Use ◄ ► to navigate' })
|
|
|
|
await interaction.editReply({
|
|
embeds: [embed],
|
|
components: [row],
|
|
files: [`${asset_path}nuts_main.png`]
|
|
})
|
|
}
|
|
|
|
async function nutsStats(interaction) {
|
|
const db = mClient.db(process.env.M_DB);
|
|
const nStatsColl = db.collection('stats_nuts');
|
|
var type = interaction?.options?.getString('type') || 'lookup'
|
|
var target = interaction?.options?.getUser('lookup') || {}
|
|
|
|
if (type == 'global') {
|
|
target.id = '__global'
|
|
} else if (!target?.id) {
|
|
target = interaction.user
|
|
}
|
|
|
|
console.log(target)
|
|
const statsDoc = await nStatsColl.findOne({ userID: target.id });
|
|
const stat = statsDoc?.stat || {};
|
|
|
|
const totalCount = Object.values(stat).reduce((a, b) => a + b, 0);
|
|
const totalNuts = Object.entries(stat).reduce(
|
|
(sum, [num, count]) => sum + Number(num) * count,
|
|
0
|
|
);
|
|
|
|
const rolledNumbers = Object.entries(stat).filter(([_, count]) => count > 0);
|
|
|
|
let nutMin = { number: 0, count: 0 };
|
|
let nutMax = { number: 0, count: 0 };
|
|
|
|
if (rolledNumbers.length > 0) {
|
|
nutMin = nutMax = { number: Number(rolledNumbers[0][0]), count: rolledNumbers[0][1] };
|
|
|
|
for (const [numStr, count] of rolledNumbers) {
|
|
const num = Number(numStr);
|
|
|
|
if (count > nutMax.count || (count === nutMax.count && num > nutMax.number)) {
|
|
nutMax = { number: num, count };
|
|
}
|
|
|
|
if (count < nutMin.count || (count === nutMin.count && num < nutMin.number)) {
|
|
nutMin = { number: num, count };
|
|
}
|
|
}
|
|
}
|
|
|
|
const nutAvg = totalCount ? totalNuts / totalCount : 0;
|
|
|
|
const fields = Array.from({ length: 11 }, (_, i) => ({
|
|
name: `[${i}]`,
|
|
value: `x${stat[i] ?? 0}`,
|
|
inline: true
|
|
}));
|
|
|
|
const embed = new EmbedBuilder()
|
|
.setTitle("Nut Statistic")
|
|
.setDescription(
|
|
`Total Nut Actions: **${totalCount}**\r\n` +
|
|
`Total Nuts nutted: **${totalNuts}**\r\n` +
|
|
`Nut Average: **${nutAvg.toFixed(3)}**\r\n` +
|
|
`Most Common Nut: **${nutMax.number} (x${nutMax.count})**\r\n` +
|
|
`Least Common Nut: **${nutMin.number} (x${nutMin.count})**`
|
|
)
|
|
.addFields(fields)
|
|
.setColor(0x51267)
|
|
.setTimestamp()
|
|
.setThumbnail('attachment://nuts_main.png')
|
|
|
|
await interaction.editReply({
|
|
embeds: [embed],
|
|
files: [`${asset_path}nuts_main.png`]
|
|
});
|
|
}
|
|
|
|
async function nutsCooldown(interaction) {
|
|
const db = mClient.db(process.env.M_DB)
|
|
const nutsColl = db.collection('items_cooldowns')
|
|
const cooldown = await nutsColl.findOne({ userID: interaction.user.id })
|
|
|
|
let content = `Du kannst wieder nussen! :)`
|
|
let thumbnail = 'attachment://nuts_main.png'
|
|
let file = `${asset_path}nuts_main.png`
|
|
let title = 'Go Nuts!'
|
|
|
|
let date = (Date.now() / 1000)
|
|
if (cooldown.cooldown > date) {
|
|
content = `<t:${cooldown.cooldown}:R> kannst du wieder nussen! ;)`
|
|
thumbnail = 'attachment://nuts_onCD.avif'
|
|
file = `${asset_path}nuts_onCD.avif`
|
|
title = 'To Nut or Not to Nut...'
|
|
}
|
|
|
|
const embed = new EmbedBuilder()
|
|
.setThumbnail(thumbnail)
|
|
.setTitle(title)
|
|
.setDescription(content)
|
|
|
|
await interaction.editReply({
|
|
embeds: [embed],
|
|
files: [file]
|
|
})
|
|
}
|
|
|
|
async function nutsNut(interaction, quickMode) {
|
|
const db = mClient.db(process.env.M_DB)
|
|
const nutsColl = db.collection('items_nuts')
|
|
const cdColl = db.collection('items_cooldowns')
|
|
const nutsStatsColl = db.collection('stats_nuts')
|
|
|
|
const cdData = await cdColl.findOne({ userID: interaction.user.id })
|
|
const embed = new EmbedBuilder()
|
|
|
|
const assets = {
|
|
high: 'attachment://nuts_high.jpg',
|
|
normal: 'attachment://nuts_normal.jpg',
|
|
low: 'attachment://nuts_low.jpg',
|
|
none: 'attachment://nuts_none.avif',
|
|
onCD: 'attachment://nuts_onCD.avif',
|
|
box: 'attachment://nuts_box.png',
|
|
explosion: 'attachment://nuts_explosion.gif'
|
|
}
|
|
|
|
// Helper for singular/plural
|
|
const formatNut = (amount) => `${amount} ${amount === 1 ? 'Nuss' : 'Nüsse'}`
|
|
|
|
// check cooldown
|
|
if (cdData?.cooldown > Date.now() / 1000) {
|
|
// on cooldown
|
|
embed.setTitle('To Nut or Not to Nut...')
|
|
embed.setDescription(`<t:${Math.floor(cdData.cooldown)}:R> kannst du wieder nussen! ;)`)
|
|
embed.setThumbnail(assets.onCD)
|
|
|
|
return interaction.editReply({
|
|
embeds: [embed],
|
|
files: [`${asset_path}nuts_onCD.avif`]
|
|
})
|
|
}
|
|
// set 1 hour cooldown
|
|
const cd = Math.floor((Date.now() + 3600000) / 1000)
|
|
await cdColl.findOneAndUpdate({
|
|
userID: interaction.user.id
|
|
}, {
|
|
$set: {
|
|
cooldown: cd,
|
|
application: 'nuts'
|
|
}
|
|
}, {
|
|
upsert: true
|
|
})
|
|
|
|
// generate nut amount
|
|
const amount = Math.floor(Math.random() * 10)
|
|
|
|
// update nuts and stats
|
|
await nutsColl.findOneAndUpdate(
|
|
{ userID: interaction.user.id },
|
|
{ $inc: { nuts: amount } },
|
|
{ upsert: true }
|
|
)
|
|
|
|
await nutsStatsColl.findOneAndUpdate(
|
|
{ userID: interaction.user.id },
|
|
{ $inc: { [`stat.${amount}`]: 1 } },
|
|
{ upsert: true }
|
|
)
|
|
|
|
await nutsStatsColl.findOneAndUpdate(
|
|
{ userID: "__global" },
|
|
{ $inc: { [`stat.${amount}`]: 1 } },
|
|
{ upsert: true }
|
|
)
|
|
|
|
|
|
if (quickMode) {
|
|
return interaction.editReply({ content: `Du hast ${formatNut(amount)} bekommen! :chestnut:` })
|
|
}
|
|
|
|
// pseudo animation
|
|
embed.setImage(assets.box)
|
|
await interaction.editReply({
|
|
embeds: [embed],
|
|
files: [`${asset_path}nuts_box.png`]
|
|
})
|
|
await delay(1337)
|
|
embed.setImage(assets.explosion)
|
|
await interaction.editReply({
|
|
embeds: [embed],
|
|
files: [`${asset_path}nuts_explosion.gif`]
|
|
})
|
|
await delay(1337)
|
|
|
|
let assetFile
|
|
if (amount === 0) assetFile = assets.none
|
|
else if (amount > 8) assetFile = assets.high
|
|
else if (amount > 4) assetFile = assets.normal
|
|
else assetFile = assets.low
|
|
|
|
embed.setTitle(`Du hast ${formatNut(amount)} bekommen!`)
|
|
embed.setThumbnail(assetFile)
|
|
embed.setImage(null)
|
|
|
|
return interaction.editReply({
|
|
embeds: [embed],
|
|
files: [`${asset_path}${assetFile.split('://')[1]}`]
|
|
})
|
|
|
|
|
|
}
|
|
module.exports = {
|
|
data: new SlashCommandBuilder()
|
|
.setName('nuts')
|
|
.setDescription('rund um die nuss')
|
|
.addSubcommand(s =>
|
|
s
|
|
.setName('give')
|
|
.setDescription('gib nuss!!')
|
|
.addUserOption(o => o.setName('target').setDescription('wer bekommt da nuts?').setRequired(true))
|
|
.addNumberOption(o => o.setName('amount').setDescription('wie viele?').setRequired(true)))
|
|
.addSubcommand(s =>
|
|
s
|
|
.setName('check')
|
|
.setDescription('check out deez nuts')
|
|
.addUserOption(o => o.setName('target').setDescription('check out those nuts!')))
|
|
.addSubcommand(s =>
|
|
s
|
|
.setName('leaderboard')
|
|
.setDescription('wer hat die dicksten Nüsse?'))
|
|
.addSubcommand(s =>
|
|
s
|
|
.setName('stats')
|
|
.setDescription('wie viele Nüsse wurden genusst, Genosse?')
|
|
.addStringOption(o =>
|
|
o.setName('type')
|
|
.setDescription('set type to global or user')
|
|
.addChoices(
|
|
{ name: 'global', value: 'global' },
|
|
{ name: 'user', value: 'user' }
|
|
),)
|
|
.addUserOption(o =>
|
|
o.setName('lookup')
|
|
.setDescription('look up specific user nut statistic')
|
|
)
|
|
)
|
|
|
|
.addSubcommand(s =>
|
|
s
|
|
.setName('cooldown')
|
|
.setDescription('wie lange bis ich nussen kann?'))
|
|
.addSubcommand(s =>
|
|
s
|
|
.setName('nut')
|
|
.setDescription('willst du nuss?'))
|
|
.addSubcommand(s =>
|
|
s.setName('quick')
|
|
.setDescription('A quick nut, mlord?')
|
|
|
|
),
|
|
async execute(interaction) {
|
|
switch (interaction.options._subcommand) {
|
|
case 'give':
|
|
nutsGive(interaction)
|
|
break;
|
|
case 'check':
|
|
await interaction.deferReply()
|
|
nutsCheck(interaction)
|
|
break;
|
|
case 'leaderboard':
|
|
await interaction.deferReply()
|
|
nutsLeaderboard(interaction)
|
|
break;
|
|
case 'stats':
|
|
await interaction.deferReply()
|
|
nutsStats(interaction)
|
|
break;
|
|
case 'cooldown':
|
|
await interaction.deferReply()
|
|
nutsCooldown(interaction)
|
|
break;
|
|
case 'nut':
|
|
await interaction.deferReply()
|
|
nutsNut(interaction, false)
|
|
break;
|
|
case 'quick':
|
|
await interaction.deferReply()
|
|
nutsNut(interaction, true)
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|