parent
b86c61be28
commit
cabd7a42a9
7
api/.env
7
api/.env
@ -1,2 +1,5 @@
|
||||
ORIGIN=https://fh.snipcola.com
|
||||
PORT=1000
|
||||
# ORIGIN=https://fh.snipcola.com
|
||||
PORT=1000
|
||||
|
||||
CACHE_TIMEOUT=300
|
||||
TIMEOUT=4
|
@ -3,16 +3,20 @@
|
||||
"author": "Snipcola",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"main": "./proxy.js",
|
||||
"main": "./src/index.js",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"start": "node .",
|
||||
"dev": "nodemon ."
|
||||
},
|
||||
"dependencies": {
|
||||
"nodemon": "^3.0.3",
|
||||
"cors-anywhere": "^0.4.4",
|
||||
"dotenv": "^16.4.1",
|
||||
"fastify": "^3.29.0",
|
||||
"@fastify/cors": "^7.0.0",
|
||||
"fastify-response-caching": "^0.0.4",
|
||||
"node-fetch": "^3.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^3.0.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
149
api/proxy.js
149
api/proxy.js
@ -1,149 +0,0 @@
|
||||
// Config
|
||||
const config = {
|
||||
hosts: [
|
||||
"vidsrc.to",
|
||||
"vidsrc.me",
|
||||
"flixon.click",
|
||||
"2embed.me",
|
||||
"databasegdriveplayer.xyz"
|
||||
],
|
||||
blacklist: {
|
||||
status: [
|
||||
404, // Not Found
|
||||
500 // Internal Server Error
|
||||
],
|
||||
text: [
|
||||
"not found", // Generic
|
||||
"no sources", // Generic
|
||||
"onionplay streaming mirrors", // flixon.click
|
||||
"no movie found", // 2embed.me
|
||||
"no tv show found", // 2embed.me
|
||||
`,"file":"","kind"` // databasegdriveplayer.xyz
|
||||
]
|
||||
},
|
||||
cacheMaxAge: 21600,
|
||||
timeout: 5000
|
||||
};
|
||||
|
||||
// Imports
|
||||
import dotenv from "dotenv";
|
||||
import fetch from "node-fetch";
|
||||
import proxy from "cors-anywhere";
|
||||
|
||||
import { fileURLToPath } from "url";
|
||||
import path, { dirname } from "path";
|
||||
|
||||
import { URL } from "url";
|
||||
|
||||
// DotEnv
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
dotenv.config({ path: path.join(__dirname, ".env") });
|
||||
|
||||
// Variables
|
||||
const allowedOrigins = process.env.ORIGIN?.split(",") || ["*"];
|
||||
const allowedHosts = config.hosts || [];
|
||||
|
||||
const host = process.env.HOST || "0.0.0.0";
|
||||
const port = process.env.PORT || 5000;
|
||||
|
||||
// Functions
|
||||
function promiseWithTimeout(promise, timeout) {
|
||||
return Promise.race([promise, new Promise((res) => setTimeout(res, timeout))]);
|
||||
}
|
||||
|
||||
async function handleRequest(req, res, _url) {
|
||||
// Parse URL
|
||||
let url;
|
||||
|
||||
try {
|
||||
const tempURL = new URL(`http://localhost${req?.url}`);
|
||||
url = new URL(tempURL.searchParams.get("url"));
|
||||
}
|
||||
catch {
|
||||
url = null;
|
||||
}
|
||||
|
||||
// Variables
|
||||
const hostname = url?.hostname;
|
||||
const origin = req?.headers?.origin;
|
||||
|
||||
const allowedHost = allowedHosts.includes(hostname);
|
||||
const allowedOrigin = !origin || allowedOrigins.includes("*") || allowedOrigins.includes(origin);
|
||||
|
||||
// Functions
|
||||
function sendJSON(status, data) {
|
||||
res.writeHead(status, { "Content-Type": "application/json" });
|
||||
res.end(JSON.stringify(data));
|
||||
}
|
||||
|
||||
function unauthorized() {
|
||||
sendJSON(401, { success: false, message: "Unauthorized" });
|
||||
}
|
||||
|
||||
function notFound() {
|
||||
sendJSON(404, { success: false, message: "Not Found" });
|
||||
}
|
||||
|
||||
function send(valid) {
|
||||
if (valid) sendJSON(200, { success: true });
|
||||
else sendJSON(500, { success: false, message: "Invalid" });
|
||||
}
|
||||
|
||||
// Origin Check
|
||||
if (!allowedOrigin) {
|
||||
unauthorized();
|
||||
return true;
|
||||
} else {
|
||||
res.setHeader("Access-Control-Allow-Origin", origin || "*");
|
||||
}
|
||||
|
||||
// Host Check
|
||||
if (!allowedHost) {
|
||||
notFound();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Response Check
|
||||
let response;
|
||||
|
||||
try { response = await promiseWithTimeout(fetch(url?.href), config.timeout) }
|
||||
catch {
|
||||
send(false);
|
||||
return true;
|
||||
};
|
||||
|
||||
// Timeout Check
|
||||
if (!response) {
|
||||
send(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Blacklist Check
|
||||
const text = (await response.text())?.toLowerCase() || "";
|
||||
const blacklistedStatus = config.blacklist?.status.includes(response.status);
|
||||
const blacklistedText = config.blacklist?.text.some((t) => text.includes(t));
|
||||
|
||||
if (blacklistedStatus || blacklistedText) {
|
||||
send(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Valid
|
||||
send(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleLoad() {
|
||||
console.log(`Running on ${host}:${port}, origin(s): ${allowedOrigins.join(", ")}`);
|
||||
}
|
||||
|
||||
// Server
|
||||
const server = proxy.createServer({
|
||||
handleInitialRequest: handleRequest,
|
||||
corsMaxAge: config.cacheMaxAge || 3600
|
||||
});
|
||||
|
||||
// Listen
|
||||
server.listen(port, host, handleLoad);
|
14
api/src/index.js
Normal file
14
api/src/index.js
Normal file
@ -0,0 +1,14 @@
|
||||
import { initializeEnvironmentVariables } from "./lib/other/env.js";
|
||||
import { initializeServer } from "./lib/server.js";
|
||||
|
||||
initializeEnvironmentVariables();
|
||||
const { success, address, error } = await initializeServer();
|
||||
|
||||
switch (success) {
|
||||
case true:
|
||||
console.log(`[Server] Running at ${address}`);
|
||||
break;
|
||||
case false:
|
||||
console.error(`[Server] Error caught:\n`, error);
|
||||
process.exit(1);
|
||||
}
|
39
api/src/lib/other/check.js
Normal file
39
api/src/lib/other/check.js
Normal file
@ -0,0 +1,39 @@
|
||||
import config from "./config.js";
|
||||
import fetch from "node-fetch";
|
||||
|
||||
function promiseWithTimeout(promise, timeout) {
|
||||
return Promise.race([
|
||||
promise,
|
||||
new Promise(function (res) {
|
||||
setTimeout(res, (timeout || 5) * 1000);
|
||||
})
|
||||
]);
|
||||
}
|
||||
|
||||
async function get(url) {
|
||||
try {
|
||||
const response = await promiseWithTimeout(fetch(url), process.env.TIMEOUT);
|
||||
const text = await response.text();
|
||||
|
||||
return {
|
||||
status: response.status,
|
||||
text: text.toLowerCase() || ""
|
||||
};
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function check(url) {
|
||||
const response = await get(url);
|
||||
|
||||
switch (response) {
|
||||
case null:
|
||||
return false;
|
||||
default:
|
||||
const blacklistedStatus = config.blacklist.status.includes(response.status);
|
||||
const blacklistedText = config.blacklist.text.some((t) => response.text.includes(t));
|
||||
|
||||
return !(blacklistedStatus || blacklistedText);
|
||||
}
|
||||
}
|
74
api/src/lib/other/config.js
Normal file
74
api/src/lib/other/config.js
Normal file
@ -0,0 +1,74 @@
|
||||
export default {
|
||||
providers: [
|
||||
{
|
||||
base: "vidsrc.to",
|
||||
url: function (type, params) {
|
||||
switch (type) {
|
||||
case "movie":
|
||||
return `https://${this.base}/embed/movie/${params.id}`;
|
||||
case "tv":
|
||||
return `https://${this.base}/embed/tv/${params.id}/${params.season}/${params.episode}`;
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
base: "vidsrc.me",
|
||||
url: function (type, params) {
|
||||
switch (type) {
|
||||
case "movie":
|
||||
return `https://${this.base}/embed/movie?tmdb=${params.id}`;
|
||||
case "tv":
|
||||
return `https://${this.base}/embed/tv?tmdb=${params.id}&season=${params.season}&episode=${params.episode}`;
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
base: "flixon.click",
|
||||
url: function (type, params) {
|
||||
switch (type) {
|
||||
case "movie":
|
||||
return `https://${this.base}/${params.imdbId}`;
|
||||
case "tv":
|
||||
return `https://${this.base}/${params.id}-${params.season}-${params.episode}`;
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
base: "2embed.me",
|
||||
url: function (type, params) {
|
||||
switch (type) {
|
||||
case "movie":
|
||||
return `https://${this.base}/player/movie/${params.imdbId}`;
|
||||
case "tv":
|
||||
return `https://${this.base}/player/tv/${params.id}/S${params.season}/E${params.episode}`;
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
base: "databasegdriveplayer.xyz",
|
||||
url: function (type, params) {
|
||||
switch (type) {
|
||||
case "movie":
|
||||
return `https://${this.base}/player.php?tmdb=${params.id}`;
|
||||
case "tv":
|
||||
return `https://${this.base}/player.php?type=series&tmdb=${params.id}&season=${params.season}&episode=${params.episode}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
blacklist: {
|
||||
status: [
|
||||
404, // Not Found
|
||||
500 // Internal Server Error
|
||||
],
|
||||
text: [
|
||||
"not found", // Generic
|
||||
"no sources", // Generic
|
||||
"media is unavailable", // vidsrc.xyz
|
||||
"onionplay streaming mirrors", // flixon.click
|
||||
"no movie found", // 2embed.me
|
||||
"no tv show found", // 2embed.me
|
||||
`,"file":"","kind"` // databasegdriveplayer.xyz
|
||||
]
|
||||
}
|
||||
};
|
10
api/src/lib/other/env.js
Normal file
10
api/src/lib/other/env.js
Normal file
@ -0,0 +1,10 @@
|
||||
import dotenv from "dotenv";
|
||||
import { fileURLToPath } from "url";
|
||||
import path, { dirname } from "path";
|
||||
|
||||
export function initializeEnvironmentVariables() {
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
dotenv.config({ path: path.join(__dirname, "..", "..", "..", ".env") });
|
||||
}
|
30
api/src/lib/server.js
Normal file
30
api/src/lib/server.js
Normal file
@ -0,0 +1,30 @@
|
||||
import fastify from "fastify";
|
||||
|
||||
import { applyCors } from "./server/cors.js";
|
||||
import { applyCaching } from "./server/cache.js";
|
||||
import { applyRoutes } from "./server/routes.js";
|
||||
|
||||
function runServer(server, host, port) {
|
||||
return new Promise(function (res) {
|
||||
server.listen({
|
||||
host: host || "0.0.0.0",
|
||||
port: port || 5000
|
||||
}, function (error, address) {
|
||||
if (error) res({ success: false, error });
|
||||
res({ success: true, address });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function initializeServer() {
|
||||
return new Promise(async function (res) {
|
||||
const server = fastify();
|
||||
|
||||
await applyCors(server, process.env.ORIGIN);
|
||||
await applyCaching(server, process.env.CACHE_TIMEOUT);
|
||||
applyRoutes(server);
|
||||
|
||||
const response = await runServer(server, process.env.HOST, process.env.PORT);
|
||||
res(response);
|
||||
});
|
||||
}
|
5
api/src/lib/server/cache.js
Normal file
5
api/src/lib/server/cache.js
Normal file
@ -0,0 +1,5 @@
|
||||
import caching from "fastify-response-caching";
|
||||
|
||||
export async function applyCaching(server, time) {
|
||||
await server.register(caching, { ttl: (time || 300) * 60 * 1000 });
|
||||
}
|
5
api/src/lib/server/cors.js
Normal file
5
api/src/lib/server/cors.js
Normal file
@ -0,0 +1,5 @@
|
||||
import cors from "@fastify/cors";
|
||||
|
||||
export async function applyCors(server, origin) {
|
||||
await server.register(cors, { origin: origin || "*" });
|
||||
}
|
31
api/src/lib/server/request.js
Normal file
31
api/src/lib/server/request.js
Normal file
@ -0,0 +1,31 @@
|
||||
import config from "../other/config.js";
|
||||
import { check } from "../other/check.js";
|
||||
|
||||
export function onRootRequest() {
|
||||
return { success: true, providers: config.providers.map((p) => p.base) };
|
||||
}
|
||||
|
||||
export async function onRequest(type, req) {
|
||||
// Provider Check
|
||||
const provider = config.providers.find((p) => p.base === req.params.provider);
|
||||
if (!provider) return { success: false, message: "Unsupported provider" };
|
||||
|
||||
// Parameters
|
||||
const id = req.params.id;
|
||||
const imdbId = req.params.imdbId;
|
||||
const season = req.params.season;
|
||||
const episode = req.params.episode;
|
||||
|
||||
// Empty Check
|
||||
if (id === "" || imdbId === "" || season === "" || episode === "") {
|
||||
return { success: false, message: "Missing parameters" };
|
||||
}
|
||||
|
||||
// URL
|
||||
const url = provider.url(type, { id, imdbId, season, episode });
|
||||
|
||||
// Return
|
||||
return await check(url)
|
||||
? { success: true, url }
|
||||
: { success: false };
|
||||
}
|
13
api/src/lib/server/routes.js
Normal file
13
api/src/lib/server/routes.js
Normal file
@ -0,0 +1,13 @@
|
||||
import { onRootRequest, onRequest } from "./request.js";
|
||||
|
||||
export function applyRoutes(server) {
|
||||
server.get("/", onRootRequest);
|
||||
|
||||
server.get("/:provider/:id/:imdbId?", async function (...args) {
|
||||
return await onRequest("movie", ...args);
|
||||
});
|
||||
|
||||
server.get("/:provider/:id/:season/:episode/:imdbId?", async function (...args) {
|
||||
return await onRequest("tv", ...args);
|
||||
});
|
||||
}
|
@ -1,23 +1,27 @@
|
||||
export async function isValidProxy(proxy) {
|
||||
let response;
|
||||
let json;
|
||||
try {
|
||||
const response = await fetch(proxy);
|
||||
const json = await response.json();
|
||||
|
||||
try { response = await fetch(proxy.base) }
|
||||
catch { return false };
|
||||
|
||||
try { json = await response.json() }
|
||||
catch { return false };
|
||||
|
||||
return json?.success !== null && json?.message !== null;
|
||||
return json.success
|
||||
? json.providers
|
||||
: false;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export async function isValidUrl(proxy, url) {
|
||||
let response;
|
||||
export async function isValidUrl(proxy, provider, info, season, episode) {
|
||||
try {
|
||||
const response = (info.type === "movie")
|
||||
? await fetch(`${proxy}/${provider}/${info.id}/${info.imdbId}`)
|
||||
: await fetch(`${proxy}/${provider}/${info.id}/${season}/${episode}/${info.imdbId}`);
|
||||
const json = await response.json();
|
||||
|
||||
try { response = await fetch(proxy.url(url)) }
|
||||
catch {};
|
||||
|
||||
return response
|
||||
? response.status === 200
|
||||
: true;
|
||||
return json.success
|
||||
? json.url
|
||||
: false;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -2,13 +2,12 @@ import { getQuery, onQueryChange, setQuery, removeQuery } from "../query.js";
|
||||
import { setModal, showModal, changeHeaderText, hideModal } from "./modal.js";
|
||||
import { getDetails } from "../api/details.js";
|
||||
import { elementExists, onWindowResize, removeWindowResize, splitArray, getCenteringDirection, onKeyPress, promiseTimeout, onSwipe } from "../functions.js";
|
||||
import { config, providers, proxies, proxy as proxyConfig } from "../config.js";
|
||||
import { config, proxies, proxy as proxyConfig } from "../config.js";
|
||||
import { getProvider, setProvider } from "../store/provider.js";
|
||||
import { preloadImages, getNonCachedImages, unloadImages } from "../cache.js";
|
||||
import { getLastPlayed, setLastPlayed } from "../store/last-played.js";
|
||||
import { addContinueWatching } from "../store/continue.js";
|
||||
import { getWatchSection } from "../store/watch-sections.js";
|
||||
import { getThemeAbsolute } from "../store/theme.js";
|
||||
import { initializeArea } from "./area.js";
|
||||
import { isValidProxy, isValidUrl } from "../api/proxy.js";
|
||||
import { toggleDim } from "./dim.js";
|
||||
@ -227,29 +226,23 @@ function modal(info, recommendationImages) {
|
||||
let disabled = false;
|
||||
let seasonsDisabled = false;
|
||||
|
||||
let validProviders = {};
|
||||
let providers = [];
|
||||
let validProviders = [];
|
||||
let forceProvider;
|
||||
|
||||
let validProxy = null;
|
||||
let proxiesChecked = false;
|
||||
|
||||
function getUrl(provider) {
|
||||
const theme = getThemeAbsolute();
|
||||
|
||||
return info.type === "movie"
|
||||
? provider.movieUrl({ id: info.id, imdbId: info.imdbId, theme })
|
||||
: provider.showUrl({ id: info.id, season: seasonNumber, episode: episodeNumber, theme });
|
||||
}
|
||||
|
||||
function getValidProvider() {
|
||||
const provider = validProviders[getProvider()];
|
||||
if (!provider) forceProvider = Object.values(validProviders)[0];
|
||||
return forceProvider || provider;
|
||||
const currentProvider = getProvider();
|
||||
const provider = validProviders.find((p) => p.provider === currentProvider);
|
||||
|
||||
if (!provider) forceProvider = validProviders[0]?.provider;
|
||||
return forceProvider || provider?.provider;
|
||||
}
|
||||
|
||||
function getValidProviderKey() {
|
||||
const provider = getValidProvider();
|
||||
return Object.keys(validProviders)[Object.values(validProviders).indexOf(provider)];
|
||||
function getUrl(provider) {
|
||||
return validProviders.find((p) => p.provider === provider)?.url;
|
||||
}
|
||||
|
||||
function videoAlert(toggle, icon, text) {
|
||||
@ -259,7 +252,7 @@ function modal(info, recommendationImages) {
|
||||
}
|
||||
|
||||
async function checkProviders() {
|
||||
validProviders = {};
|
||||
validProviders = [];
|
||||
forceProvider = null;
|
||||
|
||||
disabled = true;
|
||||
@ -276,19 +269,29 @@ function modal(info, recommendationImages) {
|
||||
|
||||
const promises = Object.values(proxies).map(function (proxy) {
|
||||
return new Promise(async function (res, rej) {
|
||||
if (await isValidProxy(proxy)) res(proxy);
|
||||
const providers = await isValidProxy(proxy);
|
||||
|
||||
if (providers) res({ proxy, providers });
|
||||
else rej();
|
||||
});
|
||||
});
|
||||
|
||||
const response = await Promise.any([...promises, promiseTimeout(proxyConfig.checkTimeout)]);
|
||||
if (response) validProxy = response;
|
||||
|
||||
if (response) {
|
||||
providers = response.providers;
|
||||
validProxy = response.proxy;
|
||||
|
||||
if (getProvider() === null && providers[0]) {
|
||||
setProvider(providers[0]);
|
||||
}
|
||||
}
|
||||
|
||||
proxiesChecked = true;
|
||||
}
|
||||
|
||||
async function providersCheck(proxy) {
|
||||
const total = Object.keys(providers).length;
|
||||
const total = providers.length;
|
||||
let checked = 0;
|
||||
|
||||
function updateAlert() {
|
||||
@ -297,18 +300,20 @@ function modal(info, recommendationImages) {
|
||||
|
||||
updateAlert();
|
||||
|
||||
const promises = Object.entries(providers).map(async function ([key, value]) {
|
||||
const url = getUrl(value);
|
||||
const valid = await Promise.any([isValidUrl(proxy, url), promiseTimeout(proxyConfig.validCheckTimeout)]);
|
||||
const promises = providers.map(async function (provider) {
|
||||
const url = await Promise.any([
|
||||
isValidUrl(proxy, provider, info, seasonNumber, episodeNumber),
|
||||
promiseTimeout(proxyConfig.validCheckTimeout)
|
||||
]);
|
||||
|
||||
if (valid) validProviders[key] = value;
|
||||
if (url) validProviders.push({ provider, url });
|
||||
checked++;
|
||||
|
||||
updateAlert();
|
||||
});
|
||||
|
||||
await Promise.all(promises);
|
||||
validProviders = Object.fromEntries(Object.entries(validProviders).sort(([a], [b]) => Object.keys(providers).indexOf(a) - Object.keys(providers).indexOf(b)));
|
||||
validProviders = validProviders.sort(({ provider: a }, { provider: b }) => providers.indexOf(a) - providers.indexOf(b));
|
||||
}
|
||||
|
||||
if (!proxiesChecked) await proxiesCheck();
|
||||
@ -318,8 +323,8 @@ function modal(info, recommendationImages) {
|
||||
|
||||
providersSelect.innerHTML = "";
|
||||
|
||||
if (Object.keys(validProviders).length > 0) {
|
||||
Object.keys(validProviders).forEach(function (providerName) {
|
||||
if (validProviders.length > 0 && validProxy) {
|
||||
validProviders.forEach(function ({ provider: providerName }) {
|
||||
const provider = document.createElement("option");
|
||||
|
||||
provider.value = providerName.toLowerCase();
|
||||
@ -328,13 +333,14 @@ function modal(info, recommendationImages) {
|
||||
providersSelect.append(provider);
|
||||
});
|
||||
|
||||
providersSelect.value = getValidProviderKey();
|
||||
providersSelect.value = getValidProvider();
|
||||
providersElem.classList.remove("disabled");
|
||||
|
||||
disabled = false;
|
||||
playVideo();
|
||||
} else {
|
||||
videoAlert(true, "censor", "No providers available");
|
||||
if (validProxy) videoAlert(true, "censor", "No providers available");
|
||||
else videoAlert(true, "censor", "No proxies available");
|
||||
}
|
||||
|
||||
seasonsDisabled = false;
|
||||
@ -400,7 +406,7 @@ function modal(info, recommendationImages) {
|
||||
function nextProvider() {
|
||||
if (disabled) return;
|
||||
|
||||
const provider = getValidProviderKey();
|
||||
const provider = getValidProvider();
|
||||
const providers = Array.from(providersSelect.children);
|
||||
|
||||
const providerElem = providers.find((p) => p.value === provider);
|
||||
@ -416,7 +422,7 @@ function modal(info, recommendationImages) {
|
||||
function previousProvider() {
|
||||
if (disabled) return;
|
||||
|
||||
const provider = getValidProviderKey();
|
||||
const provider = getValidProvider();
|
||||
const providers = Array.from(providersSelect.children);
|
||||
|
||||
const providerElem = providers.find((p) => p.value === provider);
|
||||
|
@ -144,63 +144,10 @@ export const proxy = {
|
||||
};
|
||||
|
||||
export const proxies = [
|
||||
{
|
||||
base: "/proxy",
|
||||
url: function (path) {
|
||||
return `/proxy?url=${path}`;
|
||||
}
|
||||
},
|
||||
{
|
||||
base: "https://fh-site.vercel.app/proxy",
|
||||
url: function (path) {
|
||||
return `https://fh-site.vercel.app/proxy?url=${path}`;
|
||||
}
|
||||
}
|
||||
"/api",
|
||||
"https://fh-site.vercel.app/api"
|
||||
];
|
||||
|
||||
export const providers = {
|
||||
"vidsrc.to": {
|
||||
movieUrl: function ({ id }) {
|
||||
return `https://vidsrc.to/embed/movie/${id}`;
|
||||
},
|
||||
showUrl: function ({ id, season, episode }) {
|
||||
return `https://vidsrc.to/embed/tv/${id}/${season}/${episode}`;
|
||||
}
|
||||
},
|
||||
"vidsrc.me": {
|
||||
movieUrl: function ({ id }) {
|
||||
return `https://vidsrc.me/embed/movie?tmdb=${id}`;
|
||||
},
|
||||
showUrl: function ({ id, season, episode }) {
|
||||
return `https://vidsrc.me/embed/tv?tmdb=${id}&season=${season}&episode=${episode}`;
|
||||
}
|
||||
},
|
||||
"flixon.click": {
|
||||
movieUrl: function ({ imdbId }) {
|
||||
return `https://flixon.click/${imdbId}`;
|
||||
},
|
||||
showUrl: function ({ id, season, episode }) {
|
||||
return `https://flixon.click/${id}-${season}-${episode}`;
|
||||
}
|
||||
},
|
||||
"2embed.me": {
|
||||
movieUrl: function ({ imdbId }) {
|
||||
return `https://2embed.me/player/movie/${imdbId}`;
|
||||
},
|
||||
showUrl: function ({ id, season, episode }) {
|
||||
return `https://2embed.me/player/tv/${id}/S${season}/E${episode}`;
|
||||
}
|
||||
},
|
||||
"databasegdriveplayer.xyz": {
|
||||
movieUrl: function ({ id }) {
|
||||
return `https://databasegdriveplayer.xyz/player.php?tmdb=${id}`;
|
||||
},
|
||||
showUrl: function ({ id, season, episode }) {
|
||||
return `https://databasegdriveplayer.xyz/player.php?type=series&tmdb=${id}&season=${season}&episode=${episode}`;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const store = {
|
||||
names: {
|
||||
cache: function (key) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { store, providers } from "../config.js";
|
||||
import { store } from "../config.js";
|
||||
|
||||
function get() {
|
||||
const provider = localStorage.getItem(store.names.provider);
|
||||
@ -15,9 +15,8 @@ export function getProvider() {
|
||||
if (provider) {
|
||||
return provider;
|
||||
} else {
|
||||
const defaultProvider = Object.keys(providers)[0];
|
||||
setProvider(defaultProvider);
|
||||
return defaultProvider;
|
||||
setProvider(null);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,18 +22,6 @@ export function getTheme() {
|
||||
}
|
||||
}
|
||||
|
||||
export function getThemeAbsolute() {
|
||||
const theme = getTheme();
|
||||
|
||||
if (theme === "auto") {
|
||||
return (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches)
|
||||
? "dark"
|
||||
: "light";
|
||||
} else {
|
||||
return theme;
|
||||
}
|
||||
}
|
||||
|
||||
export function setTheme(theme) {
|
||||
set(theme);
|
||||
initializeTheme();
|
||||
|
@ -4,8 +4,8 @@
|
||||
"buildCommand": "npm run build",
|
||||
"routes": [
|
||||
{
|
||||
"src": "/proxy",
|
||||
"dest": "/api/proxy"
|
||||
"src": "/api",
|
||||
"dest": "/api/index"
|
||||
}
|
||||
],
|
||||
"env": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user