From b7a21a072229969cc687b1e80d82e850a377b5c1 Mon Sep 17 00:00:00 2001 From: Swakshan Date: Sat, 15 Mar 2025 22:08:58 +0530 Subject: [PATCH 1/5] extension(animegg): Added popular and latest --- javascript/anime/src/en/animegg.js | 141 +++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 javascript/anime/src/en/animegg.js diff --git a/javascript/anime/src/en/animegg.js b/javascript/anime/src/en/animegg.js new file mode 100644 index 00000000..27472f1d --- /dev/null +++ b/javascript/anime/src/en/animegg.js @@ -0,0 +1,141 @@ +const mangayomiSources = [{ + "name": "AnimeGG", + "lang": "en", + "baseUrl": "https://www.animegg.org", + "apiUrl": "", + "iconUrl": "https://www.google.com/s2/favicons?sz=256&domain=https://www.animegg.org/", + "typeSource": "single", + "itemType": 1, + "version": "0.0.1", + "pkgPath": "anime/src/en/animegg.js" +}]; + +class DefaultExtension extends MProvider { + + constructor() { + super(); + this.client = new Client(); + } + + getHeaders(url) { + return { + Referer: this.getSourcePreferences.baseUrl, + Origin: this.getSourcePreferences.baseUrl + } + } + + getPreference(key) { + return new SharedPreferences().get(key); + } + + async request(slug) { + var url = `${this.source.baseUrl}${slug}` + var res = await this.client.get(url, this.getHeaders()); + return new Document(res.body); + } + + async fetchPopularnLatest(slug) { + var body = await this.request(slug) + var items = body.select("li.fea") + var list = [] + var hasNextPage = true + if (items.length > 0) { + for (var item of items) { + var imageUrl = item.selectFirst('img').getSrc + var link = item.selectFirst('a').getHref + var name = item.selectFirst(".rightpop").text + list.push({ + name, + imageUrl, + link + }); + + } + } + else { + hasNextPage = false + } + return { list, hasNextPage } + } + + async getPopular(page) { + var start = (page - 1) * 25; + var limit = start + 25; + + var category = "" + var pop = parseInt(this.getPreference("animegg_popular_category")) + switch (pop) { + case 1: { + category = "sortBy=createdAt&sortDirection=DESC&"; + break; + } + case 2: { + category = "ongoing=true&"; + break; + } + case 3: { + category = "ongoing=false&"; + break; + } + case 4: { + category = "sortBy=sortLetter&sortDirection=ASC&"; + break; + } + + } + var slug = `/popular-series?${category}start=${start}&limit=${limit}` + return await this.fetchPopularnLatest(slug) + + + } + get supportsLatest() { + throw new Error("supportsLatest not implemented"); + } + async getLatestUpdates(page) { + var start = (page - 1) * 25; + var limit = start + 25; + + var slug = `/releases?start=${start}&limit=${limit}` + return await this.fetchPopularnLatest(slug) + + } + async search(query, page, filters) { + throw new Error("search not implemented"); + } + async getDetail(url) { + throw new Error("getDetail not implemented"); + } + // For novel html content + async getHtmlContent(url) { + throw new Error("getHtmlContent not implemented"); + } + // Clean html up for reader + async cleanHtmlContent(html) { + throw new Error("cleanHtmlContent not implemented"); + } + // For anime episode video list + async getVideoList(url) { + throw new Error("getVideoList not implemented"); + } + // For manga chapter pages + async getPageList(url) { + throw new Error("getPageList not implemented"); + } + getFilterList() { + throw new Error("getFilterList not implemented"); + } + getSourcePreferences() { + return [ + { + key: "animegg_popular_category", + listPreference: { + title: 'Preferred popular category', + summary: '', + valueIndex: 0, + entries: ["Popular", "Newest", "Ongoing", "Completed", "Alphabetical"], + entryValues: ["0", "1", "2", "3", "4"] + } + } + ] + } +} From 959e6fea3da14b27dc4642ecac9e1bb17fb50cdf Mon Sep 17 00:00:00 2001 From: Swakshan Date: Sat, 15 Mar 2025 22:21:58 +0530 Subject: [PATCH 2/5] extension(animegg): Added search --- javascript/anime/src/en/animegg.js | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/javascript/anime/src/en/animegg.js b/javascript/anime/src/en/animegg.js index 27472f1d..6edf18a8 100644 --- a/javascript/anime/src/en/animegg.js +++ b/javascript/anime/src/en/animegg.js @@ -6,7 +6,7 @@ const mangayomiSources = [{ "iconUrl": "https://www.google.com/s2/favicons?sz=256&domain=https://www.animegg.org/", "typeSource": "single", "itemType": 1, - "version": "0.0.1", + "version": "0.0.2", "pkgPath": "anime/src/en/animegg.js" }]; @@ -100,7 +100,23 @@ class DefaultExtension extends MProvider { } async search(query, page, filters) { - throw new Error("search not implemented"); + var slug = `/search?q=${query}` + var body = await this.request(slug) + var items = body.select(".moose.page > a") + var list = [] + for (var item of items) { + var imageUrl = item.selectFirst('img').getSrc + var link = item.getHref + var name = item.selectFirst("h2").text + list.push({ + name, + imageUrl, + link + }); + + } + + return { list, hasNextPage:false } } async getDetail(url) { throw new Error("getDetail not implemented"); From e1699fc0845b675fdac60590f8d98b36fe7420e6 Mon Sep 17 00:00:00 2001 From: Swakshan Date: Sun, 16 Mar 2025 17:27:05 +0530 Subject: [PATCH 3/5] extension(animegg): Added details --- javascript/anime/src/en/animegg.js | 51 ++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/javascript/anime/src/en/animegg.js b/javascript/anime/src/en/animegg.js index 6edf18a8..df6c3454 100644 --- a/javascript/anime/src/en/animegg.js +++ b/javascript/anime/src/en/animegg.js @@ -6,7 +6,7 @@ const mangayomiSources = [{ "iconUrl": "https://www.google.com/s2/favicons?sz=256&domain=https://www.animegg.org/", "typeSource": "single", "itemType": 1, - "version": "0.0.2", + "version": "0.0.3", "pkgPath": "anime/src/en/animegg.js" }]; @@ -118,8 +118,55 @@ class DefaultExtension extends MProvider { return { list, hasNextPage:false } } + + statusCode(status) { + return { + "Ongoing": 0, + "Completed": 1, + }[status] ?? 5; + } + async getDetail(url) { - throw new Error("getDetail not implemented"); + var link = this.source.baseUrl + url; + + var body = await this.request(url) + + var media = body.selectFirst(".media") + var title = media.selectFirst("h1").text + var spans = media.selectFirst("p.infoami").select("span") + var statusText = spans[spans.length - 1].text.replace("Status: ",'') + var status = this.statusCode(statusText) + + + var tagscat = media.select(".tagscat > li") + var genre = [] + tagscat.forEach(tag => genre.push(tag.text)) + var description = body.selectFirst("p.ptext").text + var chapters = [] + + var episodesList = body.select(".newmanga > li") + episodesList.forEach(ep => { + var epTitle = ep.selectFirst('i.anititle').text + var epNumber = ep.selectFirst('strong').text.replace(title,"Episode") + var epName = epNumber == epTitle?epNumber:`${epNumber} - ${epTitle}` + var epUrl = ep.selectFirst("a").getHref + + var scanlator = ""; + var type = ep.select("span.btn-xs") + type.forEach(t => { + scanlator += t.text + ", "; + + }) + scanlator = scanlator.slice(0, -2); + + chapters.push({ name: epName, url: epUrl,scanlator}) + }) + + + return { description, status, genre, chapters, link } + + + } // For novel html content async getHtmlContent(url) { From 52901bc9000270535d02764383f75b70fa801642 Mon Sep 17 00:00:00 2001 From: Swakshan Date: Sun, 16 Mar 2025 17:32:13 +0530 Subject: [PATCH 4/5] extension(animegg): update name & link logic --- javascript/anime/src/en/animegg.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/javascript/anime/src/en/animegg.js b/javascript/anime/src/en/animegg.js index df6c3454..a666c2f5 100644 --- a/javascript/anime/src/en/animegg.js +++ b/javascript/anime/src/en/animegg.js @@ -42,8 +42,9 @@ class DefaultExtension extends MProvider { if (items.length > 0) { for (var item of items) { var imageUrl = item.selectFirst('img').getSrc - var link = item.selectFirst('a').getHref - var name = item.selectFirst(".rightpop").text + var linkSection = item.selectFirst('.rightpop').selectFirst('a') + var link =linkSection.getHref + var name = linkSection.text list.push({ name, imageUrl, From d761743543d6a6078a78a503462c67d0becca422 Mon Sep 17 00:00:00 2001 From: Swakshan Date: Sun, 16 Mar 2025 18:36:19 +0530 Subject: [PATCH 5/5] extension(animegg): extract streams --- javascript/anime/src/en/animegg.js | 97 +++++++++++++++++------------- 1 file changed, 56 insertions(+), 41 deletions(-) diff --git a/javascript/anime/src/en/animegg.js b/javascript/anime/src/en/animegg.js index a666c2f5..1e705dd9 100644 --- a/javascript/anime/src/en/animegg.js +++ b/javascript/anime/src/en/animegg.js @@ -6,7 +6,7 @@ const mangayomiSources = [{ "iconUrl": "https://www.google.com/s2/favicons?sz=256&domain=https://www.animegg.org/", "typeSource": "single", "itemType": 1, - "version": "0.0.3", + "version": "1.0.0", "pkgPath": "anime/src/en/animegg.js" }]; @@ -19,8 +19,8 @@ class DefaultExtension extends MProvider { getHeaders(url) { return { - Referer: this.getSourcePreferences.baseUrl, - Origin: this.getSourcePreferences.baseUrl + "Referer": this.source.baseUrl, + "Origin": this.source.baseUrl } } @@ -28,12 +28,15 @@ class DefaultExtension extends MProvider { return new SharedPreferences().get(key); } - async request(slug) { + async requestText(slug) { var url = `${this.source.baseUrl}${slug}` var res = await this.client.get(url, this.getHeaders()); - return new Document(res.body); + return res.body; } - + async request(slug) { + return new Document(await this.requestText(slug)); + } + async fetchPopularnLatest(slug) { var body = await this.request(slug) var items = body.select("li.fea") @@ -43,7 +46,7 @@ class DefaultExtension extends MProvider { for (var item of items) { var imageUrl = item.selectFirst('img').getSrc var linkSection = item.selectFirst('.rightpop').selectFirst('a') - var link =linkSection.getHref + var link = linkSection.getHref var name = linkSection.text list.push({ name, @@ -86,7 +89,7 @@ class DefaultExtension extends MProvider { } var slug = `/popular-series?${category}start=${start}&limit=${limit}` return await this.fetchPopularnLatest(slug) - + } get supportsLatest() { @@ -105,19 +108,19 @@ class DefaultExtension extends MProvider { var body = await this.request(slug) var items = body.select(".moose.page > a") var list = [] - for (var item of items) { - var imageUrl = item.selectFirst('img').getSrc - var link = item.getHref - var name = item.selectFirst("h2").text - list.push({ - name, - imageUrl, - link - }); + for (var item of items) { + var imageUrl = item.selectFirst('img').getSrc + var link = item.getHref + var name = item.selectFirst("h2").text + list.push({ + name, + imageUrl, + link + }); - } - - return { list, hasNextPage:false } + } + + return { list, hasNextPage: false } } statusCode(status) { @@ -135,7 +138,7 @@ class DefaultExtension extends MProvider { var media = body.selectFirst(".media") var title = media.selectFirst("h1").text var spans = media.selectFirst("p.infoami").select("span") - var statusText = spans[spans.length - 1].text.replace("Status: ",'') + var statusText = spans[spans.length - 1].text.replace("Status: ", '') var status = this.statusCode(statusText) @@ -148,8 +151,8 @@ class DefaultExtension extends MProvider { var episodesList = body.select(".newmanga > li") episodesList.forEach(ep => { var epTitle = ep.selectFirst('i.anititle').text - var epNumber = ep.selectFirst('strong').text.replace(title,"Episode") - var epName = epNumber == epTitle?epNumber:`${epNumber} - ${epTitle}` + var epNumber = ep.selectFirst('strong').text.replace(title, "Episode") + var epName = epNumber == epTitle ? epNumber : `${epNumber} - ${epTitle}` var epUrl = ep.selectFirst("a").getHref var scanlator = ""; @@ -160,34 +163,46 @@ class DefaultExtension extends MProvider { }) scanlator = scanlator.slice(0, -2); - chapters.push({ name: epName, url: epUrl,scanlator}) + chapters.push({ name: epName, url: epUrl, scanlator }) }) - return { description, status, genre, chapters, link } + return { description, status, genre, chapters, link } } - // For novel html content - async getHtmlContent(url) { - throw new Error("getHtmlContent not implemented"); - } - // Clean html up for reader - async cleanHtmlContent(html) { - throw new Error("cleanHtmlContent not implemented"); - } + // For anime episode video list async getVideoList(url) { - throw new Error("getVideoList not implemented"); - } - // For manga chapter pages - async getPageList(url) { - throw new Error("getPageList not implemented"); - } - getFilterList() { - throw new Error("getFilterList not implemented"); + var body = await this.request(url) + var iframe = body.selectFirst("iframe") + var src = iframe.attr('src') + + body = await this.requestText(src) + var sKey = "var videoSources = " + var eKey = "var httpProtocol" + var start = body.indexOf(sKey) + sKey.length + var end = body.indexOf(eKey) - 8 + var videoSourcesStr = body.substring(start, end) + let videoSources = eval("(" + videoSourcesStr + ")"); + var streams = [] + var headers = this.getHeaders(); + videoSources.forEach(videoSource => { + var url = this.source.baseUrl +videoSource.file + var quality = videoSource.label + + streams.push({ + url, + originalUrl: url, + quality, + headers + }); + }); + return streams.reverse(); + } + getSourcePreferences() { return [ {