From 950c1e051ab758b36ef75467b34155ba25293fa8 Mon Sep 17 00:00:00 2001 From: Pas <74743263+Pasithea0@users.noreply.github.com> Date: Wed, 12 Mar 2025 22:34:56 -0600 Subject: [PATCH] update formating and schemas --- .gitignore | 1 + server/routes/users/[id]/bookmarks.ts | 5 +- .../users/[id]/bookmarks/[tmdbid]/index.ts | 63 +++++----- server/routes/users/[id]/progress.ts | 29 ++--- server/routes/users/[id]/progress/import.ts | 101 +++++++++------- server/routes/users/[id]/sessions.ts | 10 +- server/routes/users/[id]/settings.ts | 110 ++++++++---------- 7 files changed, 163 insertions(+), 156 deletions(-) diff --git a/.gitignore b/.gitignore index a9d9387..f4c22ec 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ dist .env .vscode .metrics.json +.metrics.json diff --git a/server/routes/users/[id]/bookmarks.ts b/server/routes/users/[id]/bookmarks.ts index 5e83c0a..d099173 100644 --- a/server/routes/users/[id]/bookmarks.ts +++ b/server/routes/users/[id]/bookmarks.ts @@ -5,7 +5,7 @@ const bookmarkMetaSchema = z.object({ title: z.string(), year: z.number().optional(), poster: z.string().optional(), - type: z.enum(['movie', 'tv']), + type: z.enum(['movie', 'show']), }); const bookmarkDataSchema = z.object({ @@ -33,7 +33,6 @@ export default defineEventHandler(async (event) => { return bookmarks.map(bookmark => ({ tmdbId: bookmark.tmdb_id, - userId: bookmark.user_id, meta: bookmark.meta, updatedAt: bookmark.updated_at })); @@ -68,7 +67,6 @@ export default defineEventHandler(async (event) => { results.push({ tmdbId: bookmark.tmdb_id, - userId: bookmark.user_id, meta: bookmark.meta, updatedAt: bookmark.updated_at }); @@ -111,7 +109,6 @@ export default defineEventHandler(async (event) => { return { tmdbId: bookmark.tmdb_id, - userId: bookmark.user_id, meta: bookmark.meta, updatedAt: bookmark.updated_at }; diff --git a/server/routes/users/[id]/bookmarks/[tmdbid]/index.ts b/server/routes/users/[id]/bookmarks/[tmdbid]/index.ts index b721643..3578143 100644 --- a/server/routes/users/[id]/bookmarks/[tmdbid]/index.ts +++ b/server/routes/users/[id]/bookmarks/[tmdbid]/index.ts @@ -1,3 +1,13 @@ +import { useAuth } from '~/utils/auth'; +import { z } from 'zod'; + +const bookmarkMetaSchema = z.object({ + title: z.string(), + year: z.number(), + poster: z.string().optional(), + type: z.enum(['movie', 'show']) +}); + export default defineEventHandler(async (event) => { const userId = getRouterParam(event, 'id') const tmdbId = getRouterParam(event, 'tmdbid') @@ -12,34 +22,35 @@ export default defineEventHandler(async (event) => { } if (event.method === "POST") { - const body = await readBody(event); - const bookmark = await prisma.bookmarks.create({ - data: { - user_id: session.user, - tmdb_id: tmdbId, - meta: body.meta, - updated_at: new Date() - } - }); - - return { - tmdbId: bookmark.tmdb_id, - userId: bookmark.user_id, - meta: bookmark.meta, - updatedAt: bookmark.updated_at - }; -} else if (event.method === "DELETE") { - await prisma.bookmarks.delete({ - where: { - tmdb_id_user_id: { + const body = await readBody(event); + const validatedBody = bookmarkMetaSchema.parse(body); + + const bookmark = await prisma.bookmarks.create({ + data: { + user_id: session.user, tmdb_id: tmdbId, - user_id: session.user + meta: validatedBody, + updated_at: new Date() } - } - }); - - return { success: true, tmdbId }; -} + }); + + return { + tmdbId: bookmark.tmdb_id, + meta: bookmark.meta, + updatedAt: bookmark.updated_at + }; + } else if (event.method === "DELETE") { + await prisma.bookmarks.delete({ + where: { + tmdb_id_user_id: { + tmdb_id: tmdbId, + user_id: session.user + } + } + }); + + return { success: true, tmdbId }; + } throw createError({ statusCode: 405, diff --git a/server/routes/users/[id]/progress.ts b/server/routes/users/[id]/progress.ts index 6783164..b0111d5 100644 --- a/server/routes/users/[id]/progress.ts +++ b/server/routes/users/[id]/progress.ts @@ -4,16 +4,16 @@ import { randomUUID } from 'crypto'; const progressMetaSchema = z.object({ title: z.string(), + year: z.number().optional(), poster: z.string().optional(), - type: z.enum(['movie', 'tv', 'show']), - year: z.number().optional() + type: z.enum(['movie', 'show']) }); const progressItemSchema = z.object({ meta: progressMetaSchema, tmdbId: z.string(), - duration: z.number().transform((n) => Math.round(n)), - watched: z.number().transform((n) => Math.round(n)), + duration: z.number().transform((n) => n.toString()), + watched: z.number().transform((n) => n.toString()), seasonId: z.string().optional(), episodeId: z.string().optional(), seasonNumber: z.number().optional(), @@ -45,7 +45,7 @@ export default defineEventHandler(async (event) => { if (session.user !== userId) { throw createError({ statusCode: 403, - message: 'Cannot modify user other than yourself' + message: 'Cannot access other user information' }); } @@ -57,15 +57,18 @@ export default defineEventHandler(async (event) => { return items.map(item => ({ id: item.id, tmdbId: item.tmdb_id, - userId: item.user_id, - seasonId: item.season_id, - episodeId: item.episode_id, - seasonNumber: item.season_number, - episodeNumber: item.episode_number, + episode: { + id: item.episode_id || null, + number: item.episode_number || null + }, + season: { + id: item.season_id || null, + number: item.season_number || null + }, meta: item.meta, - duration: Number(item.duration), - watched: Number(item.watched), - updatedAt: item.updated_at + duration: item.duration.toString(), + watched: item.watched.toString(), + updatedAt: item.updated_at.toISOString() })); } diff --git a/server/routes/users/[id]/progress/import.ts b/server/routes/users/[id]/progress/import.ts index d55cbff..cc00216 100644 --- a/server/routes/users/[id]/progress/import.ts +++ b/server/routes/users/[id]/progress/import.ts @@ -4,21 +4,21 @@ import { randomUUID } from 'crypto'; const progressMetaSchema = z.object({ title: z.string(), - poster: z.string().optional(), - type: z.enum(['movie', 'tv', 'show']), - year: z.number().optional() + type: z.enum(['movie', 'show']), + year: z.number(), + poster: z.string().optional() }); const progressItemSchema = z.object({ meta: progressMetaSchema, tmdbId: z.string(), - duration: z.number().transform((n) => Math.round(n)), - watched: z.number().transform((n) => Math.round(n)), + duration: z.number(), + watched: z.number(), seasonId: z.string().optional(), episodeId: z.string().optional(), seasonNumber: z.number().optional(), episodeNumber: z.number().optional(), - updatedAt: z.string().datetime({ offset: true }).optional(), + updatedAt: z.string().datetime({ offset: true }).optional() }); // 13th July 2021 - movie-web epoch @@ -90,50 +90,61 @@ export default defineEventHandler(async (event) => { } } - for (const newItem of newItems) { + // Create new items + for (const item of newItems) { itemsToUpsert.push({ id: randomUUID(), - tmdb_id: newItem.tmdbId, + tmdb_id: item.tmdbId, user_id: userId, - season_id: newItem.seasonId || null, - episode_id: newItem.episodeId || null, - season_number: newItem.seasonNumber || null, - episode_number: newItem.episodeNumber || null, - duration: BigInt(newItem.duration), - watched: BigInt(newItem.watched), - meta: newItem.meta, - updated_at: defaultAndCoerceDateTime(newItem.updatedAt) + season_id: item.seasonId || null, + episode_id: item.episodeId || null, + season_number: item.seasonNumber || null, + episode_number: item.episodeNumber || null, + duration: BigInt(item.duration), + watched: BigInt(item.watched), + meta: item.meta, + updated_at: defaultAndCoerceDateTime(item.updatedAt) }); } - const result = await prisma.$transaction( - itemsToUpsert.map(item => - prisma.progress_items.upsert({ - where: { - id: item.id - }, - update: { - watched: item.watched, - duration: item.duration, - meta: item.meta, - updated_at: item.updated_at - }, - create: item - }) - ) - ); + // Upsert all items + const results = []; + for (const item of itemsToUpsert) { + const result = await prisma.progress_items.upsert({ + where: { + tmdb_id_user_id_season_id_episode_id: { + tmdb_id: item.tmdb_id, + user_id: item.user_id, + season_id: item.season_id, + episode_id: item.episode_id + } + }, + create: item, + update: { + duration: item.duration, + watched: item.watched, + meta: item.meta, + updated_at: item.updated_at + } + }); + + results.push({ + id: result.id, + tmdbId: result.tmdb_id, + episode: { + id: result.episode_id || null, + number: result.episode_number || null + }, + season: { + id: result.season_id || null, + number: result.season_number || null + }, + meta: result.meta, + duration: result.duration.toString(), + watched: result.watched.toString(), + updatedAt: result.updated_at.toISOString() + }); + } - return result.map(item => ({ - id: item.id, - tmdbId: item.tmdb_id, - userId: item.user_id, - seasonId: item.season_id, - episodeId: item.episode_id, - seasonNumber: item.season_number, - episodeNumber: item.episode_number, - meta: item.meta, - duration: Number(item.duration), - watched: Number(item.watched), - updatedAt: item.updated_at - })); + return results; }); \ No newline at end of file diff --git a/server/routes/users/[id]/sessions.ts b/server/routes/users/[id]/sessions.ts index a24423e..4d63613 100644 --- a/server/routes/users/[id]/sessions.ts +++ b/server/routes/users/[id]/sessions.ts @@ -18,12 +18,10 @@ export default defineEventHandler(async (event) => { return sessions.map(s => ({ id: s.id, - user: s.user, - createdAt: s.created_at, - accessedAt: s.accessed_at, - expiresAt: s.expires_at, + userId: s.user, + createdAt: s.created_at.toISOString(), + accessedAt: s.accessed_at.toISOString(), device: s.device, - userAgent: s.user_agent, - current: s.id === session.id + userAgent: s.user_agent })); }); \ No newline at end of file diff --git a/server/routes/users/[id]/settings.ts b/server/routes/users/[id]/settings.ts index 8be1ab3..b62a188 100644 --- a/server/routes/users/[id]/settings.ts +++ b/server/routes/users/[id]/settings.ts @@ -2,12 +2,12 @@ import { useAuth } from '~/utils/auth'; import { z } from 'zod'; const userSettingsSchema = z.object({ - application_theme: z.string().optional(), - application_language: z.string().optional(), - default_subtitle_language: z.string().optional(), - proxy_urls: z.array(z.string()).optional(), - trakt_key: z.string().optional(), - febbox_key: z.string().optional() + applicationTheme: z.string().nullable().optional(), + applicationLanguage: z.string(), + defaultSubtitleLanguage: z.string().nullable().optional(), + proxyUrls: z.array(z.string()).nullable().optional(), + traktKey: z.string().nullable().optional(), + febboxKey: z.string().nullable().optional() }); export default defineEventHandler(async (event) => { @@ -22,46 +22,60 @@ export default defineEventHandler(async (event) => { }); } + if (event.method === 'GET') { + const settings = await prisma.user_settings.findUnique({ + where: { id: userId } + }); + + return { + id: userId, + applicationTheme: settings?.application_theme || null, + applicationLanguage: settings?.application_language || 'en', + defaultSubtitleLanguage: settings?.default_subtitle_language || null, + proxyUrls: settings?.proxy_urls || null, + traktKey: settings?.trakt_key || null, + febboxKey: settings?.febbox_key || null + }; + } + if (event.method === 'PUT') { try { const body = await readBody(event); - const validatedSettings = userSettingsSchema.parse(body); + const validatedBody = userSettingsSchema.parse(body); - const existingSettings = await prisma.user_settings.findUnique({ - where: { id: userId } + const data = { + application_theme: validatedBody.applicationTheme, + application_language: validatedBody.applicationLanguage, + default_subtitle_language: validatedBody.defaultSubtitleLanguage ?? null, + proxy_urls: validatedBody.proxyUrls ?? null, + trakt_key: validatedBody.traktKey ?? null, + febbox_key: validatedBody.febboxKey ?? null + }; + + const settings = await prisma.user_settings.upsert({ + where: { id: userId }, + update: data, + create: { + id: userId, + ...data + } }); - let settings; - - if (existingSettings) { - settings = await prisma.user_settings.update({ - where: { id: userId }, - data: validatedSettings - }); - } else { - settings = await prisma.user_settings.create({ - data: { - id: userId, - ...validatedSettings - } - }); - } - return { - settings: { - applicationTheme: settings.application_theme, - applicationLanguage: settings.application_language, - defaultSubtitleLanguage: settings.default_subtitle_language, - proxyUrls: settings.proxy_urls, - traktKey: settings.trakt_key, - febboxKey: settings.febbox_key - } + id: userId, + applicationTheme: settings.application_theme, + applicationLanguage: settings.application_language, + defaultSubtitleLanguage: settings.default_subtitle_language, + proxyUrls: settings.proxy_urls, + traktKey: settings.trakt_key, + febboxKey: settings.febbox_key }; } catch (error) { if (error instanceof z.ZodError) { throw createError({ statusCode: 400, - message: 'Invalid settings data' + message: 'Invalid settings data', + cause: error.errors }); } @@ -70,34 +84,6 @@ export default defineEventHandler(async (event) => { message: 'Failed to update settings' }); } - } else if (event.method === 'GET') { - const settings = await prisma.user_settings.findUnique({ - where: { id: userId } - }); - - if (!settings) { - return { - settings: { - applicationTheme: null, - applicationLanguage: null, - defaultSubtitleLanguage: null, - proxyUrls: [], - traktKey: null, - febboxKey: null - } - }; - } - - return { - settings: { - applicationTheme: settings.application_theme, - applicationLanguage: settings.application_language, - defaultSubtitleLanguage: settings.default_subtitle_language, - proxyUrls: settings.proxy_urls, - traktKey: settings.trakt_key, - febboxKey: settings.febbox_key - } - }; } throw createError({