diff --git a/apps/golinks-v2/src/api/discord.ts b/apps/golinks-v2/src/api/discord.ts index 55e67c9..4506ed8 100644 --- a/apps/golinks-v2/src/api/discord.ts +++ b/apps/golinks-v2/src/api/discord.ts @@ -2,6 +2,7 @@ import { OpenAPIRoute, Num, Bool, Str, contentJson } from 'chanfana'; import { z } from 'zod'; import { Context } from 'hono'; import { DiscordInvites } from 'types'; +import { addDiscordInvite } from 'lib/db'; export class DiscordInviteLinkCreate extends OpenAPIRoute { schema = { @@ -21,15 +22,17 @@ export class DiscordInviteLinkCreate extends OpenAPIRoute { ], request: { body: { - 'application/json': { - schema: z.object({ - slug: Str({ required: true }), - inviteCode: Str({ default: 'exmaple' }), - name: Str({ default: 'Example server' }), - description: Str({ default: 'This is a example Discord server.' }), - nsfw: z.boolean().default(false), - is_active: z.boolean().default(true), - }), + content: { + "application/json": { + schema: z.object({ + slug: Str({ required: true }), + inviteCode: Str({ default: 'exmaple' }), + name: Str({ default: 'Example server' }), + description: Str({ default: 'This is a example Discord server.' }), + nsfw: z.boolean().default(false), + is_active: z.boolean().default(true), + }), + } }, }, }, @@ -47,9 +50,32 @@ export class DiscordInviteLinkCreate extends OpenAPIRoute { }, }; async handle(c: Context) { - const data = await this.getValidatedData(); - const { body } = data; - return body; + try { + const data = await this.getValidatedData(); + const linkToCreate = data.body; + console.log(`[golinks-api] received body for link creation ${JSON.stringify(linkToCreate)}`); + const { slug, inviteCode, name, description, is_active, nsfw } = linkToCreate; + + const result = await addDiscordInvite(c.env.golinks, slug, inviteCode, name, description, is_active, nsfw) + return c.newResponse( + JSON.stringify({ + success: true, + result: result, + }), + 200, + { 'Content-Type': 'application/json' }, + ); + } catch (error) { + console.error(error) + return c.newResponse( + JSON.stringify({ + success: false, + error: `${error.name}:${error.code}` || "An unexpected error occurred while adding the invite code to database." + }), + 500, + { 'Content-Type': 'application/json' }, + ) + } } } diff --git a/apps/golinks-v2/src/api/golinks.ts b/apps/golinks-v2/src/api/golinks.ts index 2c0044e..8dcfcc8 100644 --- a/apps/golinks-v2/src/api/golinks.ts +++ b/apps/golinks-v2/src/api/golinks.ts @@ -17,7 +17,7 @@ export class GoLinkCreate extends OpenAPIRoute { type: 'string', }, required: true, - description: 'Admin API key', + description: 'Admin API key for golinks API', }, ], request: { @@ -41,12 +41,14 @@ export class GoLinkCreate extends OpenAPIRoute { responses: { '200': { description: 'Returns the generated golink information', - contentJson: { - schema: z.object({ - success: Bool(), - result: GoLinks - }) - } + content: { + 'application/json': { + schema: z.object({ + success: Bool(), + result: GoLinks, + }), + }, + }, }, '400': { description: 'Existing entry found', @@ -68,37 +70,20 @@ export class GoLinkCreate extends OpenAPIRoute { console.log(`[golinks-api] received body for link creation ${JSON.stringify(linkToCreate)}`); const slug = linkToCreate.slug !== undefined ? linkToCreate.slug : generateSlug(12); - const result = addGoLink(c.env.golinks, slug, linkToCreate.targetUrl, linkToCreate.is_active) - .then((value) => { - return { - success: true, - result: value, - }; - }) - .catch((err) => { - if (err.code == 'P2002') { - return c.newResponse( - JSON.stringify({ - success: false, - error: `Existing entry found (error code: ${err.name}:${err.code})`, - }), - 400, - { 'Content-Type': 'application/json' }, - ); - } else { - return c.newResponse( - JSON.stringify({ - success: false, - error: 'Something went wrong on the backend. The devDebug object should provide hints for devs on where to fix.', - devDebug: err, - }), - 500, - { 'Content-Type': 'application/json' }, - ); - } - }); + const result = await addGoLink(c.env.golinks, slug, linkToCreate.targetUrl, linkToCreate.is_active); - return result; + if (result) { + return c.newResponse( + JSON.stringify({ + success: true, + result: result, + }), + 200, + { 'Content-Type': 'application/json' }, + ); + } else { + return c.newResponse('Something went wrong', 400); + } } } diff --git a/apps/golinks-v2/src/lib/db.ts b/apps/golinks-v2/src/lib/db.ts index 3013320..5e6b7ab 100644 --- a/apps/golinks-v2/src/lib/db.ts +++ b/apps/golinks-v2/src/lib/db.ts @@ -1,4 +1,4 @@ -import { GoLink, PrismaClient } from "@prisma/client" +import { DiscordInviteLink, GoLink, PrismaClient } from "@prisma/client" import { PrismaD1 } from "@prisma/adapter-d1" import { Env, EnvBindings } from "../types" import { Str } from "chanfana" @@ -42,7 +42,7 @@ export async function getGoLinks(db: EnvBindings['golinks'], page: number, is_active: isActive !== undefined ? isActive : undefined, // Filter by isActive if provided }, orderBy: { - id: 'asc', // Sort by ID in ascending order (you can change this if needed) + id: 'desc', // Sort by newer IDs }, skip, take, @@ -50,6 +50,35 @@ export async function getGoLinks(db: EnvBindings['golinks'], page: number, return result; } +/** + * Get a list of Discord invite codes in the database. + * @param db Always point to `c.env.golinks` + * @param page + * @param isActive + * @param isNsfw + * @returns + */ +export async function getDiscordInvites(db: EnvBindings['golinks'], page: number, isActive?: boolean, isNsfw?: boolean) { + const adapter = new PrismaD1(db); + const prisma = new PrismaClient({ adapter }); // Assuming you have a Prisma client instance + + const skip = getOffset(page); + const take = PAGE_SIZE; + + const result = await prisma.discordInviteLink.findMany({ + where: { + is_active: isActive !== undefined ? isActive : undefined, // Filter by isActive if provided + nsfw: isNsfw !== undefined ? isNsfw : false // Hide NSFW servers for safety by default. + }, + orderBy: { + id: 'desc', // Sort by newer IDs + }, + skip, + take, + }); + return result; +}; + /** * * @param db Always point to `c.env.golinks` @@ -68,6 +97,18 @@ export async function getLink(db: EnvBindings['golinks'], slug: string): Pr return result; } +export async function getDiscordInvite(db: EnvBindings["golinks"], slug: string): Promise | null { + const adapter = new PrismaD1(db) + const prisma = new PrismaClient({adapter}) + + const result = await prisma.discordInviteLink.findUnique({ + where: { + slug + } + }) + return result +} + export async function addGoLink( db: EnvBindings["golinks"], slug: string, targetUrl: string, isActive?: boolean): Promise | null { const adapter = new PrismaD1(db) @@ -81,3 +122,27 @@ export async function addGoLink( }); return result } + +export async function addDiscordInvite( + db: EnvBindings['golinks'], + slug: string, + inviteCode: string, + name: string, + description: string, + is_active?: boolean, + nsfw?: boolean +) { + const adapter = new PrismaD1(db); + const prisma = new PrismaClient({adapter}) + const result = prisma.discordInviteLink.create({ + data: { + slug, + inviteCode, + name, + description, + is_active: is_active !== undefined ? is_active : true, + nsfw: nsfw !== undefined ? nsfw : false + } + }) + return result +};