From cc6b40762d3b47279e46a3742421fea177232bfd Mon Sep 17 00:00:00 2001 From: Swakshan Date: Thu, 9 Jan 2025 12:46:23 +0530 Subject: [PATCH] extension(aniplay): Added anilist support for latest, popular, search --- javascript/anime/src/en/aniplay.js | 237 +++++++++++++++++++++++++++++ 1 file changed, 237 insertions(+) create mode 100644 javascript/anime/src/en/aniplay.js diff --git a/javascript/anime/src/en/aniplay.js b/javascript/anime/src/en/aniplay.js new file mode 100644 index 00000000..9e30bedb --- /dev/null +++ b/javascript/anime/src/en/aniplay.js @@ -0,0 +1,237 @@ +const mangayomiSources = [{ + "name": "Aniplay", + "lang": "en", + "baseUrl": "https://aniplaynow.live", + "apiUrl": "https://aniplaynow.live", + "iconUrl": "https://www.google.com/s2/favicons?sz=128&domain=https://aniplaynow.live/", + "typeSource": "single", + "isManga": false, + "version": "0.0.3", + "dateFormat": "", + "dateFormatLocale": "", + "pkgPath": "anime/src/en/aniplay.js" +}]; + +class DefaultExtension extends MProvider { + + constructor() { + super(); + this.client = new Client(); + } + + getHeaders(url) { + return { + Referer: this.source.apiUrl + } + } + + getPreference(key) { + const preferences = new SharedPreferences(); + return preferences.get(key); + } + + + // code from torrentioanime.js + anilistQuery() { + return ` + query ($page: Int, $perPage: Int, $sort: [MediaSort], $search: String) { + Page(page: $page, perPage: $perPage) { + pageInfo { + currentPage + hasNextPage + } + media(type: ANIME, sort: $sort, search: $search, status_in: [RELEASING, FINISHED, NOT_YET_RELEASED]) { + id + title { + romaji + english + native + } + coverImage { + extraLarge + large + } + description + status + tags { + name + } + genres + studios { + nodes { + name + } + } + countryOfOrigin + isAdult + } + } + } + `.trim(); + } + + anilistLatestQuery() { + const currentTimeInSeconds = Math.floor(Date.now() / 1000); + return ` + query ($page: Int, $perPage: Int, $sort: [AiringSort]) { + Page(page: $page, perPage: $perPage) { + pageInfo { + currentPage + hasNextPage + } + airingSchedules( + airingAt_greater: 0 + airingAt_lesser: ${currentTimeInSeconds - 10000} + sort: $sort + ) { + media { + id + title { + romaji + english + native + } + coverImage { + extraLarge + large + } + description + status + tags { + name + } + genres + studios { + nodes { + name + } + } + countryOfOrigin + isAdult + } + } + } + } + `.trim(); + } + async makeGraphQLRequest(query, variables) { + const res = await this.client.post("https://graphql.anilist.co", {}, + { + query, variables + }); + return res; + } + + parseSearchJson(jsonLine, isLatestQuery = false) { + const jsonData = JSON.parse(jsonLine); + jsonData.type = isLatestQuery ? "AnilistMetaLatest" : "AnilistMeta"; + const metaData = jsonData; + + const mediaList = metaData.type == "AnilistMeta" + ? metaData.data?.Page?.media || [] + : metaData.data?.Page?.airingSchedules.map(schedule => schedule.media) || []; + + const hasNextPage = metaData.type == "AnilistMeta" || metaData.type == "AnilistMetaLatest" + ? metaData.data?.Page?.pageInfo?.hasNextPage || false + : false; + + const animeList = mediaList + .filter(media => !((media?.countryOfOrigin === "CN" || media?.isAdult) && isLatestQuery)) + .map(media => { + const anime = {}; + anime.link = media?.id?.toString() || ""; + 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 || ""; + + return anime; + }); + + return { "list": animeList, "hasNextPage": hasNextPage }; + } + + async getPopular(page) { + const variables = JSON.stringify({ + page: page, + perPage: 30, + sort: "TRENDING_DESC" + }); + + const res = await this.makeGraphQLRequest(this.anilistQuery(), variables); + + return this.parseSearchJson(res.body) + } + + async getLatestUpdates(page) { + const variables = JSON.stringify({ + page: page, + perPage: 30, + sort: "TIME_DESC" + }); + + const res = await this.makeGraphQLRequest(this.anilistLatestQuery(), variables); + + return this.parseSearchJson(res.body, true) + } + + async search(query, page, filters) { + const variables = JSON.stringify({ + page: page, + perPage: 30, + sort: "POPULARITY_DESC", + search: query + }); + + const res = await this.makeGraphQLRequest(this.anilistQuery(), variables); + + return this.parseSearchJson(res.body) + } + + get supportsLatest() { + throw new Error("supportsLatest 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": "aniplay_pref_title", + "listPreference": { + "title": "Preferred Title", + "summary": "", + "valueIndex": 0, + "entries": [ + "Romaji", + "English", + "Native"], + "entryValues": [ + "romaji", + "english", + "native"], + } + },] + } +}