fix more errors

This commit is contained in:
Pas 2026-02-04 12:08:49 -07:00
parent 6c2dd97b0c
commit 17a3fb3c2d
2 changed files with 74 additions and 52 deletions

View file

@ -55,19 +55,29 @@ export default defineEventHandler(async event => {
try { try {
const body = await readBody(event); const body = await readBody(event);
const validatedBody = watchHistoryItemSchema.parse(body); // Accept single object (normal playback) or array (e.g. user import)
const bodySchema = z.union([
watchHistoryItemSchema,
z.array(watchHistoryItemSchema),
]);
const parsed = bodySchema.parse(body);
const items = Array.isArray(parsed) ? parsed : [parsed];
const results = [];
for (const validatedBody of items) {
const itemTmdbId = items.length === 1 ? tmdbId : (validatedBody.tmdbId ?? tmdbId);
const watchedAt = defaultAndCoerceDateTime(validatedBody.watchedAt); const watchedAt = defaultAndCoerceDateTime(validatedBody.watchedAt);
const now = new Date(); const now = new Date();
// Normalize IDs for movies (use '\n' instead of null to satisfy unique constraint) // Normalize IDs for movies (use '\n' instead of null to satisfy unique constraint)
const normSeasonId = validatedBody.meta.type === 'movie' ? '\n' : validatedBody.seasonId || null; const normSeasonId = validatedBody.meta.type === 'movie' ? '\n' : validatedBody.seasonId ?? null;
const normEpisodeId = validatedBody.meta.type === 'movie' ? '\n' : validatedBody.episodeId || null; const normEpisodeId = validatedBody.meta.type === 'movie' ? '\n' : validatedBody.episodeId ?? null;
const existingItem = await prisma.watch_history.findUnique({ const existingItem = await prisma.watch_history.findUnique({
where: { where: {
tmdb_id_user_id_season_id_episode_id: { tmdb_id_user_id_season_id_episode_id: {
tmdb_id: tmdbId, tmdb_id: itemTmdbId,
user_id: userId, user_id: userId,
season_id: normSeasonId, season_id: normSeasonId,
episode_id: normEpisodeId, episode_id: normEpisodeId,
@ -75,8 +85,6 @@ export default defineEventHandler(async event => {
}, },
}); });
let watchHistoryItem;
const data = { const data = {
duration: parseFloat(validatedBody.duration), duration: parseFloat(validatedBody.duration),
watched: parseFloat(validatedBody.watched), watched: parseFloat(validatedBody.watched),
@ -86,29 +94,29 @@ export default defineEventHandler(async event => {
updated_at: now, updated_at: now,
}; };
let watchHistoryItem;
if (existingItem) { if (existingItem) {
watchHistoryItem = await prisma.watch_history.update({ watchHistoryItem = await prisma.watch_history.update({
where: { where: { id: existingItem.id },
id: existingItem.id,
},
data, data,
}); });
} else { } else {
watchHistoryItem = await prisma.watch_history.create({ watchHistoryItem = await prisma.watch_history.create({
data: { data: {
id: randomUUID(), id: randomUUID(),
tmdb_id: tmdbId, tmdb_id: itemTmdbId,
user_id: userId, user_id: userId,
season_id: normSeasonId, season_id: normSeasonId,
episode_id: normEpisodeId, episode_id: normEpisodeId,
season_number: validatedBody.seasonNumber || null, season_number: validatedBody.seasonNumber ?? null,
episode_number: validatedBody.episodeNumber || null, episode_number: validatedBody.episodeNumber ?? null,
...data, ...data,
}, },
}); });
} }
return { results.push({
success: true, success: true,
id: watchHistoryItem.id, id: watchHistoryItem.id,
tmdbId: watchHistoryItem.tmdb_id, tmdbId: watchHistoryItem.tmdb_id,
@ -123,7 +131,10 @@ export default defineEventHandler(async event => {
watchedAt: watchHistoryItem.watched_at.toISOString(), watchedAt: watchHistoryItem.watched_at.toISOString(),
completed: watchHistoryItem.completed, completed: watchHistoryItem.completed,
updatedAt: watchHistoryItem.updated_at.toISOString(), updatedAt: watchHistoryItem.updated_at.toISOString(),
}; });
}
return results.length === 1 ? results[0] : { success: true, count: results.length, items: results };
} catch (dbError) { } catch (dbError) {
console.error('Database error:', dbError); console.error('Database error:', dbError);
throw createError({ throw createError({

View file

@ -10,6 +10,17 @@ const METRICS_DAILY_FILE = '.metrics_daily.json';
const METRICS_WEEKLY_FILE = '.metrics_weekly.json'; const METRICS_WEEKLY_FILE = '.metrics_weekly.json';
const METRICS_MONTHLY_FILE = '.metrics_monthly.json'; const METRICS_MONTHLY_FILE = '.metrics_monthly.json';
function getMetricsFileName(interval: string): string {
const fileMap: Record<string, string> = {
default: METRICS_FILE,
daily: METRICS_DAILY_FILE,
weekly: METRICS_WEEKLY_FILE,
monthly: METRICS_MONTHLY_FILE,
};
const name = fileMap[interval] ?? `.metrics_${interval}.json`;
return path.join(process.cwd(), name);
}
// Global registries // Global registries
const registries = { const registries = {
default: register, // All-time metrics (never cleared) default: register, // All-time metrics (never cleared)