add bcine

This commit is contained in:
janisslsm committed 2026-07-23 14:23:47 +03:00
1 parent 13f10fb7d8
commit 1b8cb7f6e9
5 files changed
+443

No files matched your search

+191
View File
@@ -0,0 +1,191 @@
// bcine - bundled from src/bcine/
var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
// src/bcine/http.js
var SITE_URL = "https://bcine.ru";
var EMBED_URL = "https://1embed.cc";
var HEADERS = {
"Accept": "*/*",
"Origin": EMBED_URL,
"Referer": `${SITE_URL}/`,
"User-Agent": "Mozilla/5.0 (Linux; Android 15) AppleWebKit/537.36 Chrome/140.0.0.0 Mobile Safari/537.36"
};
function mergeHeaders(headers) {
return __spreadValues(__spreadValues({}, HEADERS), headers || {});
}
async function fetchText(url, options = {}) {
const response = await fetch(url, __spreadProps(__spreadValues({}, options), {
headers: mergeHeaders(options.headers)
}));
if (!response.ok) {
const error = new Error(`HTTP ${response.status} for ${url}`);
error.status = response.status;
throw error;
}
return await response.text();
}
async function fetchJson(url, options = {}) {
return JSON.parse(await fetchText(url, options));
}
// src/bcine/extractor.js
var BCINE_PROVIDER = "xpa";
var CINEMETA_URL = "https://v3-cinemeta.strem.io/meta";
var TMDB_ID_CACHE = {};
function isPositiveInteger(value) {
return Number.isInteger(Number(value)) && Number(value) > 0;
}
async function resolveTmdbId(value, mediaType) {
const id = String(value || "").trim();
if (/^\d+$/.test(id))
return id;
if (!/^tt\d+$/i.test(id))
return null;
const cacheKey = `${mediaType}:${id.toLowerCase()}`;
if (TMDB_ID_CACHE[cacheKey])
return TMDB_ID_CACHE[cacheKey];
const catalogType = mediaType === "movie" ? "movie" : "series";
const metadata = await fetchJson(
`${CINEMETA_URL}/${catalogType}/${encodeURIComponent(id)}.json`,
{ headers: { "Accept": "application/json" } }
);
const resolved = metadata && metadata.meta && metadata.meta.moviedb_id;
if (!resolved || !/^\d+$/.test(String(resolved))) {
return null;
}
TMDB_ID_CACHE[cacheKey] = String(resolved);
return TMDB_ID_CACHE[cacheKey];
}
function getEmbedUrl(tmdbId, mediaType, season, episode) {
const path = mediaType === "movie" ? `/embed/movie/${tmdbId}` : `/embed/tv/${tmdbId}/${season}/${episode}`;
return `${EMBED_URL}${path}?sr=buke&autoplay=1`;
}
function getQuality(server) {
const value = `${server && server.title || ""} ${server && server.quality || ""}`;
const match = value.match(/(2160|1440|1080|720|480|360)p?/i);
return match ? `${match[1]}p` : /4k/i.test(value) ? "4K" : "Auto";
}
function getAbsoluteUrl(value) {
const url = String(value || "").trim();
if (!url)
return "";
if (/^https?:\/\//i.test(url))
return url;
if (url.charAt(0) === "/")
return `${EMBED_URL}${url}`;
return "";
}
async function getSessionToken(referer) {
const response = await fetchJson(`${EMBED_URL}/api/token`, {
headers: {
"Accept": "application/json",
"Referer": referer
}
});
if (!response || typeof response.token !== "string" || !response.token) {
throw new Error("bCine player did not return a session token");
}
return response.token;
}
async function getSourcePayload(tmdbId, mediaType, season, episode) {
const referer = getEmbedUrl(tmdbId, mediaType, season, episode);
const token = await getSessionToken(referer);
const request = {
type: mediaType,
id: String(tmdbId),
provider: BCINE_PROVIDER
};
if (mediaType === "tv") {
request.season = Number(season);
request.episode = Number(episode);
}
const payload = await fetchJson(`${EMBED_URL}/api/sources`, {
method: "POST",
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
"Referer": referer,
"x-bcine-key": token
},
body: JSON.stringify(request)
});
return { payload, referer };
}
function normalizeStreams(payload, referer) {
const streams = [];
const seenUrls = {};
const servers = payload && Array.isArray(payload.servers) ? payload.servers : [];
for (const server of servers) {
const url = getAbsoluteUrl(server && server.url);
if (!url || seenUrls[url] || !/\.m3u8|\/api\/proxy/i.test(url)) {
continue;
}
seenUrls[url] = true;
const quality = getQuality(server);
const label = String(server.title || server.name || "HLS").trim();
streams.push({
name: "bCine",
title: `bCine \xB7 ${label}`,
url,
quality,
headers: {
"Origin": EMBED_URL,
"Referer": referer,
"User-Agent": HEADERS["User-Agent"]
}
});
}
return streams;
}
async function extractStreams(tmdbId, mediaType, season, episode) {
if (mediaType !== "movie" && mediaType !== "tv") {
return [];
}
if (mediaType === "tv" && (!isPositiveInteger(season) || !isPositiveInteger(episode))) {
return [];
}
const resolvedTmdbId = await resolveTmdbId(tmdbId, mediaType);
if (!resolvedTmdbId) {
return [];
}
const { payload, referer } = await getSourcePayload(
resolvedTmdbId,
mediaType,
Number(season),
Number(episode)
);
return normalizeStreams(payload, referer);
}
// src/bcine/index.js
async function getStreams(tmdbId, mediaType, season, episode) {
try {
const episodeLabel = mediaType === "tv" ? ` S${season}E${episode}` : "";
console.log(`[bCine] Request: ${mediaType} ${tmdbId}${episodeLabel}`);
const streams = await extractStreams(tmdbId, mediaType, season, episode);
console.log(`[bCine] Found ${streams.length} stream(s)`);
return streams;
} catch (error) {
console.error(`[bCine] Error: ${error.message}`);
return [];
}
}
module.exports = { getStreams };