From 4d88e8ee1f47af6dff2dbb4cf25b744dc81134c1 Mon Sep 17 00:00:00 2001 From: Andrei Jiroh Halili Date: Thu, 18 Jul 2024 00:08:54 +0800 Subject: [PATCH] feat(golinks): more backend changes Signed-off-by: Andrei Jiroh Halili --- apps/golinks-v2/src/api/discord.ts | 63 ++++++++++++++++++++-- apps/golinks-v2/src/api/golinks.ts | 84 +++++++++++++++--------------- apps/golinks-v2/src/index.ts | 35 +++++++------ apps/golinks-v2/src/lib/db.ts | 11 ++-- 4 files changed, 126 insertions(+), 67 deletions(-) diff --git a/apps/golinks-v2/src/api/discord.ts b/apps/golinks-v2/src/api/discord.ts index 4506ed8..0d09db3 100644 --- a/apps/golinks-v2/src/api/discord.ts +++ b/apps/golinks-v2/src/api/discord.ts @@ -1,8 +1,8 @@ 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'; +import { DiscordInvites, EnvBindings } from 'types'; +import { addDiscordInvite, getDiscordInvites } from 'lib/db'; export class DiscordInviteLinkCreate extends OpenAPIRoute { schema = { @@ -80,7 +80,62 @@ export class DiscordInviteLinkCreate extends OpenAPIRoute { } export class DiscordInviteLinkList extends OpenAPIRoute { - schema = { - tags: ["discord-invites"] + schema = { + tags: ["discord-invites"], + summary: "Get a information about a custom invite link", + description: "Resolves a custom invite link slug into a object of information about a Discord invite code.", + request: { + query: z.object({ + page: Num({ + description: "Page number", + default: 0, + required: false, + }), + isActive: Bool({ + description: "Filter by is_active status", + required: false, + }), + nsfw: Bool({ + description: "Filter server list by NSFW status (NSFW servers are hidden by default).", + required: false + }) + }), + }, + responses: { + "200": { + description: "Returns a list of Discord servers in the database.", + content: { + "application/json": { + schema: z.object({ + success: Bool(), + result: DiscordInvites.array() + }) + } + } + } + } + }; + + async handle(c: Context) { + try { + const data = await this.getValidatedData() + console.log(`[api] query params: JSON.stringify(${data.query})`) + const { page, isActive, nsfw } = data.query; + const links = await getDiscordInvites(c.env.golinks, page, isActive, nsfw) + + return { + success: true, + result: links + } + } catch (err) { + return c.newResponse( + JSON.stringify({ + success: false, + error: `${err.name}:${err.code} (${err.message})` + }), + 500, + { "Content-Type": "application/json" } + ) } + } } diff --git a/apps/golinks-v2/src/api/golinks.ts b/apps/golinks-v2/src/api/golinks.ts index 8dcfcc8..fbf28ae 100644 --- a/apps/golinks-v2/src/api/golinks.ts +++ b/apps/golinks-v2/src/api/golinks.ts @@ -88,50 +88,48 @@ export class GoLinkCreate extends OpenAPIRoute { } export class GoLinkList extends OpenAPIRoute { - schema = { - tags: ["golinks"], - summary: "List all golinks", - request: { - query: z.object({ - page: Num({ - description: "Page number", - default: 0, - required: false - }), - isActive: Bool({ - description: "Filter by is_active status", - required: false - }) - }) - }, - responses: { - "200": { - description: "Returns a list of golinks", - content: { - "application/json": { - schema: z.object({ - series: z.object({ - success: Bool(), - result: z.object({ - links: GoLinks.array() - }) - }) - }) - } - } - } - } - }; + schema = { + tags: ["golinks"], + summary: "List all golinks", + request: { + query: z.object({ + page: Num({ + description: "Page number", + default: 0, + required: false, + }), + isActive: Bool({ + description: "Filter by is_active status", + required: false, + }), + }), + }, + responses: { + "200": { + description: "Returns a list of golinks", + content: { + "application/json": { + schema: z.object({ + series: z.object({ + success: Bool(), + result: GoLinks.array(), + }), + }), + }, + }, + }, + }, + }; - async handle(c) { - const data = await this.getValidatedData() - const { page, isActive } = data.query + async handle(c) { + const data = await this.getValidatedData(); + const { page, isActive } = data.query; - const links = await getGoLinks(c.env.golinks, page !== undefined ? page : 0, isActive) + const links = await getGoLinks(c.env.golinks, page !== undefined ? page : 0, isActive); - return { - success: true, - result: links, - }; - } + return { + success: true, + result: links, + }; + } } diff --git a/apps/golinks-v2/src/index.ts b/apps/golinks-v2/src/index.ts index f61a2bf..d817164 100644 --- a/apps/golinks-v2/src/index.ts +++ b/apps/golinks-v2/src/index.ts @@ -2,8 +2,7 @@ import { GoLinkCreate, GoLinkList } from "api/golinks"; import { fromHono } from "chanfana"; import { Context, Hono } from "hono"; import { cors } from 'hono/cors'; -import { EnvBindings } from './types'; -import { Env } from "../worker-configuration" +import { EnvBindings, Env } from "./types"; import { getDiscordInvite, getLink } from "lib/db"; import { adminApiKey, contact, getWorkersDashboardUrl, homepage, servers } from "lib/constants"; import { DiscordInviteLinkCreate, DiscordInviteLinkList } from "api/discord"; @@ -64,21 +63,25 @@ app.get("/workers/dashboard", (c) => { }) app.get('/:link', async (c) => { - const { link } = c.req.param(); - console.log(`[redirector]: incoming request with path - ${link}`); - const result = await getLink(c.env.golinks, link); - console.log(`[redirector]: resulting data - ${JSON.stringify(result)}`); - if (!result.targetUrl) { - return c.newResponse( - JSON.stringify({ - sucesss: false, - error: "Not Found" - }), - 404, { - "Content-Type": "application/json" - }) + try { + const { link } = c.req.param(); + console.log(`[redirector]: incoming request with path - ${link}`); + const result = await getLink(c.env.golinks, link); + console.log(`[redirector]: resulting data - ${JSON.stringify(result)}`); + if (!result.targetUrl) { + return c.newResponse( + JSON.stringify({ + sucesss: false, + error: "Not Found" + }), + 404, { + "Content-Type": "application/json" + }) + } + return c.redirect(result.targetUrl); + } catch { + return c.newResponse(`404 Not Found`, 404) } - return c.redirect(result.targetUrl); }); app.get("/discord/:inviteCode", async (c) => { try { diff --git a/apps/golinks-v2/src/lib/db.ts b/apps/golinks-v2/src/lib/db.ts index 5e6b7ab..340212a 100644 --- a/apps/golinks-v2/src/lib/db.ts +++ b/apps/golinks-v2/src/lib/db.ts @@ -1,6 +1,6 @@ -import { DiscordInviteLink, GoLink, PrismaClient } from "@prisma/client" +import { DiscordInviteLink, GoLink, Prisma, PrismaClient } from "@prisma/client" import { PrismaD1 } from "@prisma/adapter-d1" -import { Env, EnvBindings } from "../types" +import { Env, EnvBindings } from "../types"; import { Str } from "chanfana" const PAGE_SIZE = 10 @@ -65,7 +65,7 @@ export async function getDiscordInvites(db: EnvBindings['golinks'], page: n const skip = getOffset(page); const take = PAGE_SIZE; - const result = await prisma.discordInviteLink.findMany({ + const result = 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. @@ -97,7 +97,10 @@ export async function getLink(db: EnvBindings['golinks'], slug: string): Pr return result; } -export async function getDiscordInvite(db: EnvBindings["golinks"], slug: string): Promise | null { +export async function getDiscordInvite( + db: EnvBindings["golinks"], + slug: string +): Promise | null { const adapter = new PrismaD1(db) const prisma = new PrismaClient({adapter}) -- 2.51.2