83 lines
2.3 KiB
TypeScript
83 lines
2.3 KiB
TypeScript
import { nrkRadio } from "./nrk/nrk.ts";
|
|
import { Series, storage } from "./storage.ts";
|
|
import * as datetime from "datetime";
|
|
|
|
const SYNC_INTERVAL_HOURS = 1;
|
|
|
|
async function initialFetch(options: { id: string }) {
|
|
const series = await nrkRadio.getSeries(options.id);
|
|
const stored = storage.write(series);
|
|
if (!stored) {
|
|
throw new Error(`Failed to store series ${options.id}`);
|
|
}
|
|
|
|
return series;
|
|
}
|
|
|
|
async function updateFetch(existingSeries: Series) {
|
|
const series = await nrkRadio.getSeries(existingSeries.id);
|
|
const newEpisodes = series.episodes.filter((episode) => {
|
|
return !existingSeries.episodes.find((serieEpisode) => serieEpisode.id === episode.id);
|
|
});
|
|
|
|
if (newEpisodes.length === 0) {
|
|
return existingSeries;
|
|
}
|
|
|
|
const updated = {
|
|
...existingSeries,
|
|
lastFetch: new Date(),
|
|
/**
|
|
* Since we don't control the API,
|
|
* we should not make assumptions about the order,
|
|
* but rather sort the episode to what we want.
|
|
*/
|
|
episodes: [...newEpisodes, ...existingSeries.episodes]
|
|
.sort((a, b) => a.date.getTime() > b.date.getTime() ? -1 : 1),
|
|
};
|
|
|
|
const updateSuccessful = await storage.write(updated);
|
|
if (!updateSuccessful) {
|
|
throw new Error(`Failed to update series ${existingSeries.id}`);
|
|
}
|
|
|
|
return updated;
|
|
}
|
|
|
|
async function getSeries(options: { id: string }): Promise<Series> {
|
|
const seriesFromStorage = await storage.read(options);
|
|
|
|
/**
|
|
* We don't have the feed in storage,
|
|
* and we need to fetch it for the first time.
|
|
*/
|
|
if (seriesFromStorage === null) {
|
|
// TODO: schedule a job to fetch the entire backlog https://github.com/olaven/NRSS/issues/24
|
|
return await initialFetch(options);
|
|
}
|
|
|
|
const timeSinceLastFetch =
|
|
datetime.difference(seriesFromStorage.lastFetchedAt, new Date(), { units: ["hours"] }).hours;
|
|
|
|
// we have the feed in storage and it's not too old
|
|
if (
|
|
seriesFromStorage !== null &&
|
|
timeSinceLastFetch !== null &&
|
|
timeSinceLastFetch !== undefined &&
|
|
timeSinceLastFetch <= SYNC_INTERVAL_HOURS
|
|
) {
|
|
return seriesFromStorage;
|
|
}
|
|
|
|
/**
|
|
* We have the feed in storage, but it's too old
|
|
* and needs to be refreshed.
|
|
*/
|
|
const updatedSeries = await updateFetch(seriesFromStorage);
|
|
return updatedSeries;
|
|
}
|
|
|
|
export const caching = {
|
|
getSeries,
|
|
};
|