mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-24 02:02:36 -04:00
Fix nextEntry
& lastPlayedAt
calculations on history/watchlist
This commit is contained in:
parent
67d7643261
commit
09dd78b272
@ -181,6 +181,12 @@ export const historyH = new Elysia({ tags: ["profiles"] })
|
||||
const vals = values(
|
||||
body.map((x) => ({ ...x, entryUseId: isUuid(x.entry) })),
|
||||
).as("hist");
|
||||
const valEqEntries = sql`
|
||||
case
|
||||
when hist.entryUseId::boolean then ${entries.id} = hist.entry::uuid
|
||||
else ${entries.slug} = hist.entry
|
||||
end
|
||||
`;
|
||||
|
||||
const rows = await db
|
||||
.insert(history)
|
||||
@ -195,19 +201,7 @@ export const historyH = new Elysia({ tags: ["profiles"] })
|
||||
playedDate: sql`hist.playedDate::timestamptz`,
|
||||
})
|
||||
.from(vals)
|
||||
.innerJoin(
|
||||
entries,
|
||||
or(
|
||||
and(
|
||||
sql`hist.entryUseId::boolean`,
|
||||
eq(entries.id, sql`hist.entry::uuid`),
|
||||
),
|
||||
and(
|
||||
not(sql`hist.entryUseId::boolean`),
|
||||
eq(entries.slug, sql`hist.entry`),
|
||||
),
|
||||
),
|
||||
)
|
||||
.innerJoin(entries, valEqEntries)
|
||||
.leftJoin(videos, eq(videos.id, sql`hist.videoId::uuid`)),
|
||||
)
|
||||
.returning({ pk: history.pk });
|
||||
@ -273,9 +267,15 @@ export const historyH = new Elysia({ tags: ["profiles"] })
|
||||
else 0
|
||||
end
|
||||
`,
|
||||
nextEntry: nextEntryQ.pk,
|
||||
nextEntry: sql`
|
||||
case
|
||||
when hist.percent::integer >= 95 then ${nextEntryQ.pk}
|
||||
else ${entries.pk}
|
||||
end
|
||||
`,
|
||||
score: sql`null`,
|
||||
startedAt: sql`hist.playedDate::timestamptz`,
|
||||
lastPlayedAt: sql`hist.playedDate::timestamptz`,
|
||||
completedAt: sql`
|
||||
case
|
||||
when ${nextEntryQ.pk} is null then hist.playedDate::timestamptz
|
||||
@ -286,19 +286,7 @@ export const historyH = new Elysia({ tags: ["profiles"] })
|
||||
updatedAt: sql`now()`,
|
||||
})
|
||||
.from(vals)
|
||||
.leftJoin(
|
||||
entries,
|
||||
or(
|
||||
and(
|
||||
sql`hist.entryUseId::boolean`,
|
||||
eq(entries.id, sql`hist.entry::uuid`),
|
||||
),
|
||||
and(
|
||||
not(sql`hist.entryUseId::boolean`),
|
||||
eq(entries.slug, sql`hist.entry`),
|
||||
),
|
||||
),
|
||||
)
|
||||
.leftJoin(entries, valEqEntries)
|
||||
.leftJoinLateral(nextEntryQ, sql`true`),
|
||||
)
|
||||
.onConflictDoUpdate({
|
||||
@ -321,6 +309,7 @@ export const historyH = new Elysia({ tags: ["profiles"] })
|
||||
else excluded.next_entry
|
||||
end
|
||||
`,
|
||||
lastPlayedAt: sql`excluded.last_played_at`,
|
||||
completedAt: coalesce(
|
||||
watchlist.completedAt,
|
||||
sql`excluded.completed_at`,
|
||||
|
@ -8,7 +8,7 @@ import {
|
||||
watchStatusQ,
|
||||
} from "~/controllers/shows/logic";
|
||||
import { db } from "~/db";
|
||||
import { shows } from "~/db/schema";
|
||||
import { entries, shows } from "~/db/schema";
|
||||
import { watchlist } from "~/db/schema/watchlist";
|
||||
import { conflictUpdateAllExcept, getColumns } from "~/db/utils";
|
||||
import { KError } from "~/models/error";
|
||||
@ -32,18 +32,39 @@ async function setWatchStatus({
|
||||
status,
|
||||
userId,
|
||||
}: {
|
||||
show: { pk: number; kind: "movie" | "serie" };
|
||||
status: SerieWatchStatus;
|
||||
show:
|
||||
| { pk: number; kind: "movie" }
|
||||
| { pk: number; kind: "serie"; entriesCount: number };
|
||||
status: Omit<SerieWatchStatus, "seenCount">;
|
||||
userId: string;
|
||||
}) {
|
||||
const profilePk = await getOrCreateProfile(userId);
|
||||
|
||||
const firstEntryQ = db
|
||||
.select({ pk: entries.pk })
|
||||
.from(entries)
|
||||
.where(eq(entries.showPk, show.pk))
|
||||
.orderBy(entries.order)
|
||||
.limit(1);
|
||||
|
||||
const [ret] = await db
|
||||
.insert(watchlist)
|
||||
.values({
|
||||
...status,
|
||||
profilePk: profilePk,
|
||||
seenCount:
|
||||
status.status === "completed"
|
||||
? show.kind === "movie"
|
||||
? 100
|
||||
: show.entriesCount
|
||||
: 0,
|
||||
showPk: show.pk,
|
||||
nextEntry:
|
||||
show.kind === "movie" &&
|
||||
(status.status === "watching" || status.status === "rewatching")
|
||||
? sql`${firstEntryQ}`
|
||||
: sql`null`,
|
||||
lastPlayedAt: status.startedAt,
|
||||
})
|
||||
.onConflictDoUpdate({
|
||||
target: [watchlist.profilePk, watchlist.showPk],
|
||||
@ -53,10 +74,32 @@ async function setWatchStatus({
|
||||
"showPk",
|
||||
"createdAt",
|
||||
"seenCount",
|
||||
"nextEntry",
|
||||
"lastPlayedAt",
|
||||
]),
|
||||
// do not reset movie's progress during drop
|
||||
...(show.kind === "movie" && status.status !== "dropped"
|
||||
? { seenCount: sql`excluded.seen_count` }
|
||||
...(status.status === "completed"
|
||||
? {
|
||||
seenCount: sql`excluded.seen_count`,
|
||||
nextEntry: sql`null`,
|
||||
}
|
||||
: {}),
|
||||
// only set seenCount & nextEntry when marking as "rewatching"
|
||||
// if it's already rewatching, the history updates are more up-dated.
|
||||
...(status.status === "rewatching"
|
||||
? {
|
||||
seenCount: sql`
|
||||
case when ${watchlist.status} != 'rewatching'
|
||||
then excluded.seen_count
|
||||
else
|
||||
${watchlist.seenCount}
|
||||
end`,
|
||||
nextEntry: sql`
|
||||
case when ${watchlist.status} != 'rewatching'
|
||||
then excluded.next_entry
|
||||
else
|
||||
${watchlist.nextEntry}
|
||||
end`,
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
})
|
||||
@ -115,6 +158,7 @@ export const watchlistH = new Elysia({ tags: ["profiles"] })
|
||||
),
|
||||
languages: langs,
|
||||
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
||||
relations: ["nextEntry"],
|
||||
userId: sub,
|
||||
});
|
||||
return createPage(items, { url, sort, limit });
|
||||
@ -159,6 +203,7 @@ export const watchlistH = new Elysia({ tags: ["profiles"] })
|
||||
),
|
||||
languages: langs,
|
||||
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
||||
relations: ["nextEntry"],
|
||||
userId: uInfo.id,
|
||||
});
|
||||
return createPage(items, { url, sort, limit });
|
||||
@ -195,7 +240,7 @@ export const watchlistH = new Elysia({ tags: ["profiles"] })
|
||||
"/series/:id/watchstatus",
|
||||
async ({ params: { id }, body, jwt: { sub }, error }) => {
|
||||
const [show] = await db
|
||||
.select({ pk: shows.pk })
|
||||
.select({ pk: shows.pk, entriesCount: shows.entriesCount })
|
||||
.from(shows)
|
||||
.where(
|
||||
and(
|
||||
@ -211,7 +256,7 @@ export const watchlistH = new Elysia({ tags: ["profiles"] })
|
||||
});
|
||||
}
|
||||
return await setWatchStatus({
|
||||
show: { pk: show.pk, kind: "serie" },
|
||||
show: { pk: show.pk, kind: "serie", entriesCount: show.entriesCount },
|
||||
userId: sub,
|
||||
status: body,
|
||||
});
|
||||
@ -224,7 +269,7 @@ export const watchlistH = new Elysia({ tags: ["profiles"] })
|
||||
example: madeInAbyss.slug,
|
||||
}),
|
||||
}),
|
||||
body: SerieWatchStatus,
|
||||
body: t.Omit(SerieWatchStatus, ["seenCount"]),
|
||||
response: {
|
||||
200: t.Intersect([SerieWatchStatus, DbMetadata]),
|
||||
404: KError,
|
||||
@ -258,8 +303,6 @@ export const watchlistH = new Elysia({ tags: ["profiles"] })
|
||||
status: {
|
||||
...body,
|
||||
startedAt: body.completedAt,
|
||||
// for movies, watch-percent is stored in `seenCount`.
|
||||
seenCount: body.status === "completed" ? 100 : 0,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
@ -184,7 +184,10 @@ export const getNews = async ({
|
||||
return [resp, body] as const;
|
||||
};
|
||||
|
||||
export const setSerieStatus = async (id: string, status: SerieWatchStatus) => {
|
||||
export const setSerieStatus = async (
|
||||
id: string,
|
||||
status: Omit<SerieWatchStatus, "seenCount">,
|
||||
) => {
|
||||
const resp = await app.handle(
|
||||
new Request(buildUrl(`series/${id}/watchstatus`), {
|
||||
method: "POST",
|
||||
|
Loading…
x
Reference in New Issue
Block a user