1
0
Fork 0
mirror of https://github.com/sussy-code/smov.git synced 2024-12-20 14:37:43 +01:00

migrations but better

Co-authored-by: William Oldham <github@binaryoverload.co.uk>
This commit is contained in:
mrjvs 2023-06-22 22:37:16 +02:00
parent 545120d5cc
commit c4c7816543
8 changed files with 79 additions and 60 deletions

View file

@ -143,21 +143,24 @@ export async function searchMedia(
return data; return data;
} }
export async function getMediaDetails(id: string, type: TMDBContentTypes) { // Conditional type which for inferring the return type based on the content type
let data; type MediaDetailReturn<T extends TMDBContentTypes> = T extends "movie"
? TMDBMovieData
: T extends "show"
? TMDBShowData
: never;
switch (type) { export function getMediaDetails<
case "movie": T extends TMDBContentTypes,
data = await get<TMDBMovieData>(`/movie/${id}`); TReturn = MediaDetailReturn<T>
break; >(id: string, type: T): Promise<TReturn> {
case "show": if (type === "movie") {
data = await get<TMDBShowData>(`/tv/${id}`); return get<TReturn>(`/movie/${id}`);
break;
default:
throw new Error("Invalid media type");
} }
if (type === "show") {
return data; return get<TReturn>(`/tv/${id}`);
}
throw new Error("Invalid media type");
} }
export function getMediaPoster(posterPath: string | null): string | undefined { export function getMediaPoster(posterPath: string | null): string | undefined {

View file

@ -8,7 +8,7 @@ const gomoviesBase = "https://gomovies.sx";
registerProvider({ registerProvider({
id: "gomovies", id: "gomovies",
displayName: "GOmovies", displayName: "GOmovies",
rank: 300, rank: 200,
type: [MWMediaType.MOVIE, MWMediaType.SERIES], type: [MWMediaType.MOVIE, MWMediaType.SERIES],
async scrape({ media, episode }) { async scrape({ media, episode }) {

View file

@ -142,7 +142,7 @@ const convertSubtitles = (subtitleGroup: any): MWCaption | null => {
registerProvider({ registerProvider({
id: "superstream", id: "superstream",
displayName: "Superstream", displayName: "Superstream",
rank: 200, rank: 300,
type: [MWMediaType.MOVIE, MWMediaType.SERIES], type: [MWMediaType.MOVIE, MWMediaType.SERIES],
async scrape({ media, episode, progress }) { async scrape({ media, episode, progress }) {

View file

@ -14,7 +14,7 @@ export const BookmarkStore = createVersionedStore<BookmarkStoreData>()
}) })
.addVersion({ .addVersion({
version: 1, version: 1,
migrate(old: OldBookmarks) { migrate(old: BookmarkStoreData) {
return migrateV2Bookmarks(old); return migrateV2Bookmarks(old);
}, },
}) })

View file

@ -1,14 +1,20 @@
import { getLegacyMetaFromId } from "@/backend/metadata/getmeta"; import { getLegacyMetaFromId } from "@/backend/metadata/getmeta";
import { getMovieFromExternalId } from "@/backend/metadata/tmdb"; import {
getEpisodes,
getMediaDetails,
getMovieFromExternalId,
} from "@/backend/metadata/tmdb";
import { MWMediaType } from "@/backend/metadata/types/mw"; import { MWMediaType } from "@/backend/metadata/types/mw";
import { BookmarkStoreData } from "@/state/bookmark/types";
import { isNotNull } from "@/utils/typeguard";
import { WatchedStoreData } from "../types"; import { WatchedStoreData } from "../types";
async function migrateId( async function migrateId(
id: number, id: string,
type: MWMediaType type: MWMediaType
): Promise<string | undefined> { ): Promise<string | undefined> {
const meta = await getLegacyMetaFromId(type, id.toString()); const meta = await getLegacyMetaFromId(type, id);
if (!meta) return undefined; if (!meta) return undefined;
const { tmdbId, imdbId } = meta; const { tmdbId, imdbId } = meta;
@ -25,57 +31,59 @@ async function migrateId(
} }
} }
export async function migrateV2Bookmarks(old: any) { export async function migrateV2Bookmarks(old: BookmarkStoreData) {
const oldData = old; const updatedBookmarks = old.bookmarks.map(async (item) => ({
if (!oldData) return; ...item,
id: await migrateId(item.id, item.type).catch(() => undefined),
const updatedBookmarks = oldData.bookmarks.map( }));
async (item: { id: number; type: MWMediaType }) => ({
...item,
id: await migrateId(item.id, item.type),
})
);
return { return {
bookmarks: (await Promise.all(updatedBookmarks)).filter((item) => item.id), bookmarks: (await Promise.all(updatedBookmarks)).filter((item) => item.id),
}; };
} }
export async function migrateV3Videos(old: any) { export async function migrateV3Videos(
const oldData = old; old: WatchedStoreData
if (!oldData) return; ): Promise<WatchedStoreData> {
const updatedItems = await Promise.all( const updatedItems = await Promise.all(
oldData.items.map(async (item: any) => { old.items.map(async (progress) => {
const migratedId = await migrateId( try {
item.item.meta.id, const migratedId = await migrateId(
item.item.meta.type progress.item.meta.id,
); progress.item.meta.type
);
const migratedItem = { if (!migratedId) return null;
...item,
item: {
...item.item,
meta: {
...item.item.meta,
id: migratedId,
},
},
};
return { const clone = structuredClone(progress);
...item, clone.item.meta.id = migratedId;
item: migratedId ? migratedItem : item.item, if (clone.item.series) {
}; const series = clone.item.series;
const details = await getMediaDetails(migratedId, "show");
const season = details.seasons.find(
(v) => v.season_number === series.season
);
if (!season) return null;
const episodes = await getEpisodes(migratedId, season.season_number);
const episode = episodes.find(
(v) => v.episode_number === series.episode
);
if (!episode) return null;
clone.item.series.episodeId = episode.id.toString();
clone.item.series.seasonId = season.id.toString();
}
return clone;
} catch (err) {
return null;
}
}) })
); );
const newData: WatchedStoreData = {
items: updatedItems.map((item) => item.item),
};
return { return {
...oldData, items: updatedItems.filter(isNotNull),
items: newData.items,
}; };
} }

View file

@ -22,7 +22,7 @@ export const VideoProgressStore = createVersionedStore<WatchedStoreData>()
}) })
.addVersion({ .addVersion({
version: 2, version: 2,
migrate(old: OldData) { migrate(old: WatchedStoreData) {
return migrateV3Videos(old); return migrateV3Videos(old);
}, },
}) })

View file

@ -46,8 +46,13 @@ export async function initializeStores() {
let mostRecentData = data; let mostRecentData = data;
try { try {
for (const version of relevantVersions) { for (const version of relevantVersions) {
if (version.migrate) if (version.migrate) {
localStorage.setItem(
`BACKUP-v${version.version}-${internal.key}`,
JSON.stringify(mostRecentData)
);
mostRecentData = await version.migrate(mostRecentData); mostRecentData = await version.migrate(mostRecentData);
}
} }
} catch (err) { } catch (err) {
console.error(`FAILED TO MIGRATE STORE ${internal.key}`, err); console.error(`FAILED TO MIGRATE STORE ${internal.key}`, err);

3
src/utils/typeguard.ts Normal file
View file

@ -0,0 +1,3 @@
export function isNotNull<T>(obj: T | null): obj is T {
return obj != null;
}