mirror of
https://github.com/Radiquum/AniX.git
synced 2025-06-05 11:39:36 +05:00
feat: rewrite player parsing to js and add it them to repo
This commit is contained in:
parent
743f756920
commit
990b3c1736
9 changed files with 1275 additions and 34 deletions
|
@ -1,5 +1,5 @@
|
|||
# пример заполнения: example.com
|
||||
NEXT_PUBLIC_KODIK_PARSER_DOMAIN= # Домен парсера кодика, требуется для просмотра с данного источника
|
||||
NEXT_PUBLIC_ANILIBRIA_PARSER_DOMAIN= # Домен парсера анилибрии, если не заполнено, используется официальное апи
|
||||
NEXT_PUBLIC_SIBNET_PARSER_DOMAIN= # Домен парсера сибнет, требуется для просмотра с данного источника
|
||||
# пример заполнения: https://example.com, http://0.0.0.0:80
|
||||
NEXT_PUBLIC_KODIK_PARSER_URL= # Домен парсера кодика, требуется для просмотра с данного источника
|
||||
NEXT_PUBLIC_ANILIBRIA_PARSER_URL= # Домен парсера анилибрии, если не заполнено, используется официальное апи
|
||||
NEXT_PUBLIC_SIBNET_PARSER_URL= # Домен парсера сибнет, требуется для просмотра с данного источника
|
||||
# ---
|
|
@ -75,16 +75,16 @@ export const _fetchKodikManifest = async (
|
|||
setPlayerError: (state) => void
|
||||
) => {
|
||||
// Fetch episode links via edge function
|
||||
if (!process.env.NEXT_PUBLIC_KODIK_PARSER_DOMAIN) {
|
||||
if (!process.env.NEXT_PUBLIC_KODIK_PARSER_URL) {
|
||||
setPlayerError({
|
||||
message: "Источник не настроен",
|
||||
detail: "переменная 'NEXT_PUBLIC_KODIK_PARSER_DOMAIN' не обнаружена",
|
||||
detail: "переменная 'NEXT_PUBLIC_KODIK_PARSER_URL' не обнаружена",
|
||||
});
|
||||
return { manifest: null, poster: null };
|
||||
}
|
||||
|
||||
const data = await _fetchPlayer(
|
||||
`https://${process.env.NEXT_PUBLIC_KODIK_PARSER_DOMAIN}/?url=${url}&player=kodik`,
|
||||
`${process.env.NEXT_PUBLIC_KODIK_PARSER_URL}/?url=${url}&player=kodik`,
|
||||
setPlayerError
|
||||
);
|
||||
if (data) {
|
||||
|
@ -213,9 +213,9 @@ export const _fetchAnilibriaManifest = async (
|
|||
const epid = url.split("?id=")[1].split("&ep=")[1];
|
||||
const _url = `https://api.anilibria.tv/v3/title?id=${id}`;
|
||||
let data = null;
|
||||
if (process.env.NEXT_PUBLIC_ANILIBRIA_PARSER_DOMAIN) {
|
||||
if (process.env.NEXT_PUBLIC_ANILIBRIA_PARSER_URL) {
|
||||
data = await _fetchPlayer(
|
||||
`https://${process.env.NEXT_PUBLIC_ANILIBRIA_PARSER_DOMAIN}/?url=${_url}&player=libria`,
|
||||
`${process.env.NEXT_PUBLIC_ANILIBRIA_PARSER_URL}/?url=${_url}&player=libria`,
|
||||
setPlayerError
|
||||
);
|
||||
} else {
|
||||
|
@ -243,15 +243,15 @@ export const _fetchSibnetManifest = async (
|
|||
setPlayerError: (state) => void
|
||||
) => {
|
||||
// Fetch data via cloud endpoint
|
||||
if (!process.env.NEXT_PUBLIC_SIBNET_PARSER_DOMAIN) {
|
||||
if (!process.env.NEXT_PUBLIC_SIBNET_PARSER_URL) {
|
||||
setPlayerError({
|
||||
message: "Источник не настроен",
|
||||
detail: "переменная 'NEXT_PUBLIC_SIBNET_PARSER_DOMAIN' не обнаружена",
|
||||
detail: "переменная 'NEXT_PUBLIC_SIBNET_PARSER_URL' не обнаружена",
|
||||
});
|
||||
return { manifest: null, poster: null };
|
||||
}
|
||||
const data = await _fetchPlayer(
|
||||
`https://${process.env.NEXT_PUBLIC_SIBNET_PARSER_DOMAIN}/?url=${url}`,
|
||||
`${process.env.NEXT_PUBLIC_SIBNET_PARSER_URL}/?url=${url}&player=sibnet`,
|
||||
setPlayerError
|
||||
);
|
||||
if (data) {
|
||||
|
|
1034
package-lock.json
generated
1034
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -12,6 +12,7 @@
|
|||
"dependencies": {
|
||||
"apexcharts": "^3.52.0",
|
||||
"deepmerge-ts": "^7.1.0",
|
||||
"express": "^5.1.0",
|
||||
"flowbite": "^2.4.1",
|
||||
"flowbite-react": "^0.11.7",
|
||||
"hls-video-element": "^1.5.0",
|
||||
|
@ -25,6 +26,7 @@
|
|||
"react-toastify": "^11.0.5",
|
||||
"swiper": "^11.1.4",
|
||||
"swr": "^2.2.5",
|
||||
"tsx": "^4.19.4",
|
||||
"videojs-video-element": "^1.4.1",
|
||||
"zustand": "^4.5.4"
|
||||
},
|
||||
|
|
45
player-parsers/index.ts
Normal file
45
player-parsers/index.ts
Normal file
|
@ -0,0 +1,45 @@
|
|||
import { asJSON } from "./shared";
|
||||
import { getAnilibriaURL } from "./libria";
|
||||
import { getSibnetURL } from "./sibnet";
|
||||
import { getKodikURL } from "./kodik";
|
||||
|
||||
import express from "express";
|
||||
const app = express();
|
||||
|
||||
const host = "0.0.0.0";
|
||||
const port = 7000;
|
||||
const allowedPlayers = ["kodik", "libria", "sibnet"];
|
||||
|
||||
app.get("/", (req, res) => {
|
||||
const url = req.query.url;
|
||||
const player = req.query.player;
|
||||
|
||||
if (!url) {
|
||||
asJSON(res, { message: "no 'url' query provided" }, 400)
|
||||
return
|
||||
}
|
||||
|
||||
if (!player) {
|
||||
asJSON(res, { message: "no 'player' query provided" }, 400)
|
||||
return
|
||||
}
|
||||
|
||||
switch (player) {
|
||||
case "libria":
|
||||
getAnilibriaURL(res, url)
|
||||
return
|
||||
case "sibnet":
|
||||
getSibnetURL(res, url)
|
||||
return
|
||||
case "kodik":
|
||||
getKodikURL(res, url)
|
||||
return
|
||||
default:
|
||||
asJSON(res, { message: `player '${player}' is not supported. choose one of: ${allowedPlayers.join(", ")}` }, 400)
|
||||
return
|
||||
}
|
||||
});
|
||||
|
||||
app.listen(port, host, function () {
|
||||
console.log(`Server listens http://${host}:${port}`);
|
||||
});
|
95
player-parsers/kodik.ts
Normal file
95
player-parsers/kodik.ts
Normal file
|
@ -0,0 +1,95 @@
|
|||
import { asJSON, randomUA } from "./shared";
|
||||
const altDomains = ["kodik.info", "aniqit.com", "kodik.cc", "kodik.biz"];
|
||||
|
||||
export async function getKodikURL(res, url: string) {
|
||||
const origDomain = url.replace("https://", "").split("/")[0];
|
||||
let domain = url.replace("https://", "").split("/")[0];
|
||||
|
||||
if (!altDomains.includes(domain)) {
|
||||
asJSON(res, { message: "Wrong url provided for player kodik" }, 400);
|
||||
return;
|
||||
}
|
||||
|
||||
let user_agent = randomUA();
|
||||
|
||||
let pageRes = await fetch(url, {
|
||||
headers: {
|
||||
"User-Agent": user_agent,
|
||||
},
|
||||
});
|
||||
|
||||
if (!pageRes.ok) {
|
||||
for (let i = 0; i < altDomains.length - 1; i++) {
|
||||
if (url.includes(altDomains[i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
user_agent = randomUA();
|
||||
const altDomain = altDomains[i];
|
||||
const altUrl = url.replace(
|
||||
`https://${origDomain}/`,
|
||||
`https://${altDomain}/`
|
||||
);
|
||||
|
||||
domain = altDomain;
|
||||
pageRes = await fetch(altUrl, {
|
||||
headers: {
|
||||
"User-Agent": user_agent,
|
||||
},
|
||||
});
|
||||
|
||||
if (pageRes.ok) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!pageRes.ok) {
|
||||
asJSON(res, { message: "KODIK: failed to load page" }, 500);
|
||||
return;
|
||||
}
|
||||
|
||||
const pageData = await pageRes.text();
|
||||
const urlParamsRe = /var urlParams = .*;$/m;
|
||||
const urlParamsMatch = urlParamsRe.exec(pageData);
|
||||
|
||||
if (!urlParamsMatch || urlParamsMatch.length == 0) {
|
||||
asJSON(res, { message: `KODIK: failed to find data to parse` }, 500);
|
||||
return;
|
||||
}
|
||||
|
||||
const urlParamsStr = urlParamsMatch[0]
|
||||
.replace("var urlParams = '", "")
|
||||
.replace("';", "");
|
||||
|
||||
const urlStr = url.replace(`https://${origDomain}/`, "");
|
||||
const type = urlStr.split("/")[0];
|
||||
const id = urlStr.split("/")[1];
|
||||
const hash = urlStr.split("/")[2];
|
||||
|
||||
const urlParams = JSON.parse(urlParamsStr);
|
||||
urlParams["type"] = type;
|
||||
urlParams["id"] = id;
|
||||
urlParams["hash"] = hash;
|
||||
|
||||
const formData = new FormData();
|
||||
for (const [key, value] of Object.entries(urlParams)) {
|
||||
formData.append(key, value as any);
|
||||
}
|
||||
|
||||
const linksRes = await fetch(`https://${domain}/ftor`, {
|
||||
method: "POST",
|
||||
body: formData,
|
||||
headers: {
|
||||
"User-Agent": user_agent,
|
||||
},
|
||||
});
|
||||
|
||||
if (!linksRes.ok) {
|
||||
asJSON(res, { message: `KODIK: failed to get links` }, 500);
|
||||
return;
|
||||
}
|
||||
|
||||
asJSON(res, await linksRes.json(), 200);
|
||||
return;
|
||||
}
|
17
player-parsers/libria.ts
Normal file
17
player-parsers/libria.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { asJSON } from "./shared";
|
||||
|
||||
export async function getAnilibriaURL(res, url: string) {
|
||||
|
||||
if (!url.includes("anilibria")) {
|
||||
asJSON(res, { message: "Wrong url provided for player libria" }, 400);
|
||||
return
|
||||
}
|
||||
|
||||
let apiRes = await fetch(url);
|
||||
if (!apiRes.ok) {
|
||||
asJSON(res, { message: "LIBRIA: failed to get api response" }, 500);
|
||||
return
|
||||
}
|
||||
asJSON(res, await apiRes.json(), 200);
|
||||
return
|
||||
}
|
33
player-parsers/shared.ts
Normal file
33
player-parsers/shared.ts
Normal file
|
@ -0,0 +1,33 @@
|
|||
export const corsHeaders = {
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
"Access-Control-Allow-Methods": "GET,HEAD,POST,OPTIONS",
|
||||
"Cache-Control": "no-cache",
|
||||
};
|
||||
|
||||
export const resHeaders = {
|
||||
...corsHeaders,
|
||||
"Content-Type": "application/json",
|
||||
};
|
||||
|
||||
export const USERAGENTS = [
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.5 Safari/605.1.15",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.53 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Windows; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/10.1.2 Safari/603.3.8",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Windows; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Safari/605.1.15",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.53 Safari/537.36",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Safari/605.1.15",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Windows; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.53 Safari/537.36",
|
||||
];
|
||||
|
||||
export function asJSON(res, object: any, status: number) {
|
||||
res.status(status).type('application/json');
|
||||
res.set(corsHeaders)
|
||||
res.send(JSON.stringify(object));
|
||||
}
|
||||
|
||||
export function randomUA() {
|
||||
return USERAGENTS[Math.floor(Math.random() * USERAGENTS.length - 1)]
|
||||
}
|
59
player-parsers/sibnet.ts
Normal file
59
player-parsers/sibnet.ts
Normal file
|
@ -0,0 +1,59 @@
|
|||
import { asJSON, randomUA } from "./shared";
|
||||
|
||||
export async function getSibnetURL(res, url: string) {
|
||||
|
||||
if (!url.includes("sibnet")) {
|
||||
asJSON(res, { message: "Wrong url provided for player sibnet" }, 400);
|
||||
return
|
||||
}
|
||||
|
||||
const user_agent = randomUA();
|
||||
|
||||
let pageRes = await fetch(url, {
|
||||
headers: {
|
||||
"User-Agent": user_agent,
|
||||
},
|
||||
});
|
||||
if (!pageRes.ok) {
|
||||
asJSON(res, { message: `SIBNET:${pageRes.status}: failed to load page` }, 500)
|
||||
return
|
||||
}
|
||||
const pageData = await pageRes.text();
|
||||
const videoRe = /\/v\/.*?\.mp4/;
|
||||
const videoMatch = videoRe.exec(pageData);
|
||||
|
||||
if (!videoMatch || videoMatch.length == 0) {
|
||||
asJSON(res, { message: `SIBNET: failed to find data to parse` }, 500)
|
||||
return
|
||||
}
|
||||
|
||||
const posterRe = /\/upload\/cover\/.*?\.jpg/;
|
||||
const posterMatch = posterRe.exec(pageData);
|
||||
|
||||
const actualVideoRes = await fetch(
|
||||
`https://video.sibnet.ru${videoMatch[0]}`,
|
||||
{
|
||||
headers: {
|
||||
"User-Agent": user_agent,
|
||||
Referer: url,
|
||||
},
|
||||
redirect: "manual",
|
||||
}
|
||||
);
|
||||
|
||||
if (!actualVideoRes.headers.get("location")) {
|
||||
asJSON(res, { message: `SIBNET: failed to get video link` }, 500)
|
||||
return
|
||||
}
|
||||
|
||||
const video = actualVideoRes.headers.get("location");
|
||||
const poster =
|
||||
posterMatch ?
|
||||
posterMatch.length > 0 ?
|
||||
`https://st.sibnet.ru${posterMatch[0]}`
|
||||
: null
|
||||
: null;
|
||||
|
||||
asJSON(res, { video, poster }, 200)
|
||||
return
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue