diff --git a/prisma/migrations/20240813105028_new_defaults/migration.sql b/prisma/migrations/20240813105028_new_defaults/migration.sql new file mode 100644 index 0000000..c5fec17 --- /dev/null +++ b/prisma/migrations/20240813105028_new_defaults/migration.sql @@ -0,0 +1,3 @@ +-- AlterTable +ALTER TABLE "User" ALTER COLUMN "levelCard" SET DEFAULT 'https://cdn.mikn.dev/bot-assets/mikanbot/default-lvlcard.png', +ALTER COLUMN "rankColor" SET DEFAULT 'FF7700'; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 6f9d4db..9b26c48 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -18,8 +18,8 @@ model User { id String @id premium Boolean @default(false) premiumUntil DateTime? - levelCard String @default("https://cdn.mikn.dev/mikan-bg.png") - rankColor String @default("#FF7700") + levelCard String @default("https://cdn.mikn.dev/bot-assets/mikanbot/default-lvlcard.png") + rankColor String @default("FF7700") mdUID String @default("unlinked") } diff --git a/src/api/server.ts b/src/api/server.ts index bc450ea..d0e04d6 100644 --- a/src/api/server.ts +++ b/src/api/server.ts @@ -1,6 +1,8 @@ import { Elysia } from "elysia"; import { dmUser } from ".."; +import { PrismaClient } from "@prisma/client"; +const prisma = new PrismaClient(); const app = new Elysia(); app.post("/accLink", async ({ query, body }) => { @@ -18,6 +20,27 @@ app.post("/accLink", async ({ query, body }) => { if (key !== process.env.API_SIGNING_KEY) return new Response("Invalid key", { status: 401 }); + + const user = await prisma.user.findUnique({ + where: { + id: uid, + }, + }); + + if (!user) return new Response("User not found", { status: 404 }); + + await prisma.user.update({ + where: { + id: uid, + }, + data: { + mdUID: acc, + }, + }); + + await dmUser(uid, "MikanDev Accounts", `Your account has been linked!\n\n**MikanDev UID:** ${acc}\n**Discord ID:**${uid}`); + + return new Response("Account linked", { status: 200 }); }); app.post("/dm", async ({ query, body }) => { diff --git a/src/commands/mikandev.ts b/src/commands/mikandev.ts new file mode 100644 index 0000000..3892e8c --- /dev/null +++ b/src/commands/mikandev.ts @@ -0,0 +1,63 @@ +import { + type CommandInteraction, + EmbedBuilder, + ButtonBuilder, + ActionRowBuilder, + ButtonStyle, + Colors, +} from "discord.js"; +import { PrismaClient } from "@prisma/client"; + +const prisma = new PrismaClient(); + +export default { + name: "mikandev", + description: "Manage your MikanDev account", + cooldown: 0, + isPremium: false, + botPermissions: [], + userPermissions: [], + validations: [], + slashCommand: { + enabled: true, + options: [], + }, + interactionRun: async (interaction: CommandInteraction) => { + const userDb = await prisma.user.findUnique({ + where: { + id: interaction.user.id, + }, + }); + const uid = userDb?.mdUID; + + if (uid === "unlinked") { + const embed = new EmbedBuilder() + .setTitle("MikanDev Account") + .setDescription("You haven't linked your MikanDev account yet!") + .setColor(Colors.Red); + const button = new ButtonBuilder() + .setStyle(ButtonStyle.Link) + .setLabel("Link Account") + .setURL( + `https://mikn.dev/account/link?app=mikanbot&discord=${interaction.user.id}`, + ); + + const row = new ActionRowBuilder().addComponents(button); + + await interaction.reply({ + embeds: [embed], + components: [row], + ephemeral: true, + }); + } + if (uid !== "unlinked") { + const embed = new EmbedBuilder() + .setTitle("MikanDev Account") + .setDescription( + `You have linked your MikanDev account with UID: ${uid}`, + ) + .setColor(Colors.Green); + await interaction.reply({ embeds: [embed] }); + } + }, +}; diff --git a/src/commands/rank.ts b/src/commands/rank.ts index 5016049..0ef378b 100644 --- a/src/commands/rank.ts +++ b/src/commands/rank.ts @@ -20,9 +20,13 @@ function getLevelFromXP(xp: number): number { function getXPfromLevel(level: number): number { let xp = 0; + let xpRequired = 50; + for (let i = 1; i < level; i++) { - xp += 50 * 2 ** (i - 1); + xp += xpRequired; + xpRequired *= 2; } + return xp; } @@ -55,9 +59,10 @@ export default { id: interaction.user.id, }, }); - const uid = userDb?.mdUID - const premium = userDb?.premium - const bg = userDb?.levelCard + const uid = userDb?.mdUID; + const premium = userDb?.premium; + const bg = userDb?.levelCard; + const color = userDb?.rankColor; const lvlDB = await prisma.guildLvl.findMany({ where: { @@ -68,24 +73,29 @@ export default { }, }); - const rank = lvlDB.findIndex((x) => x.id === `${interaction.guild?.id}-${interaction.user.id}`) + 1; + const rank = + lvlDB.findIndex( + (x) => + x.id === `${interaction.guild?.id}-${interaction.user.id}`, + ) + 1; - const userLevel = lvlDB.find((x) => x.id === `${interaction.guild?.id}-${interaction.user.id}`); + const userLevel = lvlDB.find( + (x) => x.id === `${interaction.guild?.id}-${interaction.user.id}`, + ); - const level = userLevel?.level; + const level = userLevel?.level || 1; const xp = userLevel?.xp; const xpRequired = getXPfromLevel(level + 1); - const url = `${process.env.IMG_BACKEND}/level?level=${level}&username=${username}¤tXP=${xp}&totalXP=${xpRequired}&rank=${rank}&mdAcc=${uid !== "unlinked"}&premium=${premium}&avatar=${avatar}&bg=${bg}`; + const url = `${process.env.IMG_BACKEND}/level?level=${level}&username=${username}¤tXP=${xp}&totalXP=${xpRequired}&rank=${rank}&mdAcc=${uid !== "unlinked"}&premium=${premium}&avatar=${avatar}&bg=${bg}&color=${color}`; const response = await fetch(url); - + const buffer = Buffer.from(await response.arrayBuffer()); - const attachment = new AttachmentBuilder(buffer,{ name: "rank.png" }); + const attachment = new AttachmentBuilder(buffer, { name: "rank.png" }); interaction.editReply({ content: "", files: [attachment] }); }, }; - diff --git a/src/handlers/lvl.ts b/src/handlers/lvl.ts index c76a47f..757ac80 100644 --- a/src/handlers/lvl.ts +++ b/src/handlers/lvl.ts @@ -61,10 +61,13 @@ export async function handleLevel(message: Message) { if (currentCooldown > new Date()) return; const cooldownTime = new Date(Date.now() + cooldown); const level = getLevelFromXP(newXP); - const lvlMessage = levelMessage?.replace(/{user}/g, message.author.toString()).replace( /{level}/g, level.toString()); + const lvlMessage = levelMessage + ?.replace(/{user}/g, message.author.toString()) + .replace(/{level}/g, level.toString()); if (lvlDB.level < level) { message.channel.send( - lvlMessage || `Congratulations ${message.author.toString()}! You have leveled up to level ${level}!`, + lvlMessage || + `Congratulations ${message.author.toString()}! You have leveled up to level ${level}!`, ); } await prisma.guildLvl.update({ @@ -78,4 +81,4 @@ export async function handleLevel(message: Message) { }, }); } -} \ No newline at end of file +} diff --git a/src/index.ts b/src/index.ts index 0c8d78a..1c7faaa 100644 --- a/src/index.ts +++ b/src/index.ts @@ -37,9 +37,13 @@ client.on("ready", () => { }); client.on("interactionCreate", async (interaction) => { - if (!interaction.isCommand()) return; - console.log(`Received command: ${interaction.commandName}`); - await handleCommand(interaction); + if (interaction.isCommand()) { + console.log(`Received command: ${interaction.commandName}`); + await handleCommand(interaction); + } + if (interaction.isButton()) { + console.log(`Received button: ${interaction.customId}`); + } }); client.on("messageCreate", async (message) => {