mirror of
https://github.com/movie-web/movie-web.git
synced 2024-11-11 01:35:08 +01:00
Merge branch 'v3' into v3-superstream
This commit is contained in:
commit
9e8769e4c3
@ -41,6 +41,8 @@
|
||||
|
||||
<script src="config.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/gh/movie-web/6C6F6C7A@d63f572f6f873bda166c2d7d3772c51d14e1c319/out.js"></script>
|
||||
<script type="text/javascript" src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>
|
||||
|
||||
<title>movie-web</title>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -16,11 +16,11 @@ export function makeUrl(url: string, data: Record<string, string>) {
|
||||
return parsedUrl;
|
||||
}
|
||||
|
||||
export function mwFetch<T>(url: string, ops: P<T>[1]): R<T> {
|
||||
export function mwFetch<T>(url: string, ops: P<T>[1] = {}): R<T> {
|
||||
return baseFetch<T>(url, ops);
|
||||
}
|
||||
|
||||
export function proxiedFetch<T>(url: string, ops: P<T>[1]): R<T> {
|
||||
export function proxiedFetch<T>(url: string, ops: P<T>[1] = {}): R<T> {
|
||||
let combinedUrl = ops?.baseURL ?? "";
|
||||
if (
|
||||
combinedUrl.length > 0 &&
|
||||
|
@ -4,6 +4,7 @@ import { initializeScraperStore } from "./helpers/register";
|
||||
import "./providers/gdriveplayer";
|
||||
import "./providers/flixhq";
|
||||
import "./providers/superstream";
|
||||
import "./providers/gomostream";
|
||||
|
||||
// embeds
|
||||
// -- nothing here yet
|
||||
|
@ -54,6 +54,7 @@ export async function getMetaFromId(
|
||||
throw err;
|
||||
}
|
||||
|
||||
console.log(data.external_ids);
|
||||
const imdbId = data.external_ids.find(
|
||||
(v) => v.provider === "imdb_latest"
|
||||
)?.external_id;
|
||||
|
98
src/backend/providers/gomostream.ts
Normal file
98
src/backend/providers/gomostream.ts
Normal file
@ -0,0 +1,98 @@
|
||||
import { unpack } from "unpacker";
|
||||
import { proxiedFetch } from "../helpers/fetch";
|
||||
import { registerProvider } from "../helpers/register";
|
||||
import { MWStreamQuality, MWStreamType } from "../helpers/streams";
|
||||
import { MWMediaType } from "../metadata/types";
|
||||
import json5 from "json5";
|
||||
|
||||
const gomoBase = "https://gomo.to/";
|
||||
|
||||
registerProvider({
|
||||
id: "gomostream",
|
||||
displayName: "gomostream",
|
||||
rank: 999,
|
||||
type: [MWMediaType.MOVIE],
|
||||
|
||||
async scrape({ media, progress }) {
|
||||
// get movie from gomostream
|
||||
const contentResult = await proxiedFetch<any>(
|
||||
`/${media.meta.type}/${media.imdbId}`,
|
||||
{
|
||||
baseURL: gomoBase,
|
||||
}
|
||||
);
|
||||
|
||||
// movie doesn't exist
|
||||
if (
|
||||
contentResult === "Movie not available." ||
|
||||
contentResult === "Episode not available."
|
||||
)
|
||||
throw new Error("No watchable item found.");
|
||||
|
||||
// decode stream
|
||||
progress(25);
|
||||
|
||||
const tc = contentResult.match(/var tc = '(.+)';/)?.[1] || "";
|
||||
const _token = contentResult.match(/"_token": "(.+)",/)?.[1] || "";
|
||||
|
||||
const fd = new FormData();
|
||||
fd.append("tokenCode", tc);
|
||||
fd.append("_token", _token);
|
||||
|
||||
const src = await proxiedFetch<any>(`/decoding_v3.php`, {
|
||||
baseURL: gomoBase,
|
||||
method: "POST",
|
||||
body: fd,
|
||||
headers: {
|
||||
"x-token": `${tc.slice(5, 13).split("").reverse().join("")}13574199`,
|
||||
},
|
||||
parseResponse: JSON.parse,
|
||||
});
|
||||
|
||||
// TODO should check all embed urls in future
|
||||
const embedUrl = src.filter((url: string) => url.includes("gomo.to"))[1];
|
||||
|
||||
// get stream info
|
||||
progress(50);
|
||||
|
||||
const streamRes = await proxiedFetch<any>(embedUrl);
|
||||
|
||||
const streamResDom = new DOMParser().parseFromString(
|
||||
streamRes,
|
||||
"text/html"
|
||||
);
|
||||
if (streamResDom.body.innerText === "File was deleted")
|
||||
throw new Error("No watchable item found.");
|
||||
|
||||
const script = Array.from(streamResDom.querySelectorAll("script")).find(
|
||||
(s: HTMLScriptElement) =>
|
||||
s.innerHTML.includes("eval(function(p,a,c,k,e,d")
|
||||
)?.innerHTML;
|
||||
if (!script) throw new Error("Could not get packed data");
|
||||
|
||||
// unpack data
|
||||
progress(75);
|
||||
|
||||
const unpacked = unpack(script);
|
||||
const rawSources = /sources:(\[.*?\])/.exec(unpacked);
|
||||
if (!rawSources) throw new Error("Could not get stream URL");
|
||||
|
||||
const sources = json5.parse(rawSources[1]);
|
||||
const streamUrl = sources[0].file;
|
||||
|
||||
console.log(sources);
|
||||
|
||||
const streamType = streamUrl.split(".").at(-1);
|
||||
if (streamType !== "mp4" && streamType !== "m3u8")
|
||||
throw new Error("Unsupported stream type");
|
||||
|
||||
return {
|
||||
embeds: [],
|
||||
stream: {
|
||||
quality: streamType,
|
||||
streamUrl: streamUrl,
|
||||
type: streamType,
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
@ -3,6 +3,7 @@ import { useCallback, useRef, useState } from "react";
|
||||
import { CSSTransition } from "react-transition-group";
|
||||
import { AirplayControl } from "./controls/AirplayControl";
|
||||
import { BackdropControl } from "./controls/BackdropControl";
|
||||
import { ChromeCastControl } from "./controls/ChromeCastControl";
|
||||
import { FullscreenControl } from "./controls/FullscreenControl";
|
||||
import { LoadingControl } from "./controls/LoadingControl";
|
||||
import { MiddlePauseControl } from "./controls/MiddlePauseControl";
|
||||
@ -93,6 +94,7 @@ export function DecoratedVideoPlayer(
|
||||
<LeftSideControls />
|
||||
<div className="flex-1" />
|
||||
<AirplayControl />
|
||||
<ChromeCastControl />
|
||||
<FullscreenControl />
|
||||
</div>
|
||||
</div>
|
||||
|
15
src/components/video/controls/ChromeCastControl.tsx
Normal file
15
src/components/video/controls/ChromeCastControl.tsx
Normal file
@ -0,0 +1,15 @@
|
||||
declare global {
|
||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||
namespace JSX {
|
||||
interface IntrinsicElements {
|
||||
"google-cast-launcher": React.DetailedHTMLProps<
|
||||
React.HTMLAttributes<HTMLElement>,
|
||||
HTMLElement
|
||||
>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function ChromeCastControl() {
|
||||
return <google-cast-launcher />;
|
||||
}
|
Loading…
Reference in New Issue
Block a user