mirror of
https://github.com/movie-web/movie-web.git
synced 2024-11-10 22:55:07 +01:00
commit
f7d51e6d8b
@ -10,6 +10,7 @@ export enum MWCaptionType {
|
||||
|
||||
export enum MWStreamQuality {
|
||||
Q360P = "360p",
|
||||
Q540P = "540p",
|
||||
Q480P = "480p",
|
||||
Q720P = "720p",
|
||||
Q1080P = "1080p",
|
||||
|
@ -1,7 +1,11 @@
|
||||
import { compareTitle } from "@/utils/titleMatch";
|
||||
import { proxiedFetch } from "../helpers/fetch";
|
||||
import { registerProvider } from "../helpers/register";
|
||||
import { MWStreamQuality, MWStreamType } from "../helpers/streams";
|
||||
import {
|
||||
MWCaptionType,
|
||||
MWStreamQuality,
|
||||
MWStreamType,
|
||||
} from "../helpers/streams";
|
||||
import { MWMediaType } from "../metadata/types";
|
||||
|
||||
// const flixHqBase = "https://api.consumet.org/movies/flixhq";
|
||||
@ -9,13 +13,52 @@ import { MWMediaType } from "../metadata/types";
|
||||
// SEE ISSUE: https://github.com/consumet/api.consumet.org/issues/326
|
||||
const flixHqBase = "https://c.delusionz.xyz/movies/flixhq";
|
||||
|
||||
interface FLIXMediaBase {
|
||||
id: number;
|
||||
title: string;
|
||||
url: string;
|
||||
image: string;
|
||||
}
|
||||
|
||||
interface FLIXTVSerie extends FLIXMediaBase {
|
||||
type: "TV Series";
|
||||
seasons: number | null;
|
||||
}
|
||||
|
||||
interface FLIXMovie extends FLIXMediaBase {
|
||||
type: "Movie";
|
||||
releaseDate: string;
|
||||
}
|
||||
|
||||
function castSubtitles({ url, lang }: { url: string; lang: string }) {
|
||||
return {
|
||||
url,
|
||||
langIso: lang,
|
||||
type:
|
||||
url.substring(url.length - 3) === "vtt"
|
||||
? MWCaptionType.VTT
|
||||
: MWCaptionType.SRT,
|
||||
};
|
||||
}
|
||||
|
||||
const qualityMap: Record<string, MWStreamQuality> = {
|
||||
"360": MWStreamQuality.Q360P,
|
||||
"540": MWStreamQuality.Q540P,
|
||||
"480": MWStreamQuality.Q480P,
|
||||
"720": MWStreamQuality.Q720P,
|
||||
"1080": MWStreamQuality.Q1080P,
|
||||
};
|
||||
|
||||
registerProvider({
|
||||
id: "flixhq",
|
||||
displayName: "FlixHQ",
|
||||
rank: 100,
|
||||
type: [MWMediaType.MOVIE],
|
||||
type: [MWMediaType.MOVIE, MWMediaType.SERIES],
|
||||
|
||||
async scrape({ media, progress }) {
|
||||
if (!this.type.includes(media.meta.type)) {
|
||||
throw new Error("Unsupported type");
|
||||
}
|
||||
// search for relevant item
|
||||
const searchResults = await proxiedFetch<any>(
|
||||
`/${encodeURIComponent(media.meta.title)}`,
|
||||
@ -23,11 +66,22 @@ registerProvider({
|
||||
baseURL: flixHqBase,
|
||||
}
|
||||
);
|
||||
const foundItem = searchResults.results.find((v: any) => {
|
||||
return (
|
||||
compareTitle(v.title, media.meta.title) &&
|
||||
v.releaseDate === media.meta.year
|
||||
);
|
||||
const foundItem = searchResults.results.find((v: FLIXMediaBase) => {
|
||||
if (media.meta.type === MWMediaType.MOVIE) {
|
||||
const movie = v as FLIXMovie;
|
||||
return (
|
||||
compareTitle(movie.title, media.meta.title) &&
|
||||
movie.releaseDate === media.meta.year
|
||||
);
|
||||
}
|
||||
const serie = v as FLIXTVSerie;
|
||||
if (serie.seasons && media.meta.seasons) {
|
||||
return (
|
||||
compareTitle(serie.title, media.meta.title) &&
|
||||
serie.seasons === media.meta.seasons.length
|
||||
);
|
||||
}
|
||||
return compareTitle(serie.title, media.meta.title);
|
||||
});
|
||||
if (!foundItem) throw new Error("No watchable item found");
|
||||
const flixId = foundItem.id;
|
||||
@ -40,7 +94,7 @@ registerProvider({
|
||||
id: flixId,
|
||||
},
|
||||
});
|
||||
|
||||
if (!mediaInfo.episodes) throw new Error("No watchable item found");
|
||||
// get stream info from media
|
||||
progress(75);
|
||||
const watchInfo = await proxiedFetch<any>("/watch", {
|
||||
@ -51,18 +105,22 @@ registerProvider({
|
||||
},
|
||||
});
|
||||
|
||||
// get best quality source
|
||||
const source = watchInfo.sources.reduce((p: any, c: any) =>
|
||||
c.quality > p.quality ? c : p
|
||||
);
|
||||
if (!watchInfo.sources) throw new Error("No watchable item found");
|
||||
|
||||
// get best quality source
|
||||
// comes sorted by quality in descending order
|
||||
const source = watchInfo.sources[0];
|
||||
return {
|
||||
embeds: [],
|
||||
stream: {
|
||||
streamUrl: source.url,
|
||||
quality: MWStreamQuality.QUNKNOWN,
|
||||
quality: qualityMap[source.quality],
|
||||
type: source.isM3U8 ? MWStreamType.HLS : MWStreamType.MP4,
|
||||
captions: [],
|
||||
captions: watchInfo.subtitles
|
||||
.filter(
|
||||
(x: { url: string; lang: string }) => !x.lang.includes("(maybe)")
|
||||
)
|
||||
.map(castSubtitles),
|
||||
},
|
||||
};
|
||||
},
|
||||
|
@ -9,13 +9,13 @@ import { MWMediaType } from "../metadata/types";
|
||||
|
||||
const netfilmBase = "https://net-film.vercel.app";
|
||||
|
||||
const qualityMap = {
|
||||
"360": MWStreamQuality.Q360P,
|
||||
"480": MWStreamQuality.Q480P,
|
||||
"720": MWStreamQuality.Q720P,
|
||||
"1080": MWStreamQuality.Q1080P,
|
||||
const qualityMap: Record<number, MWStreamQuality> = {
|
||||
360: MWStreamQuality.Q360P,
|
||||
540: MWStreamQuality.Q540P,
|
||||
480: MWStreamQuality.Q480P,
|
||||
720: MWStreamQuality.Q720P,
|
||||
1080: MWStreamQuality.Q1080P,
|
||||
};
|
||||
type QualityInMap = keyof typeof qualityMap;
|
||||
|
||||
registerProvider({
|
||||
id: "netfilm",
|
||||
@ -24,6 +24,9 @@ registerProvider({
|
||||
type: [MWMediaType.MOVIE, MWMediaType.SERIES],
|
||||
|
||||
async scrape({ media, episode, progress }) {
|
||||
if (!this.type.includes(media.meta.type)) {
|
||||
throw new Error("Unsupported type");
|
||||
}
|
||||
// search for relevant item
|
||||
const searchResponse = await proxiedFetch<any>(
|
||||
`/api/search?keyword=${encodeURIComponent(media.meta.title)}`,
|
||||
@ -54,8 +57,8 @@ registerProvider({
|
||||
const data = watchInfo.data;
|
||||
|
||||
// get best quality source
|
||||
const source = data.qualities.reduce((p: any, c: any) =>
|
||||
c.quality > p.quality ? c : p
|
||||
const source: { url: string; quality: number } = data.qualities.reduce(
|
||||
(p: any, c: any) => (c.quality > p.quality ? c : p)
|
||||
);
|
||||
|
||||
const mappedCaptions = data.subtitles.map((sub: Record<string, any>) => ({
|
||||
@ -71,7 +74,7 @@ registerProvider({
|
||||
streamUrl: source.url
|
||||
.replace("akm-cdn", "aws-cdn")
|
||||
.replace("gg-cdn", "aws-cdn"),
|
||||
quality: qualityMap[source.quality as QualityInMap],
|
||||
quality: qualityMap[source.quality],
|
||||
type: MWStreamType.HLS,
|
||||
captions: mappedCaptions,
|
||||
},
|
||||
@ -124,8 +127,8 @@ registerProvider({
|
||||
const data = episodeStream.data;
|
||||
|
||||
// get best quality source
|
||||
const source = data.qualities.reduce((p: any, c: any) =>
|
||||
c.quality > p.quality ? c : p
|
||||
const source: { url: string; quality: number } = data.qualities.reduce(
|
||||
(p: any, c: any) => (c.quality > p.quality ? c : p)
|
||||
);
|
||||
|
||||
const mappedCaptions = data.subtitles.map((sub: Record<string, any>) => ({
|
||||
@ -141,7 +144,7 @@ registerProvider({
|
||||
streamUrl: source.url
|
||||
.replace("akm-cdn", "aws-cdn")
|
||||
.replace("gg-cdn", "aws-cdn"),
|
||||
quality: qualityMap[source.quality as QualityInMap],
|
||||
quality: qualityMap[source.quality],
|
||||
type: MWStreamType.HLS,
|
||||
captions: mappedCaptions,
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user