forked from cosmic/scythe
Compare commits
No commits in common. "cfb7b31b361651b63357e5a57f47355cf6a30984" and "7d1cf86a079b9a9cacdaf10a265a9dc1f0440bed" have entirely different histories.
cfb7b31b36
...
7d1cf86a07
|
|
@ -2,10 +2,6 @@ FROM oven/bun:latest
|
|||
|
||||
WORKDIR /app
|
||||
|
||||
COPY package.json package.json
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN bun i
|
||||
|
||||
CMD [ "./entrypoint.sh" ]
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
|
||||
"javascript": {
|
||||
"parser": {
|
||||
"unsafeParameterDecoratorsEnabled": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,8 +5,8 @@
|
|||
"private": true,
|
||||
"scripts": {
|
||||
"start": "bun run src/index.ts",
|
||||
"migrate": "bunx drizzle-kit migrate",
|
||||
"migrate:generate": "bunx drizzle-kit generate"
|
||||
"migrate": "bun drizzle-kit migrate",
|
||||
"migrate:generate": "bun drizzle-kit generate"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bun": "^1.2.5",
|
||||
|
|
|
|||
|
|
@ -1,29 +1,17 @@
|
|||
import { Discord, Slash, SlashGroup, SlashOption } from "discordx";
|
||||
import {
|
||||
ApplicationCommandOptionType,
|
||||
CommandInteraction,
|
||||
EmbedBuilder,
|
||||
GuildMember,
|
||||
MessageFlags,
|
||||
} from "discord.js";
|
||||
import { ApplicationCommandOptionType, CommandInteraction, EmbedBuilder, GuildMember, MessageFlags } from "discord.js";
|
||||
|
||||
import db from "../db";
|
||||
import { colonTable } from "../db/schema";
|
||||
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",
|
||||
})
|
||||
@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,
|
||||
});
|
||||
await inter.reply({ content: "You're not allowed to run this.", flags: MessageFlags.Ephemeral })
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -33,10 +21,7 @@ export class ColonThreeInit {
|
|||
continue;
|
||||
}
|
||||
|
||||
const check = await db
|
||||
.select()
|
||||
.from(colonTable)
|
||||
.where(eq(colonTable.user, user.id));
|
||||
const check = await db.select().from(colonTable).where(eq(colonTable.user, user.id));
|
||||
|
||||
if (check.length >= 1) {
|
||||
continue;
|
||||
|
|
@ -45,21 +30,18 @@ export class ColonThreeInit {
|
|||
await db.insert(colonTable).values({
|
||||
user: user.id,
|
||||
amount: 0,
|
||||
messages_count: 0,
|
||||
messages_count: 0
|
||||
});
|
||||
}
|
||||
|
||||
await inter.reply({
|
||||
content: "All users have been initalized",
|
||||
flags: MessageFlags.Ephemeral,
|
||||
});
|
||||
await inter.reply({ content: "All users have been initalized", flags: MessageFlags.Ephemeral });
|
||||
}
|
||||
}
|
||||
|
||||
@Discord()
|
||||
@SlashGroup({
|
||||
description: "The :3 Commands",
|
||||
name: "colonthree",
|
||||
name: "colonthree"
|
||||
})
|
||||
@SlashGroup("colonthree")
|
||||
export class ColonThree {
|
||||
|
|
@ -72,54 +54,45 @@ export class ColonThree {
|
|||
type: ApplicationCommandOptionType.User,
|
||||
})
|
||||
user: GuildMember,
|
||||
inter: CommandInteraction,
|
||||
inter: CommandInteraction
|
||||
) {
|
||||
const statsUser = (
|
||||
await db
|
||||
.select()
|
||||
.from(colonTable)
|
||||
.where(eq(colonTable.user, user?.id || inter.user.id))
|
||||
.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,
|
||||
});
|
||||
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,
|
||||
});
|
||||
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()!,
|
||||
})
|
||||
.setAuthor({ name: userObject.username, iconURL: userObject.avatarURL()! })
|
||||
.addFields(
|
||||
{
|
||||
name: "**Total :3 Sent**",
|
||||
name: '**Total :3 Sent**',
|
||||
value: `► **${statsUser.amount}** times`,
|
||||
inline: true,
|
||||
inline: true
|
||||
},
|
||||
{
|
||||
name: "**Average :3 per Message**",
|
||||
name: '**Average :3 per Message**',
|
||||
value: `► **${(statsUser.amount / statsUser.messages_count).toFixed(2)}**`,
|
||||
inline: true,
|
||||
inline: true
|
||||
},
|
||||
{
|
||||
name: "**Messages Count**",
|
||||
name: '**Messages Count**',
|
||||
value: `► **${statsUser.messages_count}**`,
|
||||
inline: true,
|
||||
},
|
||||
inline: true
|
||||
}
|
||||
);
|
||||
|
||||
await inter.reply( { embeds: [embed], flags: MessageFlags.Ephemeral });
|
||||
|
|
@ -141,29 +114,29 @@ export class ColonThree {
|
|||
type: ApplicationCommandOptionType.User,
|
||||
})
|
||||
y: GuildMember,
|
||||
inter: CommandInteraction,
|
||||
inter: CommandInteraction
|
||||
) {
|
||||
const xStats = (
|
||||
await db.select().from(colonTable).where(eq(colonTable.user, x.id))
|
||||
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,
|
||||
});
|
||||
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))
|
||||
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,
|
||||
});
|
||||
await inter.reply({ content: `Failed to get <@${y.id}>'s stats.`, flags: MessageFlags.Ephemeral });
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -175,41 +148,33 @@ export class ColonThree {
|
|||
{
|
||||
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,
|
||||
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,
|
||||
},
|
||||
);
|
||||
inline: true
|
||||
}
|
||||
)
|
||||
|
||||
await inter.reply({ embeds: [embed] });
|
||||
}
|
||||
|
||||
@Slash({ description: "Leaderboard" })
|
||||
async board(inter: CommandInteraction) {
|
||||
const theColonThreeLeaders = await db
|
||||
.select()
|
||||
const theColonThreeLeaders = await db.select()
|
||||
.from(colonTable)
|
||||
.orderBy(desc(colonTable.amount));
|
||||
|
||||
const topTen = theColonThreeLeaders
|
||||
.slice(0, 10)
|
||||
.filter((user) => user.amount >= 1);
|
||||
.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}.**`;
|
||||
const medal = rank === 1 ? "🥇" : rank === 2 ? "🥈" : rank === 3 ? "🥉" : `**${rank}.**`;
|
||||
|
||||
return `${medal} <@${user.user}> » **${user.amount}** :3 (avg: **${avg}**)`;
|
||||
});
|
||||
|
|
@ -218,11 +183,11 @@ export class ColonThree {
|
|||
.setTitle(`🏆 :3 Leaderboard`)
|
||||
.setDescription(leaderboardText.join("\n") || "*No data yet!*")
|
||||
.addFields({
|
||||
name: "Stats",
|
||||
name: 'Stats',
|
||||
value: `► **Tracking users:** ${theColonThreeLeaders.length}`,
|
||||
inline: false,
|
||||
inline: false
|
||||
})
|
||||
.setFooter({ text: "Keep using :3!!!!!!" })
|
||||
.setFooter({ text: 'Keep using :3!!!!!!' })
|
||||
.setTimestamp();
|
||||
|
||||
await inter.reply({ embeds: [embed] });
|
||||
|
|
@ -237,48 +202,40 @@ export class ColonThree {
|
|||
type: ApplicationCommandOptionType.String,
|
||||
})
|
||||
confirmation: string,
|
||||
inter: CommandInteraction,
|
||||
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,
|
||||
});
|
||||
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,
|
||||
});
|
||||
await inter.reply({ content: 'You need to type "confirm" to delete.', flags: MessageFlags.Ephemeral });
|
||||
}
|
||||
|
||||
@Slash({ description: "Start tracking" })
|
||||
async start(inter: CommandInteraction) {
|
||||
async start(
|
||||
inter: CommandInteraction
|
||||
) {
|
||||
const check = (
|
||||
await db
|
||||
.select()
|
||||
.from(colonTable)
|
||||
.where(eq(colonTable.user, inter.user.id))
|
||||
.where(eq(colonTable.user, inter.user.id)
|
||||
)
|
||||
)[0];
|
||||
|
||||
if (check) {
|
||||
await inter.reply({
|
||||
content: "Scythe already tracks your :3 data.",
|
||||
flags: MessageFlags.Ephemeral,
|
||||
});
|
||||
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,
|
||||
messages_count: 0
|
||||
});
|
||||
await inter.reply({ content: "Scythe starts tracking your :3 data again.", flags: MessageFlags.Ephemeral });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,103 +0,0 @@
|
|||
import {
|
||||
ApplicationCommandOptionType,
|
||||
MessageFlags,
|
||||
TextChannel,
|
||||
type CommandInteraction,
|
||||
} from "discord.js";
|
||||
import { Discord, Slash, SlashOption } from "discordx";
|
||||
import db from "../db";
|
||||
import { byeTable, greetsTable } from "../db/schema";
|
||||
import { sql } from "drizzle-orm";
|
||||
|
||||
@Discord()
|
||||
export class GreetCmds {
|
||||
@Slash({ name: "hello-setup", description: "set up the hello message :3" })
|
||||
async helloSetup(
|
||||
@SlashOption({
|
||||
name: "channel",
|
||||
description: "channel to send in",
|
||||
required: true,
|
||||
type: ApplicationCommandOptionType.Channel,
|
||||
})
|
||||
channel: TextChannel,
|
||||
@SlashOption({
|
||||
name: "message",
|
||||
description: "message to send",
|
||||
required: true,
|
||||
type: ApplicationCommandOptionType.String,
|
||||
})
|
||||
message: string,
|
||||
inter: CommandInteraction,
|
||||
) {
|
||||
if (inter.user.id != inter.guild?.ownerId) {
|
||||
return await inter.reply({
|
||||
content: "you cannot use this command u goober!",
|
||||
flags: MessageFlags.Ephemeral,
|
||||
});
|
||||
}
|
||||
if (!inter.guildId) {
|
||||
return await inter.reply("you can't use this in DMs silly!");
|
||||
}
|
||||
await db
|
||||
.insert(greetsTable)
|
||||
.values({
|
||||
guild: inter.guildId,
|
||||
channel: channel.id,
|
||||
message,
|
||||
})
|
||||
.onConflictDoUpdate({
|
||||
target: greetsTable.guild,
|
||||
set: { message, channel: channel.id },
|
||||
setWhere: sql`guild = ${inter.guildId}`,
|
||||
});
|
||||
await inter.reply({
|
||||
content: "setup done! :3",
|
||||
flags: MessageFlags.Ephemeral,
|
||||
});
|
||||
}
|
||||
|
||||
@Slash({ name: "bye-setup", description: "set up the bye message :3" })
|
||||
async byeSetup(
|
||||
@SlashOption({
|
||||
name: "channel",
|
||||
description: "channel to send in",
|
||||
required: true,
|
||||
type: ApplicationCommandOptionType.Channel,
|
||||
})
|
||||
channel: TextChannel,
|
||||
@SlashOption({
|
||||
name: "message",
|
||||
description: "message to send",
|
||||
required: true,
|
||||
type: ApplicationCommandOptionType.String,
|
||||
})
|
||||
message: string,
|
||||
inter: CommandInteraction,
|
||||
) {
|
||||
if (inter.user.id != inter.guild?.ownerId) {
|
||||
return await inter.reply({
|
||||
content: "you cannot use this command u goober!",
|
||||
flags: MessageFlags.Ephemeral,
|
||||
});
|
||||
}
|
||||
if (!inter.guildId) {
|
||||
return await inter.reply("you can't use this in DMs silly!");
|
||||
}
|
||||
await db
|
||||
.insert(byeTable)
|
||||
.values({
|
||||
guild: inter.guildId,
|
||||
channel: channel.id,
|
||||
message,
|
||||
})
|
||||
.onConflictDoUpdate({
|
||||
target: byeTable.guild,
|
||||
set: { message, channel: channel.id },
|
||||
setWhere: sql`guild = ${inter.guildId}`,
|
||||
});
|
||||
await inter.reply({
|
||||
content: "setup done! :3",
|
||||
flags: MessageFlags.Ephemeral,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
import {
|
||||
ApplicationCommandOptionType,
|
||||
CommandInteraction,
|
||||
MessageFlags,
|
||||
type TextChannel,
|
||||
} from "discord.js";
|
||||
import { Discord, Slash, SlashOption } from "discordx";
|
||||
import db from "../db";
|
||||
import { introTable } from "../db/schema";
|
||||
import { sql } from "drizzle-orm";
|
||||
|
||||
@Discord()
|
||||
export class Intro {
|
||||
@Slash({ name: "intro-purge", description: "sets up intro purge" })
|
||||
async introPurge(
|
||||
@SlashOption({
|
||||
name: "channel",
|
||||
description: "channel to check",
|
||||
required: true,
|
||||
type: ApplicationCommandOptionType.Channel,
|
||||
})
|
||||
channel: TextChannel,
|
||||
inter: CommandInteraction,
|
||||
) {
|
||||
await db
|
||||
.insert(introTable)
|
||||
.values({
|
||||
guild: inter.guildId!,
|
||||
channel: channel.id,
|
||||
})
|
||||
.onConflictDoUpdate({
|
||||
target: introTable.guild,
|
||||
set: { channel: channel.id },
|
||||
setWhere: sql`guild = ${inter.guildId}`,
|
||||
});
|
||||
await inter.reply({content: "intro setup done!", flags: MessageFlags.Ephemeral});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +1,4 @@
|
|||
import {
|
||||
ActionRowBuilder,
|
||||
ButtonBuilder,
|
||||
ButtonStyle,
|
||||
EmbedBuilder,
|
||||
MessageFlags,
|
||||
type CommandInteraction,
|
||||
type TextChannel,
|
||||
} from "discord.js";
|
||||
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder, Message, MessageFlags, type CommandInteraction, type TextChannel } from "discord.js";
|
||||
import { Discord, Slash } from "discordx";
|
||||
|
||||
@Discord()
|
||||
|
|
@ -14,33 +6,30 @@ export class TicketCmd {
|
|||
@Slash({ name: "setup-ticket", description: "Setup the tickets" })
|
||||
async snipe(inter: CommandInteraction) {
|
||||
if (inter.user.id != Bun.env.OWNER) {
|
||||
await inter.reply({
|
||||
content: "You're not the owner",
|
||||
flags: MessageFlags.Ephemeral,
|
||||
});
|
||||
await inter.reply({ content: "You're not the owner", flags: MessageFlags.Ephemeral });
|
||||
return;
|
||||
}
|
||||
|
||||
const channel = inter.client.channels.cache.get(
|
||||
Bun.env.TICKET_CHANNEL,
|
||||
) as TextChannel;
|
||||
const channel = inter.client.channels.cache.get(Bun.env.TICKET_CHANNEL) as TextChannel;
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(`Tickets`)
|
||||
.setDescription(`Click the button to make a ticket! :3`);
|
||||
.setDescription(
|
||||
`Click the button to make a ticket! :3`,
|
||||
);
|
||||
|
||||
const createButton = new ButtonBuilder()
|
||||
.setCustomId("createTicket")
|
||||
.setLabel("Create Ticket")
|
||||
.setCustomId('createTicket')
|
||||
.setLabel('Create Ticket')
|
||||
.setStyle(ButtonStyle.Primary);
|
||||
|
||||
const row = new ActionRowBuilder<ButtonBuilder>().addComponents(
|
||||
createButton,
|
||||
);
|
||||
|
||||
const row = new ActionRowBuilder<ButtonBuilder>()
|
||||
.addComponents(createButton);
|
||||
|
||||
await channel.send({
|
||||
embeds: [embed],
|
||||
components: [row],
|
||||
components: [row]
|
||||
});
|
||||
|
||||
await inter.reply({ content: "Done", flags: MessageFlags.Ephemeral });
|
||||
|
|
|
|||
|
|
@ -1,37 +1,19 @@
|
|||
import {
|
||||
ApplicationCommandOptionType,
|
||||
type CommandInteraction,
|
||||
type TextChannel,
|
||||
} from "discord.js";
|
||||
import { Discord, Slash, SlashOption } from "discordx";
|
||||
import db from "../db";
|
||||
import { uptimeTable } from "../db/schema";
|
||||
import type { CommandInteraction, TextChannel } from "discord.js";
|
||||
import { Discord, Slash } from "discordx";
|
||||
|
||||
@Discord()
|
||||
export class UptimeCmd {
|
||||
@Slash({ name: "uptime-setup", description: "set up uptime cmd" })
|
||||
async uptimeCmd(
|
||||
@SlashOption({
|
||||
name: "channel",
|
||||
description: "channel to send in",
|
||||
required: true,
|
||||
type: ApplicationCommandOptionType.Channel,
|
||||
})
|
||||
channel: TextChannel,
|
||||
inter: CommandInteraction,
|
||||
) {
|
||||
if (inter.user.id != inter.guild?.ownerId) {
|
||||
return await inter.reply("you cannot run this command :p");
|
||||
async uptimeCmd(inter: CommandInteraction) {
|
||||
if (inter.user.id != Bun.env.OWNER) {
|
||||
await inter.reply("you cannot run this command :p");
|
||||
return;
|
||||
}
|
||||
|
||||
const msg = await channel.send(
|
||||
const channel = inter.client.channels.cache.get(
|
||||
Bun.env.SCYTHE_CHANNEL,
|
||||
) as TextChannel;
|
||||
await channel.send(
|
||||
`bot is up, last ping: <t:${Math.floor(Date.now()/1000)}:f> | if the ping was more than 1 minute ago, cosmic needs to check the bot lol :3`,
|
||||
);
|
||||
|
||||
await db.insert(uptimeTable).values({
|
||||
guild: inter.guildId!,
|
||||
channel: channel.id,
|
||||
message: msg.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import {
|
|||
ChannelType,
|
||||
EmbedBuilder,
|
||||
MessageFlags,
|
||||
PermissionsBitField,
|
||||
PermissionsBitField
|
||||
} from "discord.js";
|
||||
|
||||
import { ButtonComponent, Discord } from "discordx";
|
||||
|
|
@ -20,14 +20,11 @@ import { eq } from "drizzle-orm";
|
|||
export class TicketComponenets {
|
||||
@ButtonComponent({ id: "createTicket" })
|
||||
async createHandler(inter: ButtonInteraction): Promise<void> {
|
||||
const check = await db
|
||||
.select()
|
||||
.from(ticketsTable)
|
||||
.where(eq(ticketsTable.user, inter.user.id));
|
||||
const check = await db.select().from(ticketsTable).where(eq(ticketsTable.user, inter.user.id));
|
||||
if (check.length >= 1) {
|
||||
await inter.reply({
|
||||
content: "You already have a ticket open.",
|
||||
flags: MessageFlags.Ephemeral,
|
||||
flags: MessageFlags.Ephemeral
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
|
@ -42,52 +39,45 @@ export class TicketComponenets {
|
|||
},
|
||||
{
|
||||
id: inter.user.id,
|
||||
allow: [
|
||||
PermissionsBitField.Flags.ViewChannel,
|
||||
PermissionsBitField.Flags.SendMessages,
|
||||
],
|
||||
allow: [PermissionsBitField.Flags.ViewChannel, PermissionsBitField.Flags.SendMessages],
|
||||
},
|
||||
{
|
||||
id: Bun.env.MOD_ROLE,
|
||||
allow: [
|
||||
PermissionsBitField.Flags.ViewChannel,
|
||||
PermissionsBitField.Flags.SendMessages,
|
||||
],
|
||||
},
|
||||
],
|
||||
allow: [PermissionsBitField.Flags.ViewChannel, PermissionsBitField.Flags.SendMessages],
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const category = inter.guild?.channels.cache.get(
|
||||
Bun.env.TICKET_CATEGORY,
|
||||
) as CategoryChannel;
|
||||
const category = inter.guild?.channels.cache.get(Bun.env.TICKET_CATEGORY) as CategoryChannel;
|
||||
channel = await channel.setParent(category);
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(`Tickets`)
|
||||
.setDescription(`<@${inter.user.id}> here's your ticket!`);
|
||||
.setDescription(
|
||||
`<@${inter.user.id}> here's your ticket!`,
|
||||
);
|
||||
|
||||
const deleteButton = new ButtonBuilder()
|
||||
.setCustomId("deleteTicket")
|
||||
.setLabel("Delete Ticket")
|
||||
.setCustomId('deleteTicket')
|
||||
.setLabel('Delete Ticket')
|
||||
.setStyle(ButtonStyle.Primary);
|
||||
|
||||
const row = new ActionRowBuilder<ButtonBuilder>().addComponents(
|
||||
deleteButton,
|
||||
);
|
||||
const row = new ActionRowBuilder<ButtonBuilder>()
|
||||
.addComponents(deleteButton);
|
||||
|
||||
await channel.send({
|
||||
embeds: [embed],
|
||||
components: [row],
|
||||
components: [row]
|
||||
});
|
||||
|
||||
await inter.reply({
|
||||
content: `<#${channel.id}>`,
|
||||
flags: MessageFlags.Ephemeral,
|
||||
});
|
||||
flags: MessageFlags.Ephemeral
|
||||
})
|
||||
|
||||
await db.insert(ticketsTable).values({
|
||||
user: inter.user.id,
|
||||
channel: channel.id,
|
||||
channel: channel.id
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
import { drizzle } from "drizzle-orm/libsql";
|
||||
import { drizzle } from 'drizzle-orm/libsql';
|
||||
|
||||
export default drizzle(Bun.env.DB);
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
CREATE TABLE `bye` (
|
||||
`guild` text PRIMARY KEY NOT NULL,
|
||||
`channel` text NOT NULL,
|
||||
`message` text NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `greets` (
|
||||
`guild` text PRIMARY KEY NOT NULL,
|
||||
`channel` text NOT NULL,
|
||||
`message` text NOT NULL
|
||||
);
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
CREATE TABLE `intro` (
|
||||
`guild` text PRIMARY KEY NOT NULL,
|
||||
`channel` text NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `uptime` (
|
||||
`guild` text PRIMARY KEY NOT NULL,
|
||||
`channel` text NOT NULL,
|
||||
`message` text NOT NULL
|
||||
);
|
||||
|
|
@ -1,135 +0,0 @@
|
|||
{
|
||||
"version": "6",
|
||||
"dialect": "sqlite",
|
||||
"id": "2218a8ed-3583-479c-b142-997455b0c7dc",
|
||||
"prevId": "a3e18d09-b7d4-48e3-8920-1fa55c43ee70",
|
||||
"tables": {
|
||||
"bye": {
|
||||
"name": "bye",
|
||||
"columns": {
|
||||
"guild": {
|
||||
"name": "guild",
|
||||
"type": "text",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"channel": {
|
||||
"name": "channel",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"message": {
|
||||
"name": "message",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraints": {}
|
||||
},
|
||||
"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": {}
|
||||
},
|
||||
"greets": {
|
||||
"name": "greets",
|
||||
"columns": {
|
||||
"guild": {
|
||||
"name": "guild",
|
||||
"type": "text",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"channel": {
|
||||
"name": "channel",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"message": {
|
||||
"name": "message",
|
||||
"type": "text",
|
||||
"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": {}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,190 +0,0 @@
|
|||
{
|
||||
"version": "6",
|
||||
"dialect": "sqlite",
|
||||
"id": "fb3b9c6d-7d3b-4651-b230-e163bf08b586",
|
||||
"prevId": "2218a8ed-3583-479c-b142-997455b0c7dc",
|
||||
"tables": {
|
||||
"bye": {
|
||||
"name": "bye",
|
||||
"columns": {
|
||||
"guild": {
|
||||
"name": "guild",
|
||||
"type": "text",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"channel": {
|
||||
"name": "channel",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"message": {
|
||||
"name": "message",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraints": {}
|
||||
},
|
||||
"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": {}
|
||||
},
|
||||
"greets": {
|
||||
"name": "greets",
|
||||
"columns": {
|
||||
"guild": {
|
||||
"name": "guild",
|
||||
"type": "text",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"channel": {
|
||||
"name": "channel",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"message": {
|
||||
"name": "message",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraints": {}
|
||||
},
|
||||
"intro": {
|
||||
"name": "intro",
|
||||
"columns": {
|
||||
"guild": {
|
||||
"name": "guild",
|
||||
"type": "text",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"channel": {
|
||||
"name": "channel",
|
||||
"type": "text",
|
||||
"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": {}
|
||||
},
|
||||
"uptime": {
|
||||
"name": "uptime",
|
||||
"columns": {
|
||||
"guild": {
|
||||
"name": "guild",
|
||||
"type": "text",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"channel": {
|
||||
"name": "channel",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"message": {
|
||||
"name": "message",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraints": {}
|
||||
}
|
||||
},
|
||||
"views": {},
|
||||
"enums": {},
|
||||
"_meta": {
|
||||
"schemas": {},
|
||||
"tables": {},
|
||||
"columns": {}
|
||||
},
|
||||
"internal": {
|
||||
"indexes": {}
|
||||
}
|
||||
}
|
||||
|
|
@ -15,20 +15,6 @@
|
|||
"when": 1742844574438,
|
||||
"tag": "0001_warm_ego",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 2,
|
||||
"version": "6",
|
||||
"when": 1742864217240,
|
||||
"tag": "0002_colorful_colleen_wing",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 3,
|
||||
"version": "6",
|
||||
"when": 1742927150677,
|
||||
"tag": "0003_clumsy_mephistopheles",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -4,36 +4,13 @@ import type { InferSelectModel } from "drizzle-orm";
|
|||
|
||||
export const ticketsTable = sqliteTable("tickets", {
|
||||
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 const greetsTable = sqliteTable("greets", {
|
||||
guild: text().primaryKey().notNull(),
|
||||
channel: text().notNull(),
|
||||
message: text().notNull(),
|
||||
});
|
||||
|
||||
export const byeTable = sqliteTable("bye", {
|
||||
guild: text().primaryKey().notNull(),
|
||||
channel: text().notNull(),
|
||||
message: text().notNull(),
|
||||
});
|
||||
|
||||
export const uptimeTable = sqliteTable("uptime", {
|
||||
guild: text().primaryKey(),
|
||||
channel: text().notNull(),
|
||||
message: text().notNull(),
|
||||
});
|
||||
|
||||
export const introTable = sqliteTable("intro", {
|
||||
guild: text().primaryKey(),
|
||||
channel: text().notNull(),
|
||||
});
|
||||
messages_count: int().notNull()
|
||||
})
|
||||
|
||||
export type ColonThreeType = InferSelectModel<typeof colonTable>;
|
||||
|
|
@ -2,63 +2,39 @@ import type { TextChannel } from "discord.js";
|
|||
import { Client, Discord, On, type ArgsOf } from "discordx";
|
||||
|
||||
import db from "../db";
|
||||
import { byeTable, colonTable, greetsTable } from "../db/schema";
|
||||
import { colonTable } from "../db/schema";
|
||||
import { eq } from "drizzle-orm";
|
||||
|
||||
@Discord()
|
||||
export class MemberEvents {
|
||||
@On({ event: "guildMemberAdd" })
|
||||
async memberAdd([member]: ArgsOf<"guildMemberAdd">, client: Client) {
|
||||
const greetRes = await db
|
||||
.select()
|
||||
.from(greetsTable)
|
||||
.where(eq(greetsTable.guild, member.guild.id));
|
||||
if (greetRes.length > 0) {
|
||||
const channel = client.channels.cache.get(
|
||||
greetRes[0].channel,
|
||||
) as TextChannel;
|
||||
const channel = client.channels.cache.get(Bun.env.WELCOME!) as TextChannel;
|
||||
await channel.send(
|
||||
greetRes[0].message.replace("{user}", `<@${member.user.id}>`),
|
||||
`Welcome to **${member.guild.name}** <@${member.user.id}> ! You are member #${member.guild.memberCount}! Get a color role and Operating System role(s) in the Channels & Roles section if you want and enjoy your stay <3`,
|
||||
);
|
||||
}
|
||||
|
||||
if (member.user.bot) {
|
||||
const botRole = member.guild.roles.cache.get(Bun.env.BOT_ROLE!);
|
||||
if (botRole) {
|
||||
await member.roles.add(botRole);
|
||||
}
|
||||
} else {
|
||||
if(Date.now() - member.user.createdAt.getTime() < 1000 * 60 * 60 * 24 * 7) {
|
||||
try {
|
||||
await member.send("to protect against raids, bots, and other disturbances, accounts under a week old are kicked upon joining. please wait for your account to mature before rejoining.")
|
||||
} catch(_) {}
|
||||
await member.kick("account less than week old")
|
||||
return;
|
||||
}
|
||||
await db.insert(colonTable).values({
|
||||
user: member.id,
|
||||
amount: 0,
|
||||
messages_count: 0,
|
||||
messages_count: 0
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@On({ event: "guildMemberRemove" })
|
||||
async memberRemove([member]: ArgsOf<"guildMemberRemove">, client: Client) {
|
||||
const byeRes = await db
|
||||
.select()
|
||||
.from(byeTable)
|
||||
.where(eq(byeTable.guild, member.guild.id));
|
||||
if (byeRes.length > 0) {
|
||||
const channel = client.channels.cache.get(
|
||||
byeRes[0].channel,
|
||||
) as TextChannel;
|
||||
await channel.send(
|
||||
byeRes[0].message.replace("{user}", `${member.user.username}`),
|
||||
);
|
||||
}
|
||||
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 db.delete(colonTable).where(eq(colonTable.user, member.id));
|
||||
await db
|
||||
.delete(colonTable)
|
||||
.where(eq(colonTable.user, member.id));
|
||||
}
|
||||
|
||||
@On({ event: "guildMemberUpdate" })
|
||||
|
|
|
|||
|
|
@ -46,20 +46,14 @@ export class MessageEvents {
|
|||
if (cThreeRegex.test(msg.content)) {
|
||||
let colonThrees = msg.content.match(cThreeRegex);
|
||||
|
||||
await db
|
||||
.update(colonTable)
|
||||
.set({
|
||||
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));
|
||||
}).where(eq(colonTable.user, msg.author.id));
|
||||
} else {
|
||||
await db
|
||||
.update(colonTable)
|
||||
.set({
|
||||
await db.update(colonTable).set({
|
||||
messages_count: sql`${colonTable.messages_count} + 1`,
|
||||
})
|
||||
.where(eq(colonTable.user, msg.author.id));
|
||||
}).where(eq(colonTable.user, msg.author.id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { Client, Discord, On, type ArgsOf } from "discordx";
|
||||
import { underageCheck } from "../utils/underage";
|
||||
import { bumpRemind } from "../utils/bump";
|
||||
import {stat, mkdir} from "fs/promises";
|
||||
import { uptimeLoop } from "../utils/uptime-loop";
|
||||
import { introCheck } from "../utils/intro-check";
|
||||
|
||||
@Discord()
|
||||
export class Ready {
|
||||
|
|
@ -12,6 +12,9 @@ export class Ready {
|
|||
await client.initApplicationCommands();
|
||||
await client.guilds.fetch();
|
||||
const members = client.guilds.cache.get(Bun.env.GUILD!)?.members;
|
||||
if(!((await stat("data")).isDirectory())) {
|
||||
await mkdir("data")
|
||||
}
|
||||
if (!(await Bun.file("bump.json").exists())) {
|
||||
await Bun.write("bump.json", "{}");
|
||||
}
|
||||
|
|
@ -20,6 +23,5 @@ export class Ready {
|
|||
}
|
||||
bumpRemind(client);
|
||||
uptimeLoop(client);
|
||||
introCheck(client);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,9 +22,7 @@ const client = new Client({
|
|||
client.on("error", console.error);
|
||||
|
||||
const run = async () => {
|
||||
await importx(
|
||||
`${dirname(import.meta.url)}/{events,commands,components}/**/*.ts`,
|
||||
);
|
||||
await importx(`${dirname(import.meta.url)}/{events,commands,components}/**/*.ts`);
|
||||
client.login(Bun.env.TOKEN!);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,22 +0,0 @@
|
|||
import type { Client } from "discordx";
|
||||
import db from "../db";
|
||||
import { introTable } from "../db/schema";
|
||||
import type { TextChannel } from "discord.js";
|
||||
import { sleep } from "./underage";
|
||||
|
||||
export const introCheck = async (client: Client) => {
|
||||
while (true) {
|
||||
const channelRes = await db.select().from(introTable);
|
||||
for (const c of channelRes) {
|
||||
const channel = client.channels.cache.get(c.channel) as TextChannel;
|
||||
const guild = client.guilds.cache.get(c.guild);
|
||||
const msgs = await channel.messages.fetch({ limit: 10 });
|
||||
for (const m of msgs) {
|
||||
if (!guild?.members.cache.has(m[1].author.id)) {
|
||||
await m[1].delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
await sleep(1000 * 60 * 20);
|
||||
}
|
||||
};
|
||||
|
|
@ -1,19 +1,16 @@
|
|||
import type { Client } from "discordx";
|
||||
import { sleep } from "./underage";
|
||||
import type { TextChannel } from "discord.js";
|
||||
import db from "../db";
|
||||
import { uptimeTable } from "../db/schema";
|
||||
|
||||
export const uptimeLoop = async (client: Client) => {
|
||||
while (true) {
|
||||
await sleep(30 * 1000);
|
||||
const uptimeRes = await db.select().from(uptimeTable);
|
||||
for (const i of uptimeRes) {
|
||||
const channel = client.channels.cache.get(i.channel) as TextChannel;
|
||||
const msg = await channel.messages.fetch(i.message);
|
||||
const channel = client.channels.cache.get(
|
||||
Bun.env.SCYTHE_CHANNEL,
|
||||
) as TextChannel;
|
||||
const msg = await channel.messages.fetch(Bun.env.UPTIME_MESSAGE);
|
||||
await msg.edit(
|
||||
`bot is up, last ping: <t:${Math.floor(Date.now()/1000)}:f> | if the ping was more than 1 minute ago, cosmic needs to check the bot lol :3`,
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue