mirror of
https://github.com/Inside4ndroid/TMDB-Embed-API.git
synced 2026-10-22 09:35:11 +00:00
Merge pull request #19 from An0n-00/main
Change names to embedsu, add correct quality parsing and change routes, parse subtitle languages and format them in ISO 639-1:2002 standard (yes, i am bored)
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# Unoffical Vidsrc (embed.su) API! 👋
|
||||
# Unoffical vidsrc (embed.su) API! 👋
|
||||
## Sponsorship / Donations
|
||||
|
||||
Your sponsorship is vital in helping me achieve this mission. With your support, I can:
|
||||
@@ -44,18 +44,17 @@ TVSHOWS :
|
||||
The providers are currently :
|
||||
|
||||
```
|
||||
vidsrc
|
||||
asiaheroku
|
||||
embedsu
|
||||
```
|
||||
|
||||
## Example Movie
|
||||
```
|
||||
https://your-domain/vidsrc/916224
|
||||
https://your-domain/embedsu/916224
|
||||
```
|
||||
|
||||
## Example Show
|
||||
```
|
||||
https://your-domain/asiaheroku/1429?s=1&e=1
|
||||
https://your-domain/embedsu/1429?s=1&e=1
|
||||
```
|
||||
|
||||
## Deployment
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import express from "express";
|
||||
import { getvidsrc } from "./src/vidsrcpro.js";
|
||||
import { getEmbedSu } from "./src/embedsu.js";
|
||||
|
||||
const port = 3000;
|
||||
|
||||
@@ -9,24 +9,24 @@ app.get('/', (req, res) => {
|
||||
res.status(200).json({
|
||||
intro: "Welcome to the unofficial vidsrcPro provider",
|
||||
routes: {
|
||||
movie: "/vidsrc/:movieTMDBid",
|
||||
show: "/vidsrc/:showTMDBid?s=seasonNumber&e=episodeNumber"
|
||||
movie: "/embedsu/:movieTMDBid",
|
||||
show: "/embedsu/:showTMDBid?s=seasonNumber&e=episodeNumber"
|
||||
},
|
||||
author: "This api is developed and created by Inside4ndroid Studios"
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/vidsrc/:tmdbId', async (req, res) => {
|
||||
app.get('/embedsu/:tmdbId', async (req, res) => {
|
||||
const id = req.params.tmdbId;
|
||||
const season = req.query.s;
|
||||
const episode = req.query.e;
|
||||
|
||||
try {
|
||||
if (season && episode) {
|
||||
const vidsrcresponse = await getvidsrc(id, season, episode);
|
||||
const vidsrcresponse = await getEmbedSu(id, season, episode);
|
||||
res.status(200).json(vidsrcresponse);
|
||||
} else {
|
||||
const vidsrcresponse = await getvidsrc(id);
|
||||
const vidsrcresponse = await getEmbedSu(id);
|
||||
res.status(200).json(vidsrcresponse);
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
Generated
+134
-1
@@ -9,7 +9,9 @@
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"express": "^4.18.2"
|
||||
"express": "^4.18.2",
|
||||
"fetch": "^1.1.0",
|
||||
"node-fetch": "^3.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/accepts": {
|
||||
@@ -31,6 +33,17 @@
|
||||
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/biskviit": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/biskviit/-/biskviit-1.0.1.tgz",
|
||||
"integrity": "sha512-VGCXdHbdbpEkFgtjkeoBN8vRlbj1ZRX2/mxhE8asCCRalUx2nBzOomLJv8Aw/nRt5+ccDb+tPKidg4XxcfGW4w==",
|
||||
"dependencies": {
|
||||
"psl": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/body-parser": {
|
||||
"version": "1.20.2",
|
||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
|
||||
@@ -119,6 +132,14 @@
|
||||
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/data-uri-to-buffer": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
|
||||
"integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
|
||||
"engines": {
|
||||
"node": ">= 12"
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
@@ -179,6 +200,14 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/encoding": {
|
||||
"version": "0.1.12",
|
||||
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz",
|
||||
"integrity": "sha512-bl1LAgiQc4ZWr++pNYUdRe/alecaHFeHxIJ/pNciqGdKXghaTCOwKkbKp6ye7pKZGu/GcaSXFk8PBVhgs+dJdA==",
|
||||
"dependencies": {
|
||||
"iconv-lite": "~0.4.13"
|
||||
}
|
||||
},
|
||||
"node_modules/es-define-property": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
|
||||
@@ -257,6 +286,37 @@
|
||||
"node": ">= 0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fetch": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fetch/-/fetch-1.1.0.tgz",
|
||||
"integrity": "sha512-5O8TwrGzoNblBG/jtK4NFuZwNCkZX6s5GfRNOaGtm+QGJEuNakSC/i2RW0R93KX6E0jVjNXm6O3CRN4Ql3K+yA==",
|
||||
"dependencies": {
|
||||
"biskviit": "1.0.1",
|
||||
"encoding": "0.1.12"
|
||||
}
|
||||
},
|
||||
"node_modules/fetch-blob": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
|
||||
"integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/jimmywarting"
|
||||
},
|
||||
{
|
||||
"type": "paypal",
|
||||
"url": "https://paypal.me/jimmywarting"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"node-domexception": "^1.0.0",
|
||||
"web-streams-polyfill": "^3.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.20 || >= 14.13"
|
||||
}
|
||||
},
|
||||
"node_modules/finalhandler": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
|
||||
@@ -275,6 +335,17 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/formdata-polyfill": {
|
||||
"version": "4.0.10",
|
||||
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
|
||||
"integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
|
||||
"dependencies": {
|
||||
"fetch-blob": "^3.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.20.0"
|
||||
}
|
||||
},
|
||||
"node_modules/forwarded": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
|
||||
@@ -496,6 +567,41 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/node-domexception": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
|
||||
"integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/jimmywarting"
|
||||
},
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://paypal.me/jimmywarting"
|
||||
}
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
|
||||
"integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
|
||||
"dependencies": {
|
||||
"data-uri-to-buffer": "^4.0.0",
|
||||
"fetch-blob": "^3.1.4",
|
||||
"formdata-polyfill": "^4.0.10"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/node-fetch"
|
||||
}
|
||||
},
|
||||
"node_modules/object-inspect": {
|
||||
"version": "1.13.2",
|
||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz",
|
||||
@@ -548,6 +654,25 @@
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/psl": {
|
||||
"version": "1.15.0",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz",
|
||||
"integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==",
|
||||
"dependencies": {
|
||||
"punycode": "^2.3.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/lupomontero"
|
||||
}
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/qs": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
|
||||
@@ -756,6 +881,14 @@
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/web-streams-polyfill": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
|
||||
"integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-1
@@ -11,6 +11,8 @@
|
||||
"author": "Inside4ndroid Studios Ltd",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"express": "^4.18.2"
|
||||
"express": "^4.18.2",
|
||||
"fetch": "^1.1.0",
|
||||
"node-fetch": "^3.3.2"
|
||||
}
|
||||
}
|
||||
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
import fetch from 'node-fetch';
|
||||
import { languageMap } from './languages.js';
|
||||
|
||||
export async function getEmbedSu(tmdb_id, s, e) {
|
||||
const DOMAIN = "https://embed.su";
|
||||
const headers = {
|
||||
'User-Agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
|
||||
'Referer': DOMAIN,
|
||||
'Origin': DOMAIN,
|
||||
};
|
||||
|
||||
try {
|
||||
const urlSearch = s && e ? `${DOMAIN}/embed/tv/${tmdb_id}/${s}/${e}` : `${DOMAIN}/embed/movie/${tmdb_id}`;
|
||||
const htmlSearch = await fetch(urlSearch, { method: 'GET', headers });
|
||||
const textSearch = await htmlSearch.text();
|
||||
|
||||
const hashEncodeMatch = textSearch.match(/JSON\.parse\(atob\(\`([^\`]+)/i);
|
||||
const hashEncode = hashEncodeMatch ? hashEncodeMatch[1] : "";
|
||||
|
||||
if (!hashEncode) return;
|
||||
|
||||
const hashDecode = JSON.parse(await stringAtob(hashEncode));
|
||||
const mEncrypt = hashDecode.hash;
|
||||
if (!mEncrypt) return;
|
||||
|
||||
const firstDecode = (await stringAtob(mEncrypt)).split(".").map(item => item.split("").reverse().join(""));
|
||||
const secondDecode = JSON.parse(await stringAtob(firstDecode.join("").split("").reverse().join("")));
|
||||
|
||||
if (!secondDecode || secondDecode.length === 0) return;
|
||||
|
||||
const sources = [];
|
||||
const subtitles = [];
|
||||
|
||||
for (const item of secondDecode) {
|
||||
if (item.name.toLowerCase() !== "viper") continue;
|
||||
|
||||
const urlDirect = `${DOMAIN}/api/e/${item.hash}`;
|
||||
const dataDirect = await requestGet(urlDirect, {
|
||||
"Referer": DOMAIN,
|
||||
"User-Agent": headers['User-Agent'],
|
||||
"Accept": "*/*"
|
||||
});
|
||||
|
||||
if (!dataDirect.source) continue;
|
||||
|
||||
const tracks = dataDirect.subtitles.map(sub => ({
|
||||
url: sub.file,
|
||||
lang: languageMap[sub.label.split(' ')[0]] || sub.label
|
||||
})).filter(track => track.lang);
|
||||
|
||||
const requestDirectSize = await fetch(dataDirect.source, { headers, method: "GET" });
|
||||
const parseRequest = await requestDirectSize.text();
|
||||
|
||||
const patternSize = parseRequest.split('\n').filter(item => item.includes('/proxy/'));
|
||||
|
||||
const directQuality = patternSize.map(patternItem => {
|
||||
const sizeQuality = getSizeQuality(patternItem);
|
||||
let dURL = `${DOMAIN}${patternItem}`;
|
||||
dURL = dURL.replace("embed.su/api/proxy/viper/", "").replace(".png", ".m3u8");
|
||||
return { file: dURL, type: 'hls', quality: `${sizeQuality}p`, lang: 'en' };
|
||||
});
|
||||
|
||||
if (!directQuality.length) continue;
|
||||
|
||||
sources.push({
|
||||
provider: "EmbedSu",
|
||||
files: directQuality,
|
||||
headers: {
|
||||
"Referer": DOMAIN,
|
||||
"User-Agent": headers['User-Agent'],
|
||||
"Origin": DOMAIN
|
||||
}
|
||||
});
|
||||
|
||||
subtitles.push(...tracks);
|
||||
}
|
||||
|
||||
return {
|
||||
sources,
|
||||
subtitles
|
||||
};
|
||||
} catch (e) {
|
||||
return { provider: "EmbedSu", sources: [], subtitles: [] };
|
||||
}
|
||||
}
|
||||
|
||||
function getSizeQuality(url) {
|
||||
const parts = url.split('/');
|
||||
const base64Part = parts[parts.length - 2];
|
||||
const decodedPart = atob(base64Part);
|
||||
const sizeQuality = Number(decodedPart) || 1080;
|
||||
return sizeQuality;
|
||||
}
|
||||
|
||||
async function stringAtob(input) {
|
||||
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
||||
let str = input.replace(/=+$/, '');
|
||||
let output = '';
|
||||
|
||||
if (str.length % 4 === 1) {
|
||||
throw new Error("'atob' failed: The string to be decoded is not correctly encoded.");
|
||||
}
|
||||
|
||||
for (let bc = 0, bs = 0, buffer, i = 0; buffer = str.charAt(i++); ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer, bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0) {
|
||||
buffer = chars.indexOf(buffer);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
async function requestGet(url, headers = {}) {
|
||||
try {
|
||||
const response = await fetch(url, { method: 'GET', headers });
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
export const languageMap = {
|
||||
"Abkhazian": "ab",
|
||||
"Afar": "aa",
|
||||
"Afrikaans": "af",
|
||||
"Albanian": "sq",
|
||||
"Amharic": "am",
|
||||
"Arabic": "ar",
|
||||
"Aragonese": "an",
|
||||
"Armenian": "hy",
|
||||
"Assamese": "as",
|
||||
"Aymara": "ay",
|
||||
"Azerbaijani": "az",
|
||||
"Bashkir": "ba",
|
||||
"Basque": "eu",
|
||||
"Bengali": "bn",
|
||||
"Bihari": "bh",
|
||||
"Bislama": "bi",
|
||||
"Bosnian": "bs",
|
||||
"Breton": "br",
|
||||
"Bulgarian": "bg",
|
||||
"Burmese": "my",
|
||||
"Catalan": "ca",
|
||||
"Chinese": "zh",
|
||||
"Chuvash": "cv",
|
||||
"Cornish": "kw",
|
||||
"Corsican": "co",
|
||||
"Croatian": "hr",
|
||||
"Czech": "cs",
|
||||
"Danish": "da",
|
||||
"Dutch": "nl",
|
||||
"Dzongkha": "dz",
|
||||
"English": "en",
|
||||
"Esperanto": "eo",
|
||||
"Estonian": "et",
|
||||
"Ewe": "ee",
|
||||
"Fijian": "fj",
|
||||
"Finnish": "fi",
|
||||
"French": "fr",
|
||||
"Georgian": "ka",
|
||||
"German": "de",
|
||||
"Greek": "el",
|
||||
"Guaraní": "gn",
|
||||
"Gujarati": "gu",
|
||||
"Haitian Creole": "ht",
|
||||
"Hausa": "ha",
|
||||
"Hawaiian": "haw",
|
||||
"Hebrew": "he",
|
||||
"Hindi": "hi",
|
||||
"Hmong": "hmn",
|
||||
"Hungarian": "hu",
|
||||
"Icelandic": "is",
|
||||
"Igbo": "ig",
|
||||
"Indonesian": "id",
|
||||
"Interlingua": "ia",
|
||||
"Irish": "ga",
|
||||
"Italian": "it",
|
||||
"Japanese": "ja",
|
||||
"Javanese": "jv",
|
||||
"Kannada": "kn",
|
||||
"Kazakh": "kk",
|
||||
"Khmer": "km",
|
||||
"Kinyarwanda": "rw",
|
||||
"Korean": "ko",
|
||||
"Kurdish": "ku",
|
||||
"Kyrgyz": "ky",
|
||||
"Lao": "lo",
|
||||
"Latin": "la",
|
||||
"Latvian": "lv",
|
||||
"Lingala": "ln",
|
||||
"Lithuanian": "lt",
|
||||
"Luxembourgish": "lb",
|
||||
"Macedonian": "mk",
|
||||
"Malagasy": "mg",
|
||||
"Malay": "ms",
|
||||
"Malayalam": "ml",
|
||||
"Maltese": "mt",
|
||||
"Maori": "mi",
|
||||
"Marathi": "mr",
|
||||
"Mongolian": "mn",
|
||||
"Nepali": "ne",
|
||||
"Norwegian": "no",
|
||||
"Occitan": "oc",
|
||||
"Oromo": "om",
|
||||
"Pashto": "ps",
|
||||
"Persian": "fa",
|
||||
"Polish": "pl",
|
||||
"Portuguese": "pt",
|
||||
"Quechua": "qu",
|
||||
"Romanian": "ro",
|
||||
"Russian": "ru",
|
||||
"Samoan": "sm",
|
||||
"Sanskrit": "sa",
|
||||
"Scots Gaelic": "gd",
|
||||
"Serbian": "sr",
|
||||
"Sesotho": "st",
|
||||
"Shona": "sn",
|
||||
"Sindhi": "sd",
|
||||
"Sinhalese": "si",
|
||||
"Slovak": "sk",
|
||||
"Slovenian": "sl",
|
||||
"Somali": "so",
|
||||
"Spanish": "es",
|
||||
"Sundanese": "su",
|
||||
"Swahili": "sw",
|
||||
"Swedish": "sv",
|
||||
"Tajik": "tg",
|
||||
"Tamil": "ta",
|
||||
"Tatar": "tt",
|
||||
"Telugu": "te",
|
||||
"Thai": "th",
|
||||
"Tigrinya": "ti",
|
||||
"Turkish": "tr",
|
||||
"Turkmen": "tk",
|
||||
"Ukrainian": "uk",
|
||||
"Urdu": "ur",
|
||||
"Uzbek": "uz",
|
||||
"Vietnamese": "vi",
|
||||
"Volapük": "vo",
|
||||
"Walloon": "wa",
|
||||
"Welsh": "cy",
|
||||
"Wolof": "wo",
|
||||
"Xhosa": "xh",
|
||||
"Yiddish": "yi",
|
||||
"Yoruba": "yo",
|
||||
"Zulu": "zu"
|
||||
};
|
||||
@@ -1,174 +0,0 @@
|
||||
export async function getvidsrc(tmdb_id, s, e) {
|
||||
const DOMAIN = "https://embed.su";
|
||||
const headers = {
|
||||
'user-agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
|
||||
'Referer': `${DOMAIN}`,
|
||||
'Origin': `${DOMAIN}`,
|
||||
};
|
||||
|
||||
try {
|
||||
let urlSearch = '';
|
||||
|
||||
if(s && e){
|
||||
urlSearch = `${DOMAIN}/embed/tv/${tmdb_id}/${s}/${e}`;
|
||||
} else {
|
||||
urlSearch = `${DOMAIN}/embed/movie/${tmdb_id}`;
|
||||
}
|
||||
|
||||
const htmlSearch = await fetch(urlSearch, {
|
||||
method: 'GET',
|
||||
headers: headers,
|
||||
});
|
||||
const textSearch = await htmlSearch.text();
|
||||
|
||||
const hashEncodeMatch = textSearch.match(/JSON\.parse\(atob\(\`([^\`]+)/i);
|
||||
const hashEncode = hashEncodeMatch ? hashEncodeMatch[1] : "";
|
||||
|
||||
if (!hashEncode) {
|
||||
return;
|
||||
}
|
||||
|
||||
const hashDecode = JSON.parse(await string_atob(hashEncode));
|
||||
|
||||
const mEncrypt = hashDecode.hash;
|
||||
if (!mEncrypt) {
|
||||
return;
|
||||
}
|
||||
|
||||
const firstDecode = (await string_atob(mEncrypt)).split(".").map(item => item.split("").reverse().join(""));
|
||||
const secondDecode = JSON.parse(await string_atob(firstDecode.join("").split("").reverse().join("")));
|
||||
|
||||
if (!secondDecode || secondDecode.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i = 0; i < secondDecode.length; i++) {
|
||||
const item = secondDecode[i];
|
||||
if (item.name.toLowerCase() != "viper") {
|
||||
continue;
|
||||
}
|
||||
|
||||
const urlDirect = `${DOMAIN}/api/e/${item.hash}`;
|
||||
const dataDirect = await request_get(urlDirect, {
|
||||
"Referer": "https://embed.su/",
|
||||
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
|
||||
"Accept": "*/*"
|
||||
}, false);
|
||||
|
||||
if (!dataDirect.source) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const tracks = [];
|
||||
try {
|
||||
for (let j = 0; j < dataDirect.subtitles.length; j++) {
|
||||
const itemTrack = dataDirect.subtitles[j];
|
||||
const labelMatch = itemTrack.label.match(/^([A-z]+)/i);
|
||||
const label = labelMatch ? labelMatch[1] : "";
|
||||
if (!label) {
|
||||
continue;
|
||||
}
|
||||
tracks.push({
|
||||
url: itemTrack.file,
|
||||
lang: label
|
||||
});
|
||||
}
|
||||
} catch (etrack) { }
|
||||
|
||||
const requestDirectSize = await fetch(dataDirect.source, {
|
||||
headers: {
|
||||
"Referer": `${DOMAIN}`,
|
||||
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
|
||||
"Accept": "*/*"
|
||||
},
|
||||
method: "GET",
|
||||
});
|
||||
const parseRequest = await requestDirectSize.text();
|
||||
|
||||
const patternSize = [];
|
||||
const parseDirectSize = parseRequest.split('\n');
|
||||
|
||||
for (let k = 0; k < parseDirectSize.length; k++) {
|
||||
const item = parseDirectSize[k];
|
||||
if (item.indexOf('/proxy/') == -1) {
|
||||
continue;
|
||||
}
|
||||
patternSize.push(item);
|
||||
}
|
||||
|
||||
const directQuality = [];
|
||||
for (let l = 0; l < patternSize.length; l++) {
|
||||
const patternItem = patternSize[l];
|
||||
const sizeQualityMatch = patternItem.match(/\/([0-9]+)\//i);
|
||||
const sizeQuality = sizeQualityMatch ? Number(sizeQualityMatch[1]) : 1080;
|
||||
let dURL = `${DOMAIN}${patternItem}`;
|
||||
dURL = dURL.replace("embed.su/api/proxy/viper/", "");
|
||||
dURL = dURL.replace(".png", ".m3u8");
|
||||
directQuality.push({
|
||||
url: dURL,
|
||||
quality: sizeQuality.toString(),
|
||||
isM3U8: true
|
||||
});
|
||||
}
|
||||
|
||||
if (!directQuality.length) {
|
||||
continue;
|
||||
}
|
||||
|
||||
directQuality.sort((a, b) => b.quality - a.quality);
|
||||
|
||||
const results = {
|
||||
headers: {
|
||||
"Referer": "https://embed.su/",
|
||||
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
|
||||
"Accept": "*/*"
|
||||
},
|
||||
sources: directQuality,
|
||||
subtitles: tracks
|
||||
};
|
||||
|
||||
return results;
|
||||
}
|
||||
} catch (e) {
|
||||
const results = {
|
||||
headers: {},
|
||||
sources: '',
|
||||
subtitles: ''
|
||||
};
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
||||
async function string_atob(input) {
|
||||
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
||||
var str = input.replace(/=+$/, '');
|
||||
var output = '';
|
||||
if (str.length % 4 == 1) {
|
||||
throw new Error("'atob' failed: The string to be decoded is not correctly encoded.");
|
||||
}
|
||||
for (var bc = 0, bs = 0, buffer = void 0, i = 0; buffer = str.charAt(i++); ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,
|
||||
bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0) {
|
||||
buffer = chars.indexOf(buffer);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
async function request_get(url, headers = {}) {
|
||||
try {
|
||||
headers = headers || {};
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: headers,
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user