scythe/src/commands/colonThree.ts

242 lines
7.9 KiB
TypeScript

import { Discord, Slash, SlashGroup, SlashOption } from "discordx";
import { ApplicationCommandOptionType, CommandInteraction, EmbedBuilder, GuildMember, MessageFlags } from "discord.js";
import db from "../db";
import { colonTable, type ColonThreeType } from "../db/schema";
import { eq, desc } from "drizzle-orm";
@Discord()
export class ColonThreeInit {
@Slash({ description: "Init all users for :3 Leaderboard", name: "init_colonthree" })
async init_colon(inter: CommandInteraction) {
if (Bun.env.OWNER != inter.user.id) {
await inter.reply({ content: "You're not allowed to run this.", flags: MessageFlags.Ephemeral })
return;
}
for (const userObject of await inter.guild!.members.cache) {
const user = userObject[1];
if (user.user.bot) {
continue;
}
const check = await db.select().from(colonTable).where(eq(colonTable.user, user.id));
if (check.length >= 1) {
continue;
}
await db.insert(colonTable).values({
user: user.id,
amount: 0,
messages_count: 0
});
}
await inter.reply({ content: "All users have been initalized", flags: MessageFlags.Ephemeral });
}
}
@Discord()
@SlashGroup({
description: "The :3 Commands",
name: "colonthree"
})
@SlashGroup("colonthree")
export class ColonThree {
@Slash({ description: "Stats" })
async stats(
@SlashOption({
description: "Get stats from user",
name: "user",
required: false,
type: ApplicationCommandOptionType.User,
})
user: GuildMember,
inter: CommandInteraction
) {
const statsUser = (
await db
.select()
.from(colonTable)
.where(eq(colonTable.user, (user?.id || inter.user.id)))
)[0];
if (!statsUser) {
await inter.reply({ content: `Failed to get <@${user?.id || inter.user.id}>'s stats.`, flags: MessageFlags.Ephemeral });
return;
}
const userObject = inter.client.users.cache.get(statsUser.user);
if (!userObject) {
await inter.reply({ content: "Something went wrong...", flags: MessageFlags.Ephemeral });
return;
}
const embed = new EmbedBuilder()
.setTitle(`${userObject.username}'s Stats`)
.setAuthor({ name: userObject.username, iconURL: userObject.avatarURL()! })
.addFields(
{
name: '**Total :3 Sent**',
value: `► **${statsUser.amount}** times`,
inline: true
},
{
name: '**Average :3 per Message**',
value: `► **${(statsUser.amount / statsUser.messages_count).toFixed(2)}**`,
inline: true
},
{
name: '**Messages Count**',
value: `► **${statsUser.messages_count}**`,
inline: true
}
);
await inter.reply( { embeds: [embed], flags: MessageFlags.Ephemeral });
}
@Slash({ description: "Compare" })
async compare(
@SlashOption({
description: "Get stats from user",
name: "x",
required: true,
type: ApplicationCommandOptionType.User,
})
x: GuildMember,
@SlashOption({
description: "Get stats from user",
name: "y",
required: true,
type: ApplicationCommandOptionType.User,
})
y: GuildMember,
inter: CommandInteraction
) {
const xStats = (
await db
.select()
.from(colonTable)
.where(eq(colonTable.user, x.id))
)[0];
if (!xStats) {
await inter.reply({ content: `Failed to get <@${x.id}>'s stats.`, flags: MessageFlags.Ephemeral });
return;
}
const yStats = (
await db
.select()
.from(colonTable)
.where(eq(colonTable.user, y.id))
)[0];
if (!yStats) {
await inter.reply({ content: `Failed to get <@${y.id}>'s stats.`, flags: MessageFlags.Ephemeral });
return;
}
const winner = xStats.amount > yStats.amount ? x : y;
const embed = new EmbedBuilder()
.setTitle(`🎉 ${winner.user.username} is using :3 more!`)
.addFields(
{
name: `📊 ${x.user.username}'s Stats`,
value: `► Sent **${xStats.amount}** :3\n► Avg: **${(xStats.amount / xStats.messages_count).toFixed(2)}** :3 per message`,
inline: true
},
{
name: `📊 ${y.user.username}'s Stats`,
value: `► Sent **${yStats.amount}** :3\n► Avg: **${(yStats.amount / yStats.messages_count).toFixed(2)}** :3 per message`,
inline: true
}
)
await inter.reply({ embeds: [embed] });
}
@Slash({ description: "Leaderboard" })
async board(inter: CommandInteraction) {
const theColonThreeLeaders = await db.select()
.from(colonTable)
.orderBy(desc(colonTable.amount));
const topTen = theColonThreeLeaders
.slice(0, 10)
.filter(user => user.amount >= 1);
const leaderboardText = topTen.map((user, index) => {
const rank = index + 1;
const avg = (user.amount / user.messages_count).toFixed(2);
const medal = rank === 1 ? "🥇" : rank === 2 ? "🥈" : rank === 3 ? "🥉" : `**${rank}.**`;
return `${medal} <@${user.user}> » **${user.amount}** :3 (avg: **${avg}**)`;
});
const embed = new EmbedBuilder()
.setTitle(`🏆 :3 Leaderboard`)
.setDescription(leaderboardText.join("\n") || "*No data yet!*")
.addFields({
name: 'Stats',
value: `► **Tracking users:** ${theColonThreeLeaders.length}`,
inline: false
})
.setFooter({ text: 'Keep using :3!!!!!!' })
.setTimestamp();
await inter.reply({ embeds: [embed] });
}
@Slash({ description: "Stop tracking and delete my data" })
async delete(
@SlashOption({
description: "Type confirm to delete",
name: "confirmation",
required: true,
type: ApplicationCommandOptionType.String,
})
confirmation: string,
inter: CommandInteraction
) {
if (confirmation === "confirm") {
await db.delete(colonTable).where(eq(colonTable.user, inter.user.id));
await inter.reply({ content: "All of data was deleted, you will not be tracked again.", flags: MessageFlags.Ephemeral });
return;
}
await inter.reply({ content: 'You need to type "confirm" to delete.', flags: MessageFlags.Ephemeral });
}
@Slash({ description: "Start tracking" })
async start(
inter: CommandInteraction
) {
const check = (
await db
.select()
.from(colonTable)
.where(eq(colonTable.user, inter.user.id)
)
)[0];
if (check) {
await inter.reply({ content: "Scythe already tracks your :3 data.", flags: MessageFlags.Ephemeral });
return;
}
await db.insert(colonTable).values({
user: inter.user.id,
amount: 0,
messages_count: 0
});
await inter.reply({ content: "Scythe starts tracking your :3 data again.", flags: MessageFlags.Ephemeral });
}
}