animob 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (229) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +245 -0
  3. package/animb.png +0 -0
  4. package/dist/extractors/index.d.ts +11 -0
  5. package/dist/extractors/index.js +27 -0
  6. package/dist/extractors/index.js.map +1 -0
  7. package/dist/extractors/kwik.d.ts +18 -0
  8. package/dist/extractors/kwik.js +117 -0
  9. package/dist/extractors/kwik.js.map +1 -0
  10. package/dist/extractors/lplayer.d.ts +11 -0
  11. package/dist/extractors/lplayer.js +131 -0
  12. package/dist/extractors/lplayer.js.map +1 -0
  13. package/dist/extractors/megacloud.d.ts +10 -0
  14. package/dist/extractors/megacloud.js +44 -0
  15. package/dist/extractors/megacloud.js.map +1 -0
  16. package/dist/extractors/megaup.d.ts +31 -0
  17. package/dist/extractors/megaup.js +79 -0
  18. package/dist/extractors/megaup.js.map +1 -0
  19. package/dist/extractors/mixdrop.d.ts +7 -0
  20. package/dist/extractors/mixdrop.js +32 -0
  21. package/dist/extractors/mixdrop.js.map +1 -0
  22. package/dist/extractors/movearnpre.d.ts +9 -0
  23. package/dist/extractors/movearnpre.js +154 -0
  24. package/dist/extractors/movearnpre.js.map +1 -0
  25. package/dist/extractors/sendvid.d.ts +8 -0
  26. package/dist/extractors/sendvid.js +76 -0
  27. package/dist/extractors/sendvid.js.map +1 -0
  28. package/dist/extractors/sibnet.d.ts +8 -0
  29. package/dist/extractors/sibnet.js +44 -0
  30. package/dist/extractors/sibnet.js.map +1 -0
  31. package/dist/extractors/streamsb.d.ts +11 -0
  32. package/dist/extractors/streamsb.js +65 -0
  33. package/dist/extractors/streamsb.js.map +1 -0
  34. package/dist/extractors/streamtape.d.ts +7 -0
  35. package/dist/extractors/streamtape.js +32 -0
  36. package/dist/extractors/streamtape.js.map +1 -0
  37. package/dist/extractors/streamwish.d.ts +11 -0
  38. package/dist/extractors/streamwish.js +46 -0
  39. package/dist/extractors/streamwish.js.map +1 -0
  40. package/dist/extractors/vidcloud.d.ts +11 -0
  41. package/dist/extractors/vidcloud.js +109 -0
  42. package/dist/extractors/vidcloud.js.map +1 -0
  43. package/dist/extractors/videostr.d.ts +10 -0
  44. package/dist/extractors/videostr.js +44 -0
  45. package/dist/extractors/videostr.js.map +1 -0
  46. package/dist/extractors/vidmoly.d.ts +7 -0
  47. package/dist/extractors/vidmoly.js +75 -0
  48. package/dist/extractors/vidmoly.js.map +1 -0
  49. package/dist/extractors/voe.d.ts +10 -0
  50. package/dist/extractors/voe.js +44 -0
  51. package/dist/extractors/voe.js.map +1 -0
  52. package/dist/index.d.ts +6 -0
  53. package/dist/index.js +23 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/models/anime-parser.d.ts +26 -0
  56. package/dist/models/anime-parser.js +14 -0
  57. package/dist/models/anime-parser.js.map +1 -0
  58. package/dist/models/base-parser.d.ts +10 -0
  59. package/dist/models/base-parser.js +7 -0
  60. package/dist/models/base-parser.js.map +1 -0
  61. package/dist/models/base-provider.d.ts +40 -0
  62. package/dist/models/base-provider.js +45 -0
  63. package/dist/models/base-provider.js.map +1 -0
  64. package/dist/models/base-types.d.ts +22 -0
  65. package/dist/models/base-types.js +3 -0
  66. package/dist/models/base-types.js.map +1 -0
  67. package/dist/models/book-parser.d.ts +4 -0
  68. package/dist/models/book-parser.js +7 -0
  69. package/dist/models/book-parser.js.map +1 -0
  70. package/dist/models/comic-parser.d.ts +4 -0
  71. package/dist/models/comic-parser.js +7 -0
  72. package/dist/models/comic-parser.js.map +1 -0
  73. package/dist/models/index.d.ts +13 -0
  74. package/dist/models/index.js +39 -0
  75. package/dist/models/index.js.map +1 -0
  76. package/dist/models/lightnovel-parser.d.ts +16 -0
  77. package/dist/models/lightnovel-parser.js +7 -0
  78. package/dist/models/lightnovel-parser.js.map +1 -0
  79. package/dist/models/manga-parser.d.ts +17 -0
  80. package/dist/models/manga-parser.js +10 -0
  81. package/dist/models/manga-parser.js.map +1 -0
  82. package/dist/models/movie-parser.d.ts +26 -0
  83. package/dist/models/movie-parser.js +7 -0
  84. package/dist/models/movie-parser.js.map +1 -0
  85. package/dist/models/news-parser.d.ts +4 -0
  86. package/dist/models/news-parser.js +7 -0
  87. package/dist/models/news-parser.js.map +1 -0
  88. package/dist/models/proxy.d.ts +25 -0
  89. package/dist/models/proxy.js +83 -0
  90. package/dist/models/proxy.js.map +1 -0
  91. package/dist/models/type-objects.d.ts +48 -0
  92. package/dist/models/type-objects.js +57 -0
  93. package/dist/models/type-objects.js.map +1 -0
  94. package/dist/models/types.d.ts +515 -0
  95. package/dist/models/types.js +118 -0
  96. package/dist/models/types.js.map +1 -0
  97. package/dist/models/video-extractor.d.ts +19 -0
  98. package/dist/models/video-extractor.js +10 -0
  99. package/dist/models/video-extractor.js.map +1 -0
  100. package/dist/providers/anime/animekai.d.ts +94 -0
  101. package/dist/providers/anime/animekai.js +661 -0
  102. package/dist/providers/anime/animekai.js.map +1 -0
  103. package/dist/providers/anime/animepahe.d.ts +41 -0
  104. package/dist/providers/anime/animepahe.js +270 -0
  105. package/dist/providers/anime/animepahe.js.map +1 -0
  106. package/dist/providers/anime/animesama.d.ts +25 -0
  107. package/dist/providers/anime/animesama.js +504 -0
  108. package/dist/providers/anime/animesama.js.map +1 -0
  109. package/dist/providers/anime/animesaturn.d.ts +32 -0
  110. package/dist/providers/anime/animesaturn.js +298 -0
  111. package/dist/providers/anime/animesaturn.js.map +1 -0
  112. package/dist/providers/anime/animeunity.d.ts +27 -0
  113. package/dist/providers/anime/animeunity.js +157 -0
  114. package/dist/providers/anime/animeunity.js.map +1 -0
  115. package/dist/providers/anime/hianime.d.ts +150 -0
  116. package/dist/providers/anime/hianime.js +825 -0
  117. package/dist/providers/anime/hianime.js.map +1 -0
  118. package/dist/providers/anime/index.d.ts +17 -0
  119. package/dist/providers/anime/index.js +22 -0
  120. package/dist/providers/anime/index.js.map +1 -0
  121. package/dist/providers/anime/kickassanime.d.ts +65 -0
  122. package/dist/providers/anime/kickassanime.js +582 -0
  123. package/dist/providers/anime/kickassanime.js.map +1 -0
  124. package/dist/providers/books/index.d.ts +2 -0
  125. package/dist/providers/books/index.js +4 -0
  126. package/dist/providers/books/index.js.map +1 -0
  127. package/dist/providers/comics/getComics.d.ts +9 -0
  128. package/dist/providers/comics/getComics.js +54 -0
  129. package/dist/providers/comics/getComics.js.map +1 -0
  130. package/dist/providers/comics/index.d.ts +5 -0
  131. package/dist/providers/comics/index.js +8 -0
  132. package/dist/providers/comics/index.js.map +1 -0
  133. package/dist/providers/index.d.ts +9 -0
  134. package/dist/providers/index.js +23 -0
  135. package/dist/providers/index.js.map +1 -0
  136. package/dist/providers/light-novels/index.d.ts +5 -0
  137. package/dist/providers/light-novels/index.js +8 -0
  138. package/dist/providers/light-novels/index.js.map +1 -0
  139. package/dist/providers/light-novels/novelupdates.d.ts +26 -0
  140. package/dist/providers/light-novels/novelupdates.js +155 -0
  141. package/dist/providers/light-novels/novelupdates.js.map +1 -0
  142. package/dist/providers/manga/asurascans.d.ts +16 -0
  143. package/dist/providers/manga/asurascans.js +143 -0
  144. package/dist/providers/manga/asurascans.js.map +1 -0
  145. package/dist/providers/manga/comick.d.ts +36 -0
  146. package/dist/providers/manga/comick.js +141 -0
  147. package/dist/providers/manga/comick.js.map +1 -0
  148. package/dist/providers/manga/comix.d.ts +36 -0
  149. package/dist/providers/manga/comix.js +265 -0
  150. package/dist/providers/manga/comix.js.map +1 -0
  151. package/dist/providers/manga/index.d.ts +21 -0
  152. package/dist/providers/manga/index.js +26 -0
  153. package/dist/providers/manga/index.js.map +1 -0
  154. package/dist/providers/manga/mangadex.d.ts +26 -0
  155. package/dist/providers/manga/mangadex.js +301 -0
  156. package/dist/providers/manga/mangadex.js.map +1 -0
  157. package/dist/providers/manga/mangahere.d.ts +29 -0
  158. package/dist/providers/manga/mangahere.js +376 -0
  159. package/dist/providers/manga/mangahere.js.map +1 -0
  160. package/dist/providers/manga/mangakakalot.d.ts +56 -0
  161. package/dist/providers/manga/mangakakalot.js +461 -0
  162. package/dist/providers/manga/mangakakalot.js.map +1 -0
  163. package/dist/providers/manga/mangapill.d.ts +15 -0
  164. package/dist/providers/manga/mangapill.js +104 -0
  165. package/dist/providers/manga/mangapill.js.map +1 -0
  166. package/dist/providers/manga/mangareader.d.ts +15 -0
  167. package/dist/providers/manga/mangareader.js +110 -0
  168. package/dist/providers/manga/mangareader.js.map +1 -0
  169. package/dist/providers/manga/weebcentral.d.ts +12 -0
  170. package/dist/providers/manga/weebcentral.js +169 -0
  171. package/dist/providers/manga/weebcentral.js.map +1 -0
  172. package/dist/providers/meta/anilist.d.ts +206 -0
  173. package/dist/providers/meta/anilist.js +2025 -0
  174. package/dist/providers/meta/anilist.js.map +1 -0
  175. package/dist/providers/meta/index.d.ts +9 -0
  176. package/dist/providers/meta/index.js +10 -0
  177. package/dist/providers/meta/index.js.map +1 -0
  178. package/dist/providers/meta/mal.d.ts +39 -0
  179. package/dist/providers/meta/mal.js +529 -0
  180. package/dist/providers/meta/mal.js.map +1 -0
  181. package/dist/providers/meta/tmdb.d.ts +48 -0
  182. package/dist/providers/meta/tmdb.js +364 -0
  183. package/dist/providers/meta/tmdb.js.map +1 -0
  184. package/dist/providers/movies/dramacool.d.ts +98 -0
  185. package/dist/providers/movies/dramacool.js +367 -0
  186. package/dist/providers/movies/dramacool.js.map +1 -0
  187. package/dist/providers/movies/flixhq.d.ts +90 -0
  188. package/dist/providers/movies/flixhq.js +438 -0
  189. package/dist/providers/movies/flixhq.js.map +1 -0
  190. package/dist/providers/movies/goku.d.ts +80 -0
  191. package/dist/providers/movies/goku.js +369 -0
  192. package/dist/providers/movies/goku.js.map +1 -0
  193. package/dist/providers/movies/himovies.d.ts +102 -0
  194. package/dist/providers/movies/himovies.js +445 -0
  195. package/dist/providers/movies/himovies.js.map +1 -0
  196. package/dist/providers/movies/index.d.ts +17 -0
  197. package/dist/providers/movies/index.js +22 -0
  198. package/dist/providers/movies/index.js.map +1 -0
  199. package/dist/providers/movies/netmirror.d.ts +27 -0
  200. package/dist/providers/movies/netmirror.js +259 -0
  201. package/dist/providers/movies/netmirror.js.map +1 -0
  202. package/dist/providers/movies/sflix.d.ts +106 -0
  203. package/dist/providers/movies/sflix.js +490 -0
  204. package/dist/providers/movies/sflix.js.map +1 -0
  205. package/dist/providers/movies/turkish123.d.ts +32 -0
  206. package/dist/providers/movies/turkish123.js +141 -0
  207. package/dist/providers/movies/turkish123.js.map +1 -0
  208. package/dist/providers/news/animenewsnetwork.d.ts +30 -0
  209. package/dist/providers/news/animenewsnetwork.js +105 -0
  210. package/dist/providers/news/animenewsnetwork.js.map +1 -0
  211. package/dist/providers/news/index.d.ts +5 -0
  212. package/dist/providers/news/index.js +8 -0
  213. package/dist/providers/news/index.js.map +1 -0
  214. package/dist/providers/others/index.d.ts +0 -0
  215. package/dist/providers/others/index.js +2 -0
  216. package/dist/providers/others/index.js.map +1 -0
  217. package/dist/utils/index.d.ts +3 -0
  218. package/dist/utils/index.js +33 -0
  219. package/dist/utils/index.js.map +1 -0
  220. package/dist/utils/providers-list.d.ts +11 -0
  221. package/dist/utils/providers-list.js +40 -0
  222. package/dist/utils/providers-list.js.map +1 -0
  223. package/dist/utils/queries.d.ts +13 -0
  224. package/dist/utils/queries.js +31 -0
  225. package/dist/utils/queries.js.map +1 -0
  226. package/dist/utils/utils.d.ts +32 -0
  227. package/dist/utils/utils.js +324 -0
  228. package/dist/utils/utils.js.map +1 -0
  229. package/package.json +107 -0
@@ -0,0 +1,661 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const cheerio_1 = require("cheerio");
4
+ const models_1 = require("../../models");
5
+ const extractors_1 = require("../../extractors");
6
+ const { GenerateToken, DecodeIframeData } = new extractors_1.MegaUp();
7
+ /**
8
+ * Parses an AJAX response that may come as:
9
+ * 1. A parsed JSON object (axios auto-parsed)
10
+ * 2. A raw JSON string
11
+ * 3. An HTML-wrapped JSON string (e.g. <html>...<pre>{JSON}</pre>...</html>)
12
+ *
13
+ * @param data The raw response data from axios
14
+ * @returns The parsed JSON object, or undefined if parsing failed
15
+ */
16
+ function parseAjaxResponse(data) {
17
+ if (typeof data === 'object')
18
+ return data;
19
+ if (typeof data === 'string') {
20
+ let jsonStr = data;
21
+ if (jsonStr.trimStart().startsWith('<')) {
22
+ const $ = (0, cheerio_1.load)(jsonStr);
23
+ jsonStr = $('pre').text();
24
+ }
25
+ try {
26
+ return JSON.parse(jsonStr);
27
+ }
28
+ catch (_a) {
29
+ return undefined;
30
+ }
31
+ }
32
+ return undefined;
33
+ }
34
+ /**
35
+ * Checks if the response HTML is a Cloudflare access denied / challenge page.
36
+ * Throws a descriptive error so callers know the issue is Cloudflare, not a bug.
37
+ */
38
+ function assertNotCloudflareBlock(html, context) {
39
+ if (typeof html === 'string' &&
40
+ (html.includes('Access denied') || html.includes('Just a moment')) &&
41
+ html.includes('Cloudflare')) {
42
+ throw new Error(`[${context}] Cloudflare blocked the request. The response is a challenge/block page, not the actual site content.`);
43
+ }
44
+ }
45
+ class AnimeKai extends models_1.AnimeParser {
46
+ constructor() {
47
+ super(...arguments);
48
+ this.name = 'AnimeKai';
49
+ this.baseUrl = 'https://anikai.to';
50
+ this.logo = 'https://anikai.to/assets/uploads/37585a3ffa8ec292ee9e2255f3f63b48ceca17ef2a0386.png';
51
+ this.classPath = 'ANIME.AnimeKai';
52
+ /**
53
+ * Fetch anime information
54
+ * @param id Anime ID/slug
55
+ * @returns Promise<IAnimeInfo>
56
+ */
57
+ this.fetchAnimeInfo = async (id) => {
58
+ var _a;
59
+ // Strip episode params ($ep=...,$token=...) if present — only use the anime slug
60
+ const animeSlug = id.split('$')[0];
61
+ const info = {
62
+ id: animeSlug,
63
+ title: '',
64
+ };
65
+ try {
66
+ const { data } = await this.client.get(`${this.baseUrl}/watch/${animeSlug}`, {
67
+ headers: this.Headers(),
68
+ });
69
+ if (typeof data === 'string')
70
+ assertNotCloudflareBlock(data, 'fetchAnimeInfo');
71
+ const $ = (0, cheerio_1.load)(typeof data === 'string' ? data : '');
72
+ info.title = $('.entity-scroll > .title').text();
73
+ info.japaneseTitle = (_a = $('.entity-scroll > .title').attr('data-jp')) === null || _a === void 0 ? void 0 : _a.trim();
74
+ info.image = $('div.poster > div >img').attr('src');
75
+ info.description = $('.entity-scroll > .desc').text().trim();
76
+ // Movie, TV, OVA, ONA, Special, Music
77
+ info.type = $('.entity-scroll > .info').children().last().text().toUpperCase();
78
+ info.url = `${this.baseUrl}/watch/${animeSlug}`;
79
+ info.recommendations = [];
80
+ $('section.sidebar-section:not(#related-anime) .aitem-col .aitem').each((i, ele) => {
81
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
82
+ const aTag = $(ele);
83
+ const id = (_a = aTag.attr('href')) === null || _a === void 0 ? void 0 : _a.replace('/watch/', '');
84
+ (_b = info.recommendations) === null || _b === void 0 ? void 0 : _b.push({
85
+ id: id,
86
+ title: aTag.find('.title').text().trim(),
87
+ url: `${this.baseUrl}${aTag.attr('href')}`,
88
+ image: (_d = (_c = aTag.attr('style')) === null || _c === void 0 ? void 0 : _c.match(/background-image:\s*url\('(.+?)'\)/)) === null || _d === void 0 ? void 0 : _d[1],
89
+ japaneseTitle: (_e = aTag.find('.title').attr('data-jp')) === null || _e === void 0 ? void 0 : _e.trim(),
90
+ type: aTag.find('.info').children().last().text().trim(),
91
+ sub: parseInt((_f = aTag.find('.info span.sub')) === null || _f === void 0 ? void 0 : _f.text()) || 0,
92
+ dub: parseInt((_g = aTag.find('.info span.dub')) === null || _g === void 0 ? void 0 : _g.text()) || 0,
93
+ episodes: parseInt((_h = aTag.find('.info').children().eq(-2).text().trim()) !== null && _h !== void 0 ? _h : (_j = aTag.find('.info span.sub')) === null || _j === void 0 ? void 0 : _j.text()) || 0,
94
+ });
95
+ });
96
+ info.relations = [];
97
+ $('section#related-anime .aitem-col a.aitem').each((_, el) => {
98
+ var _a, _b, _c, _d, _e, _f;
99
+ const aTag = $(el);
100
+ const infoBox = aTag.find('.info');
101
+ const id = (_b = (_a = aTag.attr('href')) === null || _a === void 0 ? void 0 : _a.replace('/watch/', '')) !== null && _b !== void 0 ? _b : '';
102
+ const title = aTag.find('.title').text().trim();
103
+ const japaneseTitle = (_c = aTag.find('.title').attr('data-jp')) === null || _c === void 0 ? void 0 : _c.trim();
104
+ const sub = parseInt(infoBox.find('.sub').text()) || 0;
105
+ const dub = parseInt(infoBox.find('.dub').text()) || 0;
106
+ const bolds = infoBox.find('span > b');
107
+ let episodes = 0;
108
+ let type = '';
109
+ let relationType = '';
110
+ bolds.each((_, b) => {
111
+ const text = $(b).text().trim();
112
+ if ($(b).hasClass('text-muted')) {
113
+ relationType = text;
114
+ }
115
+ else if (/^\d+$/.test(text)) {
116
+ episodes = parseInt(text);
117
+ }
118
+ else {
119
+ type = text; // TV, MOVIE, etc
120
+ }
121
+ });
122
+ (_d = info.relations) === null || _d === void 0 ? void 0 : _d.push({
123
+ id,
124
+ title,
125
+ url: `${this.baseUrl}${aTag.attr('href')}`,
126
+ image: (_f = (_e = aTag.attr('style')) === null || _e === void 0 ? void 0 : _e.match(/background-image:\s*url\('(.+?)'\)/)) === null || _f === void 0 ? void 0 : _f[1],
127
+ japaneseTitle,
128
+ type: type.toUpperCase(),
129
+ sub,
130
+ dub,
131
+ relationType,
132
+ episodes,
133
+ });
134
+ });
135
+ const hasSub = $('.entity-scroll > .info > span.sub').length > 0;
136
+ const hasDub = $('.entity-scroll > .info > span.dub').length > 0;
137
+ if (hasSub) {
138
+ info.subOrDub = models_1.SubOrSub.SUB;
139
+ info.hasSub = hasSub;
140
+ }
141
+ if (hasDub) {
142
+ info.subOrDub = models_1.SubOrSub.DUB;
143
+ info.hasDub = hasDub;
144
+ }
145
+ if (hasSub && hasDub) {
146
+ info.subOrDub = models_1.SubOrSub.BOTH;
147
+ }
148
+ info.genres = [];
149
+ $('.entity-scroll > .detail')
150
+ .find('div')
151
+ .each(function () {
152
+ const text = $(this).text().trim();
153
+ if (text.startsWith('Genres:')) {
154
+ const genresText = text.replace('Genres:', '').trim();
155
+ const genres = genresText.split(',').map(g => g.trim());
156
+ info.genres = genres;
157
+ }
158
+ });
159
+ switch ($('.entity-scroll > .detail').find("div:contains('Status') > span").text().trim()) {
160
+ case 'Completed':
161
+ info.status = models_1.MediaStatus.COMPLETED;
162
+ break;
163
+ case 'Releasing':
164
+ info.status = models_1.MediaStatus.ONGOING;
165
+ break;
166
+ case 'Not yet aired':
167
+ info.status = models_1.MediaStatus.NOT_YET_AIRED;
168
+ break;
169
+ default:
170
+ info.status = models_1.MediaStatus.UNKNOWN;
171
+ break;
172
+ }
173
+ info.season = $('.entity-scroll > .detail').find("div:contains('Premiered') > span").text().trim();
174
+ info.duration = $('.entity-scroll > .detail').find("div:contains('Duration') > span").text().trim();
175
+ $('.entity-scroll > .detail div')
176
+ .filter((_, el) => $(el).text().includes('Links:'))
177
+ .find('a')
178
+ .each((_, el) => {
179
+ var _a, _b, _c, _d, _e;
180
+ const href = (_a = $(el).attr('href')) !== null && _a !== void 0 ? _a : '';
181
+ if (href.includes('myanimelist'))
182
+ info.malId = (_c = (_b = href.match(/anime\/(\d+)/)) === null || _b === void 0 ? void 0 : _b[1]) !== null && _c !== void 0 ? _c : '';
183
+ if (href.includes('anilist'))
184
+ info.anilistId = (_e = (_d = href.match(/anime\/(\d+)/)) === null || _d === void 0 ? void 0 : _d[1]) !== null && _e !== void 0 ? _e : '';
185
+ });
186
+ const ani_id = $('.rate-box#anime-rating').attr('data-id');
187
+ const episodesAjax = await this.client.get(`${this.baseUrl}/ajax/episodes/list?ani_id=${ani_id}&_=${await GenerateToken(ani_id)}`, {
188
+ headers: {
189
+ ...this.Headers(),
190
+ 'X-Requested-With': 'XMLHttpRequest',
191
+ Referer: `${this.baseUrl}/watch/${animeSlug}`,
192
+ },
193
+ });
194
+ const episodesParsed = parseAjaxResponse(episodesAjax.data);
195
+ const episodesResult = episodesParsed === null || episodesParsed === void 0 ? void 0 : episodesParsed.result;
196
+ if (!episodesResult || typeof episodesResult !== 'string') {
197
+ info.totalEpisodes = 0;
198
+ info.episodes = [];
199
+ return info;
200
+ }
201
+ const $$ = (0, cheerio_1.load)(episodesResult);
202
+ info.totalEpisodes = $$('div.eplist > ul > li').length;
203
+ info.episodes = [];
204
+ $$('div.eplist > ul > li > a').each((i, el) => {
205
+ var _a;
206
+ const episodeId = `${animeSlug}$ep=${$$(el).attr('num')}$token=${$$(el).attr('token')}`; //appending token to episode id, as it is required to fetch servers keeping the structure same as other providers
207
+ const number = parseInt($$(el).attr('num'));
208
+ const title = $$(el).children('span').text().trim();
209
+ const url = `${this.baseUrl}/watch/${animeSlug}${$$(el).attr('href')}ep=${$$(el).attr('num')}`;
210
+ const isFiller = $$(el).hasClass('filler');
211
+ const isSubbed = number <= (parseInt($('.entity-scroll > .info > span.sub').text().trim()) || 0);
212
+ const isDubbed = number <= (parseInt($('.entity-scroll > .info > span.dub').text().trim()) || 0);
213
+ (_a = info.episodes) === null || _a === void 0 ? void 0 : _a.push({
214
+ id: episodeId,
215
+ number: number,
216
+ title: title,
217
+ isFiller: isFiller,
218
+ isSubbed: isSubbed,
219
+ isDubbed: isDubbed,
220
+ url: url,
221
+ });
222
+ });
223
+ return info;
224
+ }
225
+ catch (err) {
226
+ throw new Error(err.message);
227
+ }
228
+ };
229
+ /**
230
+ * Fetch episode video sources
231
+ * @param episodeId Episode ID
232
+ * @param server Server type (default: VidCloud)
233
+ * @param subOrDub Sub or dub preference (default: SUB)
234
+ * @returns Promise<ISource>
235
+ */
236
+ this.fetchEpisodeSources = async (episodeId, server = models_1.StreamingServers.MegaUp, subOrDub = models_1.SubOrSub.SUB) => {
237
+ var _a, _b;
238
+ if (episodeId.startsWith('http')) {
239
+ const serverUrl = new URL(episodeId);
240
+ switch (server) {
241
+ case models_1.StreamingServers.MegaUp:
242
+ return {
243
+ headers: { Referer: serverUrl.href },
244
+ ...(await new extractors_1.MegaUp(this.proxyConfig, this.adapter).extract(serverUrl)),
245
+ download: serverUrl.href.replace(/\/e\//, '/download/'),
246
+ };
247
+ default:
248
+ return {
249
+ headers: { Referer: serverUrl.href },
250
+ ...(await new extractors_1.MegaUp(this.proxyConfig, this.adapter).extract(serverUrl)),
251
+ download: serverUrl.href.replace(/\/e\//, '/download/'),
252
+ };
253
+ }
254
+ }
255
+ try {
256
+ const servers = await this.fetchEpisodeServers(episodeId, subOrDub);
257
+ const i = servers.findIndex(s => s.name.toLowerCase().includes(server)); //for now only megaup is available, hence directly using it
258
+ if (i === -1) {
259
+ throw new Error(`Server ${server} not found`);
260
+ }
261
+ const serverUrl = new URL(servers[i].url);
262
+ const sources = await this.fetchEpisodeSources(serverUrl.href, server, subOrDub);
263
+ sources.intro = (_a = servers[i]) === null || _a === void 0 ? void 0 : _a.intro;
264
+ sources.outro = (_b = servers[i]) === null || _b === void 0 ? void 0 : _b.outro;
265
+ return sources;
266
+ }
267
+ catch (err) {
268
+ throw new Error(err.message);
269
+ }
270
+ };
271
+ /**
272
+ * @param url string
273
+ */
274
+ this.scrapeCardPage = async (url) => {
275
+ var _a, _b;
276
+ try {
277
+ const res = {
278
+ currentPage: 0,
279
+ hasNextPage: false,
280
+ totalPages: 0,
281
+ results: [],
282
+ };
283
+ const { data } = await this.client.get(url, {
284
+ headers: this.Headers(),
285
+ });
286
+ if (typeof data === 'string')
287
+ assertNotCloudflareBlock(data, 'scrapeCardPage');
288
+ const $ = (0, cheerio_1.load)(typeof data === 'string' ? data : '');
289
+ const pagination = $('ul.pagination');
290
+ res.currentPage = parseInt(pagination.find('.page-item.active span.page-link').text().trim()) || 0;
291
+ const nextPage = (_a = pagination
292
+ .find('.page-item.active')
293
+ .next()
294
+ .find('a.page-link')
295
+ .attr('href')) === null || _a === void 0 ? void 0 : _a.split('page=')[1];
296
+ if (nextPage != undefined && nextPage != '') {
297
+ res.hasNextPage = true;
298
+ }
299
+ const totalPages = (_b = pagination.find('.page-item:last-child a.page-link').attr('href')) === null || _b === void 0 ? void 0 : _b.split('page=')[1];
300
+ if (totalPages === undefined || totalPages === '') {
301
+ res.totalPages = res.currentPage;
302
+ }
303
+ else {
304
+ res.totalPages = parseInt(totalPages) || 0;
305
+ }
306
+ res.results = await this.scrapeCard($);
307
+ if (res.results.length === 0) {
308
+ res.currentPage = 0;
309
+ res.hasNextPage = false;
310
+ res.totalPages = 0;
311
+ }
312
+ return res;
313
+ }
314
+ catch (err) {
315
+ throw new Error('Something went wrong. Please try again later.');
316
+ }
317
+ };
318
+ /**
319
+ * @param $ cheerio instance
320
+ */
321
+ this.scrapeCard = async ($) => {
322
+ try {
323
+ const results = [];
324
+ $('.aitem').each((i, ele) => {
325
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
326
+ const card = $(ele);
327
+ const atag = card.find('div.inner > a');
328
+ const id = (_a = atag.attr('href')) === null || _a === void 0 ? void 0 : _a.replace('/watch/', '');
329
+ const type = (_b = card.find('.info').children().last()) === null || _b === void 0 ? void 0 : _b.text().trim();
330
+ results.push({
331
+ id: id,
332
+ title: atag.text().trim(),
333
+ url: `${this.baseUrl}${atag.attr('href')}`,
334
+ image: (_d = (_c = card.find('img')) === null || _c === void 0 ? void 0 : _c.attr('data-src')) !== null && _d !== void 0 ? _d : (_e = card.find('img')) === null || _e === void 0 ? void 0 : _e.attr('src'),
335
+ // duration: card.find('.fdi-duration')?.text(),
336
+ japaneseTitle: (_g = (_f = card.find('a.title')) === null || _f === void 0 ? void 0 : _f.attr('data-jp')) === null || _g === void 0 ? void 0 : _g.trim(),
337
+ type: type,
338
+ // nsfw: card.find('.tick-rate')?.text() === '18+' ? true : false,
339
+ sub: parseInt((_h = card.find('.info span.sub')) === null || _h === void 0 ? void 0 : _h.text()) || 0,
340
+ dub: parseInt((_j = card.find('.info span.dub')) === null || _j === void 0 ? void 0 : _j.text()) || 0,
341
+ episodes: parseInt((_k = card.find('.info').children().eq(-2).text().trim()) !== null && _k !== void 0 ? _k : (_l = card.find('.info span.sub')) === null || _l === void 0 ? void 0 : _l.text()) || 0, //if no direct episode count, then just use sub count
342
+ });
343
+ });
344
+ return results;
345
+ }
346
+ catch (err) {
347
+ throw new Error('Something went wrong. Please try again later.');
348
+ }
349
+ };
350
+ /**
351
+ * Fetch available episode servers
352
+ * @param episodeId Episode ID
353
+ * @param subOrDub Sub or dub preference (default: SUB)
354
+ * @returns Promise<IEpisodeServer[]>
355
+ */
356
+ this.fetchEpisodeServers = async (episodeId, subOrDub = models_1.SubOrSub.SUB) => {
357
+ if (!episodeId.startsWith(this.baseUrl + '/ajax')) {
358
+ const token = episodeId.split('$token=')[1];
359
+ episodeId = `${this.baseUrl}/ajax/links/list?token=${token}&_=${await GenerateToken(token)}`;
360
+ }
361
+ try {
362
+ const { data } = await this.client.get(episodeId, { headers: this.Headers() });
363
+ const parsed = parseAjaxResponse(data);
364
+ const resultHtml = parsed === null || parsed === void 0 ? void 0 : parsed.result;
365
+ if (!resultHtml || typeof resultHtml !== 'string') {
366
+ return [];
367
+ }
368
+ const $ = (0, cheerio_1.load)(resultHtml);
369
+ const servers = [];
370
+ const subOrDubStr = subOrDub === models_1.SubOrSub.SUB ? 'softsub' : 'dub';
371
+ const serverItems = $(`.server-items.lang-group[data-id="${subOrDubStr}"] .server`);
372
+ await Promise.all(serverItems.map(async (i, server) => {
373
+ const id = $(server).attr('data-lid');
374
+ const linkResp = await this.client.get(`${this.baseUrl}/ajax/links/view?id=${id}&_=${await GenerateToken(id)}`, { headers: this.Headers() });
375
+ const linkParsed = parseAjaxResponse(linkResp.data);
376
+ const decodedIframeData = await DecodeIframeData(linkParsed === null || linkParsed === void 0 ? void 0 : linkParsed.result);
377
+ servers.push({
378
+ name: `MegaUp ${$(server).text().trim()}`.toLowerCase(), //megaup is the only server for now
379
+ url: decodedIframeData.url,
380
+ intro: {
381
+ start: decodedIframeData === null || decodedIframeData === void 0 ? void 0 : decodedIframeData.skip.intro[0],
382
+ end: decodedIframeData === null || decodedIframeData === void 0 ? void 0 : decodedIframeData.skip.intro[1],
383
+ },
384
+ outro: {
385
+ start: decodedIframeData === null || decodedIframeData === void 0 ? void 0 : decodedIframeData.skip.outro[0],
386
+ end: decodedIframeData === null || decodedIframeData === void 0 ? void 0 : decodedIframeData.skip.outro[1],
387
+ },
388
+ });
389
+ }));
390
+ return servers;
391
+ }
392
+ catch (err) {
393
+ throw new Error(err.message);
394
+ }
395
+ };
396
+ }
397
+ /**
398
+ * Search for anime
399
+ * @param query Search query string
400
+ * @param page Page number (default: 1)
401
+ * @returns Promise<ISearch<IAnimeResult>>
402
+ */
403
+ search(query, page = 1) {
404
+ if (0 >= page) {
405
+ page = 1;
406
+ }
407
+ return this.scrapeCardPage(`${this.baseUrl}/browser?keyword=${query.replace(/[\W_]+/g, '+')}&page=${page}`);
408
+ }
409
+ /**
410
+ * @param page number
411
+ */
412
+ fetchLatestCompleted(page = 1) {
413
+ if (0 >= page) {
414
+ page = 1;
415
+ }
416
+ return this.scrapeCardPage(`${this.baseUrl}/completed?page=${page}`);
417
+ }
418
+ /**
419
+ * @param page number
420
+ */
421
+ fetchRecentlyAdded(page = 1) {
422
+ if (0 >= page) {
423
+ page = 1;
424
+ }
425
+ return this.scrapeCardPage(`${this.baseUrl}/recent?page=${page}`);
426
+ }
427
+ /**
428
+ * @param page number
429
+ */
430
+ fetchRecentlyUpdated(page = 1) {
431
+ if (0 >= page) {
432
+ page = 1;
433
+ }
434
+ return this.scrapeCardPage(`${this.baseUrl}/updates?page=${page}`);
435
+ }
436
+ /**
437
+ * @param page number
438
+ */
439
+ fetchNewReleases(page = 1) {
440
+ if (0 >= page) {
441
+ page = 1;
442
+ }
443
+ return this.scrapeCardPage(`${this.baseUrl}/new-releases?page=${page}`);
444
+ }
445
+ /**
446
+ * @param page number
447
+ */
448
+ fetchMovie(page = 1) {
449
+ if (0 >= page) {
450
+ page = 1;
451
+ }
452
+ return this.scrapeCardPage(`${this.baseUrl}/movie?page=${page}`);
453
+ }
454
+ /**
455
+ * @param page number
456
+ */
457
+ fetchTV(page = 1) {
458
+ if (0 >= page) {
459
+ page = 1;
460
+ }
461
+ return this.scrapeCardPage(`${this.baseUrl}/tv?page=${page}`);
462
+ }
463
+ /**
464
+ * @param page number
465
+ */
466
+ fetchOVA(page = 1) {
467
+ if (0 >= page) {
468
+ page = 1;
469
+ }
470
+ return this.scrapeCardPage(`${this.baseUrl}/ova?page=${page}`);
471
+ }
472
+ /**
473
+ * @param page number
474
+ */
475
+ fetchONA(page = 1) {
476
+ if (0 >= page) {
477
+ page = 1;
478
+ }
479
+ return this.scrapeCardPage(`${this.baseUrl}/ona?page=${page}`);
480
+ }
481
+ /**
482
+ * @param page number
483
+ */
484
+ fetchSpecial(page = 1) {
485
+ if (0 >= page) {
486
+ page = 1;
487
+ }
488
+ return this.scrapeCardPage(`${this.baseUrl}/special?page=${page}`);
489
+ }
490
+ async fetchGenres() {
491
+ try {
492
+ const res = [];
493
+ const { data } = await this.client.get(`${this.baseUrl}/home`, { headers: this.Headers() });
494
+ if (typeof data === 'string')
495
+ assertNotCloudflareBlock(data, 'fetchGenres');
496
+ const $ = (0, cheerio_1.load)(typeof data === 'string' ? data : '');
497
+ const sideBar = $('#menu');
498
+ sideBar.find('ul.c4 li a').each((i, ele) => {
499
+ const genres = $(ele);
500
+ res.push(genres.text().toLowerCase());
501
+ });
502
+ return res;
503
+ }
504
+ catch (err) {
505
+ throw new Error('Something went wrong. Please try again later.');
506
+ }
507
+ }
508
+ /**
509
+ * @param page number
510
+ */
511
+ genreSearch(genre, page = 1) {
512
+ if (genre == '') {
513
+ throw new Error('genre is empty');
514
+ }
515
+ if (0 >= page) {
516
+ page = 1;
517
+ }
518
+ return this.scrapeCardPage(`${this.baseUrl}/genres/${genre}?page=${page}`);
519
+ }
520
+ /**
521
+ * Fetches the schedule for a given date.
522
+ * @param date The date in format 'YYYY-MM-DD'. Defaults to the current date.
523
+ * @returns A promise that resolves to an object containing the search results.
524
+ */
525
+ async fetchSchedule(date = new Date().toISOString().split('T')[0]) {
526
+ try {
527
+ const res = {
528
+ results: [],
529
+ };
530
+ const { data } = await this.client.get(`${this.baseUrl}/ajax/schedule/items?tz=5.5&time=${Math.floor(new Date(`${date}T00:00:00Z`).getTime() / 1000)}`, { headers: this.Headers() });
531
+ const parsed = parseAjaxResponse(data);
532
+ let htmlContent = (parsed === null || parsed === void 0 ? void 0 : parsed.result) || data;
533
+ if (typeof htmlContent === 'object' && htmlContent.html) {
534
+ htmlContent = htmlContent.html;
535
+ }
536
+ const $ = (0, cheerio_1.load)(typeof htmlContent === 'string' ? htmlContent : '');
537
+ $('ul li').each((i, ele) => {
538
+ var _a;
539
+ const card = $(ele);
540
+ const titleElement = card.find('span.title');
541
+ const episodeText = card.find('span').last().text().trim();
542
+ res.results.push({
543
+ id: (_a = card.find('a').attr('href')) === null || _a === void 0 ? void 0 : _a.split('/')[2], // Extract anime ID
544
+ title: titleElement.text().trim(),
545
+ japaneseTitle: titleElement.attr('data-jp'),
546
+ airingTime: card.find('span.time').text().trim(),
547
+ airingEpisode: episodeText.replace('EP ', ''), // Extract episode number
548
+ });
549
+ });
550
+ return res;
551
+ }
552
+ catch (err) {
553
+ throw new Error('Something went wrong. Please try again later.');
554
+ }
555
+ }
556
+ async fetchSpotlight() {
557
+ try {
558
+ const res = { results: [] };
559
+ const { data } = await this.client.get(`${this.baseUrl}/home`, { headers: this.Headers() });
560
+ if (typeof data === 'string')
561
+ assertNotCloudflareBlock(data, 'fetchSpotlight');
562
+ const $ = (0, cheerio_1.load)(typeof data === 'string' ? data : '');
563
+ $('div.swiper-wrapper > div.swiper-slide').each((i, el) => {
564
+ var _a, _b;
565
+ const card = $(el);
566
+ const titleElement = card.find('div.detail > p.title');
567
+ const id = (_a = card.find('div.swiper-ctrl > a.btn').attr('href')) === null || _a === void 0 ? void 0 : _a.replace('/watch/', '');
568
+ const img = card.attr('style');
569
+ res.results.push({
570
+ id: id,
571
+ title: titleElement.text(),
572
+ japaneseTitle: titleElement.attr('data-jp'),
573
+ banner: ((_b = img === null || img === void 0 ? void 0 : img.match(/background-image:\s*url\(["']?(.+?)["']?\)/)) === null || _b === void 0 ? void 0 : _b[1]) || null,
574
+ url: `${this.baseUrl}/watch/${id}`,
575
+ type: card.find('div.detail > div.info').children().eq(-2).text().trim(),
576
+ genres: card
577
+ .find('div.detail > div.info')
578
+ .children()
579
+ .last()
580
+ .text()
581
+ .trim()
582
+ .split(',')
583
+ .map(genre => genre.trim()),
584
+ releaseDate: card
585
+ .find('div.detail > div.mics >div:contains("Release")')
586
+ .children('span')
587
+ .text()
588
+ .trim(),
589
+ quality: card.find('div.detail > div.mics >div:contains("Quality")').children('span').text().trim(),
590
+ sub: parseInt(card.find('div.detail > div.info > span.sub').text().trim()) || 0,
591
+ dub: parseInt(card.find('div.detail > div.info > span.dub').text().trim()) || 0,
592
+ description: card.find('div.detail > p.desc').text().trim(),
593
+ });
594
+ });
595
+ return res;
596
+ }
597
+ catch (error) {
598
+ throw new Error('Something went wrong. Please try again later.');
599
+ }
600
+ }
601
+ async fetchSearchSuggestions(query) {
602
+ var _a, _b;
603
+ try {
604
+ const { data } = await this.client.get(`${this.baseUrl}/ajax/anime/search?keyword=${query.replace(/[\W_]+/g, '+')}`, { headers: this.Headers() });
605
+ const parsed = parseAjaxResponse(data);
606
+ const $ = (0, cheerio_1.load)((_b = (_a = parsed === null || parsed === void 0 ? void 0 : parsed.result) === null || _a === void 0 ? void 0 : _a.html) !== null && _b !== void 0 ? _b : '');
607
+ const res = {
608
+ results: [],
609
+ };
610
+ $('a.aitem').each((i, el) => {
611
+ var _a, _b, _c, _d, _e;
612
+ const card = $(el);
613
+ const image = card.find('.poster img').attr('src');
614
+ const titleElement = card.find('.title');
615
+ const title = titleElement.text().trim();
616
+ const japaneseTitle = titleElement.attr('data-jp');
617
+ const id = (_a = card.attr('href')) === null || _a === void 0 ? void 0 : _a.split('/')[2];
618
+ const year = card.find('.info').children().eq(-2).text().trim();
619
+ const type = card.find('.info').children().eq(-3).text().trim();
620
+ const sub = parseInt((_b = card.find('.info span.sub')) === null || _b === void 0 ? void 0 : _b.text()) || 0;
621
+ const dub = parseInt((_c = card.find('.info span.dub')) === null || _c === void 0 ? void 0 : _c.text()) || 0;
622
+ const episodes = parseInt((_d = card.find('.info').children().eq(-4).text().trim()) !== null && _d !== void 0 ? _d : (_e = card.find('.info span.sub')) === null || _e === void 0 ? void 0 : _e.text()) || 0;
623
+ res.results.push({
624
+ id: id,
625
+ title: title,
626
+ url: `${this.baseUrl}/watch/${id}`,
627
+ image: image,
628
+ japaneseTitle: japaneseTitle || null,
629
+ type: type,
630
+ year: year,
631
+ sub: sub,
632
+ dub: dub,
633
+ episodes: episodes,
634
+ });
635
+ });
636
+ return res;
637
+ }
638
+ catch (error) {
639
+ throw new Error('Something went wrong. Please try again later.');
640
+ }
641
+ }
642
+ Headers() {
643
+ return {
644
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36',
645
+ Connection: 'keep-alive',
646
+ Accept: 'text/html, */*; q=0.01',
647
+ 'Accept-Language': 'en-US,en;q=0.5',
648
+ 'Sec-GPC': '1',
649
+ 'Sec-Fetch-Dest': 'empty',
650
+ 'Sec-Fetch-Mode': 'cors',
651
+ 'Sec-Fetch-Site': 'same-origin',
652
+ Priority: 'u=0',
653
+ Pragma: 'no-cache',
654
+ 'Cache-Control': 'no-cache',
655
+ Referer: `${this.baseUrl}/`,
656
+ Cookie: '__p_mov=1; usertype=guest; session=vLrU4aKItp0QltI2asH83yugyWDsSSQtyl9sxWKO',
657
+ };
658
+ }
659
+ }
660
+ exports.default = AnimeKai;
661
+ //# sourceMappingURL=animekai.js.map