From 71c3692d74d0a794e43353087cc7bbf4d7fec64a Mon Sep 17 00:00:00 2001 From: Swakshan Date: Sun, 29 Dec 2024 13:56:09 +0530 Subject: [PATCH 1/6] extension(soaper): Added Popular and Latest --- javascript/anime/src/all/soaper.js | 129 +++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 javascript/anime/src/all/soaper.js diff --git a/javascript/anime/src/all/soaper.js b/javascript/anime/src/all/soaper.js new file mode 100644 index 00000000..19e8d0bd --- /dev/null +++ b/javascript/anime/src/all/soaper.js @@ -0,0 +1,129 @@ +const mangayomiSources = [{ + "name": "Soaper", + "lang": "all", + "baseUrl": "https://soaper.cc", + "apiUrl": "", + "iconUrl": "https://www.google.com/s2/favicons?sz=128&domain=https://soaper.cc/", + "typeSource": "multi", + "isManga": false, + "version": "0.0.1", + "dateFormat": "", + "dateFormatLocale": "", + "pkgPath": "" +}]; + +class DefaultExtension extends MProvider { + getHeaders(url) { + return { + "Referer": this.source.baseUrl, + "Origin": this.source.baseUrl + } + } + + async getPreference(key) { + const preferences = new SharedPreferences(); + return preferences.get(key); + } + + async request(slug) { + const baseUrl = await this.getPreference("pref_override_base_url") + var url = `${baseUrl}/${slug}` + var res = await new Client().get(url, this.getHeaders()); + var doc = new Document(res.body); + return doc + } + + async formatList(slug, page) { + const baseUrl = await this.getPreference("pref_override_base_url") + var doc = await this.request(`${slug}?page=${page}`); + var list = []; + var movies = doc.select(".thumbnail.text-center") + + for (var movie of movies) { + var linkSection = movie.selectFirst("div.img-group > a") + var link = linkSection.getHref; + var poster = linkSection.selectFirst("img").getSrc + var imageUrl = `${baseUrl}${poster}` + var name = movie.selectFirst("h5").text; + + list.push({ name, imageUrl, link }); + } + + var pagination = doc.select("ul.pagination > li") + var last_page_num = parseInt(pagination[pagination.length - 2].text); + var hasNextPage = page < last_page_num ? true : false; + return { list, hasNextPage } + } + + async filterList(year = "all", genre = "all", sort = "new", page = 1) { + + year = year == "all" ? "" : `/year/${year}` + genre = genre == "all" ? "" : `/cat/${genre}` + sort = sort == "new" ? "" : `/sort/${sort}` + + var slug = `${sort}${year}${genre}` + var movieList = await this.formatList(`movielist${slug}`, page); + var seriesList = await this.formatList(`tvlist${slug}`, page); + + var list = []; + var priority = await this.getPreference("pref_content_priority"); + if (priority === "series") { + list = [...seriesList.list, ...movieList.list]; + } else { + list = [...movieList.list, ...seriesList.list]; + } + + var hasNextPage = seriesList.hasNextPage || movieList.hasNextPage; + + return { list, hasNextPage } + } + + async getPopular(page) { + return await this.filterList("all", "all", "hot", page); + } + get supportsLatest() { + throw new Error("supportsLatest not implemented"); + } + async getLatestUpdates(page) { + return await this.filterList("all", "all", "new", page); + } + async search(query, page, filters) { + throw new Error("search not implemented"); + } + async getDetail(url) { + throw new Error("getDetail not implemented"); + } + // For anime episode video list + async getVideoList(url) { + throw new Error("getVideoList not implemented"); + } + // For manga chapter pages + async getPageList() { + throw new Error("getPageList not implemented"); + } + getFilterList() { + throw new Error("getFilterList not implemented"); + } + + getSourcePreferences() { + return [{ + "key": "pref_override_base_url", + "editTextPreference": { + "title": "Override base url", + "summary": "", + "value": "https://soaper.cc", + "dialogTitle": "Default url: https://soaper.cc", + } + }, { + key: 'pref_content_priority', + listPreference: { + title: 'Preferred content priority', + summary: 'Choose which type of content to show first', + valueIndex: 0, + entries: ["Movies", "Series"], + entryValues: ["movies", "series"] + } + }, + ]; + } +} From 22279cfce74e9c1dffa2f9720548f4ebe887c3d0 Mon Sep 17 00:00:00 2001 From: Swakshan Date: Tue, 31 Dec 2024 11:01:20 +0530 Subject: [PATCH 2/6] extension(soaper): Added Search --- javascript/anime/src/all/soaper.js | 46 ++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/javascript/anime/src/all/soaper.js b/javascript/anime/src/all/soaper.js index 19e8d0bd..07e8e9b5 100644 --- a/javascript/anime/src/all/soaper.js +++ b/javascript/anime/src/all/soaper.js @@ -6,10 +6,10 @@ const mangayomiSources = [{ "iconUrl": "https://www.google.com/s2/favicons?sz=128&domain=https://soaper.cc/", "typeSource": "multi", "isManga": false, - "version": "0.0.1", + "version": "0.0.2", "dateFormat": "", "dateFormatLocale": "", - "pkgPath": "" + "pkgPath": "anime/src/all/soaper.js" }]; class DefaultExtension extends MProvider { @@ -35,7 +35,8 @@ class DefaultExtension extends MProvider { async formatList(slug, page) { const baseUrl = await this.getPreference("pref_override_base_url") - var doc = await this.request(`${slug}?page=${page}`); + slug = parseInt(page) > 1 ? `${slug}?page=${page}` : slug + var doc = await this.request(slug); var list = []; var movies = doc.select(".thumbnail.text-center") @@ -49,14 +50,17 @@ class DefaultExtension extends MProvider { list.push({ name, imageUrl, link }); } - var pagination = doc.select("ul.pagination > li") - var last_page_num = parseInt(pagination[pagination.length - 2].text); - var hasNextPage = page < last_page_num ? true : false; + + var hasNextPage = false + if (slug.indexOf("search.html?") == -1) { + var pagination = doc.select("ul.pagination > li") + var last_page_num = parseInt(pagination[pagination.length - 2].text); + hasNextPage = page < last_page_num ? true : false; + } return { list, hasNextPage } } async filterList(year = "all", genre = "all", sort = "new", page = 1) { - year = year == "all" ? "" : `/year/${year}` genre = genre == "all" ? "" : `/cat/${genre}` sort = sort == "new" ? "" : `/sort/${sort}` @@ -87,9 +91,35 @@ class DefaultExtension extends MProvider { async getLatestUpdates(page) { return await this.filterList("all", "all", "new", page); } + + async search(query, page, filters) { - throw new Error("search not implemented"); + var seriesList = [] + var movieList = [] + var list = []; + + var res = await this.formatList(`search.html?keyword=${query}`, 1) + var movies = res["list"] + + for (var movie of movies) { + var link = movie.link + if (link.indexOf("/tv_") != -1) { + seriesList.push(movie); + } else { + movieList.push(movie); + } + } + + var priority = await this.getPreference("pref_content_priority"); + if (priority === "series") { + list = [...seriesList, ...movieList]; + } else { + list = [...movieList, ...seriesList]; + } + + return { list, hasNextPage: false } } + async getDetail(url) { throw new Error("getDetail not implemented"); } From 742b4f0e40b38a8329126b969a0490ca871577e0 Mon Sep 17 00:00:00 2001 From: Swakshan Date: Tue, 31 Dec 2024 13:13:03 +0530 Subject: [PATCH 3/6] extension(soaper): Added details --- javascript/anime/src/all/soaper.js | 46 ++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/javascript/anime/src/all/soaper.js b/javascript/anime/src/all/soaper.js index 07e8e9b5..543329de 100644 --- a/javascript/anime/src/all/soaper.js +++ b/javascript/anime/src/all/soaper.js @@ -6,7 +6,7 @@ const mangayomiSources = [{ "iconUrl": "https://www.google.com/s2/favicons?sz=128&domain=https://soaper.cc/", "typeSource": "multi", "isManga": false, - "version": "0.0.2", + "version": "0.0.3", "dateFormat": "", "dateFormatLocale": "", "pkgPath": "anime/src/all/soaper.js" @@ -42,7 +42,7 @@ class DefaultExtension extends MProvider { for (var movie of movies) { var linkSection = movie.selectFirst("div.img-group > a") - var link = linkSection.getHref; + var link = linkSection.getHref.substring(1,); var poster = linkSection.selectFirst("img").getSrc var imageUrl = `${baseUrl}${poster}` var name = movie.selectFirst("h5").text; @@ -50,7 +50,6 @@ class DefaultExtension extends MProvider { list.push({ name, imageUrl, link }); } - var hasNextPage = false if (slug.indexOf("search.html?") == -1) { var pagination = doc.select("ul.pagination > li") @@ -92,7 +91,6 @@ class DefaultExtension extends MProvider { return await this.filterList("all", "all", "new", page); } - async search(query, page, filters) { var seriesList = [] var movieList = [] @@ -103,7 +101,7 @@ class DefaultExtension extends MProvider { for (var movie of movies) { var link = movie.link - if (link.indexOf("/tv_") != -1) { + if (link.indexOf("tv_") != -1) { seriesList.push(movie); } else { movieList.push(movie); @@ -121,7 +119,43 @@ class DefaultExtension extends MProvider { } async getDetail(url) { - throw new Error("getDetail not implemented"); + var doc = await this.request(url); + + const baseUrl = await this.getPreference("pref_override_base_url") + var name = doc.selectFirst(".col-sm-12.col-lg-12.text-center").selectFirst("h4").text.trim() + var poster = doc.selectFirst(".thumbnail.text-center").selectFirst("img").getSrc + var imageUrl = `${baseUrl}${poster}` + + var description = doc.selectFirst("p#wrap").text.trim() + var link = `${baseUrl}/${url}` + + var chapters = [] + if (url.indexOf("tv_") != -1) { + var seasonList = doc.select(".alert.alert-info-ex.col-sm-12") + var seasonCount = seasonList.length + for (var season of seasonList) { + var eps = season.select(".col-sm-12.col-md-6.col-lg-4.myp1") + for (var ep of eps) { + var epLinkSection = ep.selectFirst("a") + var epLink = epLinkSection.getHref + var epName = epLinkSection.text + + chapters.push({ + name: `S${seasonCount}E${epName}`, + url: epLink, + }) + } + seasonCount--; + } + + } else { + chapters.push({ + name: "Movie", + url: url, + }) + } + + return { name, imageUrl, description, link, chapters } } // For anime episode video list async getVideoList(url) { From 5df0fe79832defb66b8c03ed33d48e2f502aeb79 Mon Sep 17 00:00:00 2001 From: Swakshan Date: Tue, 18 Mar 2025 19:01:56 +0530 Subject: [PATCH 4/6] extension(soaper): Added streams --- javascript/anime/src/all/soaper.js | 79 ++++++++++++++++++++++++------ 1 file changed, 64 insertions(+), 15 deletions(-) diff --git a/javascript/anime/src/all/soaper.js b/javascript/anime/src/all/soaper.js index 543329de..a6ce88b9 100644 --- a/javascript/anime/src/all/soaper.js +++ b/javascript/anime/src/all/soaper.js @@ -6,7 +6,7 @@ const mangayomiSources = [{ "iconUrl": "https://www.google.com/s2/favicons?sz=128&domain=https://soaper.cc/", "typeSource": "multi", "isManga": false, - "version": "0.0.3", + "version": "1.0.0", "dateFormat": "", "dateFormatLocale": "", "pkgPath": "anime/src/all/soaper.js" @@ -15,26 +15,36 @@ const mangayomiSources = [{ class DefaultExtension extends MProvider { getHeaders(url) { return { - "Referer": this.source.baseUrl, - "Origin": this.source.baseUrl + "Referer": url, + "Origin": url } } - async getPreference(key) { - const preferences = new SharedPreferences(); - return preferences.get(key); + getPreference(key) { + return new SharedPreferences().get(key); + } + + getBasueUrl(){ + return this.getPreference("pref_override_base_url") } async request(slug) { - const baseUrl = await this.getPreference("pref_override_base_url") + const baseUrl = this.getBasueUrl() var url = `${baseUrl}/${slug}` - var res = await new Client().get(url, this.getHeaders()); + var res = await new Client().get(url, this.getHeaders(baseUrl)); var doc = new Document(res.body); return doc } + async requestJSON(slug,data) { + const baseUrl = this.getBasueUrl() + var url = `${baseUrl}/${slug}` + var res = await new Client().post(url, this.getHeaders(baseUrl),data); + return JSON.parse(res.body); + } + async formatList(slug, page) { - const baseUrl = await this.getPreference("pref_override_base_url") + const baseUrl = this.getPreference("pref_override_base_url") slug = parseInt(page) > 1 ? `${slug}?page=${page}` : slug var doc = await this.request(slug); var list = []; @@ -45,7 +55,7 @@ class DefaultExtension extends MProvider { var link = linkSection.getHref.substring(1,); var poster = linkSection.selectFirst("img").getSrc var imageUrl = `${baseUrl}${poster}` - var name = movie.selectFirst("h5").text; + var name = movie.selectFirst("h5").selectFirst("a").text; list.push({ name, imageUrl, link }); } @@ -69,7 +79,7 @@ class DefaultExtension extends MProvider { var seriesList = await this.formatList(`tvlist${slug}`, page); var list = []; - var priority = await this.getPreference("pref_content_priority"); + var priority = this.getPreference("pref_content_priority"); if (priority === "series") { list = [...seriesList.list, ...movieList.list]; } else { @@ -108,7 +118,7 @@ class DefaultExtension extends MProvider { } } - var priority = await this.getPreference("pref_content_priority"); + var priority = this.getPreference("pref_content_priority"); if (priority === "series") { list = [...seriesList, ...movieList]; } else { @@ -121,7 +131,7 @@ class DefaultExtension extends MProvider { async getDetail(url) { var doc = await this.request(url); - const baseUrl = await this.getPreference("pref_override_base_url") + const baseUrl = this.getPreference("pref_override_base_url") var name = doc.selectFirst(".col-sm-12.col-lg-12.text-center").selectFirst("h4").text.trim() var poster = doc.selectFirst(".thumbnail.text-center").selectFirst("img").getSrc var imageUrl = `${baseUrl}${poster}` @@ -137,7 +147,7 @@ class DefaultExtension extends MProvider { var eps = season.select(".col-sm-12.col-md-6.col-lg-4.myp1") for (var ep of eps) { var epLinkSection = ep.selectFirst("a") - var epLink = epLinkSection.getHref + var epLink = epLinkSection.getHref.substring(1) var epName = epLinkSection.text chapters.push({ @@ -159,7 +169,46 @@ class DefaultExtension extends MProvider { } // For anime episode video list async getVideoList(url) { - throw new Error("getVideoList not implemented"); + var body = await this.request(url) + var baseUrl = this.getBasueUrl() + + var eId = body.selectFirst("#hId").attr('value') + var hIsW = body.selectFirst("#hIsW").attr('value') + var apiType = url[0].toUpperCase() + + var streams = [] + var servers = [0,1] + for(var serverNum of servers){ + var serverName = body.selectFirst(`#server_button_${serverNum}`).text + if(serverName.length < 1) continue; + var data ={ + pass:eId, + param:"", + extra:"1", + e2:hIsW, + server: ""+serverNum, + } + var res = await this.requestJSON(`home/index/Get${apiType}InfoAjax`,data) + + var streamUrl = baseUrl+res.val + var subs = [] + for (var sub of res.subs) { + subs.push({ + file: baseUrl+sub.path, + label: sub.name + }) + } + streams.push({ + url: streamUrl, + originalUrl: streamUrl, + quality: serverName, + subtitles:subs + }); + + + } + return streams + } // For manga chapter pages async getPageList() { From cd813d04cb9fd0f3d369194ea1c402e5c6026f2a Mon Sep 17 00:00:00 2001 From: Swakshan Date: Tue, 18 Mar 2025 19:02:41 +0530 Subject: [PATCH 5/6] extension(soaper): Update preference --- javascript/anime/src/all/soaper.js | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/javascript/anime/src/all/soaper.js b/javascript/anime/src/all/soaper.js index a6ce88b9..fdb38402 100644 --- a/javascript/anime/src/all/soaper.js +++ b/javascript/anime/src/all/soaper.js @@ -6,7 +6,7 @@ const mangayomiSources = [{ "iconUrl": "https://www.google.com/s2/favicons?sz=128&domain=https://soaper.cc/", "typeSource": "multi", "isManga": false, - "version": "1.0.0", + "version": "1.0.1", "dateFormat": "", "dateFormatLocale": "", "pkgPath": "anime/src/all/soaper.js" @@ -25,7 +25,7 @@ class DefaultExtension extends MProvider { } getBasueUrl(){ - return this.getPreference("pref_override_base_url") + return this.getPreference("soaper_override_base_url") } async request(slug) { @@ -44,7 +44,7 @@ class DefaultExtension extends MProvider { } async formatList(slug, page) { - const baseUrl = this.getPreference("pref_override_base_url") + const baseUrl = this.getPreference("soaper_override_base_url") slug = parseInt(page) > 1 ? `${slug}?page=${page}` : slug var doc = await this.request(slug); var list = []; @@ -79,7 +79,7 @@ class DefaultExtension extends MProvider { var seriesList = await this.formatList(`tvlist${slug}`, page); var list = []; - var priority = this.getPreference("pref_content_priority"); + var priority = this.getPreference("soaper_content_priority"); if (priority === "series") { list = [...seriesList.list, ...movieList.list]; } else { @@ -118,7 +118,7 @@ class DefaultExtension extends MProvider { } } - var priority = this.getPreference("pref_content_priority"); + var priority = this.getPreference("soaper_content_priority"); if (priority === "series") { list = [...seriesList, ...movieList]; } else { @@ -131,7 +131,7 @@ class DefaultExtension extends MProvider { async getDetail(url) { var doc = await this.request(url); - const baseUrl = this.getPreference("pref_override_base_url") + const baseUrl = this.getPreference("soaper_override_base_url") var name = doc.selectFirst(".col-sm-12.col-lg-12.text-center").selectFirst("h4").text.trim() var poster = doc.selectFirst(".thumbnail.text-center").selectFirst("img").getSrc var imageUrl = `${baseUrl}${poster}` @@ -220,15 +220,16 @@ class DefaultExtension extends MProvider { getSourcePreferences() { return [{ - "key": "pref_override_base_url", - "editTextPreference": { - "title": "Override base url", - "summary": "", - "value": "https://soaper.cc", - "dialogTitle": "Default url: https://soaper.cc", + "key": "soaper_override_base_url", + editTextPreference: { + title: "Override base url", + summary: "Default: https://soaper.cc", + value: "https://soaper.cc", + dialogTitle: "Override base url", + dialogMessage: "", } }, { - key: 'pref_content_priority', + key: 'soaper_content_priority', listPreference: { title: 'Preferred content priority', summary: 'Choose which type of content to show first', From ef7bc892a4f93e96bdad85e65ba5b0aa9a122194 Mon Sep 17 00:00:00 2001 From: Swakshan Date: Wed, 19 Mar 2025 16:31:06 +0530 Subject: [PATCH 6/6] extension(soaper): Added download server --- javascript/anime/src/all/soaper.js | 60 ++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/javascript/anime/src/all/soaper.js b/javascript/anime/src/all/soaper.js index fdb38402..ba4adac1 100644 --- a/javascript/anime/src/all/soaper.js +++ b/javascript/anime/src/all/soaper.js @@ -6,7 +6,7 @@ const mangayomiSources = [{ "iconUrl": "https://www.google.com/s2/favicons?sz=128&domain=https://soaper.cc/", "typeSource": "multi", "isManga": false, - "version": "1.0.1", + "version": "1.0.2", "dateFormat": "", "dateFormatLocale": "", "pkgPath": "anime/src/all/soaper.js" @@ -24,7 +24,7 @@ class DefaultExtension extends MProvider { return new SharedPreferences().get(key); } - getBasueUrl(){ + getBasueUrl() { return this.getPreference("soaper_override_base_url") } @@ -36,10 +36,10 @@ class DefaultExtension extends MProvider { return doc } - async requestJSON(slug,data) { + async requestJSON(slug, data) { const baseUrl = this.getBasueUrl() var url = `${baseUrl}/${slug}` - var res = await new Client().post(url, this.getHeaders(baseUrl),data); + var res = await new Client().post(url, this.getHeaders(baseUrl), data); return JSON.parse(res.body); } @@ -171,30 +171,31 @@ class DefaultExtension extends MProvider { async getVideoList(url) { var body = await this.request(url) var baseUrl = this.getBasueUrl() + var streams = [] + // Traditional servers var eId = body.selectFirst("#hId").attr('value') var hIsW = body.selectFirst("#hIsW").attr('value') var apiType = url[0].toUpperCase() - var streams = [] - var servers = [0,1] - for(var serverNum of servers){ + var servers = [0, 1] + for (var serverNum of servers) { var serverName = body.selectFirst(`#server_button_${serverNum}`).text - if(serverName.length < 1) continue; - var data ={ - pass:eId, - param:"", - extra:"1", - e2:hIsW, - server: ""+serverNum, + if (serverName.length < 1) continue; + var data = { + pass: eId, + param: "", + extra: "1", + e2: hIsW, + server: "" + serverNum, } - var res = await this.requestJSON(`home/index/Get${apiType}InfoAjax`,data) - - var streamUrl = baseUrl+res.val + var res = await this.requestJSON(`home/index/Get${apiType}InfoAjax`, data) + + var streamUrl = baseUrl + res.val var subs = [] for (var sub of res.subs) { subs.push({ - file: baseUrl+sub.path, + file: baseUrl + sub.path, label: sub.name }) } @@ -202,13 +203,32 @@ class DefaultExtension extends MProvider { url: streamUrl, originalUrl: streamUrl, quality: serverName, - subtitles:subs + subtitles: subs }); + } + // Download servers + var modal_footer = body.select(".modal-footer > a") + if (modal_footer.length > 0) { + modal_footer.reverse() + for (var item of modal_footer) { + var dSlug = item.getHref + var dBody = await this.request(dSlug) + + var res = dBody.selectFirst("#res").attr('value') + var mb = dBody.selectFirst("#mb").attr('value') + var streamLink = dBody.selectFirst("#link").attr('value') + + streams.push({ + url: streamLink, + originalUrl: streamLink, + quality: `Download Server: ${res} [${mb}]`, + }); + } } return streams - + } // For manga chapter pages async getPageList() {