From 754f8f95b41b1382b35f47106d5f60b0c70b4aab Mon Sep 17 00:00:00 2001 From: Swakshan Date: Fri, 3 Jan 2025 00:23:51 +0530 Subject: [PATCH 1/5] extension(autoembed): Added mulitple stream source --- javascript/anime/src/all/autoembed.js | 117 ++++++++++++++++++++------ 1 file changed, 93 insertions(+), 24 deletions(-) diff --git a/javascript/anime/src/all/autoembed.js b/javascript/anime/src/all/autoembed.js index 6713f666..2f76e4d0 100644 --- a/javascript/anime/src/all/autoembed.js +++ b/javascript/anime/src/all/autoembed.js @@ -6,7 +6,7 @@ const mangayomiSources = [{ "iconUrl": "https://www.google.com/s2/favicons?sz=64&domain=https://autoembed.cc/", "typeSource": "multi", "isManga": false, - "version": "1.0.3", + "version": "1.1.0", "dateFormat": "", "dateFormatLocale": "", "pkgPath": "anime/src/all/autoembed.js" @@ -129,7 +129,7 @@ class DefaultExtension extends MProvider { if (release < dateNow) { var episodeNum = video.episode var name = `S${seasonNum}:E${episodeNum} - ${video.name}` - var eplink = `${link}/${seasonNum}/${episodeNum}` + var eplink = `${link}||${seasonNum}||${episodeNum}` chaps.push({ name: name, @@ -152,7 +152,7 @@ class DefaultExtension extends MProvider { chaps.reverse(); return item; } - async extractStreams(url) { + async extractStreams(url, hdr = {}) { const response = await new Client().get(url); const body = response.body; const lines = body.split('\n'); @@ -161,12 +161,14 @@ class DefaultExtension extends MProvider { for (let i = 0; i < lines.length; i++) { if (lines[i].startsWith('#EXT-X-STREAM-INF:')) { const resolution = lines[i].match(/RESOLUTION=(\d+x\d+)/)[1]; - const m3u8Url = lines[i + 1].trim(); - + var m3u8Url = lines[i + 1].trim(); + m3u8Url = + m3u8Url.replace("./", `${url}/`) streams.push({ url: m3u8Url, originalUrl: m3u8Url, quality: resolution, + headers: hdr }); } } @@ -192,31 +194,90 @@ class DefaultExtension extends MProvider { return [...sortedStreams, ...copyStreams] } + async getSubtitleList(id, s, e) { + var api = `https://sub.wyzie.ru/search?id=${id}` + if (s != "0") api = `${api}&season=${s}&episode=${e}` + var response = await new Client().get(api); + var body = JSON.parse(response.body); + + var subs = [] + for (var sub of body) { + subs.push({ + file: sub.url + , + label: sub.display + }) + } + + return subs + } + // For anime episode video list async getVideoList(url) { + var streamAPI = parseInt(await this.getPreference("pref_stream_source")) + var parts = url.split("||"); var media_type = parts[0]; var id = parts[1]; - var api = `${this.source.apiUrl}/api/getVideoSource?type=${media_type}&id=${id}` - const response = await new Client().get(api, this.getHeaders()); - const body = JSON.parse(response.body); + var tmdb = id + var streams = [] + var subtitles = [] + switch (streamAPI) { + case 2: { + var s = "0" + var e = "0" + if (media_type == "tv") { + s = parts[2] + e = parts[3] + id = `${id}/${s}/${e}` + } + var api = `https://play2.123embed.net/server/3?path=/${media_type}/${id}` + var response = await new Client().get(api); + var body = JSON.parse(response.body); - if (response.statusCode == 404) { - throw new Error("Video unavailable"); + if (response.statusCode != 200) { + throw new Error("Video unavailable"); + } + var link = body.playlist[0].file + subtitles = await this.getSubtitleList(tmdb, s, e) + streams.push({ + url: link, + originalUrl: link, + quality: "auto", + headers: { "Origin": "https://play2.123embed.net" } + , + subtitles: subtitles + }); + + break; + } + default: { + if (media_type == "tv") { + id = `${id}/${parts[2]}/${parts[3]}` + } + var api = `${this.source.apiUrl}/api/getVideoSource?type=${media_type}&id=${id}` + var response = await new Client().get(api, this.getHeaders()); + var body = JSON.parse(response.body); + + if (response.statusCode != 200) { + throw new Error("Video unavailable"); + } + var link = body.videoSource + subtitles = + body.subtitles + streams = await this.extractStreams(link); + streams.push({ + url: link, + originalUrl: link, + quality: "auto", + subtitles: subtitles, + }); + streams = await this.sortStreams(streams); + break; + } } - var link = body.videoSource - - var subtitles = body.subtitles - var streams = await this.extractStreams(link); - streams.push({ - url: link, - originalUrl: link, - quality: "auto", - subtitles: subtitles, - }); - - return await this.sortStreams(streams); + return streams } // For manga chapter pages async getPageList() { @@ -255,8 +316,16 @@ class DefaultExtension extends MProvider { entryValues: ["movies", "series"] } }, - - + { + key: 'pref_stream_source', + listPreference: { + title: 'Preferred stream source', + summary: '', + valueIndex: 0, + entries: ["tom.autoembed.cc", "123embed.net"], + entryValues: ["1", "2"] + } + }, ]; } From 42b1f0492f6e9f93a4536c2b16c50d7160c486f7 Mon Sep 17 00:00:00 2001 From: Swakshan Date: Fri, 3 Jan 2025 13:10:02 +0530 Subject: [PATCH 2/5] extension(autoembed): Misc --- javascript/anime/src/all/autoembed.js | 63 +++++++++++++++++---------- 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/javascript/anime/src/all/autoembed.js b/javascript/anime/src/all/autoembed.js index 2f76e4d0..157c7e2d 100644 --- a/javascript/anime/src/all/autoembed.js +++ b/javascript/anime/src/all/autoembed.js @@ -6,7 +6,7 @@ const mangayomiSources = [{ "iconUrl": "https://www.google.com/s2/favicons?sz=64&domain=https://autoembed.cc/", "typeSource": "multi", "isManga": false, - "version": "1.1.0", + "version": "1.1.1", "dateFormat": "", "dateFormatLocale": "", "pkgPath": "anime/src/all/autoembed.js" @@ -152,18 +152,22 @@ class DefaultExtension extends MProvider { chaps.reverse(); return item; } - async extractStreams(url, hdr = {}) { + async extractStreams(url, lang = "", hdr = {}) { const response = await new Client().get(url); const body = response.body; const lines = body.split('\n'); - var streams = []; + var streams = [{ + url: url, + originalUrl: url, + quality: "auto", + }]; for (let i = 0; i < lines.length; i++) { if (lines[i].startsWith('#EXT-X-STREAM-INF:')) { - const resolution = lines[i].match(/RESOLUTION=(\d+x\d+)/)[1]; + var resolution = lines[i].match(/RESOLUTION=(\d+x\d+)/)[1]; + resolution = `${lang} ${resolution}` var m3u8Url = lines[i + 1].trim(); - m3u8Url = - m3u8Url.replace("./", `${url}/`) + m3u8Url = m3u8Url.replace("./", `${url}/`) streams.push({ url: m3u8Url, originalUrl: m3u8Url, @@ -172,9 +176,29 @@ class DefaultExtension extends MProvider { }); } } + return await this.sortStreams(streams); + + } + + async splitStreams(url, lang = "", hdr = {}) { + var streams = []; + var quality = ["auto", "360", "480", "720", "1080"] + for (var q of quality) { + if (q != "auto") { + url = url.replace("index.m3u8", `${q}/index.m3u8`) + q = `${q}p` + } + streams.push({ + url: url, + originalUrl: url, + quality: `${lang} - ${q}`, + headers: hdr + }); + } return streams; } + async sortStreams(streams) { var sortedStreams = []; @@ -203,8 +227,7 @@ class DefaultExtension extends MProvider { var subs = [] for (var sub of body) { subs.push({ - file: sub.url - , + file: sub.url, label: sub.display }) } @@ -215,7 +238,7 @@ class DefaultExtension extends MProvider { // For anime episode video list async getVideoList(url) { var streamAPI = parseInt(await this.getPreference("pref_stream_source")) - + var parts = url.split("||"); var media_type = parts[0]; var id = parts[1]; @@ -233,22 +256,20 @@ class DefaultExtension extends MProvider { } var api = `https://play2.123embed.net/server/3?path=/${media_type}/${id}` var response = await new Client().get(api); - var body = JSON.parse(response.body); if (response.statusCode != 200) { throw new Error("Video unavailable"); } + + var body = JSON.parse(response.body); var link = body.playlist[0].file subtitles = await this.getSubtitleList(tmdb, s, e) streams.push({ url: link, originalUrl: link, quality: "auto", - headers: { "Origin": "https://play2.123embed.net" } - , - subtitles: subtitles + headers: { "Origin": "https://play2.123embed.net" }, }); - break; } default: { @@ -257,26 +278,20 @@ class DefaultExtension extends MProvider { } var api = `${this.source.apiUrl}/api/getVideoSource?type=${media_type}&id=${id}` var response = await new Client().get(api, this.getHeaders()); - var body = JSON.parse(response.body); if (response.statusCode != 200) { throw new Error("Video unavailable"); } + + var body = JSON.parse(response.body); var link = body.videoSource - subtitles = - body.subtitles + subtitles = body.subtitles streams = await this.extractStreams(link); - streams.push({ - url: link, - originalUrl: link, - quality: "auto", - subtitles: subtitles, - }); - streams = await this.sortStreams(streams); break; } } + streams[0].subtitles = subtitles return streams } // For manga chapter pages From c4bc4d760c16619045263e1035193a2af1285c63 Mon Sep 17 00:00:00 2001 From: Swakshan Date: Fri, 3 Jan 2025 13:12:47 +0530 Subject: [PATCH 3/5] extension(autoembed): Added autoembed - Indian languages server --- javascript/anime/src/all/autoembed.js | 41 +++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/javascript/anime/src/all/autoembed.js b/javascript/anime/src/all/autoembed.js index 157c7e2d..08710fe3 100644 --- a/javascript/anime/src/all/autoembed.js +++ b/javascript/anime/src/all/autoembed.js @@ -6,7 +6,7 @@ const mangayomiSources = [{ "iconUrl": "https://www.google.com/s2/favicons?sz=64&domain=https://autoembed.cc/", "typeSource": "multi", "isManga": false, - "version": "1.1.1", + "version": "1.1.2", "dateFormat": "", "dateFormatLocale": "", "pkgPath": "anime/src/all/autoembed.js" @@ -272,6 +272,41 @@ class DefaultExtension extends MProvider { }); break; } + + case 3: { + var s = "0" + var e = "0" + if (media_type == "tv") { + s = parts[2] + e = parts[3] + id = `${id}&s=${s}&e=${e}` + } + var api = `https://autoembed.cc/embed/player.php?id=${id}` + var response = await new Client().get(api); + + if (response.statusCode != 200) { + throw new Error("Video unavailable"); + } + var body = response.body + var sKey = '"file": ' + var eKey = "]});" + var start = body.indexOf(sKey) + sKey.length + if (start < 0) { + throw new Error("Video unavailable"); + } + var end = body.substring(start,).indexOf(eKey) + start - 1 + var strms = JSON.parse(body.substring(start, end) + "]") + for (var strm of strms) { + var link = strm.file + var lang = strm.title + var streamSplit = await this.splitStreams(link, lang); + streams = [...streams, ...streamSplit] + } + subtitles = await this.getSubtitleList(tmdb, s, e) + + break; + } + default: { if (media_type == "tv") { id = `${id}/${parts[2]}/${parts[3]}` @@ -337,8 +372,8 @@ class DefaultExtension extends MProvider { title: 'Preferred stream source', summary: '', valueIndex: 0, - entries: ["tom.autoembed.cc", "123embed.net"], - entryValues: ["1", "2"] + entries: ["tom.autoembed.cc", "123embed.net", "autoembed.cc - Indian languages"], + entryValues: ["1", "2", "3"] } }, ]; From 9f97d0d48638f90801cb56919d546b2ab1962bda Mon Sep 17 00:00:00 2001 From: Swakshan Date: Fri, 3 Jan 2025 15:24:12 +0530 Subject: [PATCH 4/5] extension(autembed): Added flicky server --- javascript/anime/src/all/autoembed.js | 68 ++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 12 deletions(-) diff --git a/javascript/anime/src/all/autoembed.js b/javascript/anime/src/all/autoembed.js index 08710fe3..35b0fc7f 100644 --- a/javascript/anime/src/all/autoembed.js +++ b/javascript/anime/src/all/autoembed.js @@ -6,7 +6,7 @@ const mangayomiSources = [{ "iconUrl": "https://www.google.com/s2/favicons?sz=64&domain=https://autoembed.cc/", "typeSource": "multi", "isManga": false, - "version": "1.1.2", + "version": "1.1.3", "dateFormat": "", "dateFormatLocale": "", "pkgPath": "anime/src/all/autoembed.js" @@ -176,7 +176,7 @@ class DefaultExtension extends MProvider { }); } } - return await this.sortStreams(streams); + return streams } @@ -184,13 +184,14 @@ class DefaultExtension extends MProvider { var streams = []; var quality = ["auto", "360", "480", "720", "1080"] for (var q of quality) { + var link = url if (q != "auto") { - url = url.replace("index.m3u8", `${q}/index.m3u8`) + link = link.replace("index.m3u8", `${q}/index.m3u8`) q = `${q}p` } streams.push({ - url: url, - originalUrl: url, + url: link, + originalUrl: link, quality: `${lang} - ${q}`, headers: hdr }); @@ -263,7 +264,6 @@ class DefaultExtension extends MProvider { var body = JSON.parse(response.body); var link = body.playlist[0].file - subtitles = await this.getSubtitleList(tmdb, s, e) streams.push({ url: link, originalUrl: link, @@ -282,6 +282,7 @@ class DefaultExtension extends MProvider { id = `${id}&s=${s}&e=${e}` } var api = `https://autoembed.cc/embed/player.php?id=${id}` + var response = await new Client().get(api); if (response.statusCode != 200) { @@ -290,10 +291,12 @@ class DefaultExtension extends MProvider { var body = response.body var sKey = '"file": ' var eKey = "]});" - var start = body.indexOf(sKey) + sKey.length + var start = body.indexOf(sKey) if (start < 0) { throw new Error("Video unavailable"); } + start += sKey.length + var end = body.substring(start,).indexOf(eKey) + start - 1 var strms = JSON.parse(body.substring(start, end) + "]") for (var strm of strms) { @@ -302,7 +305,41 @@ class DefaultExtension extends MProvider { var streamSplit = await this.splitStreams(link, lang); streams = [...streams, ...streamSplit] } - subtitles = await this.getSubtitleList(tmdb, s, e) + + break; + } + case 4: { + var s = "0" + var e = "0" + if (media_type == "tv") { + s = parts[2] + e = parts[3] + id = `${id}&season=${s}&episode=${e}` + } + var api = `https://player.flicky.host/Server-main.php?id=${id}` + var response = await new Client().get(api, { "Referer": "https://flicky.host/" }); + + if (response.statusCode != 200) { + throw new Error("Video unavailable"); + } + var body = response.body + var sKey = 'streams = ' + var eKey = "];" + var start = body.indexOf(sKey) + if (start < 0) { + throw new Error("Video unavailable"); + } + start += sKey.length + + var end = body.substring(start,).indexOf(eKey) + start + 1 + var strms = JSON.parse(body.substring(start, end)) + + for (var strm of strms) { + var link = strm.url + var lang = strm.language + var streamSplit = await this.splitStreams(link, lang); + streams = [...streams, ...streamSplit] + } break; } @@ -326,8 +363,15 @@ class DefaultExtension extends MProvider { } } - streams[0].subtitles = subtitles - return streams + if (streams.length < 1) { + throw new Error("Video unavailable"); + } + + if (subtitles.length < 1) { + streams[0].subtitles = await this.getSubtitleList(tmdb, s, e) + } + + return await this.sortStreams(streams) } // For manga chapter pages async getPageList() { @@ -372,8 +416,8 @@ class DefaultExtension extends MProvider { title: 'Preferred stream source', summary: '', valueIndex: 0, - entries: ["tom.autoembed.cc", "123embed.net", "autoembed.cc - Indian languages"], - entryValues: ["1", "2", "3"] + entries: ["tom.autoembed.cc", "123embed.net", "autoembed.cc - Indian languages", "flicky.host - Indian languages"], + entryValues: ["1", "2", "3", "4"] } }, ]; From 8229e582ec7eff3dbc532b2d8bc448a70a8116a9 Mon Sep 17 00:00:00 2001 From: Swakshan Date: Fri, 3 Jan 2025 18:30:48 +0530 Subject: [PATCH 5/5] extension(autembed): Added vidapi server --- javascript/anime/src/all/autoembed.js | 33 ++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/javascript/anime/src/all/autoembed.js b/javascript/anime/src/all/autoembed.js index 35b0fc7f..b9a92841 100644 --- a/javascript/anime/src/all/autoembed.js +++ b/javascript/anime/src/all/autoembed.js @@ -6,7 +6,7 @@ const mangayomiSources = [{ "iconUrl": "https://www.google.com/s2/favicons?sz=64&domain=https://autoembed.cc/", "typeSource": "multi", "isManga": false, - "version": "1.1.3", + "version": "1.1.4", "dateFormat": "", "dateFormatLocale": "", "pkgPath": "anime/src/all/autoembed.js" @@ -152,6 +152,8 @@ class DefaultExtension extends MProvider { chaps.reverse(); return item; } + + // Extracts the streams url for different resolutions from a hls stream. async extractStreams(url, lang = "", hdr = {}) { const response = await new Client().get(url); const body = response.body; @@ -180,6 +182,7 @@ class DefaultExtension extends MProvider { } + // For some streams, we can form stream url using a default template. async splitStreams(url, lang = "", hdr = {}) { var streams = []; var quality = ["auto", "360", "480", "720", "1080"] @@ -199,7 +202,7 @@ class DefaultExtension extends MProvider { return streams; } - + // Sorts streams based on user preference. async sortStreams(streams) { var sortedStreams = []; @@ -219,6 +222,7 @@ class DefaultExtension extends MProvider { return [...sortedStreams, ...copyStreams] } + // Gets subtitles based on TMDB id. async getSubtitleList(id, s, e) { var api = `https://sub.wyzie.ru/search?id=${id}` if (s != "0") api = `${api}&season=${s}&episode=${e}` @@ -272,7 +276,6 @@ class DefaultExtension extends MProvider { }); break; } - case 3: { var s = "0" var e = "0" @@ -343,6 +346,23 @@ class DefaultExtension extends MProvider { break; } + case 5: { + if (media_type == "tv") { + id = `${id}/${parts[2]}/${parts[3]}` + } + var api = `https://vidapi.click/api/video/${media_type}/${id}` + var response = await new Client().get(api); + + if (response.statusCode != 200) { + throw new Error("Video unavailable"); + } + + var body = JSON.parse(response.body); + var link = body.sources[0].file + subtitles = body.tracks + streams = await this.extractStreams(link); + break; + } default: { if (media_type == "tv") { @@ -368,8 +388,9 @@ class DefaultExtension extends MProvider { } if (subtitles.length < 1) { - streams[0].subtitles = await this.getSubtitleList(tmdb, s, e) + subtitles = await this.getSubtitleList(tmdb, s, e) } + streams[0].subtitles = subtitles return await this.sortStreams(streams) } @@ -416,8 +437,8 @@ class DefaultExtension extends MProvider { title: 'Preferred stream source', summary: '', valueIndex: 0, - entries: ["tom.autoembed.cc", "123embed.net", "autoembed.cc - Indian languages", "flicky.host - Indian languages"], - entryValues: ["1", "2", "3", "4"] + entries: ["tom.autoembed.cc", "123embed.net", "autoembed.cc - Indian languages", "flicky.host - Indian languages", "vidapi.click"], + entryValues: ["1", "2", "3", "4", "5"] } }, ];