Change names to embedsu, add correct quality parsing and change routes, parse subtitle languages and format them in ISO 639-1:2002 standard

This commit is contained in:
An0n-00
2025-02-15 14:58:26 +01:00
parent 8c07b87676
commit ef59e4bf68
7 changed files with 396 additions and 187 deletions
+4 -5
View File
@@ -1,4 +1,4 @@
# Unoffical Vidsrc (embed.su) API! 👋 # Unoffical vidsrc (embed.su) API! 👋
## Sponsorship / Donations ## Sponsorship / Donations
Your sponsorship is vital in helping me achieve this mission. With your support, I can: Your sponsorship is vital in helping me achieve this mission. With your support, I can:
@@ -44,18 +44,17 @@ TVSHOWS :
The providers are currently : The providers are currently :
``` ```
vidsrc embedsu
asiaheroku
``` ```
## Example Movie ## Example Movie
``` ```
https://your-domain/vidsrc/916224 https://your-domain/embedsu/916224
``` ```
## Example Show ## Example Show
``` ```
https://your-domain/asiaheroku/1429?s=1&e=1 https://your-domain/embedsu/1429?s=1&e=1
``` ```
## Deployment ## Deployment
+6 -6
View File
@@ -1,5 +1,5 @@
import express from "express"; import express from "express";
import { getvidsrc } from "./src/vidsrcpro.js"; import { getEmbedSu } from "./src/embedsu.js";
const port = 3000; const port = 3000;
@@ -9,24 +9,24 @@ app.get('/', (req, res) => {
res.status(200).json({ res.status(200).json({
intro: "Welcome to the unofficial vidsrcPro provider", intro: "Welcome to the unofficial vidsrcPro provider",
routes: { routes: {
movie: "/vidsrc/:movieTMDBid", movie: "/embedsu/:movieTMDBid",
show: "/vidsrc/:showTMDBid?s=seasonNumber&e=episodeNumber" show: "/embedsu/:showTMDBid?s=seasonNumber&e=episodeNumber"
}, },
author: "This api is developed and created by Inside4ndroid Studios" 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 id = req.params.tmdbId;
const season = req.query.s; const season = req.query.s;
const episode = req.query.e; const episode = req.query.e;
try { try {
if (season && episode) { if (season && episode) {
const vidsrcresponse = await getvidsrc(id, season, episode); const vidsrcresponse = await getEmbedSu(id, season, episode);
res.status(200).json(vidsrcresponse); res.status(200).json(vidsrcresponse);
} else { } else {
const vidsrcresponse = await getvidsrc(id); const vidsrcresponse = await getEmbedSu(id);
res.status(200).json(vidsrcresponse); res.status(200).json(vidsrcresponse);
} }
} catch (error) { } catch (error) {
+134 -1
View File
@@ -9,7 +9,9 @@
"version": "1.0.0", "version": "1.0.0",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"express": "^4.18.2" "express": "^4.18.2",
"fetch": "^1.1.0",
"node-fetch": "^3.3.2"
} }
}, },
"node_modules/accepts": { "node_modules/accepts": {
@@ -31,6 +33,17 @@
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
"license": "MIT" "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": { "node_modules/body-parser": {
"version": "1.20.2", "version": "1.20.2",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
@@ -119,6 +132,14 @@
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
"license": "MIT" "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": { "node_modules/debug": {
"version": "2.6.9", "version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -179,6 +200,14 @@
"node": ">= 0.8" "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": { "node_modules/es-define-property": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
@@ -257,6 +286,37 @@
"node": ">= 0.10.0" "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": { "node_modules/finalhandler": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
@@ -275,6 +335,17 @@
"node": ">= 0.8" "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": { "node_modules/forwarded": {
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
@@ -496,6 +567,41 @@
"node": ">= 0.6" "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": { "node_modules/object-inspect": {
"version": "1.13.2", "version": "1.13.2",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz",
@@ -548,6 +654,25 @@
"node": ">= 0.10" "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": { "node_modules/qs": {
"version": "6.11.0", "version": "6.11.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
@@ -756,6 +881,14 @@
"engines": { "engines": {
"node": ">= 0.8" "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
View File
@@ -11,6 +11,8 @@
"author": "Inside4ndroid Studios Ltd", "author": "Inside4ndroid Studios Ltd",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"express": "^4.18.2" "express": "^4.18.2",
"fetch": "^1.1.0",
"node-fetch": "^3.3.2"
} }
} }
+123
View File
@@ -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 "";
}
}
+126
View File
@@ -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"
};
-174
View File
@@ -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 "";
}
}