Compare commits
1 Commits
main
..
7da2c782af
| Author | SHA1 | Date | |
|---|---|---|---|
| 7da2c782af |
@@ -1,6 +0,0 @@
|
|||||||
D_ID=
|
|
||||||
D_Token=
|
|
||||||
D_Prefix=
|
|
||||||
D_GuildID=
|
|
||||||
M_URI=
|
|
||||||
M_DB=
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
.env
|
|
||||||
node_modules
|
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
MIT No Attribution
|
||||||
|
|
||||||
|
Copyright <YEAR> <COPYRIGHT HOLDER>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||||
|
software and associated documentation files (the "Software"), to deal in the Software
|
||||||
|
without restriction, including without limitation the rights to use, copy, modify,
|
||||||
|
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
@@ -1,60 +1,2 @@
|
|||||||
# Arthonor-Neo
|
# Arthonor-Neo
|
||||||
|
|
||||||
**Moderately Advanced Discord Bot for Friends**
|
|
||||||
|
|
||||||
Arthonor-Neo is a custom Discord bot designed for community interaction and fun. It offers an assortment of commands for economy, social engagement, and server utilities. Suitable for small to medium-sized friend servers.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
### Core Interactions
|
|
||||||
- Nut Economy - Earn and spend nuts in server activities
|
|
||||||
- Honor System - Show recognition and respect to users
|
|
||||||
- Quotes - Save and retrieve memorable quotes
|
|
||||||
|
|
||||||
### Community & Events
|
|
||||||
- Automatic Welcome Messages - Greet new members
|
|
||||||
- Birthday System - Track and celebrate birthdays
|
|
||||||
- Automatic Birthday Cards - Personalized greetings on birthdays
|
|
||||||
- Wednesday Frog - Midweek server event
|
|
||||||
- WGE Core - With Periodic Reminders and Random Function
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Differences from Version 2.x
|
|
||||||
|
|
||||||
### Legacy Commands (Chat Messages)
|
|
||||||
These have been mostly removed with certain exceptions:
|
|
||||||
|
|
||||||
- Quoteadd has been kept due to the technicaly incompabiltity of replying using slash commands.
|
|
||||||
- Nuts has been kept due to frequent usage
|
|
||||||
|
|
||||||
### Removed
|
|
||||||
- Timers
|
|
||||||
- Weather commands
|
|
||||||
- GIF commands
|
|
||||||
- Certain developer tools
|
|
||||||
- WOKCommands Core
|
|
||||||
- Friday Reminder
|
|
||||||
|
|
||||||
### Upgraded to Slash Commands
|
|
||||||
- Nuts
|
|
||||||
- Quotes
|
|
||||||
- Honor
|
|
||||||
- Birthdays
|
|
||||||
- Role Selection
|
|
||||||
- Channel Selection
|
|
||||||
- Meme Commands
|
|
||||||
- WGE (NEW)
|
|
||||||
|
|
||||||
### New and Improved
|
|
||||||
- Interactive Honor Menu
|
|
||||||
- Interactive Quote Menu
|
|
||||||
|
|
||||||
### Database Migration
|
|
||||||
Some structurual changes to the command schema, and removal of predefined schematics
|
|
||||||
|
|
||||||
- Tables renamed with prefixes, e.g. items_, config_, stats_, etc.
|
|
||||||
- Split tables into a relation-ish style
|
|
||||||
- made some data more machine-friendly
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
### ToDo?:
|
|
||||||
- quotes filter by channel
|
|
||||||
- event creation + reminder 1h before
|
|
||||||
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 242 KiB |
|
Before Width: | Height: | Size: 914 KiB |
|
Before Width: | Height: | Size: 102 KiB |
|
Before Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 411 KiB |
|
Before Width: | Height: | Size: 371 KiB |
|
Before Width: | Height: | Size: 254 KiB |
|
Before Width: | Height: | Size: 176 KiB |
|
Before Width: | Height: | Size: 167 KiB |
|
Before Width: | Height: | Size: 158 KiB |
|
Before Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 158 KiB |
|
Before Width: | Height: | Size: 536 KiB |
@@ -1,18 +0,0 @@
|
|||||||
const { EmbedBuilder } = require("discord.js")
|
|
||||||
function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
name: 'abort',
|
|
||||||
description: 'abort it',
|
|
||||||
async execute(interaction) {
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setTitle('Aborted')
|
|
||||||
.setDescription('Schließe Menü. . .')
|
|
||||||
|
|
||||||
await interaction.update({
|
|
||||||
embeds: [embed],
|
|
||||||
components: []
|
|
||||||
})
|
|
||||||
await delay(2000).then(interaction.deleteReply())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
const { EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, MessageFlags } = require("discord.js")
|
|
||||||
const { mClient } = require("../..")
|
|
||||||
require('dotenv').config()
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
name: 'honor_menu_dishonor',
|
|
||||||
description: 'honor menu dishonor button',
|
|
||||||
async execute(interaction) {
|
|
||||||
let description = interaction.message.embeds[0].data.description
|
|
||||||
const target = await interaction.guild.members.fetch(description.split(' ')[0].slice(2, -1))
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const honorsColl = db.collection('items_honors')
|
|
||||||
const reason = `[-] Quick Menu Dishonor`
|
|
||||||
const theirHonorLevel = await honorsColl.findOne({ userID: target.id })
|
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setTitle('- Honor Menu WIP -')
|
|
||||||
.setDescription(`Willst du wirklich <@${target.id}> einen **Dishonor** geben?\r\n[Grund: ${reason}]`)
|
|
||||||
.addFields({
|
|
||||||
name: 'Current Honor Level', value: `${theirHonorLevel?.honors ?? 0} (**-1**)`
|
|
||||||
})
|
|
||||||
.setThumbnail(target.displayAvatarURL())
|
|
||||||
const row = new ActionRowBuilder()
|
|
||||||
.addComponents(
|
|
||||||
new ButtonBuilder()
|
|
||||||
.setLabel('✔')
|
|
||||||
.setCustomId('honor_multi_confirm')
|
|
||||||
.setStyle(ButtonStyle.Success)
|
|
||||||
)
|
|
||||||
.addComponents(
|
|
||||||
new ButtonBuilder()
|
|
||||||
.setLabel('✖')
|
|
||||||
.setCustomId('abort')
|
|
||||||
.setStyle(ButtonStyle.Danger)
|
|
||||||
)
|
|
||||||
await interaction.reply({
|
|
||||||
embeds: [embed],
|
|
||||||
components: [row],
|
|
||||||
flags: MessageFlags.Ephemeral
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
const { EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, MessageFlags } = require("discord.js")
|
|
||||||
const { mClient } = require("../..")
|
|
||||||
require('dotenv').config()
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
name: 'honor_menu_history',
|
|
||||||
description: 'show selected user honor history',
|
|
||||||
async execute(interaction) {
|
|
||||||
let description = interaction.message.embeds[0].data.description
|
|
||||||
const target = await interaction.guild.members.fetch(description.split(' ')[0].slice(2, -1))
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const reasonsColl = db.collection('history_honors')
|
|
||||||
const history = await reasonsColl.findOne({ userID: target.user.id })
|
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setTitle('- Honor History -')
|
|
||||||
.setDescription(`${target} - ${target.user.globalName ?? target.user.username}`)
|
|
||||||
.setThumbnail(target.displayAvatarURL())
|
|
||||||
.setFooter({text: 'Um zurückzukehren, wähle einen Nutzer!'})
|
|
||||||
if(history){
|
|
||||||
let temp = ''
|
|
||||||
history.reasons.forEach(reason => {
|
|
||||||
temp += reason + '\r\n'
|
|
||||||
})
|
|
||||||
embed.setDescription(temp)
|
|
||||||
}
|
|
||||||
const select = await interaction.message.components[0]
|
|
||||||
const row = await interaction.message.components[1]
|
|
||||||
|
|
||||||
await interaction.reply({
|
|
||||||
embeds: [embed],
|
|
||||||
components: [select, row],
|
|
||||||
flags: MessageFlags.Ephemeral
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
const { EmbedBuilder, ButtonBuilder, ActionRowBuilder, ButtonStyle, MessageFlags } = require("discord.js")
|
|
||||||
const { mClient } = require("../..")
|
|
||||||
require('dotenv').config()
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
name: 'honor_menu_honor',
|
|
||||||
description: 'honor menu honor button',
|
|
||||||
async execute(interaction) {
|
|
||||||
let description = interaction.message.embeds[0].data.description
|
|
||||||
const target = await interaction.guild.members.fetch(description.split(' ')[0].slice(2, -1))
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const honorsColl = db.collection('items_honors')
|
|
||||||
const reason = `[+] Quick Menu Honor`
|
|
||||||
const theirHonorLevel = await honorsColl.findOne({ userID: target.id })
|
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setTitle('- Honor Up! -')
|
|
||||||
.setDescription(`Willst du wirklich <@${target.id}> einen **Honor** geben?\r\n[Grund: ${reason}]`)
|
|
||||||
.addFields({
|
|
||||||
name: 'Current Honor Level', value: `${theirHonorLevel?.honors ?? 0} (**+1**)`
|
|
||||||
})
|
|
||||||
.setThumbnail(target.displayAvatarURL())
|
|
||||||
//.setFooter('Honor Level updaten sich nicht automatisch!')
|
|
||||||
const row = new ActionRowBuilder()
|
|
||||||
.addComponents(
|
|
||||||
new ButtonBuilder()
|
|
||||||
.setLabel('✔')
|
|
||||||
.setCustomId('honor_multi_confirm')
|
|
||||||
.setStyle(ButtonStyle.Success)
|
|
||||||
)
|
|
||||||
.addComponents(
|
|
||||||
new ButtonBuilder()
|
|
||||||
.setLabel('✖')
|
|
||||||
.setCustomId('abort')
|
|
||||||
.setStyle(ButtonStyle.Danger)
|
|
||||||
)
|
|
||||||
await interaction.reply({
|
|
||||||
embeds: [embed],
|
|
||||||
components: [row],
|
|
||||||
flags: MessageFlags.Ephemeral
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
const { EmbedBuilder, MessageFlags } = require("discord.js")
|
|
||||||
const { mClient } = require("../..")
|
|
||||||
require('dotenv').config()
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
name: 'honor_multi_confirm',
|
|
||||||
description: 'confirm it',
|
|
||||||
async execute(interaction) {
|
|
||||||
let temp = await interaction.message.embeds[0].description.split(' ')
|
|
||||||
var honor
|
|
||||||
if (temp[5] === '**Honor**') {
|
|
||||||
honor = 1
|
|
||||||
} else if (temp[5] === '**Dishonor**'){
|
|
||||||
honor = -1
|
|
||||||
} else {
|
|
||||||
return await interaction.reply({content: "ERROR", flags: MessageFlags.Ephemeral})
|
|
||||||
}
|
|
||||||
const target = await interaction.message.guild.members.fetch(temp[3].slice(2, -1))
|
|
||||||
temp = interaction.message.embeds[0].description.split('\r\n')
|
|
||||||
const reason = `${temp[1].slice(7, -1)}`
|
|
||||||
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const honorsColl = db.collection('items_honors')
|
|
||||||
const reasonsColl = db.collection('history_honors')
|
|
||||||
const theirHonorLevel = await honorsColl.findOne({ userID: target.id })
|
|
||||||
|
|
||||||
await honorsColl.findOneAndUpdate({ userID: target.id }, { $inc: { honors: honor } }, { upsert: true })
|
|
||||||
await reasonsColl.findOneAndUpdate({ userID: target.id }, { $push: { reasons: reason } }, { upsert: true })
|
|
||||||
|
|
||||||
var description
|
|
||||||
var newTitle
|
|
||||||
var newDescription
|
|
||||||
var newThumbnail
|
|
||||||
|
|
||||||
if (honor == 1) {
|
|
||||||
description = `Willst du wirklich <@${target.id}> einen **Honor** geben?\r\n[Grund: ${reason}]`
|
|
||||||
newTitle = 'Honor Up!'
|
|
||||||
newDescription = `<@${target.id}> erhält einen Honor!\r\n[Grund: ${reason}]`
|
|
||||||
newThumbnail = "https://cdn.discordapp.com/emojis/748176295535443968.webp"
|
|
||||||
} else {
|
|
||||||
description = `Willst du wirklich <@${target.id}> einen **Dishonor** geben?\r\n[Grund: ${reason}]`
|
|
||||||
newTitle = 'Honor Down!'
|
|
||||||
newDescription = `<@${target.id}> erhält einen Dishonor!\r\n[Grund: ${reason}]`
|
|
||||||
newThumbnail = "https://cdn.discordapp.com/emojis/748176295132790786.webp"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setTitle('- Honor Menu -')
|
|
||||||
.setDescription(description)
|
|
||||||
.addFields({
|
|
||||||
name: 'Current Honor Level', value: `${theirHonorLevel?.honors ?? 0} ${honor == 1 ? '(**+1**)' : '(**-1**)'}`
|
|
||||||
})
|
|
||||||
.setThumbnail(target.displayAvatarURL())
|
|
||||||
await interaction.update({
|
|
||||||
embeds: [embed]
|
|
||||||
})
|
|
||||||
|
|
||||||
const newEmbed = new EmbedBuilder()
|
|
||||||
.setTitle(newTitle)
|
|
||||||
.setDescription(newDescription)
|
|
||||||
.setThumbnail(newThumbnail)
|
|
||||||
await interaction.followUp({
|
|
||||||
embeds: [newEmbed],
|
|
||||||
components: [],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
const { EmbedBuilder } = require("discord.js")
|
|
||||||
const { mClient } = require("../..")
|
|
||||||
require('dotenv').config()
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
name: 'honors_leaderboard_left',
|
|
||||||
description: 'navigate a page up',
|
|
||||||
async execute(interaction) {
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const honorsColl = db.collection('items_honors')
|
|
||||||
const min = 0
|
|
||||||
let skip = interaction.message.embeds[0].data.description.split('.')
|
|
||||||
skip = Number(skip[0]) - 6
|
|
||||||
skip = skip - ( skip % 5)
|
|
||||||
if ( skip < 4){
|
|
||||||
skip = 0
|
|
||||||
}
|
|
||||||
const honorsData = await honorsColl.find().sort({ honors: -1 }).skip(skip).limit(5).toArray()
|
|
||||||
let fields
|
|
||||||
honorsData.forEach((data) => {
|
|
||||||
skip++
|
|
||||||
fields = (fields ? fields : '') + (`${skip}. <@${data.userID}> : ${data.honors} Honors\r\n`)
|
|
||||||
})
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setTitle('Honors Leaderboard')
|
|
||||||
.setThumbnail(interaction.guild.iconURL({ dynamic: true}))
|
|
||||||
.setDescription(fields.toString())
|
|
||||||
.setColor('#5865F2') // Discord's blurple color
|
|
||||||
.setFooter({ text: 'Use ◄ ► to navigate' });
|
|
||||||
await interaction.update({
|
|
||||||
embeds: [embed],
|
|
||||||
components: [interaction.message.components[0]]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
const { EmbedBuilder } = require("discord.js")
|
|
||||||
const { mClient } = require("../..")
|
|
||||||
require('dotenv').config()
|
|
||||||
module.exports = {
|
|
||||||
name: 'honors_leaderboard_right',
|
|
||||||
description: 'navigate a page down',
|
|
||||||
async execute(interaction) {
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const honorsColl = db.collection('items_honors')
|
|
||||||
const max = await honorsColl.countDocuments()
|
|
||||||
let skip = interaction.message.embeds[0].data.description.split('.')
|
|
||||||
skip = Number(skip[0]) +4
|
|
||||||
if (skip >= (max - (max % 5))) {
|
|
||||||
skip = max - (max % 5)
|
|
||||||
}
|
|
||||||
const honorsData = await honorsColl.find().sort({ honors: -1 }).skip(skip).limit(5).toArray()
|
|
||||||
let fields
|
|
||||||
honorsData.forEach((data) => {
|
|
||||||
skip++
|
|
||||||
fields = (fields ? fields : '') + (`${skip}. <@${data.userID}> : ${data.honors} Honors\r\n`)
|
|
||||||
})
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setTitle('Honors Leaderboard')
|
|
||||||
.setThumbnail(interaction.guild.iconURL({ dynamic: true}))
|
|
||||||
.setDescription(fields.toString())
|
|
||||||
.setColor('#5865F2') // Discord's blurple color
|
|
||||||
.setFooter({ text: 'Use ◄ ► to navigate' });
|
|
||||||
await interaction.update({
|
|
||||||
embeds: [embed],
|
|
||||||
components: [interaction.message.components[0]]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
const { EmbedBuilder } = require("discord.js")
|
|
||||||
const { mClient } = require("../..")
|
|
||||||
require('dotenv').config()
|
|
||||||
module.exports = {
|
|
||||||
name: 'honors_leaderboard_self',
|
|
||||||
description: 'navigate to your own placement',
|
|
||||||
async execute(interaction) {
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const honorsColl = db.collection('items_honors')
|
|
||||||
|
|
||||||
const self = await honorsColl.find({ userID: interaction.user.id }).toArray()
|
|
||||||
const all = await honorsColl.find().sort({ honors: -1 }).toArray()
|
|
||||||
|
|
||||||
function findIndex(){
|
|
||||||
let index = 0
|
|
||||||
for (let i = 0; i < all.length; i++) {
|
|
||||||
index++
|
|
||||||
if (all[i].honors === self[0].honors) {
|
|
||||||
return index
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let selfIndex = findIndex()
|
|
||||||
let skip = selfIndex - ( selfIndex % 5)
|
|
||||||
|
|
||||||
const honorsData = await honorsColl.find().sort({ honors: -1 }).skip(skip).limit(5).toArray()
|
|
||||||
let fields
|
|
||||||
honorsData.forEach((data) => {
|
|
||||||
skip++
|
|
||||||
fields = (fields ? fields : '') + (`${skip}. <@${data.userID}> : ${data.honors} Honors\r\n`)
|
|
||||||
})
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setTitle('Honors Leaderboard')
|
|
||||||
.setThumbnail(interaction.guild.iconURL({ dynamic: true}))
|
|
||||||
.setDescription(fields.toString())
|
|
||||||
.setColor('#5865F2') // Discord's blurple color
|
|
||||||
.setFooter({ text: 'Use ◄ ► to navigate' });
|
|
||||||
|
|
||||||
await interaction.update({
|
|
||||||
embeds: [embed],
|
|
||||||
components: [interaction.message.components[0]]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
const { EmbedBuilder } = require("discord.js")
|
|
||||||
const { mClient } = require("../..")
|
|
||||||
require('dotenv').config()
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
name: 'nuts_give_confirm',
|
|
||||||
description: 'confirm it',
|
|
||||||
async execute(interaction) {
|
|
||||||
const from = interaction.user
|
|
||||||
let temp = await interaction.message.embeds[0].description.split(' ')
|
|
||||||
const amount = Number(temp[3].split('**')[1])
|
|
||||||
const to = await interaction.message.guild.members.fetch(temp[6].slice(2,-1))
|
|
||||||
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const nutsColl = db.collection('items_nuts')
|
|
||||||
await nutsColl.findOneAndUpdate({ userID: from.id }, { $inc: { nuts: -amount } }, { upsert: true })
|
|
||||||
await nutsColl.findOneAndUpdate({ userID: to.id }, { $inc: { nuts: +amount } }, { upsert: true })
|
|
||||||
|
|
||||||
const yourBalance = await nutsColl.findOne({ userID: from.id })
|
|
||||||
const theirBalance = await nutsColl.findOne({ userID: to.id })
|
|
||||||
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(to.displayAvatarURL())
|
|
||||||
await interaction.update({
|
|
||||||
embeds: [ embed ]
|
|
||||||
})
|
|
||||||
|
|
||||||
const newEmbed = new EmbedBuilder()
|
|
||||||
.setTitle('Gib Nuss!')
|
|
||||||
.setDescription(`Du hast **${amount}** Nuts an <@${to.id}> gesendet!`)
|
|
||||||
.setFooter({ text: 'Um den gleichen Wert zu senden, klick einfach nochmal auf ✔' })
|
|
||||||
.setThumbnail(to.user.displayAvatarURL())
|
|
||||||
await interaction.followUp({
|
|
||||||
embeds: [ newEmbed ],
|
|
||||||
components: [],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
const { EmbedBuilder } = require("discord.js")
|
|
||||||
const { mClient } = require("../..")
|
|
||||||
module.exports = {
|
|
||||||
name: 'nuts_give_fake',
|
|
||||||
description: 'fake it',
|
|
||||||
async execute(interaction) {
|
|
||||||
const from = interaction.user
|
|
||||||
let temp = await interaction.message.embeds[0].description.split(' ')
|
|
||||||
const amount = Number(temp[3].split('**')[1])
|
|
||||||
const to = await interaction.message.guild.members.fetch(temp[6].slice(2,-1))
|
|
||||||
|
|
||||||
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 })
|
|
||||||
|
|
||||||
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(to.displayAvatarURL())
|
|
||||||
await interaction.update({
|
|
||||||
embeds: [ embed ]
|
|
||||||
})
|
|
||||||
|
|
||||||
const newEmbed = new EmbedBuilder()
|
|
||||||
.setTitle('Du Fieser Gauner!')
|
|
||||||
.setDescription(`Yee Haw! Was tust du hier?!`)
|
|
||||||
.setThumbnail(interaction.client.user.displayAvatarURL())
|
|
||||||
await interaction.followUp({
|
|
||||||
embeds: [ newEmbed ],
|
|
||||||
components: [],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
const { EmbedBuilder } = require("discord.js")
|
|
||||||
const { mClient } = require("../..")
|
|
||||||
require('dotenv').config()
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
name: 'nuts_leaderboard_left',
|
|
||||||
description: 'navigate a page up',
|
|
||||||
async execute(interaction) {
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const nutsColl = db.collection('items_nuts')
|
|
||||||
const min = 0
|
|
||||||
let skip = interaction.message.embeds[0].data.description.split('.')
|
|
||||||
skip = Number(skip[0]) - 6
|
|
||||||
skip = skip - ( skip % 5)
|
|
||||||
if ( skip < 4){
|
|
||||||
skip = 0
|
|
||||||
}
|
|
||||||
const nutsData = await nutsColl.find({ nuts: { $gt: 0 } }).sort({ nuts: -1 }).skip(skip).limit(5).toArray()
|
|
||||||
let fields
|
|
||||||
nutsData.forEach((data) => {
|
|
||||||
skip++
|
|
||||||
fields = (fields ? fields : '') + (`${skip}. <@${data.userID}> : ${data.nuts} Nuts\r\n`)
|
|
||||||
})
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setTitle('Nuts Leaderboard')
|
|
||||||
.setThumbnail(interaction.guild.iconURL({ dynamic: true}))
|
|
||||||
.setDescription(fields.toString())
|
|
||||||
.setColor('#5865F2') // Discord's blurple color
|
|
||||||
.setFooter({ text: 'Use ◄ ► to navigate' });
|
|
||||||
await interaction.update({
|
|
||||||
embeds: [embed],
|
|
||||||
components: [interaction.message.components[0]]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
const { EmbedBuilder } = require("discord.js")
|
|
||||||
const { mClient } = require("../..")
|
|
||||||
require('dotenv').config()
|
|
||||||
module.exports = {
|
|
||||||
name: 'nuts_leaderboard_right',
|
|
||||||
description: 'navigate a page down',
|
|
||||||
async execute(interaction) {
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const nutsColl = db.collection('items_nuts')
|
|
||||||
const max = await nutsColl.countDocuments({ nuts: { $gt: 0 } })
|
|
||||||
let skip = interaction.message.embeds[0].data.description.split('.')
|
|
||||||
skip = Number(skip[0]) +4
|
|
||||||
if (skip >= (max - (max % 5))) {
|
|
||||||
skip = max - (max % 5)
|
|
||||||
}
|
|
||||||
const nutsData = await nutsColl.find({ nuts: { $gt: 0 } }).sort({ nuts: -1 }).skip(skip).limit(5).toArray()
|
|
||||||
let fields
|
|
||||||
nutsData.forEach((data) => {
|
|
||||||
skip++
|
|
||||||
fields = (fields ? fields : '') + (`${skip}. <@${data.userID}> : ${data.nuts} Nuts\r\n`)
|
|
||||||
})
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setTitle('Nuts Leaderboard')
|
|
||||||
.setThumbnail(interaction.guild.iconURL({ dynamic: true}))
|
|
||||||
.setDescription(fields.toString())
|
|
||||||
.setColor('#5865F2') // Discord's blurple color
|
|
||||||
.setFooter({ text: 'Use ◄ ► to navigate' });
|
|
||||||
await interaction.update({
|
|
||||||
embeds: [embed],
|
|
||||||
components: [interaction.message.components[0]]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
const { EmbedBuilder } = require("discord.js")
|
|
||||||
const { mClient } = require("../..")
|
|
||||||
require('dotenv').config()
|
|
||||||
module.exports = {
|
|
||||||
name: 'nuts_leaderboard_self',
|
|
||||||
description: 'navigate to your own placement',
|
|
||||||
async execute(interaction) {
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const nutsColl = db.collection('items_nuts')
|
|
||||||
|
|
||||||
const self = await nutsColl.find({ userID: interaction.user.id }).toArray()
|
|
||||||
const all = await nutsColl.find({ nuts: { $gt: 0 } }).sort({ nuts: -1 }).toArray()
|
|
||||||
|
|
||||||
function findIndex(){
|
|
||||||
let index = 0
|
|
||||||
for (let i = 0; i < all.length; i++) {
|
|
||||||
index++
|
|
||||||
if (all[i].nuts === self[0].nuts) {
|
|
||||||
return index
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let selfIndex = findIndex()
|
|
||||||
let skip = selfIndex - ( selfIndex % 5)
|
|
||||||
|
|
||||||
const nutsData = await nutsColl.find({ nuts: { $gt: 0 } }).sort({ nuts: -1 }).skip(skip).limit(5).toArray()
|
|
||||||
let fields
|
|
||||||
nutsData.forEach((data) => {
|
|
||||||
skip++
|
|
||||||
fields = (fields ? fields : '') + (`${skip}. <@${data.userID}> : ${data.nuts} Nuts\r\n`)
|
|
||||||
})
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setTitle('Nuts Leaderboard')
|
|
||||||
.setThumbnail(interaction.guild.iconURL({ dynamic: true}))
|
|
||||||
.setDescription(fields.toString())
|
|
||||||
.setColor('#5865F2') // Discord's blurple color
|
|
||||||
.setFooter({ text: 'Use ◄ ► to navigate' });
|
|
||||||
await interaction.update({
|
|
||||||
embeds: [embed],
|
|
||||||
components: [interaction.message.components[0]]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
const { quotesLeaderboard } = require("../../commands/slash/applications/quotes");
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
name: 'quotes_leaderboard_left',
|
|
||||||
description: 'Navigate left through the quotes leaderboard',
|
|
||||||
async execute(interaction) {
|
|
||||||
await interaction.deferReply();
|
|
||||||
|
|
||||||
// Parse current page from footer
|
|
||||||
let page = 1;
|
|
||||||
const footerText = interaction.message.embeds[0]?.footer?.text || '';
|
|
||||||
const match = footerText.match(/Page (\d+) of (\d+)/);
|
|
||||||
if (match) page = Number(match[1]);
|
|
||||||
|
|
||||||
page--; // move to previous page
|
|
||||||
|
|
||||||
await quotesLeaderboard(interaction, page);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
const { quotesLeaderboard } = require("../../commands/slash/applications/quotes");
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
name: 'quotes_leaderboard_right',
|
|
||||||
description: 'Navigate right through the quotes leaderboard',
|
|
||||||
async execute(interaction) {
|
|
||||||
await interaction.deferReply();
|
|
||||||
|
|
||||||
// Parse current page from footer
|
|
||||||
let page = 1;
|
|
||||||
const footerText = interaction.message.embeds[0]?.footer?.text || '';
|
|
||||||
const match = footerText.match(/Page (\d+) of (\d+)/);
|
|
||||||
if (match) page = Number(match[1]);
|
|
||||||
|
|
||||||
page++; // move to next page
|
|
||||||
|
|
||||||
await quotesLeaderboard(interaction, page);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
const { EmbedBuilder, UserSelectMenuBuilder, ActionRowBuilder, MessageFlags } = require("discord.js")
|
|
||||||
const { mClient } = require("../..")
|
|
||||||
require('dotenv').config()
|
|
||||||
module.exports = {
|
|
||||||
name: 'quotes_list_left',
|
|
||||||
description: 'navigate left',
|
|
||||||
async execute(interaction) {
|
|
||||||
let oldEmbed = interaction.message.embeds[0].data
|
|
||||||
if (!oldEmbed.footer) { return interaction.reply({ content: 'Please use a Filter', flags: MessageFlags.Ephemeral }) }
|
|
||||||
if (oldEmbed.fields && oldEmbed.fields[0].value == 0) { return interaction.reply({ content: 'This User has no Quotes', flags: MessageFlags.Ephemeral }) }
|
|
||||||
|
|
||||||
let userID = interaction.message.embeds[0].data.footer.text.split(' ')[5].slice(2, -1)
|
|
||||||
const target = await interaction.guild.members.fetch(userID)
|
|
||||||
if (!target) { return interaction.reply({ content: 'Please use a Filter', flags: MessageFlags.Ephemeral }) }
|
|
||||||
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const quotesColl = db.collection('items_quotes')
|
|
||||||
const quotes = await quotesColl.find({ userID: target.id }).toArray()
|
|
||||||
|
|
||||||
var index = Number((await interaction.message.embeds[0].data.title).split(' ')[2].slice(1))
|
|
||||||
if (!index) { index = 0 }
|
|
||||||
index = index - 2
|
|
||||||
if (index < 1) { index = 0 }
|
|
||||||
|
|
||||||
|
|
||||||
const found = quotes[index]
|
|
||||||
|
|
||||||
const guild = await interaction.client.guilds.fetch(found.guildID)
|
|
||||||
const channel = await guild.channels.fetch(found.channelID)
|
|
||||||
const message = await channel.messages.fetch(found.messageID)
|
|
||||||
|
|
||||||
var msgData = {
|
|
||||||
content: message.content,
|
|
||||||
author: await message.author,
|
|
||||||
reference: await message.reference,
|
|
||||||
embed: await message.embeds ? 'embed' : null
|
|
||||||
} // debug
|
|
||||||
if (msgData.reference) {
|
|
||||||
let refMessage = await channel.messages.fetch(msgData.reference.messageId)
|
|
||||||
var refData = {
|
|
||||||
content: refMessage.content,
|
|
||||||
author: await refMessage.author,
|
|
||||||
embed: await refMessage.embeds.length > 0 ? 'embed' : null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var description = ''
|
|
||||||
if (refData) {
|
|
||||||
description += `> ${refData.author}`
|
|
||||||
if (refData.embed) {
|
|
||||||
description += '*an embed / a command* '
|
|
||||||
} else {
|
|
||||||
description += refData.content
|
|
||||||
}
|
|
||||||
description += `\r\n↳`
|
|
||||||
}
|
|
||||||
let messageLink = `https://discord.com/channels/${found.guildID}/${found.channelID}/${found.messageID}`
|
|
||||||
description += `${msgData.author} ${msgData.content}\r\n\r\n${messageLink}`
|
|
||||||
let timestamp = new Date(message.createdTimestamp)
|
|
||||||
let footer = timestamp.toDateString().toString()
|
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setThumbnail(msgData.author.displayAvatarURL())
|
|
||||||
.setURL(messageLink)
|
|
||||||
.setTitle(`- Quote #${index + 1} -`)
|
|
||||||
.setDescription(description)
|
|
||||||
.setFooter({ text: (`${footer} #${found.messageID} <@${found.userID}>`) })
|
|
||||||
const select = new ActionRowBuilder()
|
|
||||||
.addComponents(
|
|
||||||
new UserSelectMenuBuilder()
|
|
||||||
.setCustomId('quotes_list_mentionable')
|
|
||||||
.setPlaceholder('Filter By User')
|
|
||||||
)
|
|
||||||
|
|
||||||
const row = interaction.message.components[1]
|
|
||||||
await interaction.update({
|
|
||||||
embeds: [embed],
|
|
||||||
components: [select, row]
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
const { EmbedBuilder, UserSelectMenuBuilder, ActionRowBuilder, MessageFlags } = require("discord.js")
|
|
||||||
const { mClient } = require("../..")
|
|
||||||
require('dotenv').config()
|
|
||||||
module.exports = {
|
|
||||||
name: 'quotes_list_right',
|
|
||||||
description: 'navigate right',
|
|
||||||
async execute(interaction) {
|
|
||||||
let oldEmbed = interaction.message.embeds[0].data
|
|
||||||
if (!oldEmbed.footer) { return interaction.reply({ content: 'Please use a Filter', flags: MessageFlags.Ephemeral }) }
|
|
||||||
if (oldEmbed.fields && oldEmbed.fields[0].value == 0) { return interaction.reply({ content: 'This User has no Quotes', flags: MessageFlags.Ephemeral }) }
|
|
||||||
|
|
||||||
let userID = interaction.message.embeds[0].data.footer.text.split(' ')[5].slice(2, -1)
|
|
||||||
const target = await interaction.guild.members.fetch(userID)
|
|
||||||
if (!target) { return interaction.reply({ content: 'Please use a Filter', flags: MessageFlags.Ephemeral }) }
|
|
||||||
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const quotesColl = db.collection('items_quotes')
|
|
||||||
const quotes = await quotesColl.find({ userID: target.id }).toArray()
|
|
||||||
|
|
||||||
var index = Number((await interaction.message.embeds[0].data.title).split(' ')[2].slice(1))
|
|
||||||
if (!index) { index = 0 }
|
|
||||||
//if (index >= quotes.length){ return interaction.reply({content: 'Max Quotes Reached', flags: MessageFlags.Ephemeral})}
|
|
||||||
if (index >= quotes.length) { index-- }
|
|
||||||
|
|
||||||
// will automatically reflect the next index due to how arrays think
|
|
||||||
|
|
||||||
const found = quotes[index]
|
|
||||||
const guild = await interaction.client.guilds.fetch(found.guildID)
|
|
||||||
const channel = await guild.channels.fetch(found.channelID)
|
|
||||||
const message = await channel.messages.fetch(found.messageID)
|
|
||||||
|
|
||||||
var msgData = {
|
|
||||||
content: message.content,
|
|
||||||
author: await message.author,
|
|
||||||
reference: await message.reference,
|
|
||||||
embed: await message.embeds ? 'embed' : null
|
|
||||||
} // debug
|
|
||||||
if (msgData.reference) {
|
|
||||||
let refMessage = await channel.messages.fetch(msgData.reference.messageId)
|
|
||||||
var refData = {
|
|
||||||
content: refMessage.content,
|
|
||||||
author: await refMessage.author,
|
|
||||||
embed: await refMessage.embeds.length > 0 ? 'embed' : null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var description = ''
|
|
||||||
if (refData) {
|
|
||||||
description += `> ${refData.author}`
|
|
||||||
if (refData.embed) {
|
|
||||||
description += '*an embed / a command* '
|
|
||||||
} else {
|
|
||||||
description += refData.content
|
|
||||||
}
|
|
||||||
description += `\r\n↳`
|
|
||||||
}
|
|
||||||
let messageLink = `https://discord.com/channels/${found.guildID}/${found.channelID}/${found.messageID}`
|
|
||||||
description += `${msgData.author} ${msgData.content}\r\n\r\n${messageLink}`
|
|
||||||
let timestamp = new Date(message.createdTimestamp)
|
|
||||||
let footer = timestamp.toDateString().toString()
|
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setThumbnail(msgData.author.displayAvatarURL())
|
|
||||||
.setURL(messageLink)
|
|
||||||
.setTitle(`- Quote #${index + 1} -`)
|
|
||||||
.setDescription(description)
|
|
||||||
.setFooter({ text: (`${footer} #${found.messageID} <@${found.userID}>`) })
|
|
||||||
const select = new ActionRowBuilder()
|
|
||||||
.addComponents(
|
|
||||||
new UserSelectMenuBuilder()
|
|
||||||
.setCustomId('quotes_list_mentionable')
|
|
||||||
.setPlaceholder('Filter By User')
|
|
||||||
)
|
|
||||||
|
|
||||||
const row = interaction.message.components[1]
|
|
||||||
await interaction.update({
|
|
||||||
embeds: [embed],
|
|
||||||
components: [select, row]
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
const ping = require("../../../src/ping")
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
name: 'ping',
|
|
||||||
description: 'dev tool',
|
|
||||||
aliases: ['p'],
|
|
||||||
async execute(message, args) {
|
|
||||||
return ping(message, args, 'legacy')
|
|
||||||
}}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
const { EmbedBuilder } = require('discord.js')
|
|
||||||
const { mClient } = require('../../../index')
|
|
||||||
function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }
|
|
||||||
require('dotenv').config()
|
|
||||||
module.exports = {
|
|
||||||
name: 'checknuts',
|
|
||||||
description: 'get nuts',
|
|
||||||
aliases: ['chn'],
|
|
||||||
async execute(message, args) {
|
|
||||||
var target = message.author
|
|
||||||
var addressing = `Du hast`
|
|
||||||
if (args[0]) {
|
|
||||||
if (!args[0].startsWith('<@' || !args[0].endsWith('>'))) { return message.reply('Invalid User Specification') }
|
|
||||||
try {
|
|
||||||
target = await message.guild.members.fetch(args[0].slice(2, -1))
|
|
||||||
} catch (error) {
|
|
||||||
return message.reply({
|
|
||||||
content: `User: ${args[0]} nicht gefunden!`
|
|
||||||
}).then(async (msg) => {
|
|
||||||
await delay(4000)
|
|
||||||
message.delete()
|
|
||||||
msg.delete()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target.user.id !== message.author.id) {
|
|
||||||
if (!target.user.globalName) {
|
|
||||||
addressing = `${target.user.username} hat`
|
|
||||||
} else {
|
|
||||||
addressing = `${target.user.globalName} hat`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const nutsColl = db.collection('items_nuts')
|
|
||||||
var 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!`
|
|
||||||
}
|
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setTitle('Checknuts!')
|
|
||||||
.setThumbnail(target.displayAvatarURL())
|
|
||||||
.setDescription(content)
|
|
||||||
|
|
||||||
return message.reply({
|
|
||||||
embeds: [embed]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
const { EmbedBuilder } = require('discord.js')
|
|
||||||
const { mClient } = require('../../../index')
|
|
||||||
require('dotenv').config()
|
|
||||||
module.exports = {
|
|
||||||
name: 'nutsCooldown',
|
|
||||||
description: 'shows nut cooldown',
|
|
||||||
aliases: ['ncd'],
|
|
||||||
async execute(message, args) {
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const nutsColl = db.collection('items_cooldowns')
|
|
||||||
const cooldown = await nutsColl.findOne({ userID: message.author.id })
|
|
||||||
|
|
||||||
let content = `Du kannst wieder nussen! :)`
|
|
||||||
let thumbnail = 'https://cdn-icons-png.flaticon.com/512/7451/7451659.png'
|
|
||||||
let title = 'Go Nuts!'
|
|
||||||
if (cooldown) {
|
|
||||||
content = `<t:${cooldown.cooldown}:R> kannst du wieder nussen! ;)`
|
|
||||||
thumbnail = 'https://cdn.discordapp.com/attachments/1152723542836772914/1152987472788193361/No-nuts-PhotoRoom.png-PhotoRoom.png'
|
|
||||||
title = 'To Nut or Not to Nut...'
|
|
||||||
}
|
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setThumbnail(thumbnail)
|
|
||||||
.setTitle(title)
|
|
||||||
.setDescription(content)
|
|
||||||
|
|
||||||
await message.reply({
|
|
||||||
embeds: [embed]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
const { mClient } = require('../../../index')
|
|
||||||
require('dotenv').config()
|
|
||||||
module.exports = {
|
|
||||||
name: 'nuts',
|
|
||||||
description: 'get nuts',
|
|
||||||
aliases: ['n', 'nget', 'nutsget'],
|
|
||||||
async execute(message, args) {
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const nutsColl = db.collection('items_nuts')
|
|
||||||
const nutsStatsColl = db.collection('stats_nuts')
|
|
||||||
const cdColl = db.collection('items_cooldowns')
|
|
||||||
const cdData = await cdColl.findOne({ userID: message.author.id })
|
|
||||||
|
|
||||||
if (cdData?.cooldown > (Date.now() / 1000)) {
|
|
||||||
return await message.reply({
|
|
||||||
content: `Du kannst erst <t:${Math.floor(cdData?.cooldown)}:R> wieder nussen :(`,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
let cd = Math.floor((Date.now() + 3600000) / 1000)
|
|
||||||
await cdColl.findOneAndUpdate({
|
|
||||||
userID: message.author.id
|
|
||||||
}, {
|
|
||||||
$set: {
|
|
||||||
cooldown: cd,
|
|
||||||
application: 'nuts'
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
upsert: true
|
|
||||||
})
|
|
||||||
|
|
||||||
const amount = Math.floor(Math.random() * 10)
|
|
||||||
|
|
||||||
await nutsColl.findOneAndUpdate({
|
|
||||||
userID: message.author.id
|
|
||||||
}, {
|
|
||||||
$inc: { nuts: amount }
|
|
||||||
}, {
|
|
||||||
upsert: true
|
|
||||||
})
|
|
||||||
|
|
||||||
await nutsStatsColl.findOneAndUpdate(
|
|
||||||
{ userID: message.author.id },
|
|
||||||
{ $inc: { [`stat.${amount}`]: 1 } },
|
|
||||||
{ upsert: true }
|
|
||||||
)
|
|
||||||
|
|
||||||
await nutsStatsColl.findOneAndUpdate(
|
|
||||||
{ userID: "__global" },
|
|
||||||
{ $inc: { [`stat.${amount}`]: 1 } },
|
|
||||||
{ upsert: true }
|
|
||||||
)
|
|
||||||
// Helper for singular/plural
|
|
||||||
const formatNut = (amount) => `${amount === 1 ? 'eine' : amount} ${amount === 1 ? 'Nuss' : 'Nüsse'}`
|
|
||||||
|
|
||||||
let nutText = `Du hast ${formatNut(amount)} bekommen! :chestnut:`
|
|
||||||
if (amount <= 0) {
|
|
||||||
nutText = `Du hast keine Nuss bekommen! :yoink_help:`
|
|
||||||
}
|
|
||||||
return await message.reply({
|
|
||||||
content: nutText
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
const { EmbedBuilder } = require('discord.js')
|
|
||||||
const { mClient } = require('../../../index')
|
|
||||||
function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }
|
|
||||||
require('dotenv').config()
|
|
||||||
module.exports = {
|
|
||||||
name: 'givenuts',
|
|
||||||
description: 'give nuts',
|
|
||||||
aliases: ['gn'],
|
|
||||||
async execute(message, args) {
|
|
||||||
const from = message.author
|
|
||||||
if (args[0] == `<@${message.author.id}>` || !args[0]) {
|
|
||||||
return message.reply({
|
|
||||||
content: "Du musst einen anderen User erwähnen"
|
|
||||||
}).then(async (msg) => {
|
|
||||||
await delay(4000)
|
|
||||||
message.delete()
|
|
||||||
msg.delete()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if (!args[0].startsWith('<@' || !args[0].endsWith('>'))) { return message.reply('Invalid User Specification') }
|
|
||||||
try {
|
|
||||||
target = await message.guild.members.fetch(args[0].slice(2, -1))
|
|
||||||
} catch (error) {
|
|
||||||
return message.reply({
|
|
||||||
content: `User: ${args[0]} nicht gefunden!`
|
|
||||||
}).then(async (msg) => {
|
|
||||||
await delay(4000)
|
|
||||||
message.delete()
|
|
||||||
msg.delete()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
const to = target
|
|
||||||
|
|
||||||
try {
|
|
||||||
var amount = Number(args[1])
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error)
|
|
||||||
return message.reply({
|
|
||||||
content: 'Du musst eine Menge angeben!'
|
|
||||||
}).then(async (msg) => {
|
|
||||||
await delay(4000)
|
|
||||||
message.delete()
|
|
||||||
msg.delete()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if (!amount) {
|
|
||||||
return message.reply({content : 'Danke für nichts, du Hu-'})
|
|
||||||
}
|
|
||||||
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const nutsColl = db.collection('items_nuts')
|
|
||||||
const yourBalance = await nutsColl.findOne({ userID: from.id })
|
|
||||||
if (amount <= 0) {
|
|
||||||
return await message.reply({
|
|
||||||
content: `Hier wird nicht geklaut >:(\r\nDas gibt **${yourBalance.nuts}** Abzug!`
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if (yourBalance.nuts < amount) {
|
|
||||||
return await message.reply({
|
|
||||||
content: 'Du kannst nicht mehr geben als du hast!',
|
|
||||||
ephemeral: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
var content = `Du sendest **${amount}** Nüsse an <@${target.id}>`
|
|
||||||
|
|
||||||
if (amount == 1) {
|
|
||||||
content = `Du sendest **eine** Nuss an <@${target.id}>`
|
|
||||||
}
|
|
||||||
await nutsColl.findOneAndUpdate({ userID: from.id }, { $inc: { nuts: -amount } }, { upsert: true })
|
|
||||||
await nutsColl.findOneAndUpdate({ userID: to.id }, { $inc: { nuts: +amount } }, { upsert: true })
|
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setTitle('Gib Nuss!')
|
|
||||||
.setDescription(content)
|
|
||||||
.setThumbnail(target.displayAvatarURL())
|
|
||||||
return message.reply({ embeds: [embed] })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
const { EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js')
|
|
||||||
const { mClient } = require('../../../index')
|
|
||||||
function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }
|
|
||||||
require('dotenv').config()
|
|
||||||
module.exports = {
|
|
||||||
name: 'nutsleaderboard',
|
|
||||||
description: 'show nuts leaderboard',
|
|
||||||
aliases: ['nl', 'tn', 'topnuts'],
|
|
||||||
async execute(message, args) {
|
|
||||||
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`)
|
|
||||||
})
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setTitle('Nuts Leaderboard')
|
|
||||||
.setThumbnail(message.guild.iconURL({ dynamic: true}))
|
|
||||||
.setDescription(fields.toString())
|
|
||||||
.setColor('#5865F2') // Discord's blurple color
|
|
||||||
.setFooter({ text: 'Use ◄ ► to navigate' });
|
|
||||||
await message.reply({
|
|
||||||
embeds: [embed],
|
|
||||||
components: [row]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
const { EmbedBuilder, MessageFlags } = require("discord.js")
|
|
||||||
const { client, mClient } = require("../../../index")
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
name: 'quotesadd',
|
|
||||||
description: 'adds a quote to the database by replying to the message',
|
|
||||||
category: 'Quotes',
|
|
||||||
aliases: ['qadd', 'qa'],
|
|
||||||
async execute(message, args) {
|
|
||||||
const refMessage = message.reference // message to be quoted has been replied to
|
|
||||||
const refMessageId = refMessage.messageId
|
|
||||||
const refChannelId = refMessage.channelId
|
|
||||||
const refGuildId = refMessage.guildId
|
|
||||||
var msgData = {}
|
|
||||||
var refData = {}
|
|
||||||
const quoteGuild = await client.guilds.fetch(refGuildId)
|
|
||||||
const quoteChannel = await quoteGuild.channels.fetch(refChannelId)
|
|
||||||
const quoteMessage = await quoteChannel.messages.fetch(refMessageId)
|
|
||||||
|
|
||||||
msgData = {
|
|
||||||
content: quoteMessage.content,
|
|
||||||
author: await quoteMessage.author,
|
|
||||||
reference: await quoteMessage.reference,
|
|
||||||
embed: await quoteMessage.embeds ? 'embed' : null
|
|
||||||
} // debug
|
|
||||||
if (msgData.reference) {
|
|
||||||
const quoteRefGuild = await client.guilds.fetch(msgData.reference.guildId)
|
|
||||||
const quoteRefChannel = await quoteRefGuild.channels.fetch(msgData.reference.channelId)
|
|
||||||
const quoteRefMessage = await quoteRefChannel.messages.fetch(msgData.reference.messageId)
|
|
||||||
|
|
||||||
|
|
||||||
refData = {
|
|
||||||
content: quoteRefMessage.content,
|
|
||||||
author: await quoteRefMessage.author,
|
|
||||||
embed: await quoteRefMessage.embeds.length > 0 ? 'embed' : null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const quotesColl = db.collection('items_quotes')
|
|
||||||
const found = await quotesColl.findOne({ messageID: quoteMessage.id })
|
|
||||||
if (found) { return await message.reply({ content: 'Quote Already in Database', flags: MessageFlags.Ephemeral }) }
|
|
||||||
await quotesColl.findOneAndUpdate({ messageID: quoteMessage.id }, {
|
|
||||||
$set: {
|
|
||||||
messageID: quoteMessage.id,
|
|
||||||
channelID: quoteChannel.id,
|
|
||||||
guildID: quoteGuild.id,
|
|
||||||
userID: msgData.author.id,
|
|
||||||
count: 0
|
|
||||||
}
|
|
||||||
}, { upsert: true })
|
|
||||||
|
|
||||||
var description = ''
|
|
||||||
if (refData) {
|
|
||||||
description += `> ${refData.author}`
|
|
||||||
if (refData.embed) {
|
|
||||||
description += '*an embed / a command* '
|
|
||||||
} else {
|
|
||||||
description += refData.content
|
|
||||||
}
|
|
||||||
description += `\r\n↳`
|
|
||||||
}
|
|
||||||
const messageLink = `https://discord.com/channels/${quoteGuild.id}/${quoteChannel.id}/${quoteMessage.id}/`
|
|
||||||
description += `${msgData.author} ${msgData.content}\r\n\r\n${messageLink}`
|
|
||||||
let timestamp = new Date(message.createdTimestamp)
|
|
||||||
let footer = timestamp.toDateString().toString()
|
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setThumbnail(msgData.author.displayAvatarURL())
|
|
||||||
.setURL(messageLink)
|
|
||||||
.setTitle(`- Quote Added! -`)
|
|
||||||
.setDescription(description)
|
|
||||||
.setFooter({ text: (footer + ' #' + quoteMessage.id) })
|
|
||||||
await message.reply({ embeds: [embed] })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,201 +0,0 @@
|
|||||||
const { SlashCommandBuilder, EmbedBuilder, MessageFlags, PermissionFlagsBits } = require('discord.js')
|
|
||||||
const { mClient } = require('../../../index')
|
|
||||||
const { configDotenv } = require('dotenv')
|
|
||||||
configDotenv()
|
|
||||||
|
|
||||||
function isValidDate(day, month) {
|
|
||||||
// Define the number of days in each month
|
|
||||||
const daysInMonth = {
|
|
||||||
1: 31, // January
|
|
||||||
2: 28, // February (fuck leap years, me an' the homies hate that)
|
|
||||||
3: 31, // March
|
|
||||||
4: 30, // April
|
|
||||||
5: 31, // May
|
|
||||||
6: 30, // June
|
|
||||||
7: 31, // July
|
|
||||||
8: 31, // August
|
|
||||||
9: 30, // September
|
|
||||||
10: 31, // October
|
|
||||||
11: 30, // November
|
|
||||||
12: 31 // December
|
|
||||||
};
|
|
||||||
|
|
||||||
// Check if month is valid
|
|
||||||
if (month < 1 || month > 12) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if day is valid for the given month
|
|
||||||
if (day < 1 || day > daysInMonth[month]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
function getNextBirthdayTimestamp(day, month) {
|
|
||||||
const now = new Date();
|
|
||||||
now.setHours(0, 0, 0, 0);
|
|
||||||
|
|
||||||
const currentYear = now.getFullYear();
|
|
||||||
|
|
||||||
let nextBirthday = new Date(currentYear, month - 1, day);
|
|
||||||
|
|
||||||
// If birthday already passed this year → next year
|
|
||||||
if (nextBirthday < now) {
|
|
||||||
nextBirthday.setFullYear(currentYear + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Math.floor(nextBirthday.getTime() / 1000); // Unix timestamp
|
|
||||||
}
|
|
||||||
async function birthdaySet(interaction) {
|
|
||||||
let target = await interaction.options.getUser('user')
|
|
||||||
let day = await interaction.options.getNumber('day')
|
|
||||||
let month = await interaction.options.getNumber('month')
|
|
||||||
|
|
||||||
|
|
||||||
if (!isValidDate(day, month)) {
|
|
||||||
return interaction.reply({ content: "Invalid Date", flags: MessageFlags.Ephemeral })
|
|
||||||
}
|
|
||||||
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const bdayColl = db.collection('items_birthdays')
|
|
||||||
|
|
||||||
const found = await bdayColl.findOne({ userID: target.id })
|
|
||||||
if (found) {
|
|
||||||
return interaction.reply({ content: "Already in Database", flags: MessageFlags.Ephemeral })
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = {
|
|
||||||
guildID: interaction.guild.id,
|
|
||||||
userID: target.id,
|
|
||||||
day: day,
|
|
||||||
month: month
|
|
||||||
}
|
|
||||||
|
|
||||||
const res = await bdayColl.insertOne(data)
|
|
||||||
if (res.acknowledged) {
|
|
||||||
return interaction.reply({ content: "Birthday added successfully!" })
|
|
||||||
} else {
|
|
||||||
return interaction.reply({ content: "There was an issue!" })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async function birthdayDelete(interaction) {
|
|
||||||
var target = await interaction.options.getUser('user')
|
|
||||||
const guild = await interaction.client.guilds.cache.get(interaction.guild.id)
|
|
||||||
if (!target) {
|
|
||||||
target = await guild.members.cache.get(await interaction.options.getString('id'))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!target) {
|
|
||||||
return interaction.reply({ content: "Invalid or No User specified!" })
|
|
||||||
}
|
|
||||||
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const bdayColl = db.collection('items_birthdays')
|
|
||||||
|
|
||||||
const found = await bdayColl.findOne({ userID: target.id })
|
|
||||||
if (!found) {
|
|
||||||
return interaction.reply({ content: "Not yet in Database", flags: MessageFlags.Ephemeral })
|
|
||||||
}
|
|
||||||
|
|
||||||
const res = await bdayColl.deleteOne({ userID: target.id })
|
|
||||||
if (res.acknowledged) {
|
|
||||||
return interaction.reply({ content: "Birthday removed successfully!" })
|
|
||||||
} else {
|
|
||||||
return interaction.reply({ content: "There was an issue!" })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async function birthdayGet(interaction) {
|
|
||||||
const target = await interaction.options.getUser('user');
|
|
||||||
const db = mClient.db(process.env.M_DB);
|
|
||||||
const bdayColl = db.collection('items_birthdays');
|
|
||||||
|
|
||||||
const found = await bdayColl.findOne({ userID: target.id });
|
|
||||||
if (!found) {
|
|
||||||
return interaction.reply({
|
|
||||||
content: "Date not in Database!",
|
|
||||||
flags: MessageFlags.Ephemeral
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const now = new Date();
|
|
||||||
const isToday =
|
|
||||||
now.getDate() === found.day &&
|
|
||||||
now.getMonth() === (found.month - 1);
|
|
||||||
|
|
||||||
let description;
|
|
||||||
|
|
||||||
if (isToday) {
|
|
||||||
description = `IS TODAY! 🥳🎉`;
|
|
||||||
} else {
|
|
||||||
const unix = getNextBirthdayTimestamp(found.day, found.month);
|
|
||||||
description = `is on the <t:${unix}:d>\n<t:${unix}:R>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setThumbnail(target.displayAvatarURL())
|
|
||||||
.setTitle(`${target.globalName ?? target.username}'s Birthday...`)
|
|
||||||
.setDescription(description);
|
|
||||||
|
|
||||||
await interaction.reply({ embeds: [embed] });
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
data: new SlashCommandBuilder()
|
|
||||||
.setName('birthday')
|
|
||||||
.setDescription('manage birthdays')
|
|
||||||
.setDefaultMemberPermissions(PermissionFlagsBits.ManageRoles)
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s
|
|
||||||
.setName('set')
|
|
||||||
.setDescription('set date to birthday')
|
|
||||||
.addUserOption((option) =>
|
|
||||||
option
|
|
||||||
.setName('user')
|
|
||||||
.setDescription('user')
|
|
||||||
.setRequired(true))
|
|
||||||
.addNumberOption((option) =>
|
|
||||||
option
|
|
||||||
.setName('day')
|
|
||||||
.setDescription('day')
|
|
||||||
.setMinValue(1)
|
|
||||||
.setMaxValue(31)
|
|
||||||
.setRequired(true))
|
|
||||||
.addNumberOption((option) =>
|
|
||||||
option
|
|
||||||
.setName('month')
|
|
||||||
.setDescription('month')
|
|
||||||
.setMinValue(1)
|
|
||||||
.setMaxValue(12)
|
|
||||||
.setRequired(true))
|
|
||||||
)
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s
|
|
||||||
.setName('delete')
|
|
||||||
.setDescription('deletes a birthday')
|
|
||||||
.addUserOption((option) =>
|
|
||||||
option.setName('user').setDescription('user'))
|
|
||||||
.addStringOption((option) =>
|
|
||||||
option.setName('id').setDescription('ID')))
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s
|
|
||||||
.setName('get')
|
|
||||||
.setDescription('gets a birthday')
|
|
||||||
.addUserOption((option) =>
|
|
||||||
option.setName('user').setDescription('user').setRequired(true))),
|
|
||||||
async execute(interaction) {
|
|
||||||
switch (interaction.options._subcommand) {
|
|
||||||
case 'set':
|
|
||||||
birthdaySet(interaction)
|
|
||||||
break;
|
|
||||||
case 'delete':
|
|
||||||
birthdayDelete(interaction)
|
|
||||||
break;
|
|
||||||
case 'get':
|
|
||||||
birthdayGet(interaction)
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,172 +0,0 @@
|
|||||||
const { SlashCommandBuilder, Events, MessageFlags, PermissionFlagsBits } = require('discord.js')
|
|
||||||
const { mClient } = require('../../../index')
|
|
||||||
require('dotenv').config()
|
|
||||||
|
|
||||||
async function channelSet(interaction) {
|
|
||||||
const channel = interaction.options.getChannel('channel')
|
|
||||||
const purpose = interaction.options.getString('purpose')
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const channelColl = db.collection('config_channels')
|
|
||||||
|
|
||||||
await channelColl.findOneAndUpdate({
|
|
||||||
$and: [{ guildID: channel.guild.id }, { purpose: purpose }]
|
|
||||||
}, {
|
|
||||||
$set: {
|
|
||||||
guildID: channel.guild.id,
|
|
||||||
purpose: purpose,
|
|
||||||
channelID: channel.id
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
upsert: true
|
|
||||||
})
|
|
||||||
|
|
||||||
return await interaction.editReply({
|
|
||||||
content: `Set <#${channel.id}> as ${purpose} channel!`, flags: MessageFlags.Ephemeral
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
async function channelSimulate(interaction) {
|
|
||||||
const purpose = interaction.options.getString('purpose')
|
|
||||||
switch (purpose) {
|
|
||||||
case 'birthday':
|
|
||||||
await interaction.client.emit('Birthday', interaction.member)
|
|
||||||
break;
|
|
||||||
case 'wge':
|
|
||||||
// For Future WGE Use
|
|
||||||
break;
|
|
||||||
case 'welcome':
|
|
||||||
await interaction.client.emit(Events.GuildMemberAdd, interaction.member)
|
|
||||||
break;
|
|
||||||
case 'logs':
|
|
||||||
// For Future Log Use
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return interaction.reply({ content: 'Done.', flags: MessageFlags.Ephemeral })
|
|
||||||
}
|
|
||||||
|
|
||||||
async function roleSet(interaction) {
|
|
||||||
const guild = interaction.guild
|
|
||||||
const purpose = interaction.options.getString('purpose')
|
|
||||||
const role = interaction.options.getRole('role')
|
|
||||||
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const roleColl = db.collection('config_roles')
|
|
||||||
|
|
||||||
switch (purpose) {
|
|
||||||
case 'birthday':
|
|
||||||
await roleColl.findOneAndUpdate({
|
|
||||||
$and: [{ guildID: guild.id }, { purpose: purpose }]
|
|
||||||
}, {
|
|
||||||
$set: {
|
|
||||||
guildID: guild.id,
|
|
||||||
purpose: purpose,
|
|
||||||
roleID: role.id
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
upsert: true
|
|
||||||
})
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return await interaction.editReply({
|
|
||||||
content: `Set ${role} as default role for ${purpose} in ${guild} `
|
|
||||||
})
|
|
||||||
}
|
|
||||||
module.exports = {
|
|
||||||
data: new SlashCommandBuilder()
|
|
||||||
.setName('config')
|
|
||||||
.setDescription('configurations for admins')
|
|
||||||
.setDefaultMemberPermissions(PermissionFlagsBits.ManageChannels)
|
|
||||||
.addSubcommandGroup(sg =>
|
|
||||||
sg
|
|
||||||
.setName('channels')
|
|
||||||
.setDescription('configure channels for certain events')
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s.setName('set')
|
|
||||||
.setDescription('sets channel')
|
|
||||||
.addStringOption(o =>
|
|
||||||
o.setName('purpose').setDescription('set the purpose').setRequired(true).addChoices({
|
|
||||||
name: 'birthday',
|
|
||||||
value: 'birthday'
|
|
||||||
}, {
|
|
||||||
name: 'welcome',
|
|
||||||
value: 'welcome'
|
|
||||||
}, {
|
|
||||||
name: 'logs',
|
|
||||||
value: 'logs'
|
|
||||||
}, {
|
|
||||||
name: 'wge',
|
|
||||||
value: 'wge'
|
|
||||||
}))
|
|
||||||
.addChannelOption(c =>
|
|
||||||
c.setName('channel').setDescription('choose a channel').setRequired(true)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s
|
|
||||||
.setName('simulate')
|
|
||||||
.setDescription('simulate a specific channel event')
|
|
||||||
.addStringOption(o =>
|
|
||||||
o.setName('purpose').setDescription('set the purpose').setRequired(true).addChoices({
|
|
||||||
name: 'birthday',
|
|
||||||
value: 'birthday'
|
|
||||||
}, {
|
|
||||||
name: 'welcome',
|
|
||||||
value: 'welcome'
|
|
||||||
}, {
|
|
||||||
name: 'logs',
|
|
||||||
value: 'logs'
|
|
||||||
}, {
|
|
||||||
name: 'wge',
|
|
||||||
value: 'wge'
|
|
||||||
}))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.addSubcommandGroup(sg =>
|
|
||||||
sg.setName('roles')
|
|
||||||
.setDescription('configure roles for certain events')
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s.setName('set')
|
|
||||||
.setDescription('sets roles')
|
|
||||||
.addStringOption(o =>
|
|
||||||
o.setName('purpose').setDescription('set the purpose').setRequired(true).addChoices({
|
|
||||||
name: 'birthday',
|
|
||||||
value: 'birthday'
|
|
||||||
}))
|
|
||||||
.addRoleOption(c =>
|
|
||||||
c.setName('role').setDescription('choose a role').setRequired(true)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
async execute(interaction) {
|
|
||||||
switch (interaction.options._group) {
|
|
||||||
case 'channels':
|
|
||||||
switch (interaction.options._subcommand) {
|
|
||||||
case 'set':
|
|
||||||
await interaction.deferReply()
|
|
||||||
channelSet(interaction)
|
|
||||||
break;
|
|
||||||
case 'simulate':
|
|
||||||
channelSimulate(interaction)
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'roles':
|
|
||||||
switch (interaction.options._subcommand) {
|
|
||||||
case 'set':
|
|
||||||
await interaction.deferReply()
|
|
||||||
roleSet(interaction)
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
const { SlashCommandBuilder } = require("discord.js");
|
|
||||||
const ping = require("../../../src/ping");
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
data: new SlashCommandBuilder()
|
|
||||||
.setName('ping')
|
|
||||||
.setDescription('dev tool'),
|
|
||||||
async execute(interaction) {
|
|
||||||
return ping(interaction, null, 'slash')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,249 +0,0 @@
|
|||||||
const {
|
|
||||||
SlashCommandBuilder,
|
|
||||||
EmbedBuilder,
|
|
||||||
ActionRowBuilder,
|
|
||||||
ButtonBuilder,
|
|
||||||
ButtonStyle,
|
|
||||||
MessageFlags
|
|
||||||
} = require('discord.js');
|
|
||||||
const { mClient } = require('../../..');
|
|
||||||
require('dotenv').config()
|
|
||||||
|
|
||||||
const db = mClient.db(process.env.M_DB); // adjust if needed
|
|
||||||
const coll = db.collection('items_daily_numbers');
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
data: new SlashCommandBuilder()
|
|
||||||
.setName('ezd')
|
|
||||||
.setDescription('Ersti Zweiti Dritti')
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s
|
|
||||||
.setName('show')
|
|
||||||
.setDescription('Zeigt die täglichen Erster/Zweiter/Dritter Ergebnisse')
|
|
||||||
)
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s
|
|
||||||
.setName('leaderboard')
|
|
||||||
.setDescription('Zeigt die Rangliste der EZDler')
|
|
||||||
)
|
|
||||||
,
|
|
||||||
async execute(interaction, client) {
|
|
||||||
switch (interaction.options._subcommand) {
|
|
||||||
case 'show':
|
|
||||||
ezdShow(interaction)
|
|
||||||
break;
|
|
||||||
case 'leaderboard':
|
|
||||||
ezdLeaderboard(interaction)
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// helper: shift YYYY-MM-DD safely
|
|
||||||
function shiftDate(dateStr, offset) {
|
|
||||||
const d = new Date(dateStr);
|
|
||||||
d.setDate(d.getDate() + offset);
|
|
||||||
return d.toISOString().slice(0, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function ezdShow(interaction) {
|
|
||||||
const today = new Date().toLocaleDateString("en-CA", {
|
|
||||||
timeZone: "Europe/Berlin"
|
|
||||||
});
|
|
||||||
|
|
||||||
let currentDate = today;
|
|
||||||
|
|
||||||
const sessionId = `${interaction.user.id}-${Date.now()}`;
|
|
||||||
|
|
||||||
const buildEmbed = (doc, date) => {
|
|
||||||
const p = doc?.positions || {};
|
|
||||||
|
|
||||||
const line = (emoji, label, key) => {
|
|
||||||
const v = p[key];
|
|
||||||
return `${emoji} **${label}:** ${v ? `<@${v.userId}>` : "—"}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
const germanDate = new Date(`${date}T00:00:00`).toLocaleDateString("de-DE", {
|
|
||||||
timeZone: "Europe/Berlin",
|
|
||||||
day: "2-digit",
|
|
||||||
month: "2-digit",
|
|
||||||
year: "numeric"
|
|
||||||
});
|
|
||||||
|
|
||||||
return new EmbedBuilder()
|
|
||||||
.setTitle(`📊 EZD Übersicht – ${germanDate}`)
|
|
||||||
.setColor(0x2b2d31)
|
|
||||||
.setDescription([
|
|
||||||
line("🥇", "Ersti", "Ersti"),
|
|
||||||
line("🥈", "Zweiti", "Zweiti"),
|
|
||||||
line("🥉", "Dritti", "Dritti")
|
|
||||||
].join("\n"));
|
|
||||||
};
|
|
||||||
|
|
||||||
const buildButtons = (date) => {
|
|
||||||
return new ActionRowBuilder().addComponents(
|
|
||||||
new ButtonBuilder()
|
|
||||||
.setCustomId(`ezd_prev`)
|
|
||||||
.setLabel("⬅️")
|
|
||||||
.setStyle(ButtonStyle.Secondary),
|
|
||||||
new ButtonBuilder()
|
|
||||||
.setCustomId(`ezd_next`)
|
|
||||||
.setLabel("➡️")
|
|
||||||
.setStyle(ButtonStyle.Secondary)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const doc = await coll.findOne({ date: currentDate });
|
|
||||||
|
|
||||||
const msg = await interaction.reply({
|
|
||||||
embeds: [buildEmbed(doc, currentDate)],
|
|
||||||
components: [buildButtons(currentDate)]
|
|
||||||
});
|
|
||||||
|
|
||||||
const collector = msg.createMessageComponentCollector({
|
|
||||||
time: 1000 * 60 * 10 // 10 minutes
|
|
||||||
});
|
|
||||||
|
|
||||||
collector.on("collect", async (btn) => {
|
|
||||||
if (btn.user.id !== interaction.user.id) {
|
|
||||||
return btn.reply({
|
|
||||||
content: "❌ Diese Buttons gehören nicht dir.",
|
|
||||||
flags: MessageFlags.Ephemeral
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (btn.customId === `ezd_prev`) {
|
|
||||||
currentDate = shiftDate(currentDate, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (btn.customId === `ezd_next`) {
|
|
||||||
currentDate = shiftDate(currentDate, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const newDoc = await coll.findOne({ date: currentDate });
|
|
||||||
|
|
||||||
await btn.update({
|
|
||||||
embeds: [buildEmbed(newDoc, currentDate)],
|
|
||||||
components: [buildButtons(currentDate)]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function ezdLeaderboard(interaction) {
|
|
||||||
const docs = await coll.find({}).toArray();
|
|
||||||
|
|
||||||
const leaderboard = new Map();
|
|
||||||
|
|
||||||
const add = (entry, place) => {
|
|
||||||
if (!entry?.userId) return;
|
|
||||||
|
|
||||||
if (!leaderboard.has(entry.userId)) {
|
|
||||||
leaderboard.set(entry.userId, {
|
|
||||||
userId: entry.userId,
|
|
||||||
points: 0,
|
|
||||||
Ersti: 0,
|
|
||||||
Zweiti: 0,
|
|
||||||
Dritti: 0
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const user = leaderboard.get(entry.userId);
|
|
||||||
|
|
||||||
user[place]++;
|
|
||||||
|
|
||||||
if (place === "Ersti") user.points += 3;
|
|
||||||
if (place === "Zweiti") user.points += 2;
|
|
||||||
if (place === "Dritti") user.points += 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const doc of docs) {
|
|
||||||
const p = doc.positions || {};
|
|
||||||
|
|
||||||
add(p.Ersti, "Ersti");
|
|
||||||
add(p.Zweiti, "Zweiti");
|
|
||||||
add(p.Dritti, "Dritti");
|
|
||||||
}
|
|
||||||
|
|
||||||
const users = [...leaderboard.values()].sort((a, b) => {
|
|
||||||
if (b.points !== a.points) return b.points - a.points;
|
|
||||||
if (b.Ersti !== a.Ersti) return b.Ersti - a.Ersti;
|
|
||||||
if (b.Zweiti !== a.Zweiti) return b.Zweiti - a.Zweiti;
|
|
||||||
return b.Dritti - a.Dritti;
|
|
||||||
});
|
|
||||||
|
|
||||||
const PAGE_SIZE = 5;
|
|
||||||
const pageCount = Math.max(1, Math.ceil(users.length / PAGE_SIZE));
|
|
||||||
let page = 0;
|
|
||||||
|
|
||||||
const buildEmbed = () => {
|
|
||||||
const slice = users.slice(
|
|
||||||
page * PAGE_SIZE,
|
|
||||||
page * PAGE_SIZE + PAGE_SIZE
|
|
||||||
);
|
|
||||||
|
|
||||||
const description = slice.length
|
|
||||||
? slice.map((u, i) => {
|
|
||||||
const rank = page * PAGE_SIZE + i + 1;
|
|
||||||
|
|
||||||
return `**#${rank}** <@${u.userId}> — **${u.points}**
|
|
||||||
🥇 ${u.Ersti} · 🥈 ${u.Zweiti} · 🥉 ${u.Dritti}`;
|
|
||||||
}).join("\n\n")
|
|
||||||
: "—";
|
|
||||||
|
|
||||||
return new EmbedBuilder()
|
|
||||||
.setTitle("🏆 EZD Rangliste")
|
|
||||||
.setColor(0x2b2d31)
|
|
||||||
.setDescription(description);
|
|
||||||
};
|
|
||||||
|
|
||||||
const buildButtons = () =>
|
|
||||||
new ActionRowBuilder().addComponents(
|
|
||||||
new ButtonBuilder()
|
|
||||||
.setCustomId("ezd_lb_prev")
|
|
||||||
.setLabel("⬅️")
|
|
||||||
.setStyle(ButtonStyle.Secondary),
|
|
||||||
|
|
||||||
new ButtonBuilder()
|
|
||||||
.setCustomId("ezd_lb_page")
|
|
||||||
.setLabel(`${page + 1}/${pageCount}`)
|
|
||||||
.setStyle(ButtonStyle.Primary)
|
|
||||||
.setDisabled(true),
|
|
||||||
|
|
||||||
new ButtonBuilder()
|
|
||||||
.setCustomId("ezd_lb_next")
|
|
||||||
.setLabel("➡️")
|
|
||||||
.setStyle(ButtonStyle.Secondary)
|
|
||||||
);
|
|
||||||
|
|
||||||
const msg = await interaction.reply({
|
|
||||||
embeds: [buildEmbed()],
|
|
||||||
components: [buildButtons()]
|
|
||||||
});
|
|
||||||
|
|
||||||
const collector = msg.createMessageComponentCollector({
|
|
||||||
time: 1000 * 60 * 10
|
|
||||||
});
|
|
||||||
|
|
||||||
collector.on("collect", async btn => {
|
|
||||||
if (btn.user.id !== interaction.user.id) {
|
|
||||||
return btn.reply({
|
|
||||||
content: "❌ Diese Buttons gehören nicht dir.",
|
|
||||||
flags: MessageFlags.Ephemeral
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (btn.customId === "ezd_lb_prev")
|
|
||||||
page = (page - 1 + pageCount) % pageCount;
|
|
||||||
|
|
||||||
if (btn.customId === "ezd_lb_next")
|
|
||||||
page = (page + 1) % pageCount;
|
|
||||||
|
|
||||||
await btn.update({
|
|
||||||
embeds: [buildEmbed()],
|
|
||||||
components: [buildButtons()]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,277 +0,0 @@
|
|||||||
const { SlashCommandBuilder, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, UserSelectMenuBuilder, MessageFlags } = require('discord.js')
|
|
||||||
const { mClient } = require('../../../index')
|
|
||||||
require('dotenv').config()
|
|
||||||
function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }
|
|
||||||
|
|
||||||
async function honorHoner(interaction) {
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const honorsColl = db.collection('items_honors')
|
|
||||||
|
|
||||||
const target = await interaction.options.getUser('target')
|
|
||||||
const reason = `[+] ${await interaction.options.getString('reason') ?? 'No reason provided'}`
|
|
||||||
|
|
||||||
const theirHonorLevel = await honorsColl.findOne({ userID: target.id })
|
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setTitle('- Honor Up! -')
|
|
||||||
.setDescription(`Willst du wirklich <@${target.id}> einen **Honor** geben?\r\n[Grund: ${reason}]`)
|
|
||||||
.addFields({
|
|
||||||
name: 'Current Honor Level', value: `${theirHonorLevel?.honors ?? 0} (**+1**)`
|
|
||||||
})
|
|
||||||
.setThumbnail(target.displayAvatarURL())
|
|
||||||
const row = new ActionRowBuilder()
|
|
||||||
.addComponents(
|
|
||||||
new ButtonBuilder()
|
|
||||||
.setLabel('✔')
|
|
||||||
.setCustomId('honor_multi_confirm')
|
|
||||||
.setStyle(ButtonStyle.Success)
|
|
||||||
)
|
|
||||||
.addComponents(
|
|
||||||
new ButtonBuilder()
|
|
||||||
.setLabel('✖')
|
|
||||||
.setCustomId('abort')
|
|
||||||
.setStyle(ButtonStyle.Danger)
|
|
||||||
)
|
|
||||||
await interaction.reply({
|
|
||||||
embeds: [embed],
|
|
||||||
components: [row],
|
|
||||||
flags: MessageFlags.Ephemeral
|
|
||||||
})
|
|
||||||
}
|
|
||||||
async function honerDishonor(interaction) {
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const honorsColl = db.collection('items_honors')
|
|
||||||
|
|
||||||
const target = await interaction.options.getUser('target')
|
|
||||||
const reason = `[-] ${await interaction.options.getString('reason') ?? 'No reason provided'}`
|
|
||||||
const theirHonorLevel = await honorsColl.findOne({ userID: target.id })
|
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setTitle('- Honor Down! -')
|
|
||||||
.setDescription(`Willst du wirklich <@${target.id}> einen **Dishonor** geben?\r\n[Grund: ${reason}]`)
|
|
||||||
.addFields({
|
|
||||||
name: 'Current Honor Level', value: `${theirHonorLevel?.honors ?? 0} (**-1**)`
|
|
||||||
})
|
|
||||||
.setThumbnail(target.displayAvatarURL())
|
|
||||||
const row = new ActionRowBuilder()
|
|
||||||
.addComponents(
|
|
||||||
new ButtonBuilder()
|
|
||||||
.setLabel('✔')
|
|
||||||
.setCustomId('honor_multi_confirm')
|
|
||||||
.setStyle(ButtonStyle.Success)
|
|
||||||
)
|
|
||||||
.addComponents(
|
|
||||||
new ButtonBuilder()
|
|
||||||
.setLabel('✖')
|
|
||||||
.setCustomId('abort')
|
|
||||||
.setStyle(ButtonStyle.Danger)
|
|
||||||
)
|
|
||||||
await interaction.reply({
|
|
||||||
embeds: [embed],
|
|
||||||
components: [row],
|
|
||||||
flags: MessageFlags.Ephemeral
|
|
||||||
})
|
|
||||||
}
|
|
||||||
async function honorLeaderboard(interaction) {
|
|
||||||
const row = new ActionRowBuilder()
|
|
||||||
.addComponents(
|
|
||||||
new ButtonBuilder()
|
|
||||||
.setLabel('◄')
|
|
||||||
.setStyle(ButtonStyle.Primary)
|
|
||||||
.setCustomId('honors_leaderboard_left')
|
|
||||||
)
|
|
||||||
.addComponents(
|
|
||||||
new ButtonBuilder()
|
|
||||||
.setLabel('🧑')
|
|
||||||
.setStyle(ButtonStyle.Primary)
|
|
||||||
.setCustomId('honors_leaderboard_self')
|
|
||||||
)
|
|
||||||
.addComponents(
|
|
||||||
new ButtonBuilder()
|
|
||||||
.setLabel('►')
|
|
||||||
.setStyle(ButtonStyle.Primary)
|
|
||||||
.setCustomId('honors_leaderboard_right')
|
|
||||||
)
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const honorsColl = db.collection('items_honors')
|
|
||||||
let skip = 0
|
|
||||||
const honorsData = await honorsColl.find({}).sort({ honors: -1 }).skip(skip).limit(5).toArray()
|
|
||||||
let fields
|
|
||||||
let placements = skip + 1
|
|
||||||
honorsData.forEach((data) => {
|
|
||||||
fields = (fields ? fields : '') + (`${placements}. <@${data.userID}> : ${data.honors} Honors\r\n`)
|
|
||||||
})
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setTitle('- Honors Leaderboard -')
|
|
||||||
.setThumbnail(interaction.guild.iconURL({ dynamic: true}))
|
|
||||||
.setDescription(fields.toString())
|
|
||||||
.setColor('#5865F2') // Discord's blurple color
|
|
||||||
.setFooter({ text: 'Use ◄ ► to navigate' });
|
|
||||||
await interaction.editReply({
|
|
||||||
embeds: [embed],
|
|
||||||
components: [row]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
async function honorHistory(interaction) {
|
|
||||||
var target = interaction.options.getUser('target')
|
|
||||||
if (!target) { target = interaction.user }
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const reasonsColl = db.collection('history_honors')
|
|
||||||
var history = await reasonsColl.findOne({ userID: target.id })
|
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setTitle('- Honor History -')
|
|
||||||
.setThumbnail(target.displayAvatarURL())
|
|
||||||
|
|
||||||
if (history) {
|
|
||||||
let temp = ''
|
|
||||||
history.reasons.forEach(reason => {
|
|
||||||
temp += reason + '\r\n'
|
|
||||||
})
|
|
||||||
embed.setDescription(temp)
|
|
||||||
}
|
|
||||||
await interaction.editReply({ embeds: [embed] })
|
|
||||||
}
|
|
||||||
async function honorCheck(interaction) {
|
|
||||||
var target = interaction.options.getUser('target')
|
|
||||||
if (!target) { target = interaction.user }
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const honorsColl = db.collection('items_honors')
|
|
||||||
var honors = await honorsColl.findOne({ userID: target.id })
|
|
||||||
honors = honors?.honors ?? 0
|
|
||||||
|
|
||||||
if (!honors) {
|
|
||||||
content = 'Choose a goddamn side!'
|
|
||||||
} else {
|
|
||||||
if (honors === -20) {
|
|
||||||
content = 'They are is at max Dishonor Level! <:lowhonor:748176295132790786> <:lowhonor:748176295132790786> <:lowhonor:748176295132790786>\n```' + `You don't get to live a bad life and have good things happen to you. - Arthur M.` + '```'
|
|
||||||
} else if (honors === 20) {
|
|
||||||
content = 'They are at max Honor Level! <:highhonor:748176295535443968> <:highhonor:748176295535443968> <:highhonor:748176295535443968>'
|
|
||||||
} else if (honors > 0) {
|
|
||||||
content = 'real good, boah, REAL GOOD! <:highhonor:748176295535443968>'
|
|
||||||
} else if (honors < 0) {
|
|
||||||
content = 'What happened to Loyalty?! <:lowhonor:748176295132790786>'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setTitle('- Honor Check -')
|
|
||||||
.setDescription(`${target} has an Honor Level of **${honors}**!`)
|
|
||||||
.setThumbnail(target.displayAvatarURL())
|
|
||||||
.addFields({ name: '\u200B', value: `*${content}*` })
|
|
||||||
|
|
||||||
await interaction.editReply({
|
|
||||||
embeds: [embed]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
async function honorMenu(interaction) {
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setTitle('- Honor Menu! -')
|
|
||||||
.setDescription('- Choose someone from the Select Menu below\r\n- Choose Honor Dishonor, or History\r\n- Confirm your Selection')
|
|
||||||
.setThumbnail(interaction.guild.iconURL())
|
|
||||||
const row = new ActionRowBuilder()
|
|
||||||
.addComponents(
|
|
||||||
new ButtonBuilder()
|
|
||||||
.setEmoji(`<:honorhigh:748176295535443968>`)
|
|
||||||
.setCustomId('honor_menu_honor')
|
|
||||||
.setStyle(ButtonStyle.Success)
|
|
||||||
)
|
|
||||||
.addComponents(
|
|
||||||
new ButtonBuilder()
|
|
||||||
.setEmoji(`<:honorlow:748176295132790786>`)
|
|
||||||
.setCustomId('honor_menu_dishonor')
|
|
||||||
.setStyle(ButtonStyle.Danger)
|
|
||||||
)
|
|
||||||
.addComponents(
|
|
||||||
new ButtonBuilder()
|
|
||||||
.setEmoji(`❌`)
|
|
||||||
.setCustomId('abort')
|
|
||||||
.setStyle(ButtonStyle.Secondary)
|
|
||||||
)
|
|
||||||
.addComponents(
|
|
||||||
new ButtonBuilder()
|
|
||||||
.setEmoji('📜')
|
|
||||||
.setCustomId('honor_menu_history')
|
|
||||||
.setStyle(ButtonStyle.Secondary)
|
|
||||||
)
|
|
||||||
const select = new ActionRowBuilder()
|
|
||||||
.addComponents(
|
|
||||||
new UserSelectMenuBuilder()
|
|
||||||
.setCustomId('honor_menu_mentionable')
|
|
||||||
.setPlaceholder('Select a User')
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
await interaction.reply({
|
|
||||||
embeds: [embed],
|
|
||||||
components: [select, row],
|
|
||||||
flags: MessageFlags.Ephemeral
|
|
||||||
})
|
|
||||||
}
|
|
||||||
module.exports = {
|
|
||||||
data: new SlashCommandBuilder()
|
|
||||||
.setName('honors')
|
|
||||||
.setDescription('rund um den honor')
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s
|
|
||||||
.setName('honor')
|
|
||||||
.setDescription('honor someone')
|
|
||||||
.addUserOption(o => o.setName('target').setDescription('wer wird gehonored?').setRequired(true))
|
|
||||||
.addStringOption(o => o.setName('reason').setDescription('reason?'))
|
|
||||||
)
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s
|
|
||||||
.setName('dishonor')
|
|
||||||
.setDescription('dishonor someone')
|
|
||||||
.addUserOption(o => o.setName('target').setDescription('wer wird gehonored?').setRequired(true))
|
|
||||||
.addStringOption(o => o.setName('reason').setDescription('reason?'))
|
|
||||||
)
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s
|
|
||||||
.setName('check')
|
|
||||||
.setDescription("check someone's honor level")
|
|
||||||
.addUserOption(o => o.setName('target').setDescription('wer wird gehonored?'))
|
|
||||||
)
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s
|
|
||||||
.setName('history')
|
|
||||||
.setDescription("check someone's honor history")
|
|
||||||
.addUserOption(o => o.setName('target').setDescription('von wem?'))
|
|
||||||
)
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s
|
|
||||||
.setName('leaderboard')
|
|
||||||
.setDescription("check who's got the most honor")
|
|
||||||
)
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s
|
|
||||||
.setName('menu')
|
|
||||||
.setDescription('WIP universal honor menu'))
|
|
||||||
,
|
|
||||||
async execute(interaction) {
|
|
||||||
switch (interaction.options._subcommand) {
|
|
||||||
case 'honor':
|
|
||||||
honorHoner(interaction)
|
|
||||||
break;
|
|
||||||
case 'dishonor':
|
|
||||||
honerDishonor(interaction)
|
|
||||||
break;
|
|
||||||
case 'leaderboard':
|
|
||||||
await interaction.deferReply()
|
|
||||||
honorLeaderboard(interaction)
|
|
||||||
break;
|
|
||||||
case 'history':
|
|
||||||
await interaction.deferReply()
|
|
||||||
honorHistory(interaction)
|
|
||||||
break;
|
|
||||||
case 'check':
|
|
||||||
await interaction.deferReply()
|
|
||||||
honorCheck(interaction)
|
|
||||||
break;
|
|
||||||
case 'menu':
|
|
||||||
honorMenu(interaction)
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,454 +0,0 @@
|
|||||||
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(interaction.guild.iconURL({ dynamic: true}))
|
|
||||||
.setDescription(fields.toString())
|
|
||||||
.setColor('#5865F2')
|
|
||||||
.setFooter({ text: 'Use ◄ ► to navigate' })
|
|
||||||
|
|
||||||
await interaction.editReply({
|
|
||||||
embeds: [embed],
|
|
||||||
components: [row]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
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 === 1 ? 'eine' : 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 }
|
|
||||||
)
|
|
||||||
|
|
||||||
let nutText = `Du hast ${formatNut(amount)} bekommen! :chestnut:`
|
|
||||||
if (amount <= 0) {
|
|
||||||
nutText = `Du hast keine Nuss bekommen! :yoink_help:`
|
|
||||||
}
|
|
||||||
|
|
||||||
if (quickMode) {
|
|
||||||
return interaction.editReply({ content: nutText })
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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(nutText)
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,414 +0,0 @@
|
|||||||
/*
|
|
||||||
Random By Year?
|
|
||||||
Counter (Leaderboard)
|
|
||||||
*/
|
|
||||||
const { SlashCommandBuilder, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, UserSelectMenuBuilder, MessageFlags } = require('discord.js')
|
|
||||||
const { mClient } = require('../../../index')
|
|
||||||
require('dotenv').config()
|
|
||||||
function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }
|
|
||||||
|
|
||||||
async function quotesAdd(interaction) {
|
|
||||||
|
|
||||||
const messageLink = await interaction.options.getString('link')
|
|
||||||
//regex for message link
|
|
||||||
const regex = /^https:\/\/discord\.com\/channels\/\d+\/\d+\/\d+$/
|
|
||||||
|
|
||||||
if (!messageLink.match(regex)) {
|
|
||||||
return await interaction.editReply({
|
|
||||||
content: `Invalid URL`,
|
|
||||||
flags: MessageFlags.Ephemeral
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
let temp = messageLink.split('/')
|
|
||||||
let messageID = temp[temp.length - 1]
|
|
||||||
let channelID = temp[temp.length - 2]
|
|
||||||
let guildID = temp[temp.length - 3]
|
|
||||||
|
|
||||||
const guild = await interaction.client.guilds.fetch(guildID)
|
|
||||||
const channel = await guild.channels.fetch(channelID)
|
|
||||||
const message = await channel.messages.fetch(messageID)
|
|
||||||
|
|
||||||
var msgData = {
|
|
||||||
content: message.content,
|
|
||||||
author: await message.author,
|
|
||||||
reference: await message.reference,
|
|
||||||
embed: await message.embeds ? 'embed' : null
|
|
||||||
} // debug
|
|
||||||
if (msgData.reference) {
|
|
||||||
let refGuild = await interaction.client.guilds.fetch(msgData.reference.guildId)
|
|
||||||
let refChannel = await refGuild.channels.fetch(msgData.reference.channelId)
|
|
||||||
let refMessage = await refChannel.messages.fetch(msgData.reference.messageId)
|
|
||||||
|
|
||||||
|
|
||||||
var refData = {
|
|
||||||
content: refMessage.content,
|
|
||||||
author: await refMessage.author,
|
|
||||||
embed: await refMessage.embeds.length > 0 ? 'embed' : null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const quotesColl = db.collection('items_quotes')
|
|
||||||
const found = await quotesColl.findOne({ messageID: messageID })
|
|
||||||
if (found) { return await interaction.editReply({ content: 'Quote Already in Database', flags: MessageFlags.Ephemeral }) }
|
|
||||||
await quotesColl.findOneAndUpdate({ messageID: messageID }, {
|
|
||||||
$set: {
|
|
||||||
messageID: messageID,
|
|
||||||
channelID: channelID,
|
|
||||||
guildID: guildID,
|
|
||||||
userID: msgData.author.id,
|
|
||||||
count: 0
|
|
||||||
}
|
|
||||||
}, { upsert: true })
|
|
||||||
|
|
||||||
var description = ''
|
|
||||||
if (refData) {
|
|
||||||
description += `> ${refData.author}`
|
|
||||||
if (refData.embed) {
|
|
||||||
description += '*an embed / a command* '
|
|
||||||
} else {
|
|
||||||
description += refData.content
|
|
||||||
}
|
|
||||||
description += `\r\n↳`
|
|
||||||
}
|
|
||||||
description += `${msgData.author} ${msgData.content}\r\n\r\n${messageLink}`
|
|
||||||
let timestamp = new Date(message.createdTimestamp)
|
|
||||||
let footer = timestamp.toDateString().toString()
|
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setThumbnail(msgData.author.displayAvatarURL())
|
|
||||||
.setURL(messageLink)
|
|
||||||
.setTitle(`- Quote Added! -`)
|
|
||||||
.setDescription(description)
|
|
||||||
.setFooter({ text: (footer + ' #' + messageID) })
|
|
||||||
await interaction.editReply({ embeds: [embed] })
|
|
||||||
}
|
|
||||||
async function quotesRemove(interaction) {
|
|
||||||
const id = await interaction.options.getString('id')
|
|
||||||
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const quotesColl = db.collection('items_quotes')
|
|
||||||
const found = await quotesColl.findOne({ messageID: id })
|
|
||||||
if (!found) { return await interaction.reply({ content: 'ID not found!', flags: MessageFlags.Ephemeral }) }
|
|
||||||
|
|
||||||
await quotesColl.deleteOne({ messageID: id })
|
|
||||||
|
|
||||||
return interaction.reply({ content: 'Quote successfully removed!', flags: MessageFlags.Ephemeral })
|
|
||||||
}
|
|
||||||
async function quotesSearch(interaction) {
|
|
||||||
const id = interaction.options.getString("id")
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const quotesColl = db.collection('items_quotes')
|
|
||||||
const found = await quotesColl.findOne({ messageID: id })
|
|
||||||
if (!found) { return await interaction.reply({ content: 'ID not found!', flags: MessageFlags.Ephemeral }) }
|
|
||||||
|
|
||||||
|
|
||||||
const guild = await interaction.client.guilds.fetch(found.guildID)
|
|
||||||
const channel = await guild.channels.fetch(found.channelID)
|
|
||||||
const message = await channel.messages.fetch(found.messageID)
|
|
||||||
|
|
||||||
var msgData = {
|
|
||||||
content: message.content,
|
|
||||||
author: await message.author,
|
|
||||||
reference: await message.reference,
|
|
||||||
embed: await message.embeds ? 'embed' : null
|
|
||||||
} // debug
|
|
||||||
|
|
||||||
quotesColl.findOneAndUpdate({
|
|
||||||
messageID: found.messageID
|
|
||||||
}, {
|
|
||||||
$inc: { count: 1 }
|
|
||||||
}, {
|
|
||||||
upsert: true
|
|
||||||
})
|
|
||||||
|
|
||||||
if (msgData.reference) {
|
|
||||||
let refMessage = await channel.messages.fetch(msgData.reference.messageId)
|
|
||||||
var refData = {
|
|
||||||
content: refMessage.content,
|
|
||||||
author: await refMessage.author,
|
|
||||||
embed: await refMessage.embeds.length > 0 ? 'embed' : null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var description = ''
|
|
||||||
if (refData) {
|
|
||||||
description += `> ${refData.author}`
|
|
||||||
if (refData.embed) {
|
|
||||||
description += '*an embed / a command* '
|
|
||||||
} else {
|
|
||||||
description += refData.content
|
|
||||||
}
|
|
||||||
description += `\r\n↳`
|
|
||||||
}
|
|
||||||
let messageLink = `https://discord.com/channels/${found.guildID}/${found.channelID}/${found.messageID}`
|
|
||||||
description += `${msgData.author} ${msgData.content}\r\n\r\n${messageLink}`
|
|
||||||
let timestamp = new Date(message.createdTimestamp)
|
|
||||||
let footer = timestamp.toDateString().toString()
|
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setThumbnail(msgData.author.displayAvatarURL())
|
|
||||||
.setURL(messageLink)
|
|
||||||
.setTitle(`- Quote Found! -`)
|
|
||||||
.setDescription(description)
|
|
||||||
.setFooter({ text: (footer + ' #' + found.messageID) })
|
|
||||||
await interaction.reply({ embeds: [embed] })
|
|
||||||
|
|
||||||
}
|
|
||||||
async function quotesRandom(interaction) {
|
|
||||||
var user = interaction.options.getUser("by")
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const quotesColl = db.collection('items_quotes')
|
|
||||||
var rdm
|
|
||||||
if (user) {
|
|
||||||
rdm = await quotesColl.aggregate([
|
|
||||||
{
|
|
||||||
$match: { userID: user.id },
|
|
||||||
}, {
|
|
||||||
$sample: { size: 1 }
|
|
||||||
}
|
|
||||||
]).toArray()
|
|
||||||
} else {
|
|
||||||
rdm = await quotesColl.aggregate([
|
|
||||||
{
|
|
||||||
$sample: { size: 1 }
|
|
||||||
}
|
|
||||||
]).toArray()
|
|
||||||
}
|
|
||||||
const found = rdm[0]
|
|
||||||
if (!found) { return await interaction.reply({ content: 'No Entry Found.', flags: MessageFlags.Ephemeral }) }
|
|
||||||
const guild = await interaction.client.guilds.fetch(found.guildID)
|
|
||||||
const channel = await guild.channels.fetch(found.channelID)
|
|
||||||
const message = await channel.messages.fetch(found.messageID)
|
|
||||||
|
|
||||||
var msgData = {
|
|
||||||
content: message.content,
|
|
||||||
author: await message.author,
|
|
||||||
reference: await message.reference,
|
|
||||||
embed: await message.embeds ? 'embed' : null
|
|
||||||
} // debug
|
|
||||||
|
|
||||||
quotesColl.findOneAndUpdate({
|
|
||||||
messageID: found.messageID
|
|
||||||
}, {
|
|
||||||
$inc: { count: 1 }
|
|
||||||
}, {
|
|
||||||
upsert: true
|
|
||||||
})
|
|
||||||
|
|
||||||
if (msgData.reference) {
|
|
||||||
let refMessage = await channel.messages.fetch(msgData.reference.messageId)
|
|
||||||
var refData = {
|
|
||||||
content: refMessage.content,
|
|
||||||
author: await refMessage.author,
|
|
||||||
embed: await refMessage.embeds.length > 0 ? 'embed' : null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var description = ''
|
|
||||||
if (refData) {
|
|
||||||
description += `> ${refData.author}`
|
|
||||||
if (refData.embed) {
|
|
||||||
description += '*an embed / a command* '
|
|
||||||
} else {
|
|
||||||
description += refData.content
|
|
||||||
}
|
|
||||||
description += `\r\n↳`
|
|
||||||
}
|
|
||||||
let messageLink = `https://discord.com/channels/${found.guildID}/${found.channelID}/${found.messageID}`
|
|
||||||
description += `${msgData.author} ${msgData.content}\r\n\r\n${messageLink}`
|
|
||||||
let timestamp = new Date(message.createdTimestamp)
|
|
||||||
let footer = timestamp.toDateString().toString()
|
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setThumbnail(msgData.author.displayAvatarURL())
|
|
||||||
.setURL(messageLink)
|
|
||||||
.setTitle(`- Quote Found! -`)
|
|
||||||
.setDescription(description)
|
|
||||||
.setFooter({ text: (footer + ' #' + found.messageID) })
|
|
||||||
await interaction.reply({ embeds: [embed] })
|
|
||||||
}
|
|
||||||
async function quotesList(interaction) {
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setTitle('- Quotes List! -')
|
|
||||||
.setDescription('- Choose someone below to filter by User')
|
|
||||||
.setThumbnail(interaction.guild.iconURL())
|
|
||||||
const row = new ActionRowBuilder()
|
|
||||||
.addComponents(
|
|
||||||
new ButtonBuilder()
|
|
||||||
.setEmoji(`◀`)
|
|
||||||
.setCustomId('quotes_list_left')
|
|
||||||
.setStyle(ButtonStyle.Primary)
|
|
||||||
)
|
|
||||||
.addComponents(
|
|
||||||
new ButtonBuilder()
|
|
||||||
.setEmoji(`❌`)
|
|
||||||
.setCustomId('abort')
|
|
||||||
.setStyle(ButtonStyle.Primary)
|
|
||||||
)
|
|
||||||
.addComponents(
|
|
||||||
new ButtonBuilder()
|
|
||||||
.setEmoji(`▶`)
|
|
||||||
.setCustomId('quotes_list_right')
|
|
||||||
.setStyle(ButtonStyle.Primary)
|
|
||||||
)
|
|
||||||
|
|
||||||
const select = new ActionRowBuilder()
|
|
||||||
.addComponents(
|
|
||||||
new UserSelectMenuBuilder()
|
|
||||||
.setCustomId('quotes_list_mentionable')
|
|
||||||
.setPlaceholder('Filter by User')
|
|
||||||
)
|
|
||||||
|
|
||||||
await interaction.reply({
|
|
||||||
embeds: [embed],
|
|
||||||
components: [select, row],
|
|
||||||
flags: MessageFlags.Ephemeral
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
async function quotesLeaderboard(interaction, page = 1, limit = 5) {
|
|
||||||
const db = mClient.db(process.env.M_DB);
|
|
||||||
const quotesColl = db.collection('items_quotes');
|
|
||||||
|
|
||||||
// Total quotes in the guild
|
|
||||||
const totalQuotes = await quotesColl.countDocuments({ guildID: interaction.guild.id, count: { $gte: 0 } });
|
|
||||||
const totalPages = Math.ceil(totalQuotes / limit);
|
|
||||||
|
|
||||||
// Clamp page
|
|
||||||
if (page < 1) page = 1;
|
|
||||||
if (page > totalPages) page = totalPages;
|
|
||||||
|
|
||||||
const skip = (page - 1) * limit;
|
|
||||||
|
|
||||||
// Fetch quotes for this page
|
|
||||||
const quotesData = await quotesColl
|
|
||||||
.find({ guildID: interaction.guild.id, count: { $gte: 0 } })
|
|
||||||
.sort({ count: -1, messageID: -1 })
|
|
||||||
.skip(skip)
|
|
||||||
.limit(limit)
|
|
||||||
.toArray();
|
|
||||||
|
|
||||||
// Fallback if no quotes exist
|
|
||||||
if (!quotesData.length) {
|
|
||||||
return interaction.editReply({ content: 'No quotes found for this server yet!', components: [] });
|
|
||||||
}
|
|
||||||
|
|
||||||
const guild = await interaction.client.guilds.fetch(interaction.guild.id);
|
|
||||||
|
|
||||||
// Fetch all messages concurrently
|
|
||||||
const fields = await Promise.all(
|
|
||||||
quotesData.map(async (data, index) => {
|
|
||||||
try {
|
|
||||||
const channel = await guild.channels.fetch(data.channelID);
|
|
||||||
const message = await channel.messages.fetch(data.messageID);
|
|
||||||
const timestamp = new Date(message.createdTimestamp).toLocaleString('en-US', {
|
|
||||||
dateStyle: 'medium',
|
|
||||||
timeStyle: 'short'
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
name: `${skip + index + 1}.`,
|
|
||||||
value: `[#${data.messageID}](https://discord.com/channels/${data.guildID}/${data.channelID}/${data.messageID})\n**by** <@${data.userID}> • ⭐ ${data.count}\n_Posted on **${timestamp}**_\n${message.content}`
|
|
||||||
};
|
|
||||||
} catch {
|
|
||||||
return {
|
|
||||||
name: `${skip + index + 1}.`,
|
|
||||||
value: 'Message unavailable.'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
// Build embed
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setTitle('- Quotes Leaderboard -')
|
|
||||||
.setThumbnail(guild.iconURL({ dynamic: true }))
|
|
||||||
.setFields(fields)
|
|
||||||
.setColor('#5865F2')
|
|
||||||
.setFooter({ text: `Use ◄ ► to navigate • Page ${page} of ${totalPages}` });
|
|
||||||
|
|
||||||
// Build buttons
|
|
||||||
const row = new ActionRowBuilder()
|
|
||||||
.addComponents(
|
|
||||||
new ButtonBuilder()
|
|
||||||
.setLabel('◄')
|
|
||||||
.setStyle(ButtonStyle.Primary)
|
|
||||||
.setCustomId('quotes_leaderboard_left')
|
|
||||||
.setDisabled(page === 1),
|
|
||||||
new ButtonBuilder()
|
|
||||||
.setLabel('X')
|
|
||||||
.setStyle(ButtonStyle.Danger)
|
|
||||||
.setCustomId('abort'),
|
|
||||||
new ButtonBuilder()
|
|
||||||
.setLabel('►')
|
|
||||||
.setStyle(ButtonStyle.Primary)
|
|
||||||
.setCustomId('quotes_leaderboard_right')
|
|
||||||
.setDisabled(page === totalPages)
|
|
||||||
);
|
|
||||||
|
|
||||||
await interaction.editReply({ embeds: [embed], components: [row] });
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
data: new SlashCommandBuilder()
|
|
||||||
.setName('quotes')
|
|
||||||
.setDescription('quoten pfoten')
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s
|
|
||||||
.setName('add')
|
|
||||||
.setDescription('add a new quote either by replying to a message or inserting the message link')
|
|
||||||
.addStringOption(o => o.setName('link').setDescription('insert message link').setRequired(true)))
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s
|
|
||||||
.setName('remove')
|
|
||||||
.setDescription('remove a quote')
|
|
||||||
.addStringOption(o => o.setName('id').setDescription('insert message ID').setRequired(true)))
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s
|
|
||||||
.setName('search')
|
|
||||||
.setDescription('search by ID')
|
|
||||||
.addStringOption(o => o.setName('id').setDescription('insert message ID').setRequired(true)))
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s
|
|
||||||
.setName('random')
|
|
||||||
.setDescription('get a random quote')
|
|
||||||
.addUserOption(o => o.setName('by').setDescription('by user')))
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s
|
|
||||||
.setName('leaderboard')
|
|
||||||
.setDescription('see the most used quotes'))
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s
|
|
||||||
.setName('list')
|
|
||||||
.setDescription('[ADMIN] list all quotes')),
|
|
||||||
async execute(interaction) {
|
|
||||||
switch (interaction.options._subcommand) {
|
|
||||||
case 'add':
|
|
||||||
await interaction.deferReply()
|
|
||||||
quotesAdd(interaction)
|
|
||||||
break;
|
|
||||||
case 'remove':
|
|
||||||
quotesRemove(interaction)
|
|
||||||
break;
|
|
||||||
case 'search':
|
|
||||||
quotesSearch(interaction)
|
|
||||||
break;
|
|
||||||
case 'random':
|
|
||||||
quotesRandom(interaction)
|
|
||||||
break;
|
|
||||||
case 'leaderboard':
|
|
||||||
await interaction.deferReply()
|
|
||||||
quotesLeaderboard(interaction)
|
|
||||||
break;
|
|
||||||
case 'list':
|
|
||||||
quotesList(interaction)
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
module.exports.quotesLeaderboard = quotesLeaderboard
|
|
||||||
@@ -1,576 +0,0 @@
|
|||||||
const { ModalBuilder, UserSelectMenuBuilder, TextInputBuilder, EmbedBuilder, TimestampStyles, time, StringSelectMenuBuilder, messageLink } = require("@discordjs/builders");
|
|
||||||
const { ActionRowBuilder, ButtonBuilder, ButtonStyle, ComponentType } = require('discord.js')
|
|
||||||
const { SlashCommandBuilder, LabelBuilder, TextInputStyle, MessageFlags } = require("discord.js");
|
|
||||||
const { mClient } = require("../../..");
|
|
||||||
const db = mClient.db('neo-db')
|
|
||||||
require('dotenv').config()
|
|
||||||
|
|
||||||
function getRemaining(timer) {
|
|
||||||
if (timer.state !== 'running') {
|
|
||||||
return timer.timeRemaining;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Math.max(
|
|
||||||
0,
|
|
||||||
timer.timeRemaining - (Date.now() - timer.startedAt)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function ordinal(n) {
|
|
||||||
const s = ["th", "st", "nd", "rd"];
|
|
||||||
const v = n % 100;
|
|
||||||
|
|
||||||
return n + (s[(v - 20) % 10] || s[v] || s[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function wgeStatus(interaction) {
|
|
||||||
|
|
||||||
const wgeColl = db.collection('timer_wge')
|
|
||||||
const historyColl = db.collection('history_wge');
|
|
||||||
|
|
||||||
const results = await wgeColl.findOne({
|
|
||||||
$and: [
|
|
||||||
{ debug: false },
|
|
||||||
{ state: 'running' }
|
|
||||||
]
|
|
||||||
})
|
|
||||||
if (!results) {
|
|
||||||
return interaction.editReply({
|
|
||||||
content: 'No WGE Session currently running!',
|
|
||||||
flags: MessageFlags.Ephemeral
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const historyCount = await historyColl.countDocuments();
|
|
||||||
const iteration = historyCount + 1;
|
|
||||||
|
|
||||||
const createdAt = new Date(results.createdAt)
|
|
||||||
const expiresAt = new Date(createdAt.getTime() + Number(results.timeRemaining))
|
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setTitle(`✨ [${ordinal(iteration)}] World's Greatest Expert ✨`)
|
|
||||||
.setDescription(
|
|
||||||
`<@${results.assignedUser}> is currently the **World's Greatest Expert** in **${results.topic}**.\n\n` +
|
|
||||||
`They must submit their entry <t:${Math.floor(expiresAt.getTime() / 1000)}:R>.\n\n` +
|
|
||||||
`Thank you, <@${results.assigningUser}>, for the nomination!`
|
|
||||||
)
|
|
||||||
|
|
||||||
return interaction.editReply({
|
|
||||||
embeds: [embed]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
async function wgeStart(interaction) {
|
|
||||||
const defaultUsers = []
|
|
||||||
defaultUsers.push(process.env.D_ID)
|
|
||||||
|
|
||||||
|
|
||||||
const participantColl = db.collection('items_wge')
|
|
||||||
const participants = await participantColl.find({
|
|
||||||
status: true
|
|
||||||
}).toArray()
|
|
||||||
|
|
||||||
|
|
||||||
const wgeBaseModal = new ModalBuilder()
|
|
||||||
.setCustomId('wgeBaseModal')
|
|
||||||
.setTitle("World's Greatest Expert")
|
|
||||||
|
|
||||||
const options = [
|
|
||||||
{
|
|
||||||
label: 'RANDOM',
|
|
||||||
value: process.env.D_ID
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
const participantOptions = await Promise.all(
|
|
||||||
participants.map(async (participant) => {
|
|
||||||
try {
|
|
||||||
const member = await interaction.guild.members.fetch(participant.userID);
|
|
||||||
return {
|
|
||||||
label: `${member.displayName} (${member.user.username})`,
|
|
||||||
value: participant.userID
|
|
||||||
};
|
|
||||||
} catch {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
options.push(
|
|
||||||
...participantOptions.filter(option => option !== null)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Using StringSelectMenuBuilder because UserSelectMenuBuilder cannot be filtered for now
|
|
||||||
const wgeUserCustInput = new StringSelectMenuBuilder()
|
|
||||||
.setCustomId('wgeCustUserInput')
|
|
||||||
.setMaxValues(1)
|
|
||||||
.setMinValues(1)
|
|
||||||
.setRequired(true)
|
|
||||||
.addOptions(options)
|
|
||||||
|
|
||||||
const wgeTopicInput = new TextInputBuilder()
|
|
||||||
.setCustomId('wgeTopicInput')
|
|
||||||
.setStyle(TextInputStyle.Short)
|
|
||||||
.setRequired(true)
|
|
||||||
|
|
||||||
const wgeTopicLabel = new LabelBuilder()
|
|
||||||
.setLabel("And WHAT are they an expert in?")
|
|
||||||
.setDescription('Tell me!')
|
|
||||||
.setTextInputComponent(wgeTopicInput)
|
|
||||||
|
|
||||||
const wgeCustUserLabel = new LabelBuilder()
|
|
||||||
.setLabel('WHO is your greatest expert?')
|
|
||||||
.setDescription('Select them')
|
|
||||||
.setStringSelectMenuComponent(wgeUserCustInput)
|
|
||||||
|
|
||||||
wgeBaseModal
|
|
||||||
.addLabelComponents(wgeCustUserLabel, wgeTopicLabel)
|
|
||||||
|
|
||||||
await interaction.showModal(wgeBaseModal)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function wgeStop(interaction) {
|
|
||||||
;
|
|
||||||
const wgeColl = db.collection('timer_wge');
|
|
||||||
|
|
||||||
const timer = await wgeColl.findOne({
|
|
||||||
debug: false
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!timer) {
|
|
||||||
return interaction.reply({
|
|
||||||
content: 'Timer not found.',
|
|
||||||
flags: MessageFlags.Ephemeral
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// freeze remaining time
|
|
||||||
const remaining = getRemaining(timer);
|
|
||||||
|
|
||||||
await wgeColl.updateOne(
|
|
||||||
{ _id: timer._id },
|
|
||||||
{
|
|
||||||
$set: {
|
|
||||||
timeRemaining: remaining,
|
|
||||||
startedAt: null,
|
|
||||||
state: 'stopped'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
await interaction.reply({
|
|
||||||
content: `🛑 Timer stopped for **${timer.topic}**`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function wgeResume(interaction) {
|
|
||||||
;
|
|
||||||
const wgeColl = db.collection('timer_wge');
|
|
||||||
|
|
||||||
const timer = await wgeColl.findOne({
|
|
||||||
debug: false
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!timer) {
|
|
||||||
return interaction.reply({
|
|
||||||
content: 'Timer not found.',
|
|
||||||
flags: MessageFlags.Ephemeral
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// freeze remaining time
|
|
||||||
const remaining = getRemaining(timer);
|
|
||||||
|
|
||||||
await wgeColl.updateOne(
|
|
||||||
{ _id: timer._id },
|
|
||||||
{
|
|
||||||
$set: {
|
|
||||||
timeRemaining: remaining,
|
|
||||||
startedAt: Date.now(),
|
|
||||||
state: 'running'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
await interaction.reply({
|
|
||||||
content: `🟢 Timer resumed for **${timer.topic}**`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function wgeForfeit(interaction) {
|
|
||||||
;
|
|
||||||
const wgeColl = db.collection('timer_wge');
|
|
||||||
const participateColl = db.collection('items_wge');
|
|
||||||
|
|
||||||
// Get active WGE
|
|
||||||
const wge = await wgeColl.findOne({
|
|
||||||
debug: false,
|
|
||||||
state: 'running'
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!wge) {
|
|
||||||
return interaction.reply({
|
|
||||||
content: 'No active WGE is currently running.',
|
|
||||||
flags: MessageFlags.Ephemeral
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sanity check: only assigned user can forfeit
|
|
||||||
if (wge.assignedUser !== interaction.user.id) {
|
|
||||||
return interaction.reply({
|
|
||||||
content: `Only <@${wge.assignedUser}> can forfeit the current WGE.`,
|
|
||||||
flags: MessageFlags.Ephemeral
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pick a new participant, excluding current assignee
|
|
||||||
const [randomParticipant] = await participateColl.aggregate([
|
|
||||||
{
|
|
||||||
$match: {
|
|
||||||
status: true,
|
|
||||||
userID: { $ne: interaction.user.id }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ $sample: { size: 1 } }
|
|
||||||
]).toArray();
|
|
||||||
|
|
||||||
if (!randomParticipant) {
|
|
||||||
return interaction.reply({
|
|
||||||
content: 'No one else is participating!',
|
|
||||||
flags: MessageFlags.Ephemeral
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const member = await interaction.guild.members.fetch(
|
|
||||||
randomParticipant.userID
|
|
||||||
);
|
|
||||||
|
|
||||||
const nextUser = member.user;
|
|
||||||
|
|
||||||
const WGE_DURATION = 7 * 24 * 60 * 60 * 1000; // 7 days
|
|
||||||
|
|
||||||
await wgeColl.deleteOne({ _id: wge._id });
|
|
||||||
|
|
||||||
await wgeColl.insertOne({
|
|
||||||
assignedUser: nextUser.id,
|
|
||||||
assigningUser: wge.assigningUser,
|
|
||||||
|
|
||||||
startedAt: Date.now(),
|
|
||||||
timeRemaining: WGE_DURATION,
|
|
||||||
|
|
||||||
state: 'running',
|
|
||||||
|
|
||||||
notifications: {
|
|
||||||
half: false,
|
|
||||||
day24: false,
|
|
||||||
complete: false
|
|
||||||
},
|
|
||||||
|
|
||||||
topic: wge.topic,
|
|
||||||
debug: false,
|
|
||||||
|
|
||||||
createdAt: new Date()
|
|
||||||
});
|
|
||||||
|
|
||||||
return interaction.reply({
|
|
||||||
content: `${interaction.user} has forfeited! <@${nextUser.id}> is the next expert! Their topic is **${wge.topic}**`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function wgeParticipate(interaction) {
|
|
||||||
const status = interaction.options.getBoolean('status')
|
|
||||||
const user = interaction.user
|
|
||||||
|
|
||||||
const coll = db.collection('items_wge')
|
|
||||||
|
|
||||||
// Choice was false, ergo not participating
|
|
||||||
await coll.findOneAndUpdate({
|
|
||||||
userID: user.id
|
|
||||||
}, {
|
|
||||||
$set: {
|
|
||||||
userID: user.id,
|
|
||||||
status: status
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
upsert: true
|
|
||||||
})
|
|
||||||
|
|
||||||
interaction.reply({
|
|
||||||
content: `You are ${status ? '' : 'no longer '}participating!`,
|
|
||||||
flags: MessageFlags.Ephemeral
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
async function listParticipants(interaction) {
|
|
||||||
;
|
|
||||||
const participantColl = db.collection('items_wge');
|
|
||||||
const participants = await participantColl.find({}).toArray();
|
|
||||||
|
|
||||||
const participating = participants
|
|
||||||
.filter(p => p.status)
|
|
||||||
.map(p => `<@${p.userID}>`);
|
|
||||||
|
|
||||||
const notParticipating = participants
|
|
||||||
.filter(p => !p.status)
|
|
||||||
.map(p => `<@${p.userID}>`);
|
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setTitle('WGE Participation')
|
|
||||||
.setColor(0x5865F2)
|
|
||||||
.addFields(
|
|
||||||
{
|
|
||||||
name: `Participating (${participating.length})`,
|
|
||||||
value: participating.join('\n') || 'No participants found.',
|
|
||||||
inline: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: `Not Participating (${notParticipating.length})`,
|
|
||||||
value: notParticipating.join('\n') || 'No entries found.',
|
|
||||||
inline: true
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.setFooter({
|
|
||||||
text: `Total entries: ${participants.length}`
|
|
||||||
})
|
|
||||||
|
|
||||||
await interaction.reply({
|
|
||||||
embeds: [embed],
|
|
||||||
flags: MessageFlags.Ephemeral
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatDuration(ms) {
|
|
||||||
if (ms == null) return "unknown"
|
|
||||||
|
|
||||||
const totalSeconds = Math.floor(ms / 1000)
|
|
||||||
const days = Math.floor(totalSeconds / 86400)
|
|
||||||
const hours = Math.floor((totalSeconds % 86400) / 3600)
|
|
||||||
const minutes = Math.floor((totalSeconds % 3600) / 60)
|
|
||||||
const seconds = totalSeconds % 60
|
|
||||||
|
|
||||||
const parts = []
|
|
||||||
|
|
||||||
if (days) parts.push(`${days}d`)
|
|
||||||
if (hours) parts.push(`${hours}h`)
|
|
||||||
if (minutes) parts.push(`${minutes}m`)
|
|
||||||
if (seconds && !days) parts.push(`${seconds}s`) // only show seconds for short durations
|
|
||||||
|
|
||||||
return parts.length ? parts.join(" ") : "0s"
|
|
||||||
}
|
|
||||||
|
|
||||||
async function listHistory(interaction) {
|
|
||||||
const historyColl = db.collection('history_wge')
|
|
||||||
|
|
||||||
const wgeHistory = await historyColl
|
|
||||||
.find({ debug: false })
|
|
||||||
.sort({ createdAt: -1 })
|
|
||||||
.toArray()
|
|
||||||
|
|
||||||
if (!wgeHistory.length) {
|
|
||||||
return interaction.reply({
|
|
||||||
content: "No WGE history found.",
|
|
||||||
flags: MessageFlags.Ephemeral
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const buildEmbed = (entry, index) => {
|
|
||||||
const createdTs = entry.createdAt
|
|
||||||
? Math.floor(new Date(entry.createdAt).getTime() / 1000)
|
|
||||||
: null
|
|
||||||
|
|
||||||
return new EmbedBuilder()
|
|
||||||
.setTitle(`WGE History (${index + 1}/${wgeHistory.length})`)
|
|
||||||
.setDescription(
|
|
||||||
`<@${entry.assignedUser}> was the **World's Greatest Expert** of...\n\n` +
|
|
||||||
`**${entry.topic}**\n\n` +
|
|
||||||
|
|
||||||
`Assigned by: <@${entry.assigningUser}>\n` +
|
|
||||||
(createdTs ? `Created: <t:${createdTs}:R>` : "")
|
|
||||||
)
|
|
||||||
.setColor(0x2b2d31)
|
|
||||||
}
|
|
||||||
|
|
||||||
let page = 0
|
|
||||||
|
|
||||||
const row = new ActionRowBuilder().addComponents(
|
|
||||||
new ButtonBuilder()
|
|
||||||
.setCustomId('prev')
|
|
||||||
.setLabel('◀')
|
|
||||||
.setStyle(ButtonStyle.Secondary)
|
|
||||||
.setDisabled(true),
|
|
||||||
|
|
||||||
new ButtonBuilder()
|
|
||||||
.setCustomId('next')
|
|
||||||
.setLabel('▶')
|
|
||||||
.setStyle(ButtonStyle.Secondary)
|
|
||||||
.setDisabled(wgeHistory.length <= 1)
|
|
||||||
)
|
|
||||||
|
|
||||||
const msg = await interaction.reply({
|
|
||||||
embeds: [buildEmbed(wgeHistory[page], page)],
|
|
||||||
components: [row],
|
|
||||||
fetchReply: true
|
|
||||||
})
|
|
||||||
|
|
||||||
const collector = msg.createMessageComponentCollector({
|
|
||||||
componentType: ComponentType.Button,
|
|
||||||
time: 120000
|
|
||||||
})
|
|
||||||
|
|
||||||
collector.on('collect', async i => {
|
|
||||||
if (i.user.id !== interaction.user.id) {
|
|
||||||
return i.reply({
|
|
||||||
content: "You can't control this pagination.",
|
|
||||||
flags: MessageFlags.Ephemeral
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i.customId === 'prev') {
|
|
||||||
page--
|
|
||||||
} else if (i.customId === 'next') {
|
|
||||||
page++
|
|
||||||
}
|
|
||||||
|
|
||||||
page = Math.max(0, Math.min(page, wgeHistory.length - 1))
|
|
||||||
|
|
||||||
row.components[0].setDisabled(page === 0)
|
|
||||||
row.components[1].setDisabled(page === wgeHistory.length - 1)
|
|
||||||
|
|
||||||
await i.update({
|
|
||||||
embeds: [buildEmbed(wgeHistory[page], page)],
|
|
||||||
components: [row]
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
collector.on('end', async () => {
|
|
||||||
const disabledRow = new ActionRowBuilder().addComponents(
|
|
||||||
row.components.map(btn => ButtonBuilder.from(btn).setDisabled(true))
|
|
||||||
)
|
|
||||||
|
|
||||||
await msg.edit({ components: [disabledRow] }).catch(() => { })
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
async function wgeList(interaction) {
|
|
||||||
const thing = interaction.options.getString('thing');
|
|
||||||
|
|
||||||
switch (thing) {
|
|
||||||
case 'participants': {
|
|
||||||
listParticipants(interaction)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'history':
|
|
||||||
listHistory(interaction)
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
data: new SlashCommandBuilder()
|
|
||||||
.setName('wge')
|
|
||||||
.setDescription('welcome to worlds greatest experts')
|
|
||||||
// Show Status of Current Running WGE Session
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s
|
|
||||||
.setName('status')
|
|
||||||
.setDescription('display current wge session')
|
|
||||||
)
|
|
||||||
|
|
||||||
// Assign Someone to be the next Expert
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s
|
|
||||||
.setName('start')
|
|
||||||
.setDescription('start a new wge session')
|
|
||||||
)
|
|
||||||
|
|
||||||
// Stop the current Session Timer
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s
|
|
||||||
.setName('stop')
|
|
||||||
.setDescription('stop the current wge session')
|
|
||||||
)
|
|
||||||
|
|
||||||
// Resume the current Session Timer
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s
|
|
||||||
.setName('resume')
|
|
||||||
.setDescription('resume the current wge session timer')
|
|
||||||
)
|
|
||||||
|
|
||||||
// Forfeit your current expert topic and assign someone else
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s
|
|
||||||
.setName('forfeit')
|
|
||||||
.setDescription('forfeit your current topic')
|
|
||||||
)
|
|
||||||
|
|
||||||
// List the previous WGE Sessions
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s
|
|
||||||
.setName('history')
|
|
||||||
.setDescription('display the previous wge sessions')
|
|
||||||
)
|
|
||||||
|
|
||||||
// List the previous WGE Sessions
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s
|
|
||||||
.setName('participate')
|
|
||||||
.setDescription('do you want to play a game?')
|
|
||||||
.addBooleanOption(o =>
|
|
||||||
o.setName('status')
|
|
||||||
.setDescription('choose')
|
|
||||||
.setRequired(true)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
// List the previous WGE Sessions
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s
|
|
||||||
.setName('list')
|
|
||||||
.setDescription('list things')
|
|
||||||
.addStringOption(o =>
|
|
||||||
o.setName('thing')
|
|
||||||
.setDescription('what would you like to be listed')
|
|
||||||
.addChoices(
|
|
||||||
{ name: 'participants', value: 'participants' },
|
|
||||||
{ name: 'history', value: 'history' }
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
,
|
|
||||||
async execute(interaction) {
|
|
||||||
switch (interaction.options._subcommand) {
|
|
||||||
case 'status':
|
|
||||||
await interaction.deferReply()
|
|
||||||
wgeStatus(interaction)
|
|
||||||
break;
|
|
||||||
case 'start':
|
|
||||||
wgeStart(interaction)
|
|
||||||
break;
|
|
||||||
case 'stop':
|
|
||||||
wgeStop(interaction)
|
|
||||||
break;
|
|
||||||
case 'pause':
|
|
||||||
wgePause(interaction)
|
|
||||||
break;
|
|
||||||
case 'resume':
|
|
||||||
wgeResume(interaction)
|
|
||||||
break;
|
|
||||||
case 'forfeit':
|
|
||||||
wgeForfeit(interaction)
|
|
||||||
break;
|
|
||||||
case 'history':
|
|
||||||
wgeHistory(interaction)
|
|
||||||
break;
|
|
||||||
case 'participate':
|
|
||||||
wgeParticipate(interaction)
|
|
||||||
break;
|
|
||||||
case 'list':
|
|
||||||
wgeList(interaction)
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
const { SlashCommandBuilder } = require("discord.js");
|
|
||||||
|
|
||||||
function askMyBalls() {
|
|
||||||
var answers = [
|
|
||||||
'Absolut, so wie die Authorität unserer Göttin!',
|
|
||||||
'Unterschätze es nicht, genauso wie Roberts sexual frustration',
|
|
||||||
'Ich zedaz so',
|
|
||||||
'Ohne Zweifel',
|
|
||||||
'Definitiv, Alter',
|
|
||||||
'Microsoft Outlook gut',
|
|
||||||
'Das Sternzeichen von Yeesh leuchtet heute stark dafür',
|
|
||||||
'Mit "Support-Desk am Freitagabend" - Wahrscheinlichkeit',
|
|
||||||
'Ist die Nase von Julius wunderschön und lang?',
|
|
||||||
'So wahr wie Laviis Zeichnkünste',
|
|
||||||
'nein...ja... vielleicht?',
|
|
||||||
'Frag mich nachher nochmal',
|
|
||||||
'Die Kalkulationen sind leicht off, ich aber nicht ;)',
|
|
||||||
'Ich sag es dir ein ander Mal',
|
|
||||||
'Ohne schwere Zeiten, würden wir die guten Zeiten nie schätzen',
|
|
||||||
'Genauso schlecht wie eine Ketzerei gegen den Olymp',
|
|
||||||
'Hat der Fuchs uns jemals verraten?...**hust**',
|
|
||||||
'Mein Outlook ist abgeschmiert, mist',
|
|
||||||
'Ich bezweifle es. A propos, zweifel nicht an den Götter und ihren Priester!',
|
|
||||||
'Meine Quellen sagen.... WARNUNG! Artikel 17: Die betroffene Person hat das Recht, von dem Verantwortlichen zu verlangen, dass sie betreffende personenbezogene Daten unverzüglich gelöscht werden, und der Verantwortliche ist verpflichtet, personenbezogene Daten unverzüglich zu löschen, sofern einer der folgenden Gründe zutrifft **ERROR ERROR ERROR**?'
|
|
||||||
]
|
|
||||||
const r = Math.floor(Math.random() * answers.length)
|
|
||||||
|
|
||||||
return answers[r]
|
|
||||||
}
|
|
||||||
|
|
||||||
function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
data: new SlashCommandBuilder()
|
|
||||||
.setName('8ball')
|
|
||||||
.setDescription('dont ask me anything')
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s.setName('ask')
|
|
||||||
.setDescription('what do you want to know?')
|
|
||||||
.addStringOption(
|
|
||||||
o => o.setName('question').setDescription('ask away!').setRequired(true))
|
|
||||||
),
|
|
||||||
async execute(interaction) {
|
|
||||||
await interaction.deferReply()
|
|
||||||
await delay(2000)
|
|
||||||
await interaction.editReply(askMyBalls())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
const { SlashCommandBuilder, EmbedBuilder, AttachmentBuilder } = require("discord.js");
|
|
||||||
|
|
||||||
async function doggoPet(interaction) {
|
|
||||||
|
|
||||||
const responses = [
|
|
||||||
'*loving growl*',
|
|
||||||
'Danke, das habe ich gebraucht.',
|
|
||||||
'Ein bisschen tiefer.',
|
|
||||||
'Ja, genau dort!'
|
|
||||||
]
|
|
||||||
var r = Math.floor(Math.random() * responses.length)
|
|
||||||
|
|
||||||
const filePath = `assets/Command_Doggo/doggo.jpg`;
|
|
||||||
|
|
||||||
const attachment = new AttachmentBuilder(filePath);
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setDescription(responses[r])
|
|
||||||
.setColor(0x51267)
|
|
||||||
.setTimestamp()
|
|
||||||
.setImage(`attachment://doggo.jpg`);
|
|
||||||
|
|
||||||
await interaction.editReply({
|
|
||||||
embeds: [embed],
|
|
||||||
files: [attachment]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
async function doggoFeed(interaction) {
|
|
||||||
await interaction.editReply({
|
|
||||||
content: 'WIP placeholder'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
async function doggoWalk(interaction) {
|
|
||||||
await interaction.editReply({
|
|
||||||
content: 'WIP placeholder'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
async function doggoPlay(interaction) {
|
|
||||||
await interaction.editReply({
|
|
||||||
content: 'WIP placeholder'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
data: new SlashCommandBuilder()
|
|
||||||
.setName('doggo')
|
|
||||||
.setDescription('who is a good boi?')
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s.setName('pet')
|
|
||||||
.setDescription('beeg scratch')
|
|
||||||
)
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s.setName('feed')
|
|
||||||
.setDescription('tastge')
|
|
||||||
)
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s.setName('walk')
|
|
||||||
.setDescription('walkies')
|
|
||||||
)
|
|
||||||
.addSubcommand(s =>
|
|
||||||
s.setName('play')
|
|
||||||
.setDescription('fun time')
|
|
||||||
),
|
|
||||||
async execute(interaction) {
|
|
||||||
await interaction.deferReply()
|
|
||||||
switch (interaction.options._subcommand) {
|
|
||||||
case 'pet':
|
|
||||||
doggoPet(interaction)
|
|
||||||
break;
|
|
||||||
case 'feed':
|
|
||||||
doggoFeed(interaction)
|
|
||||||
break;
|
|
||||||
case 'walk':
|
|
||||||
doggoWalk(interaction)
|
|
||||||
break;
|
|
||||||
case 'play':
|
|
||||||
doggoPlay(interaction)
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
const { SlashCommandBuilder, AttachmentBuilder, EmbedBuilder } = require('discord.js');
|
|
||||||
const fs = require('fs/promises');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
async function makeDay() {
|
|
||||||
const date = new Date();
|
|
||||||
|
|
||||||
const tage = [
|
|
||||||
'sonntag',
|
|
||||||
'montag',
|
|
||||||
'dienstag',
|
|
||||||
'mittwoch',
|
|
||||||
'donnerstag',
|
|
||||||
'freitag',
|
|
||||||
'samstag'
|
|
||||||
];
|
|
||||||
|
|
||||||
const text = {
|
|
||||||
montag: 'Es ist Montag meine Münmler!',
|
|
||||||
mittwoch: 'Es ist Mittwoch meine Kerle!',
|
|
||||||
donnerstag: 'Es ist nicht mehr Mittwoch meine Kerle!',
|
|
||||||
freitag: 'Es ist Freitag meine Kerl*innen!',
|
|
||||||
default: 'Es ist nicht Mittwoch, meine Kerle...'
|
|
||||||
};
|
|
||||||
|
|
||||||
const today = tage[date.getDay()];
|
|
||||||
|
|
||||||
let files;
|
|
||||||
try {
|
|
||||||
files = await fs.readdir('assets/Command_Mittwoch');
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
return { filename: 'nicht_mittwoch', content: text.default };
|
|
||||||
}
|
|
||||||
|
|
||||||
const available = files.map(f => path.parse(f).name);
|
|
||||||
|
|
||||||
if (available.includes(today)) {
|
|
||||||
return {
|
|
||||||
filename: today,
|
|
||||||
content: text[today] || text.default
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
filename: 'nicht_mittwoch',
|
|
||||||
content: text.default
|
|
||||||
};
|
|
||||||
}
|
|
||||||
module.exports = {
|
|
||||||
data: new SlashCommandBuilder()
|
|
||||||
.setName('mittwoch')
|
|
||||||
.setDescription('mittwoch vibes'),
|
|
||||||
|
|
||||||
async execute(interaction) {
|
|
||||||
const { filename, content } = await makeDay();
|
|
||||||
|
|
||||||
const filePath = `assets/Command_Mittwoch/${filename}.jpg`;
|
|
||||||
|
|
||||||
const attachment = new AttachmentBuilder(filePath);
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
.setTitle(content)
|
|
||||||
.setColor(0x51267)
|
|
||||||
.setTimestamp()
|
|
||||||
.setImage(`attachment://${filename}.jpg`);
|
|
||||||
|
|
||||||
await interaction.reply({
|
|
||||||
embeds: [embed],
|
|
||||||
files: [attachment]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
const { createCanvas, loadImage } = require('canvas');
|
|
||||||
const path = require('node:path');
|
|
||||||
const { mClient } = require('..');
|
|
||||||
require('dotenv').configDotenv();
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
name: "Birthday",
|
|
||||||
once: false,
|
|
||||||
async execute(member, client) {
|
|
||||||
console.log(`${member.user.username} hat Geburtstag!`)
|
|
||||||
let found = null
|
|
||||||
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const channelsColl = db.collection('config_channels')
|
|
||||||
found = await channelsColl.find(
|
|
||||||
{
|
|
||||||
$and: [
|
|
||||||
{ guildID: member.guild.id },
|
|
||||||
{ purpose: 'birthday' }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
).toArray()
|
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
return console.log('Channel not yet set for birthday!')
|
|
||||||
}
|
|
||||||
|
|
||||||
const guild = client.guilds.cache.get(found[0].guildID);
|
|
||||||
const channel = guild.channels.cache.get(found[0].channelID);
|
|
||||||
const roleColl = db.collection('config_roles')
|
|
||||||
|
|
||||||
// Bot Role MUST BE above birthday Role, Birthday Role MUST BE above user roles
|
|
||||||
found = await roleColl.findOne({guildID: member.guild.id})
|
|
||||||
const role = guild.roles.cache.get(found.roleID)
|
|
||||||
|
|
||||||
try {
|
|
||||||
await member.roles.add(role)
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error)
|
|
||||||
}
|
|
||||||
// Create Canvas
|
|
||||||
let canvasWidth = 600;
|
|
||||||
let canvasHeight = 250;
|
|
||||||
const canvas = new createCanvas(canvasWidth, canvasHeight);
|
|
||||||
const ctx = canvas.getContext('2d');
|
|
||||||
|
|
||||||
// Draw Initial Image
|
|
||||||
const background = await loadImage(
|
|
||||||
path.join(__dirname, '../assets/Event_Birthday/bdbanner.png')
|
|
||||||
);
|
|
||||||
let x = 0;
|
|
||||||
let y = 0;
|
|
||||||
ctx.drawImage(background, x, y);
|
|
||||||
|
|
||||||
// Create Profile Picture
|
|
||||||
const pfp = await loadImage(
|
|
||||||
member.user.displayAvatarURL({
|
|
||||||
extension: 'jpg',
|
|
||||||
size: 64,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
// Draw Profile Picture on Top of Background
|
|
||||||
x = canvas.width / 2 - pfp.width / 2;
|
|
||||||
y = 20;
|
|
||||||
ctx.drawImage(pfp, x, y);
|
|
||||||
|
|
||||||
// Set styles for text
|
|
||||||
ctx.font = '35px sans-serif';
|
|
||||||
ctx.fillStyle = '#FFC0CB'; // Pink text
|
|
||||||
ctx.strokeStyle = '#000000'; // Black outline
|
|
||||||
ctx.lineWidth = 3; // Thickness of the outline
|
|
||||||
|
|
||||||
let text = `Alles Gute zum Geburtstag! `;
|
|
||||||
let textWidth = ctx.measureText(text).width;
|
|
||||||
let textX = canvas.width / 2 - textWidth / 2;
|
|
||||||
let textHeight = 35; // Approximate height of the text
|
|
||||||
|
|
||||||
// Draw the text with black outline
|
|
||||||
ctx.strokeText(text, textX, 60 + pfp.height);
|
|
||||||
ctx.fillText(text, textX, 60 + pfp.height);
|
|
||||||
|
|
||||||
// requires apt-get install ttf-ancient-fonts
|
|
||||||
ctx.font = '30px "Noto Emoji", "Segoe UI Emoji", "Apple Color Emoji", sans-serif';
|
|
||||||
text = `🎉 ${member.user.globalName ? member.user.globalName : member.user.username} 🎉`;
|
|
||||||
textWidth = ctx.measureText(text).width;
|
|
||||||
textX = canvas.width / 2 - textWidth / 2;
|
|
||||||
textHeight = 30; // Approximate height of the text
|
|
||||||
|
|
||||||
// Draw the second line of text with black outline
|
|
||||||
ctx.strokeText(text, textX, 100 + pfp.height);
|
|
||||||
ctx.fillText(text, textX, 100 + pfp.height);
|
|
||||||
|
|
||||||
const banner = canvas.toBuffer();
|
|
||||||
|
|
||||||
channel.send({
|
|
||||||
content: `@here`,
|
|
||||||
files: [{
|
|
||||||
attachment: banner,
|
|
||||||
name: 'banner.png',
|
|
||||||
description: 'a birthday banner'
|
|
||||||
}]
|
|
||||||
});
|
|
||||||
|
|
||||||
// mark as notified
|
|
||||||
|
|
||||||
const bdayColl = db.collection('items_birthdays')
|
|
||||||
await bdayColl.findOneAndUpdate({
|
|
||||||
userID: member.user.id
|
|
||||||
}, {
|
|
||||||
$set: {
|
|
||||||
notified: true
|
|
||||||
}
|
|
||||||
},{
|
|
||||||
upsert: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
const { Events, ActivityType } = require('discord.js');
|
|
||||||
const { mClient } = require('..');
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
name: Events.ClientReady,
|
|
||||||
once: true,
|
|
||||||
async execute(client) {
|
|
||||||
console.log(`Ready! Logged in as ${client.user.tag}`);
|
|
||||||
|
|
||||||
// Set presence
|
|
||||||
client.user.setPresence({
|
|
||||||
activities: [{
|
|
||||||
name: 'Red Dead Depression',
|
|
||||||
type: ActivityType.Streaming,
|
|
||||||
url: 'https://twitch.tv/desq_blocki'
|
|
||||||
}],
|
|
||||||
status: 'online'
|
|
||||||
});
|
|
||||||
|
|
||||||
// Check if a date matches today
|
|
||||||
const isToday = (day, month) => {
|
|
||||||
const today = new Date();
|
|
||||||
return today.getDate() === day && today.getMonth() === month - 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle birthdays
|
|
||||||
const handleBirthdays = async () => {
|
|
||||||
const guild = await client.guilds.fetch(process.env.D_GuildID);
|
|
||||||
const db = mClient.db(process.env.M_DB);
|
|
||||||
|
|
||||||
const bdayColl = db.collection('items_birthdays');
|
|
||||||
const allBirthdays = await bdayColl.find().toArray();
|
|
||||||
const bdayMap = new Map(allBirthdays.map(b => [b.userID, b]));
|
|
||||||
|
|
||||||
// Fetch birthday role
|
|
||||||
const bdayRoleColl = db.collection('config_roles');
|
|
||||||
const bdayRoleEntry = await bdayRoleColl.findOne({ guildID: guild.id });
|
|
||||||
const birthdayRoleID = bdayRoleEntry?.roleID;
|
|
||||||
|
|
||||||
if (!birthdayRoleID) {
|
|
||||||
console.warn("No birthday role configured in DB");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch all guild members
|
|
||||||
const members = await guild.members.fetch();
|
|
||||||
|
|
||||||
for (const member of members.values()) {
|
|
||||||
const dbEntry = bdayMap.get(member.id);
|
|
||||||
|
|
||||||
if (!dbEntry) continue;
|
|
||||||
|
|
||||||
// Reset notification once the birthday has passed
|
|
||||||
if (!isToday(dbEntry.day, dbEntry.month) && dbEntry.notified) {
|
|
||||||
await bdayColl.updateOne(
|
|
||||||
{ userID: member.id },
|
|
||||||
{ $set: { notified: false } }
|
|
||||||
);
|
|
||||||
|
|
||||||
dbEntry.notified = false; // keep local copy in sync
|
|
||||||
console.log(`Removed notified flag for ${member.user.tag}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip if already handled today
|
|
||||||
if (dbEntry.notified && isToday(dbEntry.day, dbEntry.month)) {
|
|
||||||
console.log(`${member.user.username} was already notified today, skipping...`);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isToday(dbEntry.day, dbEntry.month)) {
|
|
||||||
await member.roles.add(birthdayRoleID).catch(err =>
|
|
||||||
console.error(`Failed to add birthday role to ${member.user.tag}:`, err)
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log(`Added birthday role to ${member.user.tag}`);
|
|
||||||
client.emit('Birthday', member);
|
|
||||||
|
|
||||||
// mark as notified
|
|
||||||
await bdayColl.updateOne(
|
|
||||||
{ userID: member.id },
|
|
||||||
{ $set: { notified: true } }
|
|
||||||
);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (member.roles.cache.has(birthdayRoleID)) {
|
|
||||||
await member.roles.remove(birthdayRoleID).catch(err =>
|
|
||||||
console.error(`Failed to remove birthday role from ${member.user.tag}:`, err)
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log(`Removed birthday role from ${member.user.tag}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
await handleBirthdays();
|
|
||||||
|
|
||||||
// First check after restart
|
|
||||||
client.emit('timerCheck');
|
|
||||||
|
|
||||||
// Check every minute
|
|
||||||
setInterval(() => {
|
|
||||||
client.emit('timerCheck');
|
|
||||||
}, 60_000);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
const { Events } = require('discord.js');
|
|
||||||
const { createCanvas, loadImage } = require('canvas');
|
|
||||||
const path = require('node:path');
|
|
||||||
const { mClient } = require('..');
|
|
||||||
require('dotenv').configDotenv();
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
name: Events.GuildMemberAdd,
|
|
||||||
once: false,
|
|
||||||
async execute(member, client) {
|
|
||||||
console.log(`${member.user.username} joined the Server`);
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const channelsColl = db.collection('config_channels')
|
|
||||||
const found = await channelsColl.find(
|
|
||||||
{
|
|
||||||
$and: [
|
|
||||||
{ guildID: member.guild.id },
|
|
||||||
{ purpose: 'welcome' }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
).toArray()
|
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
return console.log('Channel not yet set for welcome!')
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const guild = client.guilds.cache.get(found[0].guildID);
|
|
||||||
const channel = guild.channels.cache.get(found[0].channelID);
|
|
||||||
|
|
||||||
// Create Canvas
|
|
||||||
let canvasWidth = 600;
|
|
||||||
let canvasHeight = 250;
|
|
||||||
const canvas = new createCanvas(canvasWidth, canvasHeight);
|
|
||||||
const ctx = canvas.getContext('2d');
|
|
||||||
|
|
||||||
// Draw Initial Image
|
|
||||||
const background = await loadImage(
|
|
||||||
path.join(__dirname, '../assets/Event_MemberJoin/background.png')
|
|
||||||
);
|
|
||||||
let x = 0;
|
|
||||||
let y = 0;
|
|
||||||
ctx.drawImage(background, x, y);
|
|
||||||
|
|
||||||
// Create Profile Picture
|
|
||||||
const pfp = await loadImage(
|
|
||||||
member.user.displayAvatarURL({
|
|
||||||
extension: 'jpg',
|
|
||||||
size: 64,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
// Draw Profile Picture on Top of Background
|
|
||||||
x = canvas.width / 2 - pfp.width / 2;
|
|
||||||
y = 20;
|
|
||||||
ctx.drawImage(pfp, x, y);
|
|
||||||
|
|
||||||
// Set styles for text
|
|
||||||
ctx.font = '35px sans-serif';
|
|
||||||
ctx.fillStyle = '#ffffff'; // White text
|
|
||||||
ctx.strokeStyle = '#000000'; // Black outline
|
|
||||||
ctx.lineWidth = 3; // Thickness of the outline
|
|
||||||
|
|
||||||
let text = `Willkommen, ${member.user.globalName?member.user.globalName:member.user.username}!`;
|
|
||||||
let textWidth = ctx.measureText(text).width;
|
|
||||||
let textX = canvas.width / 2 - textWidth / 2;
|
|
||||||
let textHeight = 35; // Approximate height of the text
|
|
||||||
|
|
||||||
// Draw the text with black outline
|
|
||||||
ctx.strokeText(text, textX, 60 + pfp.height);
|
|
||||||
ctx.fillText(text, textX, 60 + pfp.height);
|
|
||||||
|
|
||||||
ctx.font = '30px sans-serif';
|
|
||||||
text = `auf dem ✨Olymp✨`;
|
|
||||||
textWidth = ctx.measureText(text).width;
|
|
||||||
textX = canvas.width / 2 - textWidth / 2;
|
|
||||||
textHeight = 30; // Approximate height of the text
|
|
||||||
|
|
||||||
// Draw the second line of text with black outline
|
|
||||||
ctx.strokeText(text, textX, 100 + pfp.height);
|
|
||||||
ctx.fillText(text, textX, 100 + pfp.height);
|
|
||||||
const banner = canvas.toBuffer();
|
|
||||||
|
|
||||||
channel.send({
|
|
||||||
content: `Bitte guck einmal in die <#455023824791011338> ${member}`,
|
|
||||||
files: [{
|
|
||||||
attachment: banner,
|
|
||||||
name: 'banner.png',
|
|
||||||
description: 'a welcome banner'
|
|
||||||
}]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,157 +0,0 @@
|
|||||||
const { Events, MessageFlags, Message } = require('discord.js')
|
|
||||||
const { mClient } = require('../index')
|
|
||||||
require('dotenv').config()
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
name: Events.InteractionCreate,
|
|
||||||
once: false,
|
|
||||||
async execute(interaction) {
|
|
||||||
if (interaction.isChatInputCommand()) { commandHandler(interaction) }
|
|
||||||
if (interaction.isButton()) { buttonHandler(interaction) }
|
|
||||||
if (interaction.isMentionableSelectMenu()) { selectMenuHandler(interaction) }
|
|
||||||
if (interaction.isUserSelectMenu()) { selectMenuHandler(interaction) }
|
|
||||||
if (interaction.isModalSubmit()) { modalSubmitHandler(interaction) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async function commandHandler(interaction) {
|
|
||||||
const command = interaction.client.commands.get(interaction.commandName);
|
|
||||||
|
|
||||||
if (!command) {
|
|
||||||
console.error(`No command matching ${interaction.commandName} was found.`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
await command.execute(interaction);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
if (interaction.replied || interaction.deferred) {
|
|
||||||
await interaction.followUp({ content: 'There was an error while executing this command!', flags: MessageFlags.Ephemeral });
|
|
||||||
} else {
|
|
||||||
await interaction.reply({ content: 'There was an error while executing this command!', flags: MessageFlags.Ephemeral });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async function buttonHandler(interaction) {
|
|
||||||
const button = interaction.client.buttons.get(interaction.customId)
|
|
||||||
if (!button) { return }// console.error(`No button registered matching ${interaction.customId}.`) }
|
|
||||||
try {
|
|
||||||
await button.execute(interaction);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
if (interaction.replied || interaction.deferred) {
|
|
||||||
await interaction.followUp({ content: 'There was an error while executing this command!', flags: MessageFlags.Ephemeral });
|
|
||||||
} else {
|
|
||||||
await interaction.reply({ content: 'There was an error while executing this command!', flags: MessageFlags.Ephemeral });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async function selectMenuHandler(interaction) {
|
|
||||||
const selectMenu = interaction.client.selectMenus.get(interaction.customId)
|
|
||||||
if (!selectMenu) { return console.error(`No Select Menu registered matching ${interaction.customId}.`) }
|
|
||||||
try {
|
|
||||||
await selectMenu.execute(interaction);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
if (interaction.replied || interaction.deferred) {
|
|
||||||
await interaction.followUp({ content: 'There was an error while executing this command!', flags: MessageFlags.Ephemeral });
|
|
||||||
} else {
|
|
||||||
await interaction.reply({ content: 'There was an error while executing this command!', flags: MessageFlags.Ephemeral });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async function modalSubmitHandler(interaction) {
|
|
||||||
if (interaction.customId === 'wgeBaseModal') {
|
|
||||||
const db = mClient.db('neo-db')
|
|
||||||
const wgeColl = db.collection('timer_wge')
|
|
||||||
const participateColl = db.collection('items_wge')
|
|
||||||
|
|
||||||
// Get the data entered by the user
|
|
||||||
|
|
||||||
var wgeAssignedUser = {}
|
|
||||||
wgeAssignedUser.id = interaction.components[0].component.values[0]
|
|
||||||
|
|
||||||
const wgeAssigningUser = interaction.user
|
|
||||||
if (wgeAssignedUser.id === process.env.D_ID) {
|
|
||||||
// Randomizer Function
|
|
||||||
const randomParticipant = await participateColl.aggregate([
|
|
||||||
{ $match: { status: true } },
|
|
||||||
{ $sample: { size: 1 } }
|
|
||||||
]).toArray()
|
|
||||||
|
|
||||||
if (!randomParticipant) { return interaction.followUp({ content: 'No User is participating!' }) }
|
|
||||||
|
|
||||||
random = await interaction.guild.members.fetch(randomParticipant[0].userID)
|
|
||||||
wgeAssignedUser = random.user
|
|
||||||
} else {
|
|
||||||
// validate non-random user
|
|
||||||
const foundParticipant = await participateColl.findOne({
|
|
||||||
$and: [
|
|
||||||
{ assignedUser: wgeAssignedUser.id },
|
|
||||||
{ status: true}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
|
|
||||||
if(!foundParticipant || foundParticipant == null){ return interaction.reply({
|
|
||||||
content: `<@${wgeAssignedUser.id}> is not participating!`,
|
|
||||||
flags: MessageFlags.Ephemeral
|
|
||||||
})}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const prevWge = await wgeColl.findOne({
|
|
||||||
$and: [
|
|
||||||
{ debug: false },
|
|
||||||
{ state: 'running' }
|
|
||||||
]
|
|
||||||
})
|
|
||||||
|
|
||||||
if (prevWge != null) {
|
|
||||||
// Save previous run in history_wge
|
|
||||||
const historyWgeColl = db.collection('history_wge')
|
|
||||||
await historyWgeColl.insertOne({
|
|
||||||
assignedUser: prevWge.assignedUser,
|
|
||||||
assigningUser: prevWge.assigningUser,
|
|
||||||
timeRemaining: prevWge.timeRemaining,
|
|
||||||
topic: prevWge.topic,
|
|
||||||
debug: prevWge.debug,
|
|
||||||
createdAt: prevWge.createdAt
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log({
|
|
||||||
message: 'saved previous wge in history_wge',
|
|
||||||
data: prevWge
|
|
||||||
})
|
|
||||||
|
|
||||||
await wgeColl.deleteOne({
|
|
||||||
_id: prevWge._id
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const wgeAssignedTopic = interaction.fields.getTextInputValue('wgeTopicInput');
|
|
||||||
|
|
||||||
const wgeDefaultAssignedTime = 7 * 24 * 60 * 60 * 1000; // 7 days in ms
|
|
||||||
|
|
||||||
await wgeColl.insertOne({
|
|
||||||
assignedUser: wgeAssignedUser.id,
|
|
||||||
assigningUser: wgeAssigningUser.id,
|
|
||||||
|
|
||||||
startedAt: Date.now(),
|
|
||||||
timeRemaining: wgeDefaultAssignedTime,
|
|
||||||
|
|
||||||
state: 'running',
|
|
||||||
|
|
||||||
notifications: {
|
|
||||||
half: false,
|
|
||||||
day24: false,
|
|
||||||
complete: false
|
|
||||||
},
|
|
||||||
|
|
||||||
topic: wgeAssignedTopic,
|
|
||||||
debug: false,
|
|
||||||
|
|
||||||
createdAt: new Date()
|
|
||||||
});
|
|
||||||
|
|
||||||
return interaction.reply({ content: `<@${wgeAssignedUser.id}> is the next expert! Their topic is **${wgeAssignedTopic}**` })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
const { Events, MessageFlags } = require('discord.js')
|
|
||||||
require('dotenv').config()
|
|
||||||
const { client, mClient } = require('../index')
|
|
||||||
const prefix = process.env.D_Prefix
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
name: Events.MessageCreate,
|
|
||||||
once: false,
|
|
||||||
async execute(message) {
|
|
||||||
if (message.author.bot) { return }
|
|
||||||
|
|
||||||
// Erster/Zweiter/Dritter Handler
|
|
||||||
if (message.channelId === '353902391021535244' || message.channelId === '471058991481487361') {
|
|
||||||
const numbered = {
|
|
||||||
Erst: "Ersti",
|
|
||||||
Zweit: "Zweiti",
|
|
||||||
Dritt: "Dritti"
|
|
||||||
};
|
|
||||||
|
|
||||||
const found = Object.entries(numbered).find(([stem]) =>
|
|
||||||
new RegExp(`\\b\\w*${stem}\\w*\\b`, "i").test(message.content)
|
|
||||||
)?.[1];
|
|
||||||
|
|
||||||
if (!found) return;
|
|
||||||
|
|
||||||
const numberedColl = db.collection('items_daily_numbers');
|
|
||||||
const today = new Date().toLocaleDateString("en-CA", {
|
|
||||||
timeZone: "Europe/Berlin"
|
|
||||||
});
|
|
||||||
|
|
||||||
// Tages-Dokument sicherstellen
|
|
||||||
await numberedColl.findOneAndUpdate(
|
|
||||||
{ date: today },
|
|
||||||
{
|
|
||||||
$setOnInsert: {
|
|
||||||
date: today,
|
|
||||||
positions: {
|
|
||||||
Ersti: null,
|
|
||||||
Zweiti: null,
|
|
||||||
Dritti: null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ upsert: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
// 🔒 Atomarer Claim:
|
|
||||||
// - Position muss frei sein
|
|
||||||
// - User darf noch keine Position heute haben
|
|
||||||
const result = await numberedColl.findOneAndUpdate(
|
|
||||||
{
|
|
||||||
date: today,
|
|
||||||
[`positions.${found}`]: null,
|
|
||||||
|
|
||||||
"positions.Ersti.userId": { $ne: message.author.id },
|
|
||||||
"positions.Zweiti.userId": { $ne: message.author.id },
|
|
||||||
"positions.Dritti.userId": { $ne: message.author.id }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
$set: {
|
|
||||||
[`positions.${found}`]: {
|
|
||||||
userId: message.author.id,
|
|
||||||
timestamp: new Date()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ returnDocument: "after" }
|
|
||||||
);
|
|
||||||
|
|
||||||
// ❌ bereits vergeben oder schon eine Position
|
|
||||||
if (!result) {
|
|
||||||
return message.reply({
|
|
||||||
content: `❌ Du kannst pro Tag nur eine Position beanspruchen, und sie muss noch frei sein.`,
|
|
||||||
flags: MessageFlags.Ephemeral
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// ✅ Erfolg
|
|
||||||
return message.reply({
|
|
||||||
content: `✅ Du bist ${found}! :point_right: :point_left: <@${message.author.id}>`,
|
|
||||||
flags: MessageFlags.Ephemeral
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command Handler
|
|
||||||
const args = message.content.slice(prefix.length).trim().split(/ +/);
|
|
||||||
if (!message.content.startsWith(prefix)) return;
|
|
||||||
|
|
||||||
const cmd = args.shift().toLowerCase();
|
|
||||||
let command = client.legacyCommands.get(cmd)
|
|
||||||
|
|
||||||
|
|
||||||
if (!command) command = client.legacyCommands.get(client.aliases.get(cmd))
|
|
||||||
if (!command) return
|
|
||||||
try {
|
|
||||||
client.legacyCommands.get(command.name).execute(message, args)
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
// const { Events, ClientVoiceManager } = require("discord.js");
|
|
||||||
// const { getVoiceConnection } = require('@discordjs/voice')
|
|
||||||
// require('dotenv').config()
|
|
||||||
// const { client } = require('../index');
|
|
||||||
// const users_in_afk = new Set();
|
|
||||||
// const delay = ms => new Promise(res => setTimeout(res, ms));
|
|
||||||
// var connected = false;
|
|
||||||
// const url = `https://www.youtube.com/watch?v=Y4ySxP_IptE`
|
|
||||||
|
|
||||||
// module.exports = {
|
|
||||||
// name: Events.VoiceStateUpdate,
|
|
||||||
// once: false,
|
|
||||||
// async execute(oldState, newState) {
|
|
||||||
// const guild = client.guilds.cache.get(process.env.D_GuildID)
|
|
||||||
// const afk_channel = await guild.channels.fetch(guild.afkChannelId)
|
|
||||||
// const real_afk_channel = await guild.channels.fetch(process.env.D_RealTartarosID)
|
|
||||||
// const user = await guild.members.fetch(newState.id)
|
|
||||||
|
|
||||||
// if(user.id === process.env.D_ID) return;
|
|
||||||
|
|
||||||
// // if someone enters the official AFK channel, move them to one where we can play music
|
|
||||||
// if (newState.channelId === afk_channel.id) {
|
|
||||||
// await delay(1000)
|
|
||||||
|
|
||||||
// await user.voice.setChannel(real_afk_channel)
|
|
||||||
|
|
||||||
// users_in_afk.add(newState.id)
|
|
||||||
// console.log(`${users_in_afk.size} User(s) in Channel`)
|
|
||||||
|
|
||||||
// if (!connected) {
|
|
||||||
// connected = true;
|
|
||||||
// await client.distube.voices.join(real_afk_channel)
|
|
||||||
// await user.voice.setSuppressed(true) // mute user?
|
|
||||||
// await guild.members.me.voice.setSuppressed(false); //unmute self
|
|
||||||
// await client.distube.play(real_afk_channel, url, {
|
|
||||||
// member: newState.member,
|
|
||||||
// })
|
|
||||||
// //const queue = client.distube.getQueue(guild)
|
|
||||||
// //await queue.setRepeatMode(2)
|
|
||||||
// //await queue.setVolume(40)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // if someone leaves the real AFK channel, remove them from cache but wait for rejoiners, then leave if none are here
|
|
||||||
// if (oldState.channelId === real_afk_channel.id && oldState.channelId != newState.channelId) {
|
|
||||||
// users_in_afk.delete(oldState.id)
|
|
||||||
// const user = await guild.members.fetch(oldState.id)
|
|
||||||
// //await user.voice.setMute(false) //kann nicht unmuten wenn disconnected ist
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (users_in_afk.size === 0) {
|
|
||||||
// //leave if empty
|
|
||||||
// await client.distube.voices.leave(real_afk_channel)
|
|
||||||
// connected = false;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
async function getMember(client, userId) {
|
|
||||||
const guild = client.guilds.cache.get(process.env.D_GuildID);
|
|
||||||
if (!guild) return null;
|
|
||||||
|
|
||||||
// cache first (fast path)
|
|
||||||
let member = guild.members.cache.get(userId);
|
|
||||||
|
|
||||||
// fallback (safe path)
|
|
||||||
if (!member) {
|
|
||||||
member = await guild.members.fetch(userId).catch(() => null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return member;
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
name: 'timer24h',
|
|
||||||
|
|
||||||
async execute(timer, client) {
|
|
||||||
const member = await getMember(client, timer.assignedUser);
|
|
||||||
if (!member) return;
|
|
||||||
|
|
||||||
await member.send(
|
|
||||||
`⚠️ Less than 24 hours remaining for: **${timer.topic}**`
|
|
||||||
).catch(() => {});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
const { mClient } = require('../index');
|
|
||||||
function getRemaining(timer) {
|
|
||||||
if (timer.state !== 'running') {
|
|
||||||
return timer.timeRemaining;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Math.max(
|
|
||||||
0,
|
|
||||||
timer.timeRemaining - (Date.now() - timer.startedAt)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
name: 'timerCheck',
|
|
||||||
|
|
||||||
async execute(client) {
|
|
||||||
const db = mClient.db('neo-db');
|
|
||||||
const wgeColl = db.collection('timer_wge');
|
|
||||||
|
|
||||||
const timers = await wgeColl.find({
|
|
||||||
state: { $ne: 'stopped' }
|
|
||||||
}).toArray();
|
|
||||||
|
|
||||||
const now = Date.now();
|
|
||||||
|
|
||||||
for (const timer of timers) {
|
|
||||||
|
|
||||||
const remaining = getRemaining(timer);
|
|
||||||
|
|
||||||
// -------------------------
|
|
||||||
// HALF TIME (3.5 days left)
|
|
||||||
// -------------------------
|
|
||||||
if (
|
|
||||||
!timer.notifications?.half &&
|
|
||||||
remaining <= 3.5 * 24 * 60 * 60 * 1000
|
|
||||||
) {
|
|
||||||
await wgeColl.updateOne(
|
|
||||||
{ _id: timer._id },
|
|
||||||
{ $set: { "notifications.half": true } }
|
|
||||||
);
|
|
||||||
|
|
||||||
client.emit('timerHalf', timer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// -------------------------
|
|
||||||
// 24H WARNING
|
|
||||||
// -------------------------
|
|
||||||
if (
|
|
||||||
!timer.notifications?.day24 &&
|
|
||||||
remaining <= 24 * 60 * 60 * 1000
|
|
||||||
) {
|
|
||||||
await wgeColl.updateOne(
|
|
||||||
{ _id: timer._id },
|
|
||||||
{ $set: { "notifications.day24": true } }
|
|
||||||
);
|
|
||||||
|
|
||||||
client.emit('timer24h', timer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// -------------------------
|
|
||||||
// COMPLETION
|
|
||||||
// -------------------------
|
|
||||||
if (
|
|
||||||
!timer.notifications?.complete &&
|
|
||||||
remaining <= 0
|
|
||||||
) {
|
|
||||||
await wgeColl.updateOne(
|
|
||||||
{ _id: timer._id },
|
|
||||||
{ $set: { "notifications.complete": true } }
|
|
||||||
);
|
|
||||||
|
|
||||||
client.emit('timerComplete', timer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
const { mClient } = require("..");
|
|
||||||
|
|
||||||
async function getMember(client, userId) {
|
|
||||||
const guild = client.guilds.cache.get(process.env.D_GuildID);
|
|
||||||
if (!guild) return null;
|
|
||||||
|
|
||||||
// cache first (fast path)
|
|
||||||
let member = guild.members.cache.get(userId);
|
|
||||||
|
|
||||||
// fallback (safe path)
|
|
||||||
if (!member) {
|
|
||||||
member = await guild.members.fetch(userId).catch(() => null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return member;
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
name: 'timerComplete',
|
|
||||||
|
|
||||||
async execute(timer, client) {
|
|
||||||
const member = await getMember(client, timer.assignedUser);
|
|
||||||
if (!member) return;
|
|
||||||
|
|
||||||
await member.send(
|
|
||||||
`❌ Timer ran out: **${timer.topic}** ...Re-assigning randomly...`
|
|
||||||
).catch(() => { });
|
|
||||||
|
|
||||||
// Reset Timer, Reassign Randomly
|
|
||||||
const db = mClient.db('neo-db')
|
|
||||||
const wgeColl = db.collection('timer_wge')
|
|
||||||
|
|
||||||
// Randomizer Function
|
|
||||||
const participateColl = db.collection('items_wge')
|
|
||||||
const randomParticipant = await participateColl.aggregate([
|
|
||||||
{ $match: { status: true } },
|
|
||||||
{ $sample: { size: 1 } }
|
|
||||||
]).toArray()
|
|
||||||
|
|
||||||
if (!randomParticipant.length) { return interaction.reply({ content: 'No one else is participating!' }) }
|
|
||||||
|
|
||||||
const wge = await wgeColl.findOne({
|
|
||||||
$and: [
|
|
||||||
{ debug: false },
|
|
||||||
{ state: 'running' }
|
|
||||||
]
|
|
||||||
})
|
|
||||||
|
|
||||||
const channelColl = db.collection('config_channels')
|
|
||||||
const guild = await client.guilds.cache.get(process.env.D_GuildID);
|
|
||||||
const wgeChannel = await channelColl.findOne({
|
|
||||||
$and: [
|
|
||||||
{ purpose: 'wge' },
|
|
||||||
{ guildID: process.env.D_GuildID }
|
|
||||||
]
|
|
||||||
})
|
|
||||||
|
|
||||||
const channel = await client.channels.cache.get(wgeChannel.channelID)
|
|
||||||
|
|
||||||
random = await guild.members.fetch(randomParticipant[0].userID)
|
|
||||||
wgeAssignedUser = random.user
|
|
||||||
|
|
||||||
await wgeColl.deleteOne({
|
|
||||||
_id: wge._id
|
|
||||||
})
|
|
||||||
|
|
||||||
const wgeDefaultAssignedTime = 7 * 24 * 60 * 60 * 1000; // 7 days in ms
|
|
||||||
|
|
||||||
channel.send({
|
|
||||||
content: `The Timer for <@${wge.assignedUser}> has run out! Assigning randomly... \r\n<@${wgeAssignedUser.id}> is the next expert! Their topic still is **${wge.topic}**`
|
|
||||||
})
|
|
||||||
|
|
||||||
await wgeColl.insertOne({
|
|
||||||
assignedUser: wgeAssignedUser.id,
|
|
||||||
assigningUser: wge.assigningUser,
|
|
||||||
|
|
||||||
startedAt: Date.now(),
|
|
||||||
timeRemaining: wgeDefaultAssignedTime,
|
|
||||||
|
|
||||||
state: 'running',
|
|
||||||
|
|
||||||
notifications: {
|
|
||||||
half: false,
|
|
||||||
day24: false,
|
|
||||||
complete: false
|
|
||||||
},
|
|
||||||
|
|
||||||
topic: wge.topic,
|
|
||||||
debug: false,
|
|
||||||
|
|
||||||
createdAt: new Date()
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
async function getMember(client, userId) {
|
|
||||||
const guild = client.guilds.cache.get(process.env.D_GuildID);
|
|
||||||
if (!guild) return null;
|
|
||||||
|
|
||||||
// cache first (fast path)
|
|
||||||
let member = guild.members.cache.get(userId);
|
|
||||||
|
|
||||||
// fallback (safe path)
|
|
||||||
if (!member) {
|
|
||||||
member = await guild.members.fetch(userId).catch(() => null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return member;
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
name: 'timerHalf',
|
|
||||||
|
|
||||||
async execute(timer, client) {
|
|
||||||
const member = await getMember(client, timer.assignedUser);
|
|
||||||
if (!member) return;
|
|
||||||
|
|
||||||
await member.send(
|
|
||||||
`⏳ Half time reached for: **${timer.topic}**`
|
|
||||||
).catch(() => {});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
const fs = require('node:fs')
|
|
||||||
const path = require('node:path')
|
|
||||||
module.exports = (client) => {
|
|
||||||
const buttonsFoldersPath = path.join(__dirname, '../buttons');
|
|
||||||
const buttonsFolders = fs.readdirSync(buttonsFoldersPath);
|
|
||||||
let buttonCount = 0
|
|
||||||
for (const folder of buttonsFolders) {
|
|
||||||
const buttonsPath = path.join(buttonsFoldersPath, folder);
|
|
||||||
const buttonsFiles = fs.readdirSync(buttonsPath).filter(file => file.endsWith('.js'));
|
|
||||||
for (const file of buttonsFiles) {
|
|
||||||
buttonCount++
|
|
||||||
const filePath = path.join(buttonsPath, file);
|
|
||||||
const button = require(filePath);
|
|
||||||
if ('execute' in button) {
|
|
||||||
client.buttons.set(button.name, button);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.log(`[${buttonCount}] Button(s) initialized`)
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
const fs = require('node:fs')
|
|
||||||
const path = require('node:path')
|
|
||||||
module.exports = (client) => {
|
|
||||||
const legacyFoldersPath = path.join(__dirname, '../commands/legacy');
|
|
||||||
const legacyCommandFolders = fs.readdirSync(legacyFoldersPath);
|
|
||||||
let legacyCount = 0
|
|
||||||
let aliasCount = 0
|
|
||||||
for (const folder of legacyCommandFolders) {
|
|
||||||
const commandsPath = path.join(legacyFoldersPath, folder);
|
|
||||||
const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));
|
|
||||||
for (const file of commandFiles) {
|
|
||||||
legacyCount++
|
|
||||||
const filePath = path.join(commandsPath, file);
|
|
||||||
const command = require(filePath);
|
|
||||||
if ('execute' in command) {
|
|
||||||
client.legacyCommands.set(command.name, command);
|
|
||||||
}
|
|
||||||
if (command.aliases && Array.isArray(command.aliases)) {
|
|
||||||
command.aliases.forEach(alias => {
|
|
||||||
aliasCount++
|
|
||||||
client.aliases.set(alias, command.name)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.log(`[${aliasCount}] Aliase(s) initialized`)
|
|
||||||
console.log(`[${legacyCount}] Legacy Command(s) initialized`)
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
// ich hab das einfach _commands genannt, damit es beim Startup als erstes initialisiert wird.
|
|
||||||
const { REST, Routes } = require('discord.js')
|
|
||||||
const fs = require('node:fs')
|
|
||||||
const path = require('node:path')
|
|
||||||
|
|
||||||
module.exports = (client) => {
|
|
||||||
let commands = [] // only used for REST API
|
|
||||||
const foldersPath = path.join(__dirname, '../commands/slash');
|
|
||||||
const commandFolders = fs.readdirSync(foldersPath);
|
|
||||||
for (const folder of commandFolders) {
|
|
||||||
// Grab all the command files from the commands directory you created earlier
|
|
||||||
const commandsPath = path.join(foldersPath, folder);
|
|
||||||
const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));
|
|
||||||
// Grab the SlashCommandBuilder#toJSON() output of each command's data for deployment
|
|
||||||
for (const file of commandFiles) {
|
|
||||||
const filePath = path.join(commandsPath, file);
|
|
||||||
const command = require(filePath);
|
|
||||||
if ('data' in command && 'execute' in command) {
|
|
||||||
commands.push(command.data.toJSON());
|
|
||||||
client.commands.set(command.data.name, command);
|
|
||||||
} else {
|
|
||||||
console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const rest = new REST().setToken(process.env.D_Token);
|
|
||||||
(async () => {
|
|
||||||
try {
|
|
||||||
console.log(`Started refreshing ${commands.length} application (/) commands.`);
|
|
||||||
// The put method is used to fully refresh all commands in the guild with the current set
|
|
||||||
const data = await rest.put(
|
|
||||||
Routes.applicationGuildCommands(process.env.D_ID, process.env.D_GuildID),
|
|
||||||
{ body: commands },
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log(`Successfully reloaded ${data.length} application (/) commands.`);
|
|
||||||
} catch (error) {
|
|
||||||
// And of course, make sure you catch and log any errors!
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
const fs = require('node:fs')
|
|
||||||
const path = require('node:path')
|
|
||||||
module.exports = (client) => {
|
|
||||||
const eventsPath = path.join(__dirname, '../events')
|
|
||||||
const eventFiles = fs.readdirSync(eventsPath).filter(file => file.endsWith('.js'))
|
|
||||||
|
|
||||||
for (const file of eventFiles) {
|
|
||||||
const filePath = path.join(eventsPath, file)
|
|
||||||
const event = require(filePath)
|
|
||||||
if (event.once) {
|
|
||||||
client.once(event.name, (...args) => event.execute(...args, client))
|
|
||||||
// added client to commomerate global usage
|
|
||||||
} else {
|
|
||||||
client.on(event.name, (...args) => event.execute(...args, client))
|
|
||||||
// added client to commomerate global usage
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
const fs = require('node:fs')
|
|
||||||
const path = require('node:path')
|
|
||||||
module.exports = (client) => {
|
|
||||||
const selectMenusFoldersPath = path.join(__dirname, '../selectMenus');
|
|
||||||
const selectMenusFolders = fs.readdirSync(selectMenusFoldersPath);
|
|
||||||
let selectMenuCount = 0
|
|
||||||
for (const folder of selectMenusFolders) {
|
|
||||||
const Path = path.join(selectMenusFoldersPath, folder);
|
|
||||||
const Files = fs.readdirSync(Path).filter(file => file.endsWith('.js'));
|
|
||||||
for (const file of Files) {
|
|
||||||
selectMenuCount++
|
|
||||||
const filePath = path.join(Path, file);
|
|
||||||
const button = require(filePath);
|
|
||||||
if ('execute' in button) {
|
|
||||||
client.selectMenus.set(button.name, button);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.log(`[${selectMenuCount}] Select Menu(s) initialized`)
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
const { Client, GatewayIntentBits, Collection, Partials } = require('discord.js')
|
|
||||||
const { MongoClient } = require('mongodb')
|
|
||||||
require('dotenv').config()
|
|
||||||
const mClient = new MongoClient(process.env.M_URI)
|
|
||||||
exports.mClient = mClient;
|
|
||||||
const fs = require('node:fs')
|
|
||||||
|
|
||||||
const client = new Client({
|
|
||||||
intents: [
|
|
||||||
GatewayIntentBits.Guilds,
|
|
||||||
GatewayIntentBits.GuildMembers,
|
|
||||||
GatewayIntentBits.GuildMessages,
|
|
||||||
GatewayIntentBits.GuildPresences,
|
|
||||||
GatewayIntentBits.GuildMessageReactions,
|
|
||||||
GatewayIntentBits.GuildVoiceStates,
|
|
||||||
GatewayIntentBits.DirectMessages,
|
|
||||||
GatewayIntentBits.MessageContent,
|
|
||||||
],
|
|
||||||
partials: [Partials.Channel, Partials.Message, Partials.User, Partials.GuildMember, Partials.Reaction]
|
|
||||||
});
|
|
||||||
exports.client = client
|
|
||||||
|
|
||||||
client.commands = new Collection() // slash commands collection
|
|
||||||
client.legacyCommands = new Collection() // legacy commands collection
|
|
||||||
client.aliases = new Collection() // list of command aliases
|
|
||||||
client.buttons = new Collection() // list of buttons
|
|
||||||
client.selectMenus = new Collection() // list of selectMenus
|
|
||||||
|
|
||||||
fs.readdirSync('./handlers').forEach((handler) => {
|
|
||||||
require(`./handlers/${handler}`)(client)
|
|
||||||
});
|
|
||||||
|
|
||||||
client.login(process.env.D_Token)
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "arthonor-3",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "discord companion",
|
|
||||||
"main": "index.js",
|
|
||||||
"scripts": {
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git+https://github.com/DeSqBlocki/Arthonor-3.git"
|
|
||||||
},
|
|
||||||
"keywords": [
|
|
||||||
"discord"
|
|
||||||
],
|
|
||||||
"author": "DeSqBlocki",
|
|
||||||
"license": "ISC",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/DeSqBlocki/Arthonor-3/issues"
|
|
||||||
},
|
|
||||||
"homepage": "https://github.com/DeSqBlocki/Arthonor-3#readme",
|
|
||||||
"dependencies": {
|
|
||||||
"canvas": "^2.11.2",
|
|
||||||
"discord.js": "^14.15.3",
|
|
||||||
"dotenv": "^16.4.5",
|
|
||||||
"mongodb": "^6.8.0",
|
|
||||||
"nodemon": "^3.1.4"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
const { EmbedBuilder, ActionRowBuilder, UserSelectMenuBuilder, PermissionFlagsBits } = require("discord.js")
|
|
||||||
const { mClient } = require("../..")
|
|
||||||
require('dotenv').config()
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
name: 'honor_menu_mentionable',
|
|
||||||
description: 'handles honor menu mentionables',
|
|
||||||
async execute(interaction) {
|
|
||||||
const embedData = await interaction.message.embeds[0].data
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
if (!interaction.members) {
|
|
||||||
embed.setTitle(embedData.title)
|
|
||||||
.setThumbnail(embedData.thumbnail.url)
|
|
||||||
.setDescription(embedData.description);
|
|
||||||
} else {
|
|
||||||
var target = await interaction.guild.members.fetch(interaction.members.keys().next().value)
|
|
||||||
var db = mClient.db(process.env.M_DB)
|
|
||||||
var honorsColl = db.collection('items_honors')
|
|
||||||
var theirHonorLevel = await honorsColl.findOne({ userID: target.id })
|
|
||||||
|
|
||||||
const member = interaction.message.guild.members.cache.get(target.user.id)
|
|
||||||
const memberRoles = member.roles.cache
|
|
||||||
.filter((roles) => roles.id !== interaction.message.guild.id)
|
|
||||||
.map((role) => role.toString())
|
|
||||||
|
|
||||||
const description = String(`${target} - ${target.user.globalName ?? target.user.username} - ${target.user.id}\r\n\r\n${memberRoles}`).replaceAll(',', ' ')
|
|
||||||
embed.setTitle(`- User Stats -`)
|
|
||||||
.setDescription(description)
|
|
||||||
.addFields({
|
|
||||||
name: 'Current Honor Level:', value: `${theirHonorLevel?.honors ?? 0}`, inline: true
|
|
||||||
})
|
|
||||||
.setFooter({ text: 'Honor Level updaten sich nicht automatisch!' })
|
|
||||||
}
|
|
||||||
const select = new ActionRowBuilder()
|
|
||||||
.addComponents(
|
|
||||||
new UserSelectMenuBuilder()
|
|
||||||
.setCustomId('honor_menu_mentionable')
|
|
||||||
.setPlaceholder('Select a User')
|
|
||||||
)
|
|
||||||
|
|
||||||
const row = interaction.message.components[1]
|
|
||||||
await interaction.update({
|
|
||||||
embeds: [embed],
|
|
||||||
components: [select, row]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
const { EmbedBuilder, ActionRowBuilder, UserSelectMenuBuilder, PermissionFlagsBits, RoleSelectMenuComponent, UserSelectMenuComponent } = require("discord.js")
|
|
||||||
const { mClient } = require("../..")
|
|
||||||
require('dotenv').config()
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
name: 'quotes_list_mentionable',
|
|
||||||
description: 'handles quotes list mentionables',
|
|
||||||
async execute(interaction) {
|
|
||||||
const embedData = await interaction.message.embeds[0].data
|
|
||||||
const embed = new EmbedBuilder()
|
|
||||||
if (!interaction.members) {
|
|
||||||
embed.setTitle(embedData.title)
|
|
||||||
.setThumbnail(embedData.thumbnail.url)
|
|
||||||
.setDescription(embedData.description);
|
|
||||||
} else {
|
|
||||||
const target = await interaction.guild.members.fetch(interaction.members.keys().next().value)
|
|
||||||
const db = mClient.db(process.env.M_DB)
|
|
||||||
const quotesColl = db.collection('items_quotes')
|
|
||||||
const quotes = await quotesColl.find({ userID: target.id }).toArray()
|
|
||||||
const member = interaction.message.guild.members.cache.get(target.user.id)
|
|
||||||
const memberRoles = member.roles.cache
|
|
||||||
.filter((roles) => roles.id !== interaction.message.guild.id)
|
|
||||||
.map((role) => role.toString())
|
|
||||||
|
|
||||||
const description = String(`${target}\r\n\r\n${memberRoles}`).replaceAll(',', ' ')
|
|
||||||
embed.setTitle(`- User Stats -`)
|
|
||||||
.setDescription(description)
|
|
||||||
.setThumbnail(target.displayAvatarURL())
|
|
||||||
.addFields({
|
|
||||||
name: 'Number of Quotes:', value: `${quotes.length}`, inline: true
|
|
||||||
})
|
|
||||||
.setFooter({ text: (`${new Date().toLocaleDateString('en-US', { weekday: 'short' })} ${new Date().toLocaleDateString('en-US', { month: 'short' })} ${new Date().getDate()} ${new Date().getFullYear()} UserID <@${member.id}>`) })
|
|
||||||
}
|
|
||||||
const select = new ActionRowBuilder()
|
|
||||||
.addComponents(
|
|
||||||
new UserSelectMenuBuilder()
|
|
||||||
.setCustomId('quotes_list_mentionable')
|
|
||||||
.setPlaceholder('Filter By User')
|
|
||||||
)
|
|
||||||
|
|
||||||
const row = interaction.message.components[1]
|
|
||||||
await interaction.update({
|
|
||||||
embeds: [embed],
|
|
||||||
components: [select, row]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
module.exports =
|
|
||||||
function ping(interface, args, type){
|
|
||||||
if (type = 'legacy'){
|
|
||||||
// type = legacy
|
|
||||||
interface.reply('pang!')
|
|
||||||
} else {
|
|
||||||
interface.reply('pong!')
|
|
||||||
}
|
|
||||||
}
|
|
||||||