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(
|
const vals = values(
|
||||||
body.map((x) => ({ ...x, entryUseId: isUuid(x.entry) })),
|
body.map((x) => ({ ...x, entryUseId: isUuid(x.entry) })),
|
||||||
).as("hist");
|
).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
|
const rows = await db
|
||||||
.insert(history)
|
.insert(history)
|
||||||
@ -195,19 +201,7 @@ export const historyH = new Elysia({ tags: ["profiles"] })
|
|||||||
playedDate: sql`hist.playedDate::timestamptz`,
|
playedDate: sql`hist.playedDate::timestamptz`,
|
||||||
})
|
})
|
||||||
.from(vals)
|
.from(vals)
|
||||||
.innerJoin(
|
.innerJoin(entries, valEqEntries)
|
||||||
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(videos, eq(videos.id, sql`hist.videoId::uuid`)),
|
.leftJoin(videos, eq(videos.id, sql`hist.videoId::uuid`)),
|
||||||
)
|
)
|
||||||
.returning({ pk: history.pk });
|
.returning({ pk: history.pk });
|
||||||
@ -273,9 +267,15 @@ export const historyH = new Elysia({ tags: ["profiles"] })
|
|||||||
else 0
|
else 0
|
||||||
end
|
end
|
||||||
`,
|
`,
|
||||||
nextEntry: nextEntryQ.pk,
|
nextEntry: sql`
|
||||||
|
case
|
||||||
|
when hist.percent::integer >= 95 then ${nextEntryQ.pk}
|
||||||
|
else ${entries.pk}
|
||||||
|
end
|
||||||
|
`,
|
||||||
score: sql`null`,
|
score: sql`null`,
|
||||||
startedAt: sql`hist.playedDate::timestamptz`,
|
startedAt: sql`hist.playedDate::timestamptz`,
|
||||||
|
lastPlayedAt: sql`hist.playedDate::timestamptz`,
|
||||||
completedAt: sql`
|
completedAt: sql`
|
||||||
case
|
case
|
||||||
when ${nextEntryQ.pk} is null then hist.playedDate::timestamptz
|
when ${nextEntryQ.pk} is null then hist.playedDate::timestamptz
|
||||||
@ -286,19 +286,7 @@ export const historyH = new Elysia({ tags: ["profiles"] })
|
|||||||
updatedAt: sql`now()`,
|
updatedAt: sql`now()`,
|
||||||
})
|
})
|
||||||
.from(vals)
|
.from(vals)
|
||||||
.leftJoin(
|
.leftJoin(entries, valEqEntries)
|
||||||
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`),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.leftJoinLateral(nextEntryQ, sql`true`),
|
.leftJoinLateral(nextEntryQ, sql`true`),
|
||||||
)
|
)
|
||||||
.onConflictDoUpdate({
|
.onConflictDoUpdate({
|
||||||
@ -321,6 +309,7 @@ export const historyH = new Elysia({ tags: ["profiles"] })
|
|||||||
else excluded.next_entry
|
else excluded.next_entry
|
||||||
end
|
end
|
||||||
`,
|
`,
|
||||||
|
lastPlayedAt: sql`excluded.last_played_at`,
|
||||||
completedAt: coalesce(
|
completedAt: coalesce(
|
||||||
watchlist.completedAt,
|
watchlist.completedAt,
|
||||||
sql`excluded.completed_at`,
|
sql`excluded.completed_at`,
|
||||||
|
@ -8,7 +8,7 @@ import {
|
|||||||
watchStatusQ,
|
watchStatusQ,
|
||||||
} from "~/controllers/shows/logic";
|
} from "~/controllers/shows/logic";
|
||||||
import { db } from "~/db";
|
import { db } from "~/db";
|
||||||
import { shows } from "~/db/schema";
|
import { entries, shows } from "~/db/schema";
|
||||||
import { watchlist } from "~/db/schema/watchlist";
|
import { watchlist } from "~/db/schema/watchlist";
|
||||||
import { conflictUpdateAllExcept, getColumns } from "~/db/utils";
|
import { conflictUpdateAllExcept, getColumns } from "~/db/utils";
|
||||||
import { KError } from "~/models/error";
|
import { KError } from "~/models/error";
|
||||||
@ -32,18 +32,39 @@ async function setWatchStatus({
|
|||||||
status,
|
status,
|
||||||
userId,
|
userId,
|
||||||
}: {
|
}: {
|
||||||
show: { pk: number; kind: "movie" | "serie" };
|
show:
|
||||||
status: SerieWatchStatus;
|
| { pk: number; kind: "movie" }
|
||||||
|
| { pk: number; kind: "serie"; entriesCount: number };
|
||||||
|
status: Omit<SerieWatchStatus, "seenCount">;
|
||||||
userId: string;
|
userId: string;
|
||||||
}) {
|
}) {
|
||||||
const profilePk = await getOrCreateProfile(userId);
|
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
|
const [ret] = await db
|
||||||
.insert(watchlist)
|
.insert(watchlist)
|
||||||
.values({
|
.values({
|
||||||
...status,
|
...status,
|
||||||
profilePk: profilePk,
|
profilePk: profilePk,
|
||||||
|
seenCount:
|
||||||
|
status.status === "completed"
|
||||||
|
? show.kind === "movie"
|
||||||
|
? 100
|
||||||
|
: show.entriesCount
|
||||||
|
: 0,
|
||||||
showPk: show.pk,
|
showPk: show.pk,
|
||||||
|
nextEntry:
|
||||||
|
show.kind === "movie" &&
|
||||||
|
(status.status === "watching" || status.status === "rewatching")
|
||||||
|
? sql`${firstEntryQ}`
|
||||||
|
: sql`null`,
|
||||||
|
lastPlayedAt: status.startedAt,
|
||||||
})
|
})
|
||||||
.onConflictDoUpdate({
|
.onConflictDoUpdate({
|
||||||
target: [watchlist.profilePk, watchlist.showPk],
|
target: [watchlist.profilePk, watchlist.showPk],
|
||||||
@ -53,10 +74,32 @@ async function setWatchStatus({
|
|||||||
"showPk",
|
"showPk",
|
||||||
"createdAt",
|
"createdAt",
|
||||||
"seenCount",
|
"seenCount",
|
||||||
|
"nextEntry",
|
||||||
|
"lastPlayedAt",
|
||||||
]),
|
]),
|
||||||
// do not reset movie's progress during drop
|
...(status.status === "completed"
|
||||||
...(show.kind === "movie" && status.status !== "dropped"
|
? {
|
||||||
? { seenCount: sql`excluded.seen_count` }
|
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,
|
languages: langs,
|
||||||
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
||||||
|
relations: ["nextEntry"],
|
||||||
userId: sub,
|
userId: sub,
|
||||||
});
|
});
|
||||||
return createPage(items, { url, sort, limit });
|
return createPage(items, { url, sort, limit });
|
||||||
@ -159,6 +203,7 @@ export const watchlistH = new Elysia({ tags: ["profiles"] })
|
|||||||
),
|
),
|
||||||
languages: langs,
|
languages: langs,
|
||||||
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
||||||
|
relations: ["nextEntry"],
|
||||||
userId: uInfo.id,
|
userId: uInfo.id,
|
||||||
});
|
});
|
||||||
return createPage(items, { url, sort, limit });
|
return createPage(items, { url, sort, limit });
|
||||||
@ -195,7 +240,7 @@ export const watchlistH = new Elysia({ tags: ["profiles"] })
|
|||||||
"/series/:id/watchstatus",
|
"/series/:id/watchstatus",
|
||||||
async ({ params: { id }, body, jwt: { sub }, error }) => {
|
async ({ params: { id }, body, jwt: { sub }, error }) => {
|
||||||
const [show] = await db
|
const [show] = await db
|
||||||
.select({ pk: shows.pk })
|
.select({ pk: shows.pk, entriesCount: shows.entriesCount })
|
||||||
.from(shows)
|
.from(shows)
|
||||||
.where(
|
.where(
|
||||||
and(
|
and(
|
||||||
@ -211,7 +256,7 @@ export const watchlistH = new Elysia({ tags: ["profiles"] })
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
return await setWatchStatus({
|
return await setWatchStatus({
|
||||||
show: { pk: show.pk, kind: "serie" },
|
show: { pk: show.pk, kind: "serie", entriesCount: show.entriesCount },
|
||||||
userId: sub,
|
userId: sub,
|
||||||
status: body,
|
status: body,
|
||||||
});
|
});
|
||||||
@ -224,7 +269,7 @@ export const watchlistH = new Elysia({ tags: ["profiles"] })
|
|||||||
example: madeInAbyss.slug,
|
example: madeInAbyss.slug,
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
body: SerieWatchStatus,
|
body: t.Omit(SerieWatchStatus, ["seenCount"]),
|
||||||
response: {
|
response: {
|
||||||
200: t.Intersect([SerieWatchStatus, DbMetadata]),
|
200: t.Intersect([SerieWatchStatus, DbMetadata]),
|
||||||
404: KError,
|
404: KError,
|
||||||
@ -258,8 +303,6 @@ export const watchlistH = new Elysia({ tags: ["profiles"] })
|
|||||||
status: {
|
status: {
|
||||||
...body,
|
...body,
|
||||||
startedAt: body.completedAt,
|
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;
|
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(
|
const resp = await app.handle(
|
||||||
new Request(buildUrl(`series/${id}/watchstatus`), {
|
new Request(buildUrl(`series/${id}/watchstatus`), {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user