From f4f52a4fc5ed92df3c09e8bfdaedbfad8cd8ab77 Mon Sep 17 00:00:00 2001 From: Swakshan Date: Mon, 13 Jan 2025 21:46:00 +0530 Subject: [PATCH] extension(aniplay): Added details --- javascript/anime/src/en/aniplay.js | 177 ++++++++++++++++++++++++++--- 1 file changed, 161 insertions(+), 16 deletions(-) diff --git a/javascript/anime/src/en/aniplay.js b/javascript/anime/src/en/aniplay.js index 9e30bedb..c6161e22 100644 --- a/javascript/anime/src/en/aniplay.js +++ b/javascript/anime/src/en/aniplay.js @@ -5,7 +5,7 @@ const mangayomiSources = [{ "apiUrl": "https://aniplaynow.live", "iconUrl": "https://www.google.com/s2/favicons?sz=128&domain=https://aniplaynow.live/", "typeSource": "single", - "isManga": false, + "itemType": 1, "version": "0.0.3", "dateFormat": "", "dateFormatLocale": "", @@ -13,7 +13,7 @@ const mangayomiSources = [{ }]; class DefaultExtension extends MProvider { - + constructor() { super(); this.client = new Client(); @@ -70,6 +70,7 @@ class DefaultExtension extends MProvider { `.trim(); } + // code from torrentioanime.js anilistLatestQuery() { const currentTimeInSeconds = Math.floor(Date.now() / 1000); return ` @@ -114,6 +115,86 @@ class DefaultExtension extends MProvider { } `.trim(); } + + // code from torrentioanime.js + async getAnimeDetails(anilistId) { + const query = ` + query($id: Int){ + Media(id: $id){ + id + title { + romaji + english + native + } + coverImage { + extraLarge + large + } + description + status + tags { + name + } + genres + studios { + nodes { + name + } + } + countryOfOrigin + isAdult + } + } + `.trim(); + + const variables = JSON.stringify({ id: anilistId }); + + const res = await this.makeGraphQLRequest(query, variables); + const media = JSON.parse(res.body).data.Media; + const anime = {}; + anime.name = (() => { + var preferenceTitle = this.getPreference("aniplay_pref_title"); + switch (preferenceTitle) { + case "romaji": + return media?.title?.romaji || ""; + case "english": + return media?.title?.english?.trim() || media?.title?.romaji || ""; + case "native": + return media?.title?.native || ""; + default: + return ""; + } + })(); + anime.imageUrl = media?.coverImage?.extraLarge || ""; + anime.description = (media?.description || "No Description") + .replace(/

/g, "\n") + .replace(/<.*?>/g, ""); + + anime.status = (() => { + switch (media?.status) { + case "RELEASING": + return 0; + case "FINISHED": + return 1; + case "HIATUS": + return 2; + case "NOT_YET_RELEASED": + return 3; + default: + return 5; + } + })(); + + const tagsList = media?.tags?.map(tag => tag.name).filter(Boolean) || []; + const genresList = media?.genres || []; + anime.genre = [...new Set([...tagsList, ...genresList])].sort(); + const studiosList = media?.studios?.nodes?.map(node => node.name).filter(Boolean) || []; + anime.author = studiosList.sort().join(", "); + return anime; + } + + // code from torrentioanime.js async makeGraphQLRequest(query, variables) { const res = await this.client.post("https://graphql.anilist.co", {}, { @@ -122,6 +203,7 @@ class DefaultExtension extends MProvider { return res; } + // code from torrentioanime.js parseSearchJson(jsonLine, isLatestQuery = false) { const jsonData = JSON.parse(jsonLine); jsonData.type = isLatestQuery ? "AnilistMetaLatest" : "AnilistMeta"; @@ -141,7 +223,7 @@ class DefaultExtension extends MProvider { const anime = {}; anime.link = media?.id?.toString() || ""; anime.name = (() => { - var preferenceTitle = this.getPreference("aniplay_pref_title"); + var preferenceTitle = this.getPreference("aniplay_pref_title"); switch (preferenceTitle) { case "romaji": return media?.title?.romaji || ""; @@ -170,7 +252,7 @@ class DefaultExtension extends MProvider { const res = await this.makeGraphQLRequest(this.anilistQuery(), variables); - return this.parseSearchJson(res.body) + return this.parseSearchJson(res.body) } async getLatestUpdates(page) { @@ -182,7 +264,7 @@ class DefaultExtension extends MProvider { const res = await this.makeGraphQLRequest(this.anilistLatestQuery(), variables); - return this.parseSearchJson(res.body, true) + return this.parseSearchJson(res.body, true) } async search(query, page, filters) { @@ -195,14 +277,71 @@ class DefaultExtension extends MProvider { const res = await this.makeGraphQLRequest(this.anilistQuery(), variables); - return this.parseSearchJson(res.body) + return this.parseSearchJson(res.body) } get supportsLatest() { throw new Error("supportsLatest not implemented"); } + + async aniplayRequest(url, body) { + var next_action = "" + + if (url.indexOf("/info/") > -1) { + next_action = 'f3422af67c84852f5e63d50e1f51718f1c0225c4' + } else if (url.indexOf("/watch/") > -1) { + next_action = '5dbcd21c7c276c4d15f8de29d9ef27aef5ea4a5e' + } + + var headers = { + "referer": "https://aniplaynow.live", + 'next-action': next_action, + "Content-Type": "application/json", + } + + var response = await new Client().post(url, headers, body); + + if (response.statusCode != 200) { + throw new Error("Error: " + response.statusText); + } + return JSON.parse(response.body.split('1:')[1]) + + } + async getDetail(url) { - throw new Error("getDetail not implemented"); + var anilistId = url + var animeData = await this.getAnimeDetails(anilistId) + + + var link = `${this.source.baseUrl}anime/info/${anilistId}` + var body = [anilistId, true, false] + var result = await this.aniplayRequest(link, body) + if (result.length < 1) { + throw new Error("Error: No data found for the given URL"); + } + + var user_provider = this.getPreference("aniplay_pref_provider"); + var choice = result[0] + for (var ch of result) { + if (ch["providerId"] == user_provider) { + choice = ch + break; + } + } + var chapters = [] + var epList = choice.episodes + for (var ep of epList) { + var title = ep.title + var num = ep.number + var name = `E${num}: ${title}` + var dateUpload = "createdAt" in ep ? new Date(ep.createdAt) : new Date().now() + dateUpload = dateUpload.valueOf().toString(); + var epUrl = `${JSON.stringify(ep)}||${choice.providerId}` + chapters.push({ name, url: epUrl, dateUpload }) + } + animeData.link = link + animeData.chapters = chapters.reverse() + return animeData } // For anime episode video list async getVideoList(url) { @@ -223,15 +362,21 @@ class DefaultExtension extends MProvider { "title": "Preferred Title", "summary": "", "valueIndex": 0, - "entries": [ - "Romaji", - "English", - "Native"], - "entryValues": [ - "romaji", - "english", - "native"], + "entries": ["Romaji", "English", "Native"], + "entryValues": ["romaji", "english", "native"], } - },] + }, + { + "key": "aniplay_pref_provider", + "listPreference": { + "title": "Preferred provider", + "summary": "", + "valueIndex": 0, + "entries": ["Anya", "Yuki", "Kuro"], + "entryValues": ["anya", "yuki", "kuro"], + } + }, + + ] } }