forked from cosmic/scythe
Compare commits
4 Commits
d7e65bd5ec
...
7d1cf86a07
| Author | SHA1 | Date |
|---|---|---|
|
|
7d1cf86a07 | |
|
|
059e9db1cd | |
|
|
3341463fde | |
|
|
52e73235ea |
|
|
@ -0,0 +1,241 @@
|
||||||
|
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 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
CREATE TABLE `colonthree` (
|
||||||
|
`user` text PRIMARY KEY NOT NULL,
|
||||||
|
`amount` integer NOT NULL,
|
||||||
|
`messages_count` integer NOT NULL
|
||||||
|
);
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
{
|
||||||
|
"version": "6",
|
||||||
|
"dialect": "sqlite",
|
||||||
|
"id": "a3e18d09-b7d4-48e3-8920-1fa55c43ee70",
|
||||||
|
"prevId": "fa98c7d2-c794-4f03-887b-f6f5c1b3891d",
|
||||||
|
"tables": {
|
||||||
|
"colonthree": {
|
||||||
|
"name": "colonthree",
|
||||||
|
"columns": {
|
||||||
|
"user": {
|
||||||
|
"name": "user",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"amount": {
|
||||||
|
"name": "amount",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"messages_count": {
|
||||||
|
"name": "messages_count",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"tickets": {
|
||||||
|
"name": "tickets",
|
||||||
|
"columns": {
|
||||||
|
"user": {
|
||||||
|
"name": "user",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"channel": {
|
||||||
|
"name": "channel",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"views": {},
|
||||||
|
"enums": {},
|
||||||
|
"_meta": {
|
||||||
|
"schemas": {},
|
||||||
|
"tables": {},
|
||||||
|
"columns": {}
|
||||||
|
},
|
||||||
|
"internal": {
|
||||||
|
"indexes": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,6 +8,13 @@
|
||||||
"when": 1742570954158,
|
"when": 1742570954158,
|
||||||
"tag": "0000_nervous_komodo",
|
"tag": "0000_nervous_komodo",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 1,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1742844574438,
|
||||||
|
"tag": "0001_warm_ego",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,16 @@
|
||||||
import { text, sqliteTable } from "drizzle-orm/sqlite-core";
|
import { text, sqliteTable, int } from "drizzle-orm/sqlite-core";
|
||||||
|
|
||||||
|
import type { InferSelectModel } from "drizzle-orm";
|
||||||
|
|
||||||
export const ticketsTable = sqliteTable("tickets", {
|
export const ticketsTable = sqliteTable("tickets", {
|
||||||
user: text().primaryKey().notNull(),
|
user: text().primaryKey().notNull(),
|
||||||
channel: text().notNull()
|
channel: text().notNull()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const colonTable = sqliteTable("colonthree", {
|
||||||
|
user: text().primaryKey().notNull(),
|
||||||
|
amount: int().notNull(),
|
||||||
|
messages_count: int().notNull()
|
||||||
|
})
|
||||||
|
|
||||||
|
export type ColonThreeType = InferSelectModel<typeof colonTable>;
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
import type { TextChannel } from "discord.js";
|
import type { TextChannel } from "discord.js";
|
||||||
import { Client, Discord, On, type ArgsOf } from "discordx";
|
import { Client, Discord, On, type ArgsOf } from "discordx";
|
||||||
|
|
||||||
|
import db from "../db";
|
||||||
|
import { colonTable } from "../db/schema";
|
||||||
|
import { eq } from "drizzle-orm";
|
||||||
|
|
||||||
@Discord()
|
@Discord()
|
||||||
export class MemberEvents {
|
export class MemberEvents {
|
||||||
@On({ event: "guildMemberAdd" })
|
@On({ event: "guildMemberAdd" })
|
||||||
|
|
@ -14,13 +18,25 @@ export class MemberEvents {
|
||||||
if (botRole) {
|
if (botRole) {
|
||||||
await member.roles.add(botRole);
|
await member.roles.add(botRole);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
await db.insert(colonTable).values({
|
||||||
|
user: member.id,
|
||||||
|
amount: 0,
|
||||||
|
messages_count: 0
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@On({ event: "guildMemberRemove" })
|
@On({ event: "guildMemberRemove" })
|
||||||
async memberRemove([member]: ArgsOf<"guildMemberRemove">, client: Client) {
|
async memberRemove([member]: ArgsOf<"guildMemberRemove">, client: Client) {
|
||||||
const channel = client.channels.cache.get(Bun.env.GOODBYE!) as TextChannel;
|
const channel = client.channels.cache.get(Bun.env.GOODBYE!) as TextChannel;
|
||||||
await channel.send(`We're sad to see you go, ${member.user.username}.`);
|
await channel.send(`We're sad to see you go, ${member.user.username}.`);
|
||||||
|
|
||||||
|
await db
|
||||||
|
.delete(colonTable)
|
||||||
|
.where(eq(colonTable.user, member.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@On({ event: "guildMemberUpdate" })
|
@On({ event: "guildMemberUpdate" })
|
||||||
async memberUpdate([_, newM]: ArgsOf<"guildMemberUpdate">) {
|
async memberUpdate([_, newM]: ArgsOf<"guildMemberUpdate">) {
|
||||||
if (newM.roles.cache.get(Bun.env.BAD_ROLE!)) {
|
if (newM.roles.cache.get(Bun.env.BAD_ROLE!)) {
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,10 @@ import { snipeObject } from "..";
|
||||||
import { sleep } from "../utils/underage";
|
import { sleep } from "../utils/underage";
|
||||||
import { bumpRemind } from "../utils/bump";
|
import { bumpRemind } from "../utils/bump";
|
||||||
|
|
||||||
|
import db from "../db";
|
||||||
|
import { colonTable } from "../db/schema";
|
||||||
|
import { eq, sql } from "drizzle-orm";
|
||||||
|
|
||||||
@Discord()
|
@Discord()
|
||||||
export class MessageEvents {
|
export class MessageEvents {
|
||||||
@On({ event: "messageDelete" })
|
@On({ event: "messageDelete" })
|
||||||
|
|
@ -10,9 +14,11 @@ export class MessageEvents {
|
||||||
snipeObject.author = msg.author?.username ?? "unknown";
|
snipeObject.author = msg.author?.username ?? "unknown";
|
||||||
snipeObject.content = msg.content;
|
snipeObject.content = msg.content;
|
||||||
}
|
}
|
||||||
|
|
||||||
@On({ event: "messageCreate" })
|
@On({ event: "messageCreate" })
|
||||||
async messageCreate([msg]: ArgsOf<"messageCreate">, client: Client) {
|
async messageCreate([msg]: ArgsOf<"messageCreate">, client: Client) {
|
||||||
if (msg.author.id == msg.client.user.id) return;
|
if (msg.author.id == msg.client.user.id) return;
|
||||||
|
|
||||||
const linkRegex = /instagram\.com\/([^\s?]+)/;
|
const linkRegex = /instagram\.com\/([^\s?]+)/;
|
||||||
if (linkRegex.test(msg.content)) {
|
if (linkRegex.test(msg.content)) {
|
||||||
let fixedLink = msg.content.match(linkRegex);
|
let fixedLink = msg.content.match(linkRegex);
|
||||||
|
|
@ -24,6 +30,7 @@ export class MessageEvents {
|
||||||
await msg.suppressEmbeds();
|
await msg.suppressEmbeds();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg.embeds.length > 0) {
|
if (msg.embeds.length > 0) {
|
||||||
if (msg.embeds[0].description?.includes("Bump done!")) {
|
if (msg.embeds[0].description?.includes("Bump done!")) {
|
||||||
await msg.channel.send(
|
await msg.channel.send(
|
||||||
|
|
@ -34,5 +41,19 @@ export class MessageEvents {
|
||||||
bumpRemind(client);
|
bumpRemind(client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const cThreeRegex = /:3/g;
|
||||||
|
if (cThreeRegex.test(msg.content)) {
|
||||||
|
let colonThrees = msg.content.match(cThreeRegex);
|
||||||
|
|
||||||
|
await db.update(colonTable).set({
|
||||||
|
amount: sql`${colonTable.amount} + ${colonThrees?.length}`,
|
||||||
|
messages_count: sql`${colonTable.messages_count} + 1`,
|
||||||
|
}).where(eq(colonTable.user, msg.author.id));
|
||||||
|
} else {
|
||||||
|
await db.update(colonTable).set({
|
||||||
|
messages_count: sql`${colonTable.messages_count} + 1`,
|
||||||
|
}).where(eq(colonTable.user, msg.author.id));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue