mirror of
https://github.com/movie-web/movie-web.git
synced 2024-12-27 09:51:51 +01:00
Merge pull request #114 from movie-web/feat/config
Better config system
This commit is contained in:
commit
80799b7600
28
.eslintrc.js
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
vendored
5
.github/workflows/deploying.yml
vendored
@ -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:
|
||||||
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -9,7 +9,7 @@ node_modules
|
|||||||
/coverage
|
/coverage
|
||||||
|
|
||||||
# production
|
# production
|
||||||
/build
|
/dist
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
.DS_Store
|
.DS_Store
|
||||||
@ -23,3 +23,6 @@ yarn-debug.log*
|
|||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
|
|
||||||
package-lock.json
|
package-lock.json
|
||||||
|
|
||||||
|
# config
|
||||||
|
.env
|
||||||
|
10
README.md
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
Normal file
38
SELFHOSTING.md
Normal 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
6
example.env
Normal 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=...
|
@ -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>
|
||||||
|
@ -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
Normal file
7
public/config.js
Normal 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"
|
||||||
|
};
|
@ -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't able to recover, please
|
The app encountered an error and wasn'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>
|
||||||
.
|
.
|
||||||
|
@ -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
Normal file
50
src/config.ts
Normal 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
3
src/constants.ts
Normal 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";
|
@ -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";
|
||||||
|
@ -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());
|
||||||
|
@ -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");
|
||||||
|
|
||||||
|
@ -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()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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(
|
||||||
|
@ -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()
|
||||||
|
@ -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
|
||||||
|
@ -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…
Reference in New Issue
Block a user