Add /profile/:id/history api

This commit is contained in:
Zoe Roux 2025-04-07 18:25:26 +02:00
parent 4ba7750012
commit fef9e844a1
No known key found for this signature in database
3 changed files with 98 additions and 41 deletions

View File

@ -2,6 +2,7 @@ import { Elysia, t } from "elysia";
import { auth } from "./auth"; import { auth } from "./auth";
import { entriesH } from "./controllers/entries"; import { entriesH } from "./controllers/entries";
import { imagesH } from "./controllers/images"; import { imagesH } from "./controllers/images";
import { watchlistH } from "./controllers/profiles/watchlist";
import { seasonsH } from "./controllers/seasons"; import { seasonsH } from "./controllers/seasons";
import { seed } from "./controllers/seed"; import { seed } from "./controllers/seed";
import { collections } from "./controllers/shows/collections"; import { collections } from "./controllers/shows/collections";
@ -11,7 +12,6 @@ import { showsH } from "./controllers/shows/shows";
import { staffH } from "./controllers/staff"; import { staffH } from "./controllers/staff";
import { studiosH } from "./controllers/studios"; import { studiosH } from "./controllers/studios";
import { videosH } from "./controllers/videos"; import { videosH } from "./controllers/videos";
import { watchlistH } from "./controllers/profiles/watchlist";
import type { KError } from "./models/error"; import type { KError } from "./models/error";
export const base = new Elysia({ name: "base" }) export const base = new Elysia({ name: "base" })

View File

@ -1,8 +1,9 @@
import { and, eq, isNotNull, ne } from "drizzle-orm"; import { and, isNotNull, ne } from "drizzle-orm";
import Elysia, { t } from "elysia"; import Elysia, { t } from "elysia";
import { auth } from "~/auth"; import { auth, getUserInfo } from "~/auth";
import { entries } from "~/db/schema"; import { entries } from "~/db/schema";
import { Entry } from "~/models/entry"; import { Entry } from "~/models/entry";
import { KError } from "~/models/error";
import { import {
AcceptLanguage, AcceptLanguage,
Filter, Filter,
@ -37,45 +38,102 @@ export const historyH = new Elysia({ tags: ["profiles"] }).use(auth).guard(
}), }),
}, },
(app) => (app) =>
app.get( app
"/profiles/me/history", .get(
async ({ "/profiles/me/history",
query: { sort, filter, query, limit, after }, async ({
headers: { "accept-language": languages }, query: { sort, filter, query, limit, after },
request: { url }, headers: { "accept-language": languages },
jwt: { sub }, request: { url },
}) => { jwt: { sub },
const langs = processLanguages(languages); }) => {
const items = (await getEntries({ const langs = processLanguages(languages);
limit, const items = (await getEntries({
after, limit,
query, after,
sort, query,
filter: and( sort,
isNotNull(entryProgressQ.playedDate), filter: and(
ne(entries.kind, "extra"), isNotNull(entryProgressQ.playedDate),
ne(entries.kind, "unknown"), ne(entries.kind, "extra"),
filter, ne(entries.kind, "unknown"),
), filter,
languages: langs, ),
userId: sub, languages: langs,
})) as Entry[]; userId: sub,
})) as Entry[];
return createPage(items, { url, sort, limit }); return createPage(items, { url, sort, limit });
},
{
detail: {
description: "List your watch history (episodes/movies seen)",
}, },
headers: t.Object( {
{ detail: {
"accept-language": AcceptLanguage({ autoFallback: true }), description: "List your watch history (episodes/movies seen)",
},
headers: t.Object(
{
"accept-language": AcceptLanguage({ autoFallback: true }),
},
{ additionalProperties: true },
),
response: {
200: Page(Entry),
}, },
{ additionalProperties: true },
),
response: {
200: Page(Entry),
}, },
}, )
), .get(
"/profiles/:id/history",
async ({
params: { id },
query: { sort, filter, query, limit, after },
headers: { "accept-language": languages, authorization },
request: { url },
error,
}) => {
const uInfo = await getUserInfo(id, { authorization });
if ("status" in uInfo) return error(uInfo.status as 404, uInfo);
const langs = processLanguages(languages);
const items = (await getEntries({
limit,
after,
query,
sort,
filter: and(
isNotNull(entryProgressQ.playedDate),
ne(entries.kind, "extra"),
ne(entries.kind, "unknown"),
filter,
),
languages: langs,
userId: uInfo.id,
})) as Entry[];
return createPage(items, { url, sort, limit });
},
{
detail: {
description: "List your watch history (episodes/movies seen)",
},
params: t.Object({
id: t.String({
description:
"The id or username of the user to read the watchlist of",
example: "zoriya",
}),
}),
headers: t.Object({
authorization: t.TemplateLiteral("Bearer ${string}"),
"accept-language": AcceptLanguage({ autoFallback: true }),
}),
response: {
200: Page(Entry),
403: KError,
404: {
...KError,
description: "No user found with the specified id/username.",
},
422: KError,
},
},
),
); );

View File

@ -158,7 +158,6 @@ export const watchlistH = new Elysia({ tags: ["profiles"] })
error, error,
}) => { }) => {
const uInfo = await getUserInfo(id, { authorization }); const uInfo = await getUserInfo(id, { authorization });
if ("status" in uInfo) return error(uInfo.status as 404, uInfo); if ("status" in uInfo) return error(uInfo.status as 404, uInfo);
const langs = processLanguages(languages); const langs = processLanguages(languages);