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:
parent
545120d5cc
commit
c4c7816543
8 changed files with 79 additions and 60 deletions
|
@ -143,21 +143,24 @@ export async function searchMedia(
|
|||
return data;
|
||||
}
|
||||
|
||||
export async function getMediaDetails(id: string, type: TMDBContentTypes) {
|
||||
let data;
|
||||
// Conditional type which for inferring the return type based on the content type
|
||||
type MediaDetailReturn<T extends TMDBContentTypes> = T extends "movie"
|
||||
? TMDBMovieData
|
||||
: T extends "show"
|
||||
? TMDBShowData
|
||||
: never;
|
||||
|
||||
switch (type) {
|
||||
case "movie":
|
||||
data = await get<TMDBMovieData>(`/movie/${id}`);
|
||||
break;
|
||||
case "show":
|
||||
data = await get<TMDBShowData>(`/tv/${id}`);
|
||||
break;
|
||||
default:
|
||||
throw new Error("Invalid media type");
|
||||
export function getMediaDetails<
|
||||
T extends TMDBContentTypes,
|
||||
TReturn = MediaDetailReturn<T>
|
||||
>(id: string, type: T): Promise<TReturn> {
|
||||
if (type === "movie") {
|
||||
return get<TReturn>(`/movie/${id}`);
|
||||
}
|
||||
|
||||
return data;
|
||||
if (type === "show") {
|
||||
return get<TReturn>(`/tv/${id}`);
|
||||
}
|
||||
throw new Error("Invalid media type");
|
||||
}
|
||||
|
||||
export function getMediaPoster(posterPath: string | null): string | undefined {
|
||||
|
|
|
@ -8,7 +8,7 @@ const gomoviesBase = "https://gomovies.sx";
|
|||
registerProvider({
|
||||
id: "gomovies",
|
||||
displayName: "GOmovies",
|
||||
rank: 300,
|
||||
rank: 200,
|
||||
type: [MWMediaType.MOVIE, MWMediaType.SERIES],
|
||||
|
||||
async scrape({ media, episode }) {
|
||||
|
|
|
@ -142,7 +142,7 @@ const convertSubtitles = (subtitleGroup: any): MWCaption | null => {
|
|||
registerProvider({
|
||||
id: "superstream",
|
||||
displayName: "Superstream",
|
||||
rank: 200,
|
||||
rank: 300,
|
||||
type: [MWMediaType.MOVIE, MWMediaType.SERIES],
|
||||
|
||||
async scrape({ media, episode, progress }) {
|
||||
|
|
|
@ -14,7 +14,7 @@ export const BookmarkStore = createVersionedStore<BookmarkStoreData>()
|
|||
})
|
||||
.addVersion({
|
||||
version: 1,
|
||||
migrate(old: OldBookmarks) {
|
||||
migrate(old: BookmarkStoreData) {
|
||||
return migrateV2Bookmarks(old);
|
||||
},
|
||||
})
|
||||
|
|
|
@ -1,14 +1,20 @@
|
|||
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 { BookmarkStoreData } from "@/state/bookmark/types";
|
||||
import { isNotNull } from "@/utils/typeguard";
|
||||
|
||||
import { WatchedStoreData } from "../types";
|
||||
|
||||
async function migrateId(
|
||||
id: number,
|
||||
id: string,
|
||||
type: MWMediaType
|
||||
): Promise<string | undefined> {
|
||||
const meta = await getLegacyMetaFromId(type, id.toString());
|
||||
const meta = await getLegacyMetaFromId(type, id);
|
||||
|
||||
if (!meta) return undefined;
|
||||
const { tmdbId, imdbId } = meta;
|
||||
|
@ -25,57 +31,59 @@ async function migrateId(
|
|||
}
|
||||
}
|
||||
|
||||
export async function migrateV2Bookmarks(old: any) {
|
||||
const oldData = old;
|
||||
if (!oldData) return;
|
||||
|
||||
const updatedBookmarks = oldData.bookmarks.map(
|
||||
async (item: { id: number; type: MWMediaType }) => ({
|
||||
...item,
|
||||
id: await migrateId(item.id, item.type),
|
||||
})
|
||||
);
|
||||
export async function migrateV2Bookmarks(old: BookmarkStoreData) {
|
||||
const updatedBookmarks = old.bookmarks.map(async (item) => ({
|
||||
...item,
|
||||
id: await migrateId(item.id, item.type).catch(() => undefined),
|
||||
}));
|
||||
|
||||
return {
|
||||
bookmarks: (await Promise.all(updatedBookmarks)).filter((item) => item.id),
|
||||
};
|
||||
}
|
||||
|
||||
export async function migrateV3Videos(old: any) {
|
||||
const oldData = old;
|
||||
if (!oldData) return;
|
||||
|
||||
export async function migrateV3Videos(
|
||||
old: WatchedStoreData
|
||||
): Promise<WatchedStoreData> {
|
||||
const updatedItems = await Promise.all(
|
||||
oldData.items.map(async (item: any) => {
|
||||
const migratedId = await migrateId(
|
||||
item.item.meta.id,
|
||||
item.item.meta.type
|
||||
);
|
||||
old.items.map(async (progress) => {
|
||||
try {
|
||||
const migratedId = await migrateId(
|
||||
progress.item.meta.id,
|
||||
progress.item.meta.type
|
||||
);
|
||||
|
||||
const migratedItem = {
|
||||
...item,
|
||||
item: {
|
||||
...item.item,
|
||||
meta: {
|
||||
...item.item.meta,
|
||||
id: migratedId,
|
||||
},
|
||||
},
|
||||
};
|
||||
if (!migratedId) return null;
|
||||
|
||||
return {
|
||||
...item,
|
||||
item: migratedId ? migratedItem : item.item,
|
||||
};
|
||||
const clone = structuredClone(progress);
|
||||
clone.item.meta.id = migratedId;
|
||||
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 {
|
||||
...oldData,
|
||||
items: newData.items,
|
||||
items: updatedItems.filter(isNotNull),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ export const VideoProgressStore = createVersionedStore<WatchedStoreData>()
|
|||
})
|
||||
.addVersion({
|
||||
version: 2,
|
||||
migrate(old: OldData) {
|
||||
migrate(old: WatchedStoreData) {
|
||||
return migrateV3Videos(old);
|
||||
},
|
||||
})
|
||||
|
|
|
@ -46,8 +46,13 @@ export async function initializeStores() {
|
|||
let mostRecentData = data;
|
||||
try {
|
||||
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);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`FAILED TO MIGRATE STORE ${internal.key}`, err);
|
||||
|
|
3
src/utils/typeguard.ts
Normal file
3
src/utils/typeguard.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
export function isNotNull<T>(obj: T | null): obj is T {
|
||||
return obj != null;
|
||||
}
|
Loading…
Reference in a new issue