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

Better config system
This commit is contained in:
James Hawkins 2022-12-27 16:27:29 +00:00 committed by GitHub
commit 80799b7600
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 216 additions and 68 deletions

View File

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

View File

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

7
.gitignore vendored
View File

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

View File

@ -25,7 +25,13 @@ Features include:
- 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
## 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:
<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`.
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>
<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 Normal file
View File

@ -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 Normal file
View File

@ -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=...

View File

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

View File

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

7
public/config.js Normal file
View File

@ -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"
};

View File

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

View File

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

50
src/config.ts Normal file
View File

@ -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 Normal file
View File

@ -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";

View File

@ -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 GITHUB_LINK = "https://github.com/JamesHawkinss/movie-web";
export const APP_VERSION = "2.1.0";
export const APP_VERSION = "2.1.1";

View File

@ -7,7 +7,7 @@ import {
MWProviderMediaResult,
} from "@/providers/types";
import { CORS_PROXY_URL } from "@/mw_constants";
import { conf } from "@/config";
export const flixhqProvider: MWMediaProvider = {
id: "flixhq",
@ -19,7 +19,9 @@ export const flixhqProvider: MWMediaProvider = {
media: MWPortableMedia
): Promise<MWProviderMediaResult> {
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
)}`
).then((d) => d.json());
@ -33,7 +35,9 @@ export const flixhqProvider: MWMediaProvider = {
async searchForMedia(query: MWQuery): Promise<MWProviderMediaResult[]> {
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
)}`
).then((d) => d.json());
@ -52,7 +56,9 @@ export const flixhqProvider: MWMediaProvider = {
async getStream(media: MWPortableMedia): Promise<MWMediaStream> {
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
)}`
).then((d) => d.json());
@ -63,7 +69,9 @@ export const flixhqProvider: MWMediaProvider = {
});
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()
)}`
).then((d) => d.json());

View File

@ -9,7 +9,7 @@ import {
MWProviderMediaResult,
} from "@/providers/types";
import { CORS_PROXY_URL } from "@/mw_constants";
import { conf } from "@/config";
const format = {
stringify: (cipher: any) => {
@ -47,7 +47,9 @@ export const gDrivePlayerScraper: MWMediaProvider = {
media: MWPortableMedia
): Promise<MWProviderMediaResult> {
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());
return {
@ -59,7 +61,9 @@ export const gDrivePlayerScraper: MWMediaProvider = {
async searchForMedia(query: MWQuery): Promise<MWProviderMediaResult[]> {
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());
const results: MWProviderMediaResult[] = (searchRes || []).map(
@ -75,7 +79,9 @@ export const gDrivePlayerScraper: MWMediaProvider = {
async getStream(media: MWPortableMedia): Promise<MWMediaStream> {
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());
const page = new DOMParser().parseFromString(streamRes, "text/html");

View File

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

View File

@ -4,7 +4,7 @@
import { customAlphabet } from "nanoid";
import toWebVTT from "srt-webvtt";
import CryptoJS from "crypto-js";
import { CORS_PROXY_URL, TMDB_API_KEY } from "@/mw_constants";
import { conf } from "@/config";
import {
MWMediaProvider,
MWMediaType,
@ -85,7 +85,7 @@ const get = (data: object, altApi = false) => {
formatted.append("medium", "Website");
const requestUrl = altApi ? apiUrls[1] : apiUrls[0];
return fetch(`${CORS_PROXY_URL}${requestUrl}`, {
return fetch(`${conf().CORS_PROXY_URL}${requestUrl}`, {
method: "POST",
headers: {
Platform: "android",
@ -200,7 +200,7 @@ export const superStreamScraper: MWMediaProvider = {
const mappedCaptions = await Promise.all(
subtitleRes.list.map(async (subtitle: any) => {
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
const captionUrl = await toWebVTT(captionBlob); // convert to vtt so it's playable
return {
@ -253,7 +253,7 @@ export const superStreamScraper: MWMediaProvider = {
const mappedCaptions = await Promise.all(
subtitleRes.list.map(async (subtitle: any) => {
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
const captionUrl = await toWebVTT(captionBlob); // convert to vtt so it's playable
return {
@ -277,11 +277,15 @@ export const superStreamScraper: MWMediaProvider = {
const detailRes = (await get(apiQuery, true).then((r) => r.json())).data;
const firstSearchResult = (
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())
).results[0];
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());
return {

View File

@ -15,7 +15,7 @@ import {
} from "@/providers/list/theflix/search";
import { getDataFromPortableSearch } from "@/providers/list/theflix/portableToMedia";
import { CORS_PROXY_URL } from "@/mw_constants";
import { conf } from "@/config";
export const theFlixScraper: MWMediaProvider = {
id: "theflix",
@ -51,9 +51,13 @@ export const theFlixScraper: MWMediaProvider = {
let url = "";
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) {
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());
@ -76,7 +80,9 @@ export const theFlixScraper: MWMediaProvider = {
async getSeasonDataFromMedia(
media: MWPortableMedia
): 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 node: Element = Array.from(

View File

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

View File

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

View File

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