Browse Source

Merge pull request #114 from movie-web/feat/config

Better config system
pull/115/head 2.1.1
James Hawkins 3 years ago committed by GitHub
parent
commit
80799b7600
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 28
      .eslintrc.js
  2. 5
      .github/workflows/deploying.yml
  3. 7
      .gitignore
  4. 10
      README.md
  5. 38
      SELFHOSTING.md
  6. 6
      example.env
  7. 1
      index.html
  8. 2
      package.json
  9. 7
      public/config.js
  10. 6
      src/components/layout/ErrorBoundary.tsx
  11. 6
      src/components/layout/Navigation.tsx
  12. 50
      src/config.ts
  13. 3
      src/constants.ts
  14. 6
      src/mw_constants.ts
  15. 18
      src/providers/list/flixhq/index.ts
  16. 14
      src/providers/list/gdriveplayer/index.ts
  17. 16
      src/providers/list/gomostream/index.ts
  18. 16
      src/providers/list/superstream/index.ts
  19. 14
      src/providers/list/theflix/index.ts
  20. 8
      src/providers/list/theflix/portableToMedia.ts
  21. 4
      src/providers/list/theflix/search.ts
  22. 19
      src/providers/list/xemovie/index.ts

28
.eslintrc.js

@ -1,26 +1,32 @@
const a11yOff = Object.keys(require('eslint-plugin-jsx-a11y').rules) const a11yOff = Object.keys(require("eslint-plugin-jsx-a11y").rules).reduce(
.reduce((acc, rule) => { acc[`jsx-a11y/${rule}`] = 'off'; return acc }, {}) (acc, rule) => {
acc[`jsx-a11y/${rule}`] = "off";
return acc;
},
{}
);
module.exports = { module.exports = {
extends: [ extends: [
"airbnb", "airbnb",
"airbnb/hooks", "airbnb/hooks",
"plugin:@typescript-eslint/recommended", "plugin:@typescript-eslint/recommended",
"prettier", "prettier"
], ],
settings: { settings: {
"import/resolver": { "import/resolver": {
typescript: {}, typescript: {}
}, }
}, },
ignorePatterns: ["public/*", "dist/*", "/*.js", "/*.ts"],
parser: "@typescript-eslint/parser", parser: "@typescript-eslint/parser",
parserOptions: { parserOptions: {
project: "./tsconfig.json", project: "./tsconfig.json",
tsconfigRootDir: "./", tsconfigRootDir: "./"
}, },
plugins: ["@typescript-eslint", "import"], plugins: ["@typescript-eslint", "import"],
env: { env: {
browser: true, browser: true
}, },
rules: { rules: {
"react/jsx-uses-react": "off", "react/jsx-uses-react": "off",
@ -43,16 +49,16 @@ module.exports = {
"no-await-in-loop": "off", "no-await-in-loop": "off",
"react/jsx-filename-extension": [ "react/jsx-filename-extension": [
"error", "error",
{ extensions: [".js", ".tsx", ".jsx"] }, { extensions: [".js", ".tsx", ".jsx"] }
], ],
"import/extensions": [ "import/extensions": [
"error", "error",
"ignorePackages", "ignorePackages",
{ {
ts: "never", ts: "never",
tsx: "never", tsx: "never"
}, }
], ],
...a11yOff ...a11yOff
}, }
}; };

5
.github/workflows/deploying.yml

@ -43,6 +43,11 @@ jobs:
name: production-files name: production-files
path: ./dist path: ./dist
- name: Insert config
env:
DEPLOY_CONFIG: ${{ secrets.DEPLOY_CONFIG }}
run: cat "$DEPLOY_CONFIG" > ./dist/config.js
- name: Deploy to gh-pages - name: Deploy to gh-pages
uses: peaceiris/actions-gh-pages@v3 uses: peaceiris/actions-gh-pages@v3
with: with:

7
.gitignore vendored

@ -9,7 +9,7 @@ node_modules
/coverage /coverage
# production # production
/build /dist
# misc # misc
.DS_Store .DS_Store
@ -22,4 +22,7 @@ npm-debug.log*
yarn-debug.log* yarn-debug.log*
yarn-error.log* yarn-error.log*
package-lock.json package-lock.json
# config
.env

10
README.md

@ -25,7 +25,13 @@ Features include:
- No BS: just a search bar and a video player - No BS: just a search bar and a video player
- No responsibility on the hoster, no databases or api's hosted by us, just a static site - No responsibility on the hoster, no databases or api's hosted by us, just a static site
## Self-hosting / running locally ## Self-hosting
A simple guide has been written to assist in hosting your own instance of movie-web.
Check it out here: [https://github.com/movie-web/movie-web/blob/dev/SELFHOSTING.md](https://github.com/movie-web/movie-web/blob/dev/SELFHOSTING.md)
## Running locally for development
To run this project locally for contributing or testing, run the following commands: To run this project locally for contributing or testing, run the following commands:
<h5><b>note: must use yarn to install packages and run NodeJS 16</b></h5> <h5><b>note: must use yarn to install packages and run NodeJS 16</b></h5>
@ -39,7 +45,7 @@ yarn start
To build production files, simply run `yarn build`. To build production files, simply run `yarn build`.
You can also deploy the Cloudflare Worker (in worker.js) and update the proxy URL constant in `/src/mw-constants.ts`. You'll need to deploy a cloudflare service worker as well. Check the [selfhosting guide](https://github.com/movie-web/movie-web/blob/dev/SELFHOSTING.md) on how to run the service worker. Afterwards you can make a `.env` file and put in the URL. (see `example.env` for an example)
<h2>Contributing - <a href="https://github.com/JamesHawkinss/movie-web/issues"><img alt="GitHub issues" src="https://img.shields.io/github/issues/JamesHawkinss/movie-web?style=flat-square"></a> <h2>Contributing - <a href="https://github.com/JamesHawkinss/movie-web/issues"><img alt="GitHub issues" src="https://img.shields.io/github/issues/JamesHawkinss/movie-web?style=flat-square"></a>
<a href="https://github.com/JamesHawkinss/movie-web/pulls"><img alt="GitHub pull requests" src="https://img.shields.io/github/issues-pr/JamesHawkinss/movie-web?style=flat-square"></a></h2> <a href="https://github.com/JamesHawkinss/movie-web/pulls"><img alt="GitHub pull requests" src="https://img.shields.io/github/issues-pr/JamesHawkinss/movie-web?style=flat-square"></a></h2>

38
SELFHOSTING.md

@ -0,0 +1,38 @@
# Selfhosting tutorial
> **Note:** We do not provide support on how to selfhost, if you cant figure it out then tough luck. Please do not make Github issues or ask in our Discord server for support on how to selfhost.
So you wanna selfhost. This app is made of two parts:
- The proxy
- The client
## Hosting the proxy
The proxy is made as a cloudflare worker, cloudflare has a generous free plan, so you don't need to pay anything unless you get hundreds of users.
1. Create a cloudflare account at [https://dash.cloudflare.com](https://dash.cloudflare.com)
2. Navigate to `Workers`.
3. If it asks you, choose a subdomain
4. If it asks for a workers plan, press "Continue with free"
5. Create a new service with a name of your choice. Must be type `HTTP handler`
6. On the service page, Click `Quick edit`
7. Download the `worker.js` file from the latest release of the proxy: [https://github.com/movie-web/simple-proxy/releases/latest](https://github.com/movie-web/simple-proxy/releases/latest)
8. Open the downloaded `worker.js` file in notepad, VScode or similar.
9. Copy the text contents of the `worker.js` file.
10. Paste the text contents into the edit screen of the cloudflare service worker.
11. Click `Save and deploy` and confirm.
Your proxy is now hosted on cloudflare. Note the url of your worker. you will need it later.
## Hosting the client
1. Download the file `movie-web.zip` from the latest release: [https://github.com/movie-web/movie-web/releases/latest](https://github.com/movie-web/movie-web/releases/latest)
2. Extract the zip file so you can edit the files.
3. Open `config.js` in notepad, VScode or similar.
4. Put your cloudflare proxy URL inbetween the double qoutes of `VITE_CORS_PROXY_URL: "",`. Make sure to not have a slash at the end of your URL.
Example (THIS IS MINE, IT WONT WORK FOR YOU): `VITE_CORS_PROXY_URL: "https://test-proxy.test.workers.dev",`
5. Save the file
Your client has been prepared, you can now host it on any webhost.
It doesn't require php, its just a standard static page.

6
example.env

@ -0,0 +1,6 @@
# make sure the cors proxy url does NOT have a slash at the end
VITE_CORS_PROXY_URL=...
# the keys below are optional - defaults are provided
VITE_TMDB_API_KEY=...
VITE_OMDB_API_KEY=...

1
index.html

@ -39,6 +39,7 @@
rel="stylesheet" rel="stylesheet"
/> />
<script src="config.js"></script>
<title>movie-web</title> <title>movie-web</title>
</head> </head>
<body> <body>

2
package.json

@ -1,6 +1,6 @@
{ {
"name": "movie-web", "name": "movie-web",
"version": "2.1.0", "version": "2.1.1",
"private": true, "private": true,
"homepage": "https://movie.squeezebox.dev", "homepage": "https://movie.squeezebox.dev",
"dependencies": { "dependencies": {

7
public/config.js

@ -0,0 +1,7 @@
window.__CONFIG__ = {
// url must NOT end with a slash
VITE_CORS_PROXY_URL: "",
VITE_TMDB_API_KEY: "b030404650f279792a8d3287232358e3",
VITE_OMDB_API_KEY: "aa0937c0"
};

6
src/components/layout/ErrorBoundary.tsx

@ -3,7 +3,7 @@ import { IconPatch } from "@/components/buttons/IconPatch";
import { Icons } from "@/components/Icon"; import { Icons } from "@/components/Icon";
import { Link } from "@/components/text/Link"; import { Link } from "@/components/text/Link";
import { Title } from "@/components/text/Title"; import { Title } from "@/components/text/Title";
import { DISCORD_LINK, GITHUB_LINK } from "@/mw_constants"; import { conf } from "@/config";
interface ErrorBoundaryState { interface ErrorBoundaryState {
hasError: boolean; hasError: boolean;
@ -58,11 +58,11 @@ export class ErrorBoundary extends Component<
<p className="my-6 max-w-lg"> <p className="my-6 max-w-lg">
The app encountered an error and wasn&apos;t able to recover, please The app encountered an error and wasn&apos;t able to recover, please
report it to the{" "} report it to the{" "}
<Link url={DISCORD_LINK} newTab> <Link url={conf().DISCORD_LINK} newTab>
Discord server Discord server
</Link>{" "} </Link>{" "}
or on{" "} or on{" "}
<Link url={GITHUB_LINK} newTab> <Link url={conf().GITHUB_LINK} newTab>
GitHub GitHub
</Link> </Link>
. .

6
src/components/layout/Navigation.tsx

@ -2,7 +2,7 @@ import { ReactNode } from "react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { IconPatch } from "@/components/buttons/IconPatch"; import { IconPatch } from "@/components/buttons/IconPatch";
import { Icons } from "@/components/Icon"; import { Icons } from "@/components/Icon";
import { DISCORD_LINK, GITHUB_LINK } from "@/mw_constants"; import { conf } from "@/config";
import { BrandPill } from "./BrandPill"; import { BrandPill } from "./BrandPill";
export interface NavigationProps { export interface NavigationProps {
@ -26,7 +26,7 @@ export function Navigation(props: NavigationProps) {
} flex-row gap-4`} } flex-row gap-4`}
> >
<a <a
href={DISCORD_LINK} href={conf().DISCORD_LINK}
target="_blank" target="_blank"
rel="noreferrer" rel="noreferrer"
className="text-2xl text-white" className="text-2xl text-white"
@ -34,7 +34,7 @@ export function Navigation(props: NavigationProps) {
<IconPatch icon={Icons.DISCORD} clickable /> <IconPatch icon={Icons.DISCORD} clickable />
</a> </a>
<a <a
href={GITHUB_LINK} href={conf().GITHUB_LINK}
target="_blank" target="_blank"
rel="noreferrer" rel="noreferrer"
className="text-2xl text-white" className="text-2xl text-white"

50
src/config.ts

@ -0,0 +1,50 @@
import { APP_VERSION, GITHUB_LINK, DISCORD_LINK } from "@/constants";
export interface Config {
APP_VERSION: string;
GITHUB_LINK: string;
DISCORD_LINK: string;
OMDB_API_KEY: string;
TMDB_API_KEY: string;
CORS_PROXY_URL: string;
}
const env: Record<keyof Config, undefined | string> = {
OMDB_API_KEY: import.meta.env.VITE_OMDB_API_KEY,
TMDB_API_KEY: import.meta.env.VITE_TMDB_API_KEY,
APP_VERSION: undefined,
GITHUB_LINK: undefined,
DISCORD_LINK: undefined,
CORS_PROXY_URL: import.meta.env.VITE_CORS_PROXY_URL,
};
const alerts = [] as string[];
// loads from different locations, in order: environment (VITE_{KEY}), window (public/config.js)
function getKey(key: keyof Config): string {
let windowValue = (window as any)?.__CONFIG__?.[`VITE_${key}`];
if (windowValue !== undefined && windowValue.length === 0)
windowValue = undefined;
const value = env[key] ?? windowValue ?? undefined;
if (value === undefined) {
if (!alerts.includes(key)) {
// eslint-disable-next-line no-alert
window.alert(`Misconfigured instance, missing key: ${key}`);
alerts.push(key);
}
return "";
}
return value;
}
export function conf(): Config {
return {
APP_VERSION,
GITHUB_LINK,
DISCORD_LINK,
OMDB_API_KEY: getKey("OMDB_API_KEY"),
TMDB_API_KEY: getKey("TMDB_API_KEY"),
CORS_PROXY_URL: `${getKey("CORS_PROXY_URL")}/?destination=`,
};
}

3
src/constants.ts

@ -0,0 +1,3 @@
export const DISCORD_LINK = "https://discord.gg/Jhqt4Xzpfb";
export const GITHUB_LINK = "https://github.com/JamesHawkinss/movie-web";
export const APP_VERSION = "2.1.0";

6
src/mw_constants.ts

@ -1,7 +1,3 @@
export const CORS_PROXY_URL =
"https://cors.squeezebox.dev/?destination=";
export const TMDB_API_KEY = "b030404650f279792a8d3287232358e3";
export const OMDB_API_KEY = "aa0937c0";
export const DISCORD_LINK = "https://discord.gg/Jhqt4Xzpfb"; export const DISCORD_LINK = "https://discord.gg/Jhqt4Xzpfb";
export const GITHUB_LINK = "https://github.com/JamesHawkinss/movie-web"; export const GITHUB_LINK = "https://github.com/JamesHawkinss/movie-web";
export const APP_VERSION = "2.1.0"; export const APP_VERSION = "2.1.1";

18
src/providers/list/flixhq/index.ts

@ -7,7 +7,7 @@ import {
MWProviderMediaResult, MWProviderMediaResult,
} from "@/providers/types"; } from "@/providers/types";
import { CORS_PROXY_URL } from "@/mw_constants"; import { conf } from "@/config";
export const flixhqProvider: MWMediaProvider = { export const flixhqProvider: MWMediaProvider = {
id: "flixhq", id: "flixhq",
@ -19,7 +19,9 @@ export const flixhqProvider: MWMediaProvider = {
media: MWPortableMedia media: MWPortableMedia
): Promise<MWProviderMediaResult> { ): Promise<MWProviderMediaResult> {
const searchRes = await fetch( const searchRes = await fetch(
`${CORS_PROXY_URL}https://api.consumet.org/movies/flixhq/info?id=${encodeURIComponent( `${
conf().CORS_PROXY_URL
}https://api.consumet.org/movies/flixhq/info?id=${encodeURIComponent(
media.mediaId media.mediaId
)}` )}`
).then((d) => d.json()); ).then((d) => d.json());
@ -33,7 +35,9 @@ export const flixhqProvider: MWMediaProvider = {
async searchForMedia(query: MWQuery): Promise<MWProviderMediaResult[]> { async searchForMedia(query: MWQuery): Promise<MWProviderMediaResult[]> {
const searchRes = await fetch( const searchRes = await fetch(
`${CORS_PROXY_URL}https://api.consumet.org/movies/flixhq/${encodeURIComponent( `${
conf().CORS_PROXY_URL
}https://api.consumet.org/movies/flixhq/${encodeURIComponent(
query.searchQuery query.searchQuery
)}` )}`
).then((d) => d.json()); ).then((d) => d.json());
@ -52,7 +56,9 @@ export const flixhqProvider: MWMediaProvider = {
async getStream(media: MWPortableMedia): Promise<MWMediaStream> { async getStream(media: MWPortableMedia): Promise<MWMediaStream> {
const searchRes = await fetch( const searchRes = await fetch(
`${CORS_PROXY_URL}https://api.consumet.org/movies/flixhq/info?id=${encodeURIComponent( `${
conf().CORS_PROXY_URL
}https://api.consumet.org/movies/flixhq/info?id=${encodeURIComponent(
media.mediaId media.mediaId
)}` )}`
).then((d) => d.json()); ).then((d) => d.json());
@ -63,7 +69,9 @@ export const flixhqProvider: MWMediaProvider = {
}); });
const watchRes = await fetch( const watchRes = await fetch(
`${CORS_PROXY_URL}https://api.consumet.org/movies/flixhq/watch?${encodeURIComponent( `${
conf().CORS_PROXY_URL
}https://api.consumet.org/movies/flixhq/watch?${encodeURIComponent(
params.toString() params.toString()
)}` )}`
).then((d) => d.json()); ).then((d) => d.json());

14
src/providers/list/gdriveplayer/index.ts

@ -9,7 +9,7 @@ import {
MWProviderMediaResult, MWProviderMediaResult,
} from "@/providers/types"; } from "@/providers/types";
import { CORS_PROXY_URL } from "@/mw_constants"; import { conf } from "@/config";
const format = { const format = {
stringify: (cipher: any) => { stringify: (cipher: any) => {
@ -47,7 +47,9 @@ export const gDrivePlayerScraper: MWMediaProvider = {
media: MWPortableMedia media: MWPortableMedia
): Promise<MWProviderMediaResult> { ): Promise<MWProviderMediaResult> {
const res = await fetch( const res = await fetch(
`${CORS_PROXY_URL}https://api.gdriveplayer.us/v1/imdb/${media.mediaId}` `${conf().CORS_PROXY_URL}https://api.gdriveplayer.us/v1/imdb/${
media.mediaId
}`
).then((d) => d.json()); ).then((d) => d.json());
return { return {
@ -59,7 +61,9 @@ export const gDrivePlayerScraper: MWMediaProvider = {
async searchForMedia(query: MWQuery): Promise<MWProviderMediaResult[]> { async searchForMedia(query: MWQuery): Promise<MWProviderMediaResult[]> {
const searchRes = await fetch( const searchRes = await fetch(
`${CORS_PROXY_URL}https://api.gdriveplayer.us/v1/movie/search?title=${query.searchQuery}` `${
conf().CORS_PROXY_URL
}https://api.gdriveplayer.us/v1/movie/search?title=${query.searchQuery}`
).then((d) => d.json()); ).then((d) => d.json());
const results: MWProviderMediaResult[] = (searchRes || []).map( const results: MWProviderMediaResult[] = (searchRes || []).map(
@ -75,7 +79,9 @@ export const gDrivePlayerScraper: MWMediaProvider = {
async getStream(media: MWPortableMedia): Promise<MWMediaStream> { async getStream(media: MWPortableMedia): Promise<MWMediaStream> {
const streamRes = await fetch( const streamRes = await fetch(
`${CORS_PROXY_URL}https://database.gdriveplayer.us/player.php?imdb=${media.mediaId}` `${
conf().CORS_PROXY_URL
}https://database.gdriveplayer.us/player.php?imdb=${media.mediaId}`
).then((d) => d.text()); ).then((d) => d.text());
const page = new DOMParser().parseFromString(streamRes, "text/html"); const page = new DOMParser().parseFromString(streamRes, "text/html");

16
src/providers/list/gomostream/index.ts

@ -9,7 +9,7 @@ import {
MWProviderMediaResult, MWProviderMediaResult,
} from "@/providers/types"; } from "@/providers/types";
import { CORS_PROXY_URL, OMDB_API_KEY } from "@/mw_constants"; import { conf } from "@/config";
export const gomostreamScraper: MWMediaProvider = { export const gomostreamScraper: MWMediaProvider = {
id: "gomostream", id: "gomostream",
@ -21,13 +21,13 @@ export const gomostreamScraper: MWMediaProvider = {
media: MWPortableMedia media: MWPortableMedia
): Promise<MWProviderMediaResult> { ): Promise<MWProviderMediaResult> {
const params = new URLSearchParams({ const params = new URLSearchParams({
apikey: OMDB_API_KEY, apikey: conf().OMDB_API_KEY,
i: media.mediaId, i: media.mediaId,
type: media.mediaType, type: media.mediaType,
}); });
const res = await fetch( const res = await fetch(
`${CORS_PROXY_URL}http://www.omdbapi.com/?${encodeURIComponent( `${conf().CORS_PROXY_URL}http://www.omdbapi.com/?${encodeURIComponent(
params.toString() params.toString()
)}` )}`
).then((d) => d.json()); ).then((d) => d.json());
@ -43,12 +43,12 @@ export const gomostreamScraper: MWMediaProvider = {
const term = query.searchQuery.toLowerCase(); const term = query.searchQuery.toLowerCase();
const params = new URLSearchParams({ const params = new URLSearchParams({
apikey: OMDB_API_KEY, apikey: conf().OMDB_API_KEY,
s: term, s: term,
type: query.type, type: query.type,
}); });
const searchRes = await fetch( const searchRes = await fetch(
`${CORS_PROXY_URL}http://www.omdbapi.com/?${encodeURIComponent( `${conf().CORS_PROXY_URL}http://www.omdbapi.com/?${encodeURIComponent(
params.toString() params.toString()
)}` )}`
).then((d) => d.json()); ).then((d) => d.json());
@ -69,7 +69,7 @@ export const gomostreamScraper: MWMediaProvider = {
const type = const type =
media.mediaType === MWMediaType.SERIES ? "show" : media.mediaType; media.mediaType === MWMediaType.SERIES ? "show" : media.mediaType;
const res1 = await fetch( const res1 = await fetch(
`${CORS_PROXY_URL}https://gomo.to/${type}/${media.mediaId}` `${conf().CORS_PROXY_URL}https://gomo.to/${type}/${media.mediaId}`
).then((d) => d.text()); ).then((d) => d.text());
if (res1 === "Movie not available." || res1 === "Episode not available.") if (res1 === "Movie not available." || res1 === "Episode not available.")
throw new Error(res1); throw new Error(res1);
@ -82,7 +82,7 @@ export const gomostreamScraper: MWMediaProvider = {
fd.append("_token", _token); fd.append("_token", _token);
const src = await fetch( const src = await fetch(
`${CORS_PROXY_URL}https://gomo.to/decoding_v3.php`, `${conf().CORS_PROXY_URL}https://gomo.to/decoding_v3.php`,
{ {
method: "POST", method: "POST",
body: fd, body: fd,
@ -95,7 +95,7 @@ export const gomostreamScraper: MWMediaProvider = {
// maybe try all embeds in the future // maybe try all embeds in the future
const embedUrl = embeds[1]; const embedUrl = embeds[1];
const res2 = await fetch(`${CORS_PROXY_URL}${embedUrl}`).then((d) => const res2 = await fetch(`${conf().CORS_PROXY_URL}${embedUrl}`).then((d) =>
d.text() d.text()
); );

16
src/providers/list/superstream/index.ts

@ -4,7 +4,7 @@
import { customAlphabet } from "nanoid"; import { customAlphabet } from "nanoid";
import toWebVTT from "srt-webvtt"; import toWebVTT from "srt-webvtt";
import CryptoJS from "crypto-js"; import CryptoJS from "crypto-js";
import { CORS_PROXY_URL, TMDB_API_KEY } from "@/mw_constants"; import { conf } from "@/config";
import { import {
MWMediaProvider, MWMediaProvider,
MWMediaType, MWMediaType,
@ -85,7 +85,7 @@ const get = (data: object, altApi = false) => {
formatted.append("medium", "Website"); formatted.append("medium", "Website");
const requestUrl = altApi ? apiUrls[1] : apiUrls[0]; const requestUrl = altApi ? apiUrls[1] : apiUrls[0];
return fetch(`${CORS_PROXY_URL}${requestUrl}`, { return fetch(`${conf().CORS_PROXY_URL}${requestUrl}`, {
method: "POST", method: "POST",
headers: { headers: {
Platform: "android", Platform: "android",
@ -200,7 +200,7 @@ export const superStreamScraper: MWMediaProvider = {
const mappedCaptions = await Promise.all( const mappedCaptions = await Promise.all(
subtitleRes.list.map(async (subtitle: any) => { subtitleRes.list.map(async (subtitle: any) => {
const captionBlob = await fetch( const captionBlob = await fetch(
`${CORS_PROXY_URL}${subtitle.subtitles[0].file_path}` `${conf().CORS_PROXY_URL}${subtitle.subtitles[0].file_path}`
).then((captionRes) => captionRes.blob()); // cross-origin bypass ).then((captionRes) => captionRes.blob()); // cross-origin bypass
const captionUrl = await toWebVTT(captionBlob); // convert to vtt so it's playable const captionUrl = await toWebVTT(captionBlob); // convert to vtt so it's playable
return { return {
@ -253,7 +253,7 @@ export const superStreamScraper: MWMediaProvider = {
const mappedCaptions = await Promise.all( const mappedCaptions = await Promise.all(
subtitleRes.list.map(async (subtitle: any) => { subtitleRes.list.map(async (subtitle: any) => {
const captionBlob = await fetch( const captionBlob = await fetch(
`${CORS_PROXY_URL}${subtitle.subtitles[0].file_path}` `${conf().CORS_PROXY_URL}${subtitle.subtitles[0].file_path}`
).then((captionRes) => captionRes.blob()); // cross-origin bypass ).then((captionRes) => captionRes.blob()); // cross-origin bypass
const captionUrl = await toWebVTT(captionBlob); // convert to vtt so it's playable const captionUrl = await toWebVTT(captionBlob); // convert to vtt so it's playable
return { return {
@ -277,11 +277,15 @@ export const superStreamScraper: MWMediaProvider = {
const detailRes = (await get(apiQuery, true).then((r) => r.json())).data; const detailRes = (await get(apiQuery, true).then((r) => r.json())).data;
const firstSearchResult = ( const firstSearchResult = (
await fetch( await fetch(
`https://api.themoviedb.org/3/search/tv?api_key=${TMDB_API_KEY}&language=en-US&page=1&query=${detailRes.title}&include_adult=false` `https://api.themoviedb.org/3/search/tv?api_key=${
conf().TMDB_API_KEY
}&language=en-US&page=1&query=${detailRes.title}&include_adult=false`
).then((r) => r.json()) ).then((r) => r.json())
).results[0]; ).results[0];
const showDetails = await fetch( const showDetails = await fetch(
`https://api.themoviedb.org/3/tv/${firstSearchResult.id}?api_key=${TMDB_API_KEY}` `https://api.themoviedb.org/3/tv/${firstSearchResult.id}?api_key=${
conf().TMDB_API_KEY
}`
).then((r) => r.json()); ).then((r) => r.json());
return { return {

14
src/providers/list/theflix/index.ts

@ -15,7 +15,7 @@ import {
} from "@/providers/list/theflix/search"; } from "@/providers/list/theflix/search";
import { getDataFromPortableSearch } from "@/providers/list/theflix/portableToMedia"; import { getDataFromPortableSearch } from "@/providers/list/theflix/portableToMedia";
import { CORS_PROXY_URL } from "@/mw_constants"; import { conf } from "@/config";
export const theFlixScraper: MWMediaProvider = { export const theFlixScraper: MWMediaProvider = {
id: "theflix", id: "theflix",
@ -51,9 +51,13 @@ export const theFlixScraper: MWMediaProvider = {
let url = ""; let url = "";
if (media.mediaType === MWMediaType.MOVIE) { if (media.mediaType === MWMediaType.MOVIE) {
url = `${CORS_PROXY_URL}https://theflix.to/movie/${media.mediaId}?movieInfo=${media.mediaId}`; url = `${conf().CORS_PROXY_URL}https://theflix.to/movie/${
media.mediaId
}?movieInfo=${media.mediaId}`;
} else if (media.mediaType === MWMediaType.SERIES) { } else if (media.mediaType === MWMediaType.SERIES) {
url = `${CORS_PROXY_URL}https://theflix.to/tv-show/${media.mediaId}/season-${media.seasonId}/episode-${media.episodeId}`; url = `${conf().CORS_PROXY_URL}https://theflix.to/tv-show/${
media.mediaId
}/season-${media.seasonId}/episode-${media.episodeId}`;
} }
const res = await fetch(url).then((d) => d.text()); const res = await fetch(url).then((d) => d.text());
@ -76,7 +80,9 @@ export const theFlixScraper: MWMediaProvider = {
async getSeasonDataFromMedia( async getSeasonDataFromMedia(
media: MWPortableMedia media: MWPortableMedia
): Promise<MWMediaSeasons> { ): Promise<MWMediaSeasons> {
const url = `${CORS_PROXY_URL}https://theflix.to/tv-show/${media.mediaId}/season-${media.seasonId}/episode-${media.episodeId}`; const url = `${conf().CORS_PROXY_URL}https://theflix.to/tv-show/${
media.mediaId
}/season-${media.seasonId}/episode-${media.episodeId}`;
const res = await fetch(url).then((d) => d.text()); const res = await fetch(url).then((d) => d.text());
const node: Element = Array.from( const node: Element = Array.from(

8
src/providers/list/theflix/portableToMedia.ts

@ -1,4 +1,4 @@
import { CORS_PROXY_URL } from "@/mw_constants"; import { conf } from "@/config";
import { MWMediaType, MWPortableMedia } from "@/providers/types"; import { MWMediaType, MWPortableMedia } from "@/providers/types";
const getTheFlixUrl = (media: MWPortableMedia, params?: URLSearchParams) => { const getTheFlixUrl = (media: MWPortableMedia, params?: URLSearchParams) => {
@ -18,9 +18,9 @@ export async function getDataFromPortableSearch(
const params = new URLSearchParams(); const params = new URLSearchParams();
params.append("movieInfo", media.mediaId); params.append("movieInfo", media.mediaId);
const res = await fetch(CORS_PROXY_URL + getTheFlixUrl(media, params)).then( const res = await fetch(
(d) => d.text() conf().CORS_PROXY_URL + getTheFlixUrl(media, params)
); ).then((d) => d.text());
const node: Element = Array.from( const node: Element = Array.from(
new DOMParser() new DOMParser()

4
src/providers/list/theflix/search.ts

@ -1,4 +1,4 @@
import { CORS_PROXY_URL } from "@/mw_constants"; import { conf } from "@/config";
import { MWMediaType, MWProviderMediaResult, MWQuery } from "@/providers"; import { MWMediaType, MWProviderMediaResult, MWQuery } from "@/providers";
const getTheFlixUrl = (type: "tv-shows" | "movies", params: URLSearchParams) => const getTheFlixUrl = (type: "tv-shows" | "movies", params: URLSearchParams) =>
@ -8,7 +8,7 @@ export function searchTheFlix(query: MWQuery): Promise<string> {
const params = new URLSearchParams(); const params = new URLSearchParams();
params.append("search", query.searchQuery); params.append("search", query.searchQuery);
return fetch( return fetch(
CORS_PROXY_URL + conf().CORS_PROXY_URL +
getTheFlixUrl( getTheFlixUrl(
query.type === MWMediaType.MOVIE ? "movies" : "tv-shows", query.type === MWMediaType.MOVIE ? "movies" : "tv-shows",
params params

19
src/providers/list/xemovie/index.ts

@ -8,7 +8,7 @@ import {
MWMediaCaption, MWMediaCaption,
} from "@/providers/types"; } from "@/providers/types";
import { CORS_PROXY_URL } from "@/mw_constants"; import { conf } from "@/config";
export const xemovieScraper: MWMediaProvider = { export const xemovieScraper: MWMediaProvider = {
id: "xemovie", id: "xemovie",
@ -20,7 +20,7 @@ export const xemovieScraper: MWMediaProvider = {
media: MWPortableMedia media: MWPortableMedia
): Promise<MWProviderMediaResult> { ): Promise<MWProviderMediaResult> {
const res = await fetch( const res = await fetch(
`${CORS_PROXY_URL}https://xemovie.co/movies/${media.mediaId}/watch` `${conf().CORS_PROXY_URL}https://xemovie.co/movies/${media.mediaId}/watch`
).then((d) => d.text()); ).then((d) => d.text());
const DOM = new DOMParser().parseFromString(res, "text/html"); const DOM = new DOMParser().parseFromString(res, "text/html");
@ -42,9 +42,9 @@ export const xemovieScraper: MWMediaProvider = {
async searchForMedia(query: MWQuery): Promise<MWProviderMediaResult[]> { async searchForMedia(query: MWQuery): Promise<MWProviderMediaResult[]> {
const term = query.searchQuery.toLowerCase(); const term = query.searchQuery.toLowerCase();
const searchUrl = `${CORS_PROXY_URL}https://xemovie.co/search?q=${encodeURIComponent( const searchUrl = `${
term conf().CORS_PROXY_URL
)}`; }https://xemovie.co/search?q=${encodeURIComponent(term)}`;
const searchRes = await fetch(searchUrl).then((d) => d.text()); const searchRes = await fetch(searchUrl).then((d) => d.text());
const parser = new DOMParser(); const parser = new DOMParser();
@ -81,7 +81,9 @@ export const xemovieScraper: MWMediaProvider = {
if (media.mediaType !== MWMediaType.MOVIE) if (media.mediaType !== MWMediaType.MOVIE)
throw new Error("Incorrect type"); throw new Error("Incorrect type");
const url = `${CORS_PROXY_URL}https://xemovie.co/movies/${media.mediaId}/watch`; const url = `${conf().CORS_PROXY_URL}https://xemovie.co/movies/${
media.mediaId
}/watch`;
let streamUrl = ""; let streamUrl = "";
const subtitles: MWMediaCaption[] = []; const subtitles: MWMediaCaption[] = [];
@ -100,7 +102,8 @@ export const xemovieScraper: MWMediaProvider = {
const data = JSON.parse( const data = JSON.parse(
JSON.stringify( JSON.stringify(
eval( eval(
`(${script.textContent.replace("const data = ", "").split("};")[0] `(${
script.textContent.replace("const data = ", "").split("};")[0]
}})` }})`
) )
) )
@ -112,7 +115,7 @@ export const xemovieScraper: MWMediaProvider = {
subtitleTrack, subtitleTrack,
] of data.playlist[0].tracks.entries()) { ] of data.playlist[0].tracks.entries()) {
const subtitleBlob = URL.createObjectURL( const subtitleBlob = URL.createObjectURL(
await fetch(`${CORS_PROXY_URL}${subtitleTrack.file}`).then( await fetch(`${conf().CORS_PROXY_URL}${subtitleTrack.file}`).then(
(captionRes) => captionRes.blob() (captionRes) => captionRes.blob()
) )
); // do this so no need for CORS errors ); // do this so no need for CORS errors

Loading…
Cancel
Save