mirror of
https://github.com/jakejarvis/sofa.git
synced 2026-10-16 12:55:42 -04:00
feat: add upcoming episodes and movies timeline (#17)
This commit is contained in:
42 files changed
+2405
-61
No files matched your search
@@ -1,4 +1,4 @@
|
||||
import { and, desc, eq, inArray, sql } from "drizzle-orm";
|
||||
import { and, asc, desc, eq, gte, inArray, lte, sql } from "drizzle-orm";
|
||||
|
||||
import { db } from "../client";
|
||||
import {
|
||||
@@ -312,3 +312,76 @@ export function getRecommendationRowsForTitle(titleId: string) {
|
||||
export function getTitleByIdOrNull(titleId: string) {
|
||||
return db.select().from(titles).where(eq(titles.id, titleId)).get() ?? null;
|
||||
}
|
||||
|
||||
// ─── Upcoming feed queries ──────────────────────────────────────────
|
||||
|
||||
export function getUpcomingEpisodes(userId: string, fromDate: string, toDate: string) {
|
||||
return db
|
||||
.select({
|
||||
episodeId: episodes.id,
|
||||
titleId: titles.id,
|
||||
titleName: titles.title,
|
||||
posterPath: titles.posterPath,
|
||||
posterThumbHash: titles.posterThumbHash,
|
||||
seasonNumber: seasons.seasonNumber,
|
||||
episodeNumber: episodes.episodeNumber,
|
||||
episodeName: episodes.name,
|
||||
airDate: episodes.airDate,
|
||||
userStatus: userTitleStatus.status,
|
||||
})
|
||||
.from(episodes)
|
||||
.innerJoin(seasons, eq(episodes.seasonId, seasons.id))
|
||||
.innerJoin(titles, and(eq(seasons.titleId, titles.id), eq(titles.type, "tv")))
|
||||
.innerJoin(
|
||||
userTitleStatus,
|
||||
and(eq(userTitleStatus.titleId, titles.id), eq(userTitleStatus.userId, userId)),
|
||||
)
|
||||
.where(and(gte(episodes.airDate, fromDate), lte(episodes.airDate, toDate)))
|
||||
.orderBy(asc(episodes.airDate), asc(titles.title))
|
||||
.all();
|
||||
}
|
||||
|
||||
export function getUpcomingMovies(userId: string, fromDate: string, toDate: string) {
|
||||
return db
|
||||
.select({
|
||||
titleId: titles.id,
|
||||
titleName: titles.title,
|
||||
posterPath: titles.posterPath,
|
||||
posterThumbHash: titles.posterThumbHash,
|
||||
releaseDate: titles.releaseDate,
|
||||
userStatus: userTitleStatus.status,
|
||||
})
|
||||
.from(titles)
|
||||
.innerJoin(
|
||||
userTitleStatus,
|
||||
and(eq(userTitleStatus.titleId, titles.id), eq(userTitleStatus.userId, userId)),
|
||||
)
|
||||
.where(
|
||||
and(
|
||||
eq(titles.type, "movie"),
|
||||
gte(titles.releaseDate, fromDate),
|
||||
lte(titles.releaseDate, toDate),
|
||||
),
|
||||
)
|
||||
.orderBy(asc(titles.releaseDate), asc(titles.title))
|
||||
.all();
|
||||
}
|
||||
|
||||
export function getAvailabilityByTitleIds(titleIds: string[]) {
|
||||
if (titleIds.length === 0) return [];
|
||||
return db
|
||||
.select({
|
||||
titleId: availabilityOffers.titleId,
|
||||
providerId: availabilityOffers.providerId,
|
||||
providerName: availabilityOffers.providerName,
|
||||
logoPath: availabilityOffers.logoPath,
|
||||
})
|
||||
.from(availabilityOffers)
|
||||
.where(
|
||||
and(
|
||||
inArray(availabilityOffers.titleId, titleIds),
|
||||
eq(availabilityOffers.offerType, "flatrate"),
|
||||
),
|
||||
)
|
||||
.all();
|
||||
}
|
||||
@@ -160,6 +160,7 @@ export const episodes = sqliteTable(
|
||||
},
|
||||
(table) => [
|
||||
uniqueIndex("episodes_seasonId_episodeNumber").on(table.seasonId, table.episodeNumber),
|
||||
index("episodes_airDate").on(table.airDate),
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
@@ -63,6 +63,9 @@ export function insertTitle(
|
||||
tvdbId?: number;
|
||||
type?: "movie" | "tv";
|
||||
title?: string;
|
||||
releaseDate?: string;
|
||||
posterPath?: string;
|
||||
status?: string;
|
||||
} = {},
|
||||
) {
|
||||
const id = overrides.id ?? "title-1";
|
||||
@@ -74,14 +77,30 @@ export function insertTitle(
|
||||
tvdbId: overrides.tvdbId,
|
||||
type: overrides.type ?? "movie",
|
||||
title: overrides.title ?? "Test Movie",
|
||||
releaseDate: overrides.releaseDate,
|
||||
posterPath: overrides.posterPath,
|
||||
status: overrides.status,
|
||||
})
|
||||
.run();
|
||||
return id;
|
||||
}
|
||||
|
||||
export function insertTvShow(titleId = "tv-1", tmdbId = 99999, seasonCount = 1, epsPerSeason = 3) {
|
||||
insertTitle({ id: titleId, tmdbId, type: "tv", title: "Test Show" });
|
||||
export function insertTvShow(
|
||||
titleId = "tv-1",
|
||||
tmdbId = 99999,
|
||||
seasonCount = 1,
|
||||
epsPerSeason = 3,
|
||||
options: { title?: string; airDates?: string[]; status?: string } = {},
|
||||
) {
|
||||
insertTitle({
|
||||
id: titleId,
|
||||
tmdbId,
|
||||
type: "tv",
|
||||
title: options.title ?? "Test Show",
|
||||
status: options.status,
|
||||
});
|
||||
const episodeIds: string[] = [];
|
||||
let airDateIdx = 0;
|
||||
for (let s = 1; s <= seasonCount; s++) {
|
||||
const seasonId = `${titleId}-s${s}`;
|
||||
testDb.insert(seasons).values({ id: seasonId, titleId, seasonNumber: s }).run();
|
||||
@@ -94,9 +113,11 @@ export function insertTvShow(titleId = "tv-1", tmdbId = 99999, seasonCount = 1,
|
||||
seasonId,
|
||||
episodeNumber: e,
|
||||
name: `S${s}E${e}`,
|
||||
airDate: options.airDates?.[airDateIdx],
|
||||
})
|
||||
.run();
|
||||
episodeIds.push(epId);
|
||||
airDateIdx++;
|
||||
}
|
||||
}
|
||||
return { titleId, episodeIds };
|
||||
|
||||
Reference in new issue
Block a user