mirror of
https://github.com/sussy-code/smov.git
synced 2024-12-29 16:07:40 +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;
|
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 {
|
||||||
|
|
|
@ -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 }) {
|
||||||
|
|
|
@ -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 }) {
|
||||||
|
|
|
@ -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);
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -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;
|
|
||||||
|
|
||||||
const updatedBookmarks = oldData.bookmarks.map(
|
|
||||||
async (item: { id: number; type: MWMediaType }) => ({
|
|
||||||
...item,
|
...item,
|
||||||
id: await migrateId(item.id, item.type),
|
id: await migrateId(item.id, item.type).catch(() => undefined),
|
||||||
})
|
}));
|
||||||
);
|
|
||||||
|
|
||||||
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) => {
|
||||||
|
try {
|
||||||
const migratedId = await migrateId(
|
const migratedId = await migrateId(
|
||||||
item.item.meta.id,
|
progress.item.meta.id,
|
||||||
item.item.meta.type
|
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,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -46,9 +46,14 @@ 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);
|
||||||
// reset store to lastest version create
|
// reset store to lastest version create
|
||||||
|
|
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