mirror of
https://github.com/sussy-code/smov.git
synced 2024-12-30 16:17:41 +01:00
Merge pull request #1 from JamesHawkinss/v2/sources
Implement gdriveplayer and gomostream
This commit is contained in:
commit
8419956b7b
7 changed files with 6752 additions and 6997 deletions
|
@ -8,8 +8,9 @@
|
|||
"@testing-library/jest-dom": "^5.11.4",
|
||||
"@testing-library/react": "^11.1.0",
|
||||
"@testing-library/user-event": "^12.1.10",
|
||||
"@types/crypto-js": "^4.1.1",
|
||||
"@types/react-router": "^5.1.18",
|
||||
"crypto-js": "^4.0.0",
|
||||
"crypto-js": "^4.1.1",
|
||||
"fuse.js": "^6.4.6",
|
||||
"hls.js": "^1.0.7",
|
||||
"json5": "^2.2.0",
|
||||
|
@ -20,6 +21,7 @@
|
|||
"react-scripts": "^5.0.0",
|
||||
"react-tracked": "^1.7.6",
|
||||
"scheduler": "^0.20.2",
|
||||
"unpacker": "^1.0.1",
|
||||
"web-vitals": "^1.0.1"
|
||||
},
|
||||
"scripts": {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
export const CORS_PROXY_URL = "https://proxy-1.movie-web.workers.dev/?destination=";
|
||||
export const OMDB_API_KEY = "aa0937c0";
|
||||
export const DISCORD_LINK = "https://discord.gg/Jhqt4Xzpfb";
|
||||
export const GITHUB_LINK = "https://github.com/JamesHawkinss/movie-web";
|
||||
|
|
96
src/providers/list/gdriveplayer/index.ts
Normal file
96
src/providers/list/gdriveplayer/index.ts
Normal file
|
@ -0,0 +1,96 @@
|
|||
import {
|
||||
MWMediaProvider,
|
||||
MWMediaType,
|
||||
MWPortableMedia,
|
||||
MWMediaStream,
|
||||
MWQuery,
|
||||
MWMediaSeasons,
|
||||
MWProviderMediaResult
|
||||
} from "providers/types";
|
||||
|
||||
import { CORS_PROXY_URL } from "mw_constants";
|
||||
import { unpack } from "unpacker";
|
||||
import CryptoJS from "crypto-js";
|
||||
|
||||
const format = {
|
||||
stringify: (cipher: any) => {
|
||||
const ct = cipher.ciphertext.toString(CryptoJS.enc.Base64);
|
||||
const iv = cipher.iv.toString() || "";
|
||||
const salt = cipher.salt.toString() || "";
|
||||
return JSON.stringify({
|
||||
ct,
|
||||
iv,
|
||||
salt,
|
||||
});
|
||||
},
|
||||
parse: (jsonStr: string) => {
|
||||
const json = JSON.parse(jsonStr);
|
||||
const ciphertext = CryptoJS.enc.Base64.parse(json.ct);
|
||||
const iv = CryptoJS.enc.Hex.parse(json.iv) || "";
|
||||
const salt = CryptoJS.enc.Hex.parse(json.s) || "";
|
||||
|
||||
const cipher = CryptoJS.lib.CipherParams.create({
|
||||
ciphertext,
|
||||
iv,
|
||||
salt,
|
||||
});
|
||||
return cipher;
|
||||
}
|
||||
};
|
||||
|
||||
export const gDrivePlayerScraper: MWMediaProvider = {
|
||||
id: "gdriveplayer",
|
||||
enabled: true,
|
||||
type: [MWMediaType.MOVIE],
|
||||
displayName: "gdriveplayer",
|
||||
|
||||
async getMediaFromPortable(media: MWPortableMedia): Promise<MWProviderMediaResult> {
|
||||
const res = await fetch(`${CORS_PROXY_URL}https://api.gdriveplayer.us/v1/imdb/${media.mediaId}`).then((d) => d.json());
|
||||
|
||||
return {
|
||||
...media,
|
||||
title: res.Title,
|
||||
year: res.Year,
|
||||
} as MWProviderMediaResult;
|
||||
},
|
||||
|
||||
async searchForMedia(query: MWQuery): Promise<MWProviderMediaResult[]> {
|
||||
const searchRes = await fetch(`${CORS_PROXY_URL}https://api.gdriveplayer.us/v1/movie/search?title=${query.searchQuery}`).then((d) => d.json());
|
||||
|
||||
const results: MWProviderMediaResult[] = searchRes.map((item: any) => ({
|
||||
title: item.title,
|
||||
year: item.year,
|
||||
mediaId: item.imdb,
|
||||
}));
|
||||
|
||||
return results;
|
||||
|
||||
},
|
||||
|
||||
async getStream(media: MWPortableMedia): Promise<MWMediaStream> {
|
||||
const streamRes = await fetch(`${CORS_PROXY_URL}https://database.gdriveplayer.us/player.php?imdb=${media.mediaId}`).then((d) => d.text());
|
||||
const page = new DOMParser().parseFromString(streamRes, "text/html");
|
||||
|
||||
const script: HTMLElement | undefined = Array.from(
|
||||
page.querySelectorAll("script")
|
||||
).find((e) => e.textContent?.includes("eval"));
|
||||
|
||||
if (!script || !script.textContent) {
|
||||
throw new Error("Could not find stream");
|
||||
}
|
||||
|
||||
/// NOTE: this code requires re-write, it's not safe
|
||||
const data = unpack(script.textContent).split("var data=\\'")[1].split("\\'")[0].replace(/\\/g, "");
|
||||
const decryptedData = unpack(CryptoJS.AES.decrypt(data, "alsfheafsjklNIWORNiolNIOWNKLNXakjsfwnBdwjbwfkjbJjkopfjweopjASoiwnrflakefneiofrt", { format }).toString(CryptoJS.enc.Utf8));
|
||||
// eslint-disable-next-line
|
||||
const sources = JSON.parse(JSON.stringify(eval(decryptedData.split("sources:")[1].split(",image")[0].replace(/\\/g, "").replace(/document\.referrer/g, "\"\""))));
|
||||
const source = sources[sources.length - 1];
|
||||
/// END
|
||||
|
||||
return { url: `https:${source.file}`, type: source.type, captions: [] };
|
||||
},
|
||||
|
||||
async getSeasonDataFromMedia(media: MWPortableMedia): Promise<MWMediaSeasons> {
|
||||
return {} as MWMediaSeasons;
|
||||
}
|
||||
};
|
100
src/providers/list/gomostream/index.ts
Normal file
100
src/providers/list/gomostream/index.ts
Normal file
|
@ -0,0 +1,100 @@
|
|||
import {
|
||||
MWMediaProvider,
|
||||
MWMediaType,
|
||||
MWPortableMedia,
|
||||
MWMediaStream,
|
||||
MWQuery,
|
||||
MWMediaSeasons,
|
||||
MWProviderMediaResult
|
||||
} from "providers/types";
|
||||
|
||||
import { CORS_PROXY_URL, OMDB_API_KEY } from "mw_constants";
|
||||
import { unpack } from "unpacker";
|
||||
|
||||
export const gomostreamScraper: MWMediaProvider = {
|
||||
id: "gomostream",
|
||||
enabled: true,
|
||||
type: [MWMediaType.MOVIE],
|
||||
displayName: "gomostream",
|
||||
|
||||
async getMediaFromPortable(media: MWPortableMedia): Promise<MWProviderMediaResult> {
|
||||
const params = new URLSearchParams({
|
||||
apikey: OMDB_API_KEY,
|
||||
i: media.mediaId,
|
||||
type: media.mediaType
|
||||
});
|
||||
|
||||
const res = await fetch(
|
||||
`${CORS_PROXY_URL}http://www.omdbapi.com/?${encodeURIComponent(params.toString())}`,
|
||||
).then(d => d.json())
|
||||
|
||||
return {
|
||||
...media,
|
||||
title: res.Title,
|
||||
year: res.Year
|
||||
} as MWProviderMediaResult;
|
||||
},
|
||||
|
||||
async searchForMedia(query: MWQuery): Promise<MWProviderMediaResult[]> {
|
||||
const term = query.searchQuery.toLowerCase();
|
||||
|
||||
const params = new URLSearchParams({
|
||||
apikey: OMDB_API_KEY,
|
||||
s: term,
|
||||
type: query.type
|
||||
});
|
||||
const searchRes = await fetch(
|
||||
`${CORS_PROXY_URL}http://www.omdbapi.com/?${encodeURIComponent(params.toString())}`,
|
||||
).then(d => d.json())
|
||||
|
||||
const results: MWProviderMediaResult[] = searchRes.Search.map((d: any) => ({
|
||||
title: d.Title,
|
||||
year: d.Year,
|
||||
mediaId: d.imdbID
|
||||
} as MWProviderMediaResult));
|
||||
|
||||
return results;
|
||||
},
|
||||
|
||||
async getStream(media: MWPortableMedia): Promise<MWMediaStream> {
|
||||
const type = media.mediaType === MWMediaType.SERIES ? 'show' : media.mediaType;
|
||||
const res1 = await fetch(`${CORS_PROXY_URL}https://gomo.to/${type}/${media.mediaId}`).then((d) => d.text());
|
||||
if (res1 === "Movie not available." || res1 === "Episode not available.") throw new Error(res1);
|
||||
|
||||
const tc = res1.match(/var tc = '(.+)';/)?.[1] || "";
|
||||
const _token = res1.match(/"_token": "(.+)",/)?.[1] || "";
|
||||
|
||||
const fd = new FormData()
|
||||
fd.append('tokenCode', tc)
|
||||
fd.append('_token', _token)
|
||||
|
||||
const src = await fetch(`${CORS_PROXY_URL}https://gomo.to/decoding_v3.php`, {
|
||||
method: "POST",
|
||||
body: fd,
|
||||
headers: {
|
||||
'x-token': `${tc.slice(5, 13).split("").reverse().join("")}13574199`
|
||||
}
|
||||
}).then((d) => d.json());
|
||||
|
||||
const embedUrl = src.find((url: string) => url.includes('gomo.to'));
|
||||
const res2 = await fetch(`${CORS_PROXY_URL}${embedUrl}`).then((d) => d.text());
|
||||
|
||||
const res2DOM = new DOMParser().parseFromString(res2, "text/html");
|
||||
if (res2DOM.body.innerText === "File was deleted") throw new Error("File was deleted");
|
||||
|
||||
const script = res2DOM.querySelectorAll("script")[8].innerHTML;
|
||||
const unpacked = unpack(script).split('');
|
||||
unpacked.splice(0, 43);
|
||||
const index = unpacked.findIndex((e) => e === '"');
|
||||
const streamUrl = unpacked.slice(0, index).join('');
|
||||
|
||||
const streamType = streamUrl.split('.').at(-1);
|
||||
if (streamType !== "mp4" && streamType !== "m3u8") throw new Error("Unsupported stream type");
|
||||
|
||||
return { url: streamUrl, type: streamType, captions: [] };
|
||||
},
|
||||
|
||||
async getSeasonDataFromMedia(media: MWPortableMedia): Promise<MWMediaSeasons> {
|
||||
return {} as MWMediaSeasons;
|
||||
}
|
||||
};
|
|
@ -5,6 +5,7 @@ import {
|
|||
MWMediaStream,
|
||||
MWQuery,
|
||||
MWMediaSeasons,
|
||||
MWProviderMediaResult
|
||||
} from "providers/types";
|
||||
|
||||
import {
|
||||
|
@ -14,12 +15,11 @@ import {
|
|||
} from "providers/list/theflix/search";
|
||||
|
||||
import { getDataFromPortableSearch } from "providers/list/theflix/portableToMedia";
|
||||
import { MWProviderMediaResult } from "providers";
|
||||
import { CORS_PROXY_URL } from "mw_constants";
|
||||
|
||||
export const theFlixScraper: MWMediaProvider = {
|
||||
id: "theflix",
|
||||
enabled: true,
|
||||
enabled: false,
|
||||
type: [MWMediaType.MOVIE, MWMediaType.SERIES],
|
||||
displayName: "theflix",
|
||||
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
import { theFlixScraper } from "providers/list/theflix";
|
||||
import { gDrivePlayerScraper } from "providers/list/gdriveplayer";
|
||||
import { MWWrappedMediaProvider, WrapProvider } from "providers/wrapper";
|
||||
import { gomostreamScraper } from "providers/list/gomostream";
|
||||
|
||||
export const mediaProvidersUnchecked: MWWrappedMediaProvider[] = [
|
||||
WrapProvider(theFlixScraper),
|
||||
WrapProvider(gDrivePlayerScraper),
|
||||
WrapProvider(gomostreamScraper),
|
||||
];
|
||||
|
||||
export const mediaProviders: MWWrappedMediaProvider[] =
|
||||
|
|
Loading…
Reference in a new issue