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.
- package/LICENSE +674 -0
- package/README.md +245 -0
- package/animb.png +0 -0
- package/dist/extractors/index.d.ts +11 -0
- package/dist/extractors/index.js +27 -0
- package/dist/extractors/index.js.map +1 -0
- package/dist/extractors/kwik.d.ts +18 -0
- package/dist/extractors/kwik.js +117 -0
- package/dist/extractors/kwik.js.map +1 -0
- package/dist/extractors/lplayer.d.ts +11 -0
- package/dist/extractors/lplayer.js +131 -0
- package/dist/extractors/lplayer.js.map +1 -0
- package/dist/extractors/megacloud.d.ts +10 -0
- package/dist/extractors/megacloud.js +44 -0
- package/dist/extractors/megacloud.js.map +1 -0
- package/dist/extractors/megaup.d.ts +31 -0
- package/dist/extractors/megaup.js +79 -0
- package/dist/extractors/megaup.js.map +1 -0
- package/dist/extractors/mixdrop.d.ts +7 -0
- package/dist/extractors/mixdrop.js +32 -0
- package/dist/extractors/mixdrop.js.map +1 -0
- package/dist/extractors/movearnpre.d.ts +9 -0
- package/dist/extractors/movearnpre.js +154 -0
- package/dist/extractors/movearnpre.js.map +1 -0
- package/dist/extractors/sendvid.d.ts +8 -0
- package/dist/extractors/sendvid.js +76 -0
- package/dist/extractors/sendvid.js.map +1 -0
- package/dist/extractors/sibnet.d.ts +8 -0
- package/dist/extractors/sibnet.js +44 -0
- package/dist/extractors/sibnet.js.map +1 -0
- package/dist/extractors/streamsb.d.ts +11 -0
- package/dist/extractors/streamsb.js +65 -0
- package/dist/extractors/streamsb.js.map +1 -0
- package/dist/extractors/streamtape.d.ts +7 -0
- package/dist/extractors/streamtape.js +32 -0
- package/dist/extractors/streamtape.js.map +1 -0
- package/dist/extractors/streamwish.d.ts +11 -0
- package/dist/extractors/streamwish.js +46 -0
- package/dist/extractors/streamwish.js.map +1 -0
- package/dist/extractors/vidcloud.d.ts +11 -0
- package/dist/extractors/vidcloud.js +109 -0
- package/dist/extractors/vidcloud.js.map +1 -0
- package/dist/extractors/videostr.d.ts +10 -0
- package/dist/extractors/videostr.js +44 -0
- package/dist/extractors/videostr.js.map +1 -0
- package/dist/extractors/vidmoly.d.ts +7 -0
- package/dist/extractors/vidmoly.js +75 -0
- package/dist/extractors/vidmoly.js.map +1 -0
- package/dist/extractors/voe.d.ts +10 -0
- package/dist/extractors/voe.js +44 -0
- package/dist/extractors/voe.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/models/anime-parser.d.ts +26 -0
- package/dist/models/anime-parser.js +14 -0
- package/dist/models/anime-parser.js.map +1 -0
- package/dist/models/base-parser.d.ts +10 -0
- package/dist/models/base-parser.js +7 -0
- package/dist/models/base-parser.js.map +1 -0
- package/dist/models/base-provider.d.ts +40 -0
- package/dist/models/base-provider.js +45 -0
- package/dist/models/base-provider.js.map +1 -0
- package/dist/models/base-types.d.ts +22 -0
- package/dist/models/base-types.js +3 -0
- package/dist/models/base-types.js.map +1 -0
- package/dist/models/book-parser.d.ts +4 -0
- package/dist/models/book-parser.js +7 -0
- package/dist/models/book-parser.js.map +1 -0
- package/dist/models/comic-parser.d.ts +4 -0
- package/dist/models/comic-parser.js +7 -0
- package/dist/models/comic-parser.js.map +1 -0
- package/dist/models/index.d.ts +13 -0
- package/dist/models/index.js +39 -0
- package/dist/models/index.js.map +1 -0
- package/dist/models/lightnovel-parser.d.ts +16 -0
- package/dist/models/lightnovel-parser.js +7 -0
- package/dist/models/lightnovel-parser.js.map +1 -0
- package/dist/models/manga-parser.d.ts +17 -0
- package/dist/models/manga-parser.js +10 -0
- package/dist/models/manga-parser.js.map +1 -0
- package/dist/models/movie-parser.d.ts +26 -0
- package/dist/models/movie-parser.js +7 -0
- package/dist/models/movie-parser.js.map +1 -0
- package/dist/models/news-parser.d.ts +4 -0
- package/dist/models/news-parser.js +7 -0
- package/dist/models/news-parser.js.map +1 -0
- package/dist/models/proxy.d.ts +25 -0
- package/dist/models/proxy.js +83 -0
- package/dist/models/proxy.js.map +1 -0
- package/dist/models/type-objects.d.ts +48 -0
- package/dist/models/type-objects.js +57 -0
- package/dist/models/type-objects.js.map +1 -0
- package/dist/models/types.d.ts +515 -0
- package/dist/models/types.js +118 -0
- package/dist/models/types.js.map +1 -0
- package/dist/models/video-extractor.d.ts +19 -0
- package/dist/models/video-extractor.js +10 -0
- package/dist/models/video-extractor.js.map +1 -0
- package/dist/providers/anime/animekai.d.ts +94 -0
- package/dist/providers/anime/animekai.js +661 -0
- package/dist/providers/anime/animekai.js.map +1 -0
- package/dist/providers/anime/animepahe.d.ts +41 -0
- package/dist/providers/anime/animepahe.js +270 -0
- package/dist/providers/anime/animepahe.js.map +1 -0
- package/dist/providers/anime/animesama.d.ts +25 -0
- package/dist/providers/anime/animesama.js +504 -0
- package/dist/providers/anime/animesama.js.map +1 -0
- package/dist/providers/anime/animesaturn.d.ts +32 -0
- package/dist/providers/anime/animesaturn.js +298 -0
- package/dist/providers/anime/animesaturn.js.map +1 -0
- package/dist/providers/anime/animeunity.d.ts +27 -0
- package/dist/providers/anime/animeunity.js +157 -0
- package/dist/providers/anime/animeunity.js.map +1 -0
- package/dist/providers/anime/hianime.d.ts +150 -0
- package/dist/providers/anime/hianime.js +825 -0
- package/dist/providers/anime/hianime.js.map +1 -0
- package/dist/providers/anime/index.d.ts +17 -0
- package/dist/providers/anime/index.js +22 -0
- package/dist/providers/anime/index.js.map +1 -0
- package/dist/providers/anime/kickassanime.d.ts +65 -0
- package/dist/providers/anime/kickassanime.js +582 -0
- package/dist/providers/anime/kickassanime.js.map +1 -0
- package/dist/providers/books/index.d.ts +2 -0
- package/dist/providers/books/index.js +4 -0
- package/dist/providers/books/index.js.map +1 -0
- package/dist/providers/comics/getComics.d.ts +9 -0
- package/dist/providers/comics/getComics.js +54 -0
- package/dist/providers/comics/getComics.js.map +1 -0
- package/dist/providers/comics/index.d.ts +5 -0
- package/dist/providers/comics/index.js +8 -0
- package/dist/providers/comics/index.js.map +1 -0
- package/dist/providers/index.d.ts +9 -0
- package/dist/providers/index.js +23 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/light-novels/index.d.ts +5 -0
- package/dist/providers/light-novels/index.js +8 -0
- package/dist/providers/light-novels/index.js.map +1 -0
- package/dist/providers/light-novels/novelupdates.d.ts +26 -0
- package/dist/providers/light-novels/novelupdates.js +155 -0
- package/dist/providers/light-novels/novelupdates.js.map +1 -0
- package/dist/providers/manga/asurascans.d.ts +16 -0
- package/dist/providers/manga/asurascans.js +143 -0
- package/dist/providers/manga/asurascans.js.map +1 -0
- package/dist/providers/manga/comick.d.ts +36 -0
- package/dist/providers/manga/comick.js +141 -0
- package/dist/providers/manga/comick.js.map +1 -0
- package/dist/providers/manga/comix.d.ts +36 -0
- package/dist/providers/manga/comix.js +265 -0
- package/dist/providers/manga/comix.js.map +1 -0
- package/dist/providers/manga/index.d.ts +21 -0
- package/dist/providers/manga/index.js +26 -0
- package/dist/providers/manga/index.js.map +1 -0
- package/dist/providers/manga/mangadex.d.ts +26 -0
- package/dist/providers/manga/mangadex.js +301 -0
- package/dist/providers/manga/mangadex.js.map +1 -0
- package/dist/providers/manga/mangahere.d.ts +29 -0
- package/dist/providers/manga/mangahere.js +376 -0
- package/dist/providers/manga/mangahere.js.map +1 -0
- package/dist/providers/manga/mangakakalot.d.ts +56 -0
- package/dist/providers/manga/mangakakalot.js +461 -0
- package/dist/providers/manga/mangakakalot.js.map +1 -0
- package/dist/providers/manga/mangapill.d.ts +15 -0
- package/dist/providers/manga/mangapill.js +104 -0
- package/dist/providers/manga/mangapill.js.map +1 -0
- package/dist/providers/manga/mangareader.d.ts +15 -0
- package/dist/providers/manga/mangareader.js +110 -0
- package/dist/providers/manga/mangareader.js.map +1 -0
- package/dist/providers/manga/weebcentral.d.ts +12 -0
- package/dist/providers/manga/weebcentral.js +169 -0
- package/dist/providers/manga/weebcentral.js.map +1 -0
- package/dist/providers/meta/anilist.d.ts +206 -0
- package/dist/providers/meta/anilist.js +2025 -0
- package/dist/providers/meta/anilist.js.map +1 -0
- package/dist/providers/meta/index.d.ts +9 -0
- package/dist/providers/meta/index.js +10 -0
- package/dist/providers/meta/index.js.map +1 -0
- package/dist/providers/meta/mal.d.ts +39 -0
- package/dist/providers/meta/mal.js +529 -0
- package/dist/providers/meta/mal.js.map +1 -0
- package/dist/providers/meta/tmdb.d.ts +48 -0
- package/dist/providers/meta/tmdb.js +364 -0
- package/dist/providers/meta/tmdb.js.map +1 -0
- package/dist/providers/movies/dramacool.d.ts +98 -0
- package/dist/providers/movies/dramacool.js +367 -0
- package/dist/providers/movies/dramacool.js.map +1 -0
- package/dist/providers/movies/flixhq.d.ts +90 -0
- package/dist/providers/movies/flixhq.js +438 -0
- package/dist/providers/movies/flixhq.js.map +1 -0
- package/dist/providers/movies/goku.d.ts +80 -0
- package/dist/providers/movies/goku.js +369 -0
- package/dist/providers/movies/goku.js.map +1 -0
- package/dist/providers/movies/himovies.d.ts +102 -0
- package/dist/providers/movies/himovies.js +445 -0
- package/dist/providers/movies/himovies.js.map +1 -0
- package/dist/providers/movies/index.d.ts +17 -0
- package/dist/providers/movies/index.js +22 -0
- package/dist/providers/movies/index.js.map +1 -0
- package/dist/providers/movies/netmirror.d.ts +27 -0
- package/dist/providers/movies/netmirror.js +259 -0
- package/dist/providers/movies/netmirror.js.map +1 -0
- package/dist/providers/movies/sflix.d.ts +106 -0
- package/dist/providers/movies/sflix.js +490 -0
- package/dist/providers/movies/sflix.js.map +1 -0
- package/dist/providers/movies/turkish123.d.ts +32 -0
- package/dist/providers/movies/turkish123.js +141 -0
- package/dist/providers/movies/turkish123.js.map +1 -0
- package/dist/providers/news/animenewsnetwork.d.ts +30 -0
- package/dist/providers/news/animenewsnetwork.js +105 -0
- package/dist/providers/news/animenewsnetwork.js.map +1 -0
- package/dist/providers/news/index.d.ts +5 -0
- package/dist/providers/news/index.js +8 -0
- package/dist/providers/news/index.js.map +1 -0
- package/dist/providers/others/index.d.ts +0 -0
- package/dist/providers/others/index.js +2 -0
- package/dist/providers/others/index.js.map +1 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.js +33 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/providers-list.d.ts +11 -0
- package/dist/utils/providers-list.js +40 -0
- package/dist/utils/providers-list.js.map +1 -0
- package/dist/utils/queries.d.ts +13 -0
- package/dist/utils/queries.js +31 -0
- package/dist/utils/queries.js.map +1 -0
- package/dist/utils/utils.d.ts +32 -0
- package/dist/utils/utils.js +324 -0
- package/dist/utils/utils.js.map +1 -0
- package/package.json +107 -0
|
@@ -0,0 +1,825 @@
|
|
|
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 utils_1 = require("../../utils");
|
|
7
|
+
class Hianime extends models_1.AnimeParser {
|
|
8
|
+
constructor() {
|
|
9
|
+
super(...arguments);
|
|
10
|
+
this.name = 'hianime';
|
|
11
|
+
this.baseUrl = 'https://anizen.tr';
|
|
12
|
+
this.logo = 'https://is3-ssl.mzstatic.com/image/thumb/Purple112/v4/7e/91/00/7e9100ee-2b62-0942-4cdc-e9b93252ce1c/source/512x512bb.jpg';
|
|
13
|
+
this.classPath = 'ANIME.hianime';
|
|
14
|
+
/**
|
|
15
|
+
* Fetch anime information
|
|
16
|
+
* @param id Anime ID/slug
|
|
17
|
+
* @returns Promise<IAnimeInfo>
|
|
18
|
+
*/
|
|
19
|
+
this.fetchAnimeInfo = async (id) => {
|
|
20
|
+
const info = {
|
|
21
|
+
id: id,
|
|
22
|
+
title: '',
|
|
23
|
+
};
|
|
24
|
+
try {
|
|
25
|
+
const animeUrl = `${this.baseUrl}/watch/${id}`;
|
|
26
|
+
const { data } = await this.client.get(animeUrl);
|
|
27
|
+
const $ = (0, cheerio_1.load)(data);
|
|
28
|
+
const { mal_id, anilist_id } = JSON.parse($('#syncData').text());
|
|
29
|
+
info.malID = Number(mal_id);
|
|
30
|
+
info.alID = Number(anilist_id);
|
|
31
|
+
info.title = $('h2.film-name > a.text-white').text();
|
|
32
|
+
info.japaneseTitle = $('div.anisc-info div:nth-child(2) span.name').text();
|
|
33
|
+
info.image = $('img.film-poster-img').attr('src');
|
|
34
|
+
info.description = $('div.film-description').text().trim();
|
|
35
|
+
// Movie, TV, OVA, ONA, Special, Music
|
|
36
|
+
info.type = $('span.item').last().prev().prev().text().toUpperCase();
|
|
37
|
+
info.url = `${this.baseUrl}/${id}`;
|
|
38
|
+
info.recommendations = await this.scrapeCard($);
|
|
39
|
+
info.relatedAnime = [];
|
|
40
|
+
$('#main-sidebar section:nth-child(1) div.anif-block-ul li').each((i, ele) => {
|
|
41
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
42
|
+
const card = $(ele);
|
|
43
|
+
const aTag = card.find('.film-name a');
|
|
44
|
+
const id = (_a = aTag.attr('href')) === null || _a === void 0 ? void 0 : _a.split('/')[1].split('?')[0];
|
|
45
|
+
info.relatedAnime.push({
|
|
46
|
+
id: id,
|
|
47
|
+
title: aTag.text(),
|
|
48
|
+
url: `${this.baseUrl}${aTag.attr('href')}`,
|
|
49
|
+
image: (_b = card.find('img')) === null || _b === void 0 ? void 0 : _b.attr('data-src'),
|
|
50
|
+
japaneseTitle: aTag.attr('data-jname'),
|
|
51
|
+
type: (_d = (_c = card.find('.tick').contents().last()) === null || _c === void 0 ? void 0 : _c.text()) === null || _d === void 0 ? void 0 : _d.trim(),
|
|
52
|
+
sub: parseInt((_e = card.find('.tick-item.tick-sub')) === null || _e === void 0 ? void 0 : _e.text()) || 0,
|
|
53
|
+
dub: parseInt((_f = card.find('.tick-item.tick-dub')) === null || _f === void 0 ? void 0 : _f.text()) || 0,
|
|
54
|
+
episodes: parseInt((_g = card.find('.tick-item.tick-eps')) === null || _g === void 0 ? void 0 : _g.text()) || 0,
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
const hasSub = $('div.film-stats div.tick div.tick-item.tick-sub').length > 0;
|
|
58
|
+
const hasDub = $('div.film-stats div.tick div.tick-item.tick-dub').length > 0;
|
|
59
|
+
if (hasSub) {
|
|
60
|
+
info.subOrDub = models_1.SubOrSub.SUB;
|
|
61
|
+
info.hasSub = hasSub;
|
|
62
|
+
}
|
|
63
|
+
if (hasDub) {
|
|
64
|
+
info.subOrDub = models_1.SubOrSub.DUB;
|
|
65
|
+
info.hasDub = hasDub;
|
|
66
|
+
}
|
|
67
|
+
if (hasSub && hasDub) {
|
|
68
|
+
info.subOrDub = models_1.SubOrSub.BOTH;
|
|
69
|
+
}
|
|
70
|
+
// hianime - PAGE INFO
|
|
71
|
+
const zInfo = await this.client.get(info.url);
|
|
72
|
+
const $$$ = (0, cheerio_1.load)(zInfo.data);
|
|
73
|
+
info.genres = [];
|
|
74
|
+
$$$('.item.item-list')
|
|
75
|
+
.find('a')
|
|
76
|
+
.each(function () {
|
|
77
|
+
var _a;
|
|
78
|
+
const genre = $(this).text().trim();
|
|
79
|
+
if (genre != undefined)
|
|
80
|
+
(_a = info.genres) === null || _a === void 0 ? void 0 : _a.push(genre);
|
|
81
|
+
});
|
|
82
|
+
switch ($$$('.item.item-title').find("span.item-head:contains('Status')").next('span.name').text().trim()) {
|
|
83
|
+
case 'Finished Airing':
|
|
84
|
+
info.status = models_1.MediaStatus.COMPLETED;
|
|
85
|
+
break;
|
|
86
|
+
case 'Currently Airing':
|
|
87
|
+
info.status = models_1.MediaStatus.ONGOING;
|
|
88
|
+
break;
|
|
89
|
+
case 'Not yet aired':
|
|
90
|
+
info.status = models_1.MediaStatus.NOT_YET_AIRED;
|
|
91
|
+
break;
|
|
92
|
+
default:
|
|
93
|
+
info.status = models_1.MediaStatus.UNKNOWN;
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
info.season = $$$('.item.item-title')
|
|
97
|
+
.find("span.item-head:contains('Premiered')")
|
|
98
|
+
.next('span.name')
|
|
99
|
+
.text()
|
|
100
|
+
.trim();
|
|
101
|
+
if (info.japaneseTitle == '' || info.japaneseTitle == undefined) {
|
|
102
|
+
info.japaneseTitle = $$$('.item.item-title')
|
|
103
|
+
.find("span.item-head:contains('Japanese')")
|
|
104
|
+
.next('span.name')
|
|
105
|
+
.text()
|
|
106
|
+
.trim();
|
|
107
|
+
}
|
|
108
|
+
const episodesAjax = await this.client.get(`${this.baseUrl}/ajax/v2/episode/list/${id.split('-').pop()}`, {
|
|
109
|
+
headers: {
|
|
110
|
+
'X-Requested-With': 'XMLHttpRequest',
|
|
111
|
+
Referer: `${this.baseUrl}/watch/${id}`,
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
const $$ = (0, cheerio_1.load)(episodesAjax.data.html);
|
|
115
|
+
info.totalEpisodes = $$('div.detail-infor-content > div > a').length;
|
|
116
|
+
info.episodes = [];
|
|
117
|
+
$$('div.detail-infor-content > div > a').each((i, el) => {
|
|
118
|
+
var _a, _b, _c;
|
|
119
|
+
const episodeId = (_b = (_a = $$(el).attr('href')) === null || _a === void 0 ? void 0 : _a.split('/')[2]) === null || _b === void 0 ? void 0 : _b.replace('?ep=', '$episode$');
|
|
120
|
+
const number = parseInt($$(el).attr('data-number'));
|
|
121
|
+
const title = $$(el).attr('title');
|
|
122
|
+
const url = this.baseUrl + $$(el).attr('href');
|
|
123
|
+
const isFiller = $$(el).hasClass('ssl-item-filler');
|
|
124
|
+
const isSubbed = number <= (parseInt($('div.film-stats div.tick div.tick-item.tick-sub').text().trim()) || 0);
|
|
125
|
+
const isDubbed = number <= (parseInt($('div.film-stats div.tick div.tick-item.tick-dub').text().trim()) || 0);
|
|
126
|
+
(_c = info.episodes) === null || _c === void 0 ? void 0 : _c.push({
|
|
127
|
+
id: episodeId,
|
|
128
|
+
number: number,
|
|
129
|
+
title: title,
|
|
130
|
+
isFiller: isFiller,
|
|
131
|
+
isSubbed: isSubbed,
|
|
132
|
+
isDubbed: isDubbed,
|
|
133
|
+
url: url,
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
return info;
|
|
137
|
+
}
|
|
138
|
+
catch (err) {
|
|
139
|
+
throw new Error(err.message);
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
/**
|
|
143
|
+
* Fetch episode video sources
|
|
144
|
+
* @param episodeId Episode ID
|
|
145
|
+
* @param server Server type (default: VidCloud)
|
|
146
|
+
* @param subOrDub Sub or dub preference (default: SUB)
|
|
147
|
+
* @returns Promise<ISource>
|
|
148
|
+
*/
|
|
149
|
+
this.fetchEpisodeSources = async (episodeId, server = models_1.StreamingServers.VidCloud, subOrDub = models_1.SubOrSub.SUB) => {
|
|
150
|
+
if (episodeId.startsWith('http')) {
|
|
151
|
+
const serverUrl = new URL(episodeId);
|
|
152
|
+
switch (server) {
|
|
153
|
+
case models_1.StreamingServers.VidStreaming:
|
|
154
|
+
case models_1.StreamingServers.VidCloud:
|
|
155
|
+
return {
|
|
156
|
+
headers: { Referer: serverUrl.href },
|
|
157
|
+
...(await new extractors_1.MegaCloud().extract(serverUrl)),
|
|
158
|
+
};
|
|
159
|
+
case models_1.StreamingServers.StreamSB:
|
|
160
|
+
return {
|
|
161
|
+
headers: {
|
|
162
|
+
Referer: serverUrl.href,
|
|
163
|
+
watchsb: 'streamsb',
|
|
164
|
+
'User-Agent': utils_1.USER_AGENT,
|
|
165
|
+
},
|
|
166
|
+
sources: await new extractors_1.StreamSB(this.proxyConfig, this.adapter).extract(serverUrl, true),
|
|
167
|
+
};
|
|
168
|
+
case models_1.StreamingServers.StreamTape:
|
|
169
|
+
return {
|
|
170
|
+
headers: { Referer: serverUrl.href, 'User-Agent': utils_1.USER_AGENT },
|
|
171
|
+
sources: await new extractors_1.StreamTape(this.proxyConfig, this.adapter).extract(serverUrl),
|
|
172
|
+
};
|
|
173
|
+
default:
|
|
174
|
+
case models_1.StreamingServers.VidCloud:
|
|
175
|
+
return {
|
|
176
|
+
headers: { Referer: serverUrl.href },
|
|
177
|
+
...(await new extractors_1.MegaCloud().extract(serverUrl)),
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
if (!episodeId.includes('$episode$'))
|
|
182
|
+
throw new Error('Invalid episode id');
|
|
183
|
+
// keeping this for future use
|
|
184
|
+
// Fallback to using sub if no info found in case of compatibility
|
|
185
|
+
// TODO: add both options later
|
|
186
|
+
// subOrDub = episodeId.split('$')?.pop() === 'dub' ? 'dub' : 'sub';
|
|
187
|
+
episodeId = `${this.baseUrl}/watch/${episodeId
|
|
188
|
+
.replace('$episode$', '?ep=')
|
|
189
|
+
.replace(/\$auto|\$sub|\$dub/gi, '')}`;
|
|
190
|
+
try {
|
|
191
|
+
const { data } = await this.client.get(`${this.baseUrl}/ajax/v2/episode/servers?episodeId=${episodeId.split('?ep=')[1]}`);
|
|
192
|
+
const $ = (0, cheerio_1.load)(data.html);
|
|
193
|
+
/**
|
|
194
|
+
* vidtreaming -> 4
|
|
195
|
+
* rapidcloud -> 1
|
|
196
|
+
* streamsb -> 5
|
|
197
|
+
* streamtape -> 3
|
|
198
|
+
*/
|
|
199
|
+
let serverId = '';
|
|
200
|
+
try {
|
|
201
|
+
switch (server) {
|
|
202
|
+
case models_1.StreamingServers.VidCloud:
|
|
203
|
+
serverId = this.retrieveServerId($, 1, subOrDub);
|
|
204
|
+
// hianime's vidcloud server is rapidcloud
|
|
205
|
+
if (!serverId)
|
|
206
|
+
throw new Error('RapidCloud not found');
|
|
207
|
+
break;
|
|
208
|
+
case models_1.StreamingServers.VidStreaming:
|
|
209
|
+
serverId = this.retrieveServerId($, 4, subOrDub);
|
|
210
|
+
// hianime's vidcloud server is rapidcloud
|
|
211
|
+
if (!serverId)
|
|
212
|
+
throw new Error('vidtreaming not found');
|
|
213
|
+
break;
|
|
214
|
+
case models_1.StreamingServers.StreamSB:
|
|
215
|
+
serverId = this.retrieveServerId($, 5, subOrDub);
|
|
216
|
+
if (!serverId)
|
|
217
|
+
throw new Error('StreamSB not found');
|
|
218
|
+
break;
|
|
219
|
+
case models_1.StreamingServers.StreamTape:
|
|
220
|
+
serverId = this.retrieveServerId($, 3, subOrDub);
|
|
221
|
+
if (!serverId)
|
|
222
|
+
throw new Error('StreamTape not found');
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
catch (err) {
|
|
227
|
+
throw new Error("Couldn't find server. Try another server");
|
|
228
|
+
}
|
|
229
|
+
const { data: { link }, } = await this.client.get(`${this.baseUrl}/ajax/v2/episode/sources?id=${serverId}`);
|
|
230
|
+
return await this.fetchEpisodeSources(link, server, models_1.SubOrSub.SUB);
|
|
231
|
+
}
|
|
232
|
+
catch (err) {
|
|
233
|
+
throw err;
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
this.verifyLoginState = async (connectSid) => {
|
|
237
|
+
try {
|
|
238
|
+
const { data } = await this.client.get(`${this.baseUrl}/ajax/login-state`, {
|
|
239
|
+
headers: {
|
|
240
|
+
Cookie: `connect.sid=${connectSid}`,
|
|
241
|
+
},
|
|
242
|
+
});
|
|
243
|
+
return data.is_login;
|
|
244
|
+
}
|
|
245
|
+
catch (err) {
|
|
246
|
+
return false;
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
this.retrieveServerId = ($, index, subOrDub) => {
|
|
250
|
+
const rawOrSubOrDub = (raw) => $(`.ps_-block.ps_-block-sub.servers-${raw ? 'raw' : subOrDub} > .ps__-list .server-item`)
|
|
251
|
+
.map((i, el) => ($(el).attr('data-server-id') == `${index}` ? $(el) : null))
|
|
252
|
+
.get()[0]
|
|
253
|
+
.attr('data-id');
|
|
254
|
+
try {
|
|
255
|
+
// Attempt to get the subOrDub ID
|
|
256
|
+
return rawOrSubOrDub(false);
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
// If an error is thrown, attempt to get the raw ID (The raw is the newest episode uploaded to hianime)
|
|
260
|
+
return rawOrSubOrDub(true);
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
/**
|
|
264
|
+
* @param url string
|
|
265
|
+
*/
|
|
266
|
+
this.scrapeCardPage = async (url, headers) => {
|
|
267
|
+
var _a, _b, _c;
|
|
268
|
+
try {
|
|
269
|
+
const res = {
|
|
270
|
+
currentPage: 0,
|
|
271
|
+
hasNextPage: false,
|
|
272
|
+
totalPages: 0,
|
|
273
|
+
results: [],
|
|
274
|
+
};
|
|
275
|
+
const { data } = await this.client.get(url, headers);
|
|
276
|
+
const $ = (0, cheerio_1.load)(data);
|
|
277
|
+
const pagination = $('ul.pagination');
|
|
278
|
+
// Fix currentPage parsing
|
|
279
|
+
const currentPageText = (_b = (_a = pagination.find('.page-item.active')) === null || _a === void 0 ? void 0 : _a.text()) === null || _b === void 0 ? void 0 : _b.trim();
|
|
280
|
+
res.currentPage = currentPageText ? parseInt(currentPageText) : 1;
|
|
281
|
+
if (isNaN(res.currentPage)) {
|
|
282
|
+
res.currentPage = 1;
|
|
283
|
+
}
|
|
284
|
+
const nextPage = (_c = pagination.find('a[title=Next]')) === null || _c === void 0 ? void 0 : _c.attr('href');
|
|
285
|
+
if (nextPage != undefined && nextPage != '') {
|
|
286
|
+
res.hasNextPage = true;
|
|
287
|
+
}
|
|
288
|
+
// Fix totalPages parsing
|
|
289
|
+
const totalPagesHref = pagination.find('a[title=Last]').attr('href');
|
|
290
|
+
if (totalPagesHref) {
|
|
291
|
+
const totalPagesStr = totalPagesHref.split('=').pop();
|
|
292
|
+
res.totalPages = totalPagesStr ? parseInt(totalPagesStr) : res.currentPage;
|
|
293
|
+
if (isNaN(res.totalPages)) {
|
|
294
|
+
res.totalPages = res.currentPage;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
res.totalPages = res.currentPage;
|
|
299
|
+
}
|
|
300
|
+
res.results = await this.scrapeCard($);
|
|
301
|
+
if (res.results.length === 0) {
|
|
302
|
+
res.currentPage = 0;
|
|
303
|
+
res.hasNextPage = false;
|
|
304
|
+
res.totalPages = 0;
|
|
305
|
+
}
|
|
306
|
+
return res;
|
|
307
|
+
}
|
|
308
|
+
catch (err) {
|
|
309
|
+
console.error('Hianime scrapeCardPage error:', err.message);
|
|
310
|
+
throw new Error('Something went wrong. Please try again later.');
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
/**
|
|
314
|
+
* @param $ cheerio instance
|
|
315
|
+
*/
|
|
316
|
+
this.scrapeCard = async ($) => {
|
|
317
|
+
try {
|
|
318
|
+
const results = [];
|
|
319
|
+
$('.flw-item').each((i, ele) => {
|
|
320
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
321
|
+
try {
|
|
322
|
+
const card = $(ele);
|
|
323
|
+
const atag = card.find('.film-name a');
|
|
324
|
+
const href = atag.attr('href');
|
|
325
|
+
if (!href) {
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
const id = (_a = href.split('/')[1]) === null || _a === void 0 ? void 0 : _a.split('?')[0];
|
|
329
|
+
if (!id) {
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
const watchList = card.find('.dropdown-menu .added').text().trim();
|
|
333
|
+
const type = (_c = (_b = card
|
|
334
|
+
.find('.fdi-item')) === null || _b === void 0 ? void 0 : _b.first()) === null || _c === void 0 ? void 0 : _c.text().replace(' (? eps)', '').replace(/\s\(\d+ eps\)/g, '');
|
|
335
|
+
results.push({
|
|
336
|
+
id: id,
|
|
337
|
+
title: atag.text(),
|
|
338
|
+
url: `${this.baseUrl}${atag.attr('href')}`,
|
|
339
|
+
image: (_d = card.find('img')) === null || _d === void 0 ? void 0 : _d.attr('data-src'),
|
|
340
|
+
duration: (_e = card.find('.fdi-duration')) === null || _e === void 0 ? void 0 : _e.text(),
|
|
341
|
+
watchList: watchList || models_1.WatchListType.NONE,
|
|
342
|
+
japaneseTitle: atag.attr('data-jname'),
|
|
343
|
+
type: type,
|
|
344
|
+
nsfw: ((_f = card.find('.tick-rate')) === null || _f === void 0 ? void 0 : _f.text()) === '18+' ? true : false,
|
|
345
|
+
sub: parseInt((_g = card.find('.tick-item.tick-sub')) === null || _g === void 0 ? void 0 : _g.text()) || 0,
|
|
346
|
+
dub: parseInt((_h = card.find('.tick-item.tick-dub')) === null || _h === void 0 ? void 0 : _h.text()) || 0,
|
|
347
|
+
episodes: parseInt((_j = card.find('.tick-item.tick-eps')) === null || _j === void 0 ? void 0 : _j.text()) || 0,
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
catch (cardErr) {
|
|
351
|
+
// Continue with next card instead of failing completely
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
return results;
|
|
355
|
+
}
|
|
356
|
+
catch (err) {
|
|
357
|
+
console.error('Hianime scrapeCard error:', err.message);
|
|
358
|
+
throw new Error('Something went wrong. Please try again later.');
|
|
359
|
+
}
|
|
360
|
+
};
|
|
361
|
+
/**
|
|
362
|
+
* @deprecated
|
|
363
|
+
* @param episodeId Episode id
|
|
364
|
+
*/
|
|
365
|
+
this.fetchEpisodeServers = (episodeId) => {
|
|
366
|
+
throw new Error('Method not implemented.');
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Search for anime
|
|
371
|
+
* @param query Search query string
|
|
372
|
+
* @param page Page number (default: 1)
|
|
373
|
+
* @returns Promise<ISearch<IAnimeResult>>
|
|
374
|
+
*/
|
|
375
|
+
search(query, page = 1) {
|
|
376
|
+
if (0 >= page) {
|
|
377
|
+
page = 1;
|
|
378
|
+
}
|
|
379
|
+
const searchUrl = `${this.baseUrl}/search?keyword=${decodeURIComponent(query)}&page=${page}`;
|
|
380
|
+
return this.scrapeCardPage(searchUrl);
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Fetch advanced anime search results with various filters.
|
|
384
|
+
*
|
|
385
|
+
* @param page Page number (default: 1)
|
|
386
|
+
* @param type One of (Optional): movie, tv, ova, ona, special, music
|
|
387
|
+
* @param status One of (Optional): finished_airing, currently_airing, not_yet_aired
|
|
388
|
+
* @param rated One of (Optional): g, pg, pg_13, r, r_plus, rx
|
|
389
|
+
* @param score Number from 1 to 10 (Optional)
|
|
390
|
+
* @param season One of (Optional): spring, summer, fall, winter
|
|
391
|
+
* @param language One of (Optional): sub, dub, sub_dub
|
|
392
|
+
* @param startDate Start date object { year, month, day } (Optional)
|
|
393
|
+
* @param endDate End date object { year, month, day } (Optional)
|
|
394
|
+
* @param sort One of (Optional): recently_added, recently_updated, score, name_az, released_date, most_watched
|
|
395
|
+
* @param genres Array of genres (Optional): action, adventure, cars, comedy, dementia, demons, mystery, drama, ecchi, fantasy, game, historical, horror, kids, magic, martial_arts, mecha, music, parody, samurai, romance, school, sci_fi, shoujo, shoujo_ai, shounen, shounen_ai, space, sports, super_power, vampire, harem, military, slice_of_life, supernatural, police, psychological, thriller, seinen, isekai, josei
|
|
396
|
+
* @returns A Promise resolving to the search results.
|
|
397
|
+
*/
|
|
398
|
+
fetchAdvancedSearch(page = 1, type, status, rated, score, season, language, startDate, endDate, sort, genres) {
|
|
399
|
+
if (page <= 0)
|
|
400
|
+
page = 1;
|
|
401
|
+
const mappings = {
|
|
402
|
+
type: { movie: 1, tv: 2, ova: 3, ona: 4, special: 5, music: 6 },
|
|
403
|
+
status: { finished_airing: 1, currently_airing: 2, not_yet_aired: 3 },
|
|
404
|
+
rated: { g: 1, pg: 2, pg_13: 3, r: 4, r_plus: 5, rx: 6 },
|
|
405
|
+
season: { spring: 1, summer: 2, fall: 3, winter: 4 },
|
|
406
|
+
language: { sub: 1, dub: 2, sub_dub: 3 },
|
|
407
|
+
genre: {
|
|
408
|
+
action: 1,
|
|
409
|
+
adventure: 2,
|
|
410
|
+
cars: 3,
|
|
411
|
+
comedy: 4,
|
|
412
|
+
dementia: 5,
|
|
413
|
+
demons: 6,
|
|
414
|
+
mystery: 7,
|
|
415
|
+
drama: 8,
|
|
416
|
+
ecchi: 9,
|
|
417
|
+
fantasy: 10,
|
|
418
|
+
game: 11,
|
|
419
|
+
historical: 13,
|
|
420
|
+
horror: 14,
|
|
421
|
+
kids: 15,
|
|
422
|
+
magic: 16,
|
|
423
|
+
martial_arts: 17,
|
|
424
|
+
mecha: 18,
|
|
425
|
+
music: 19,
|
|
426
|
+
parody: 20,
|
|
427
|
+
samurai: 21,
|
|
428
|
+
romance: 22,
|
|
429
|
+
school: 23,
|
|
430
|
+
sci_fi: 24,
|
|
431
|
+
shoujo: 25,
|
|
432
|
+
shoujo_ai: 26,
|
|
433
|
+
shounen: 27,
|
|
434
|
+
shounen_ai: 28,
|
|
435
|
+
space: 29,
|
|
436
|
+
sports: 30,
|
|
437
|
+
super_power: 31,
|
|
438
|
+
vampire: 32,
|
|
439
|
+
harem: 35,
|
|
440
|
+
military: 38,
|
|
441
|
+
slice_of_life: 36,
|
|
442
|
+
supernatural: 37,
|
|
443
|
+
police: 39,
|
|
444
|
+
psychological: 40,
|
|
445
|
+
thriller: 41,
|
|
446
|
+
seinen: 42,
|
|
447
|
+
isekai: 44,
|
|
448
|
+
josei: 43,
|
|
449
|
+
},
|
|
450
|
+
};
|
|
451
|
+
const params = new URLSearchParams({ page: page.toString() });
|
|
452
|
+
const addParam = (key, value) => {
|
|
453
|
+
var _a;
|
|
454
|
+
if (value)
|
|
455
|
+
params.append(key, (((_a = mappings[key]) === null || _a === void 0 ? void 0 : _a[value]) || value).toString());
|
|
456
|
+
};
|
|
457
|
+
addParam('type', type);
|
|
458
|
+
addParam('status', status);
|
|
459
|
+
addParam('rated', rated);
|
|
460
|
+
if (score)
|
|
461
|
+
params.append('score', score.toString());
|
|
462
|
+
addParam('season', season);
|
|
463
|
+
addParam('language', language);
|
|
464
|
+
if (startDate) {
|
|
465
|
+
params.append('sy', startDate.year.toString());
|
|
466
|
+
params.append('sm', startDate.month.toString());
|
|
467
|
+
params.append('sd', startDate.day.toString());
|
|
468
|
+
}
|
|
469
|
+
if (endDate) {
|
|
470
|
+
params.append('ey', endDate.year.toString());
|
|
471
|
+
params.append('em', endDate.month.toString());
|
|
472
|
+
params.append('ed', endDate.day.toString());
|
|
473
|
+
}
|
|
474
|
+
if (sort)
|
|
475
|
+
params.append('sort', sort);
|
|
476
|
+
if (genres === null || genres === void 0 ? void 0 : genres.length) {
|
|
477
|
+
const genreIds = genres.map(genre => (mappings.genre[genre] || genre).toString()).join('%2C');
|
|
478
|
+
params.append('genres', genreIds);
|
|
479
|
+
}
|
|
480
|
+
return this.scrapeCardPage(`${this.baseUrl}/filter?${params.toString()}`);
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* @param page number
|
|
484
|
+
*/
|
|
485
|
+
fetchTopAiring(page = 1) {
|
|
486
|
+
if (0 >= page) {
|
|
487
|
+
page = 1;
|
|
488
|
+
}
|
|
489
|
+
return this.scrapeCardPage(`${this.baseUrl}/top-airing?page=${page}`);
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* @param page number
|
|
493
|
+
*/
|
|
494
|
+
fetchMostPopular(page = 1) {
|
|
495
|
+
if (0 >= page) {
|
|
496
|
+
page = 1;
|
|
497
|
+
}
|
|
498
|
+
return this.scrapeCardPage(`${this.baseUrl}/most-popular?page=${page}`);
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* @param page number
|
|
502
|
+
*/
|
|
503
|
+
fetchMostFavorite(page = 1) {
|
|
504
|
+
if (0 >= page) {
|
|
505
|
+
page = 1;
|
|
506
|
+
}
|
|
507
|
+
return this.scrapeCardPage(`${this.baseUrl}/most-favorite?page=${page}`);
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* @param page number
|
|
511
|
+
*/
|
|
512
|
+
fetchLatestCompleted(page = 1) {
|
|
513
|
+
if (0 >= page) {
|
|
514
|
+
page = 1;
|
|
515
|
+
}
|
|
516
|
+
return this.scrapeCardPage(`${this.baseUrl}/completed?page=${page}`);
|
|
517
|
+
}
|
|
518
|
+
/**
|
|
519
|
+
* @param page number
|
|
520
|
+
*/
|
|
521
|
+
fetchRecentlyUpdated(page = 1) {
|
|
522
|
+
if (0 >= page) {
|
|
523
|
+
page = 1;
|
|
524
|
+
}
|
|
525
|
+
return this.scrapeCardPage(`${this.baseUrl}/recently-updated?page=${page}`);
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* @param page number
|
|
529
|
+
*/
|
|
530
|
+
fetchRecentlyAdded(page = 1) {
|
|
531
|
+
if (0 >= page) {
|
|
532
|
+
page = 1;
|
|
533
|
+
}
|
|
534
|
+
return this.scrapeCardPage(`${this.baseUrl}/recently-added?page=${page}`);
|
|
535
|
+
}
|
|
536
|
+
/**
|
|
537
|
+
* @param page number
|
|
538
|
+
*/
|
|
539
|
+
fetchTopUpcoming(page = 1) {
|
|
540
|
+
if (0 >= page) {
|
|
541
|
+
page = 1;
|
|
542
|
+
}
|
|
543
|
+
return this.scrapeCardPage(`${this.baseUrl}/top-upcoming?page=${page}`);
|
|
544
|
+
}
|
|
545
|
+
/**
|
|
546
|
+
* @param studio Studio id, e.g. "toei-animation"
|
|
547
|
+
* @param page page number (optional) `default 1`
|
|
548
|
+
*/
|
|
549
|
+
fetchStudio(studio, page = 1) {
|
|
550
|
+
if (0 >= page) {
|
|
551
|
+
page = 1;
|
|
552
|
+
}
|
|
553
|
+
return this.scrapeCardPage(`${this.baseUrl}/producer/${studio}?page=${page}`);
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* @param page number
|
|
557
|
+
*/
|
|
558
|
+
fetchSubbedAnime(page = 1) {
|
|
559
|
+
if (0 >= page) {
|
|
560
|
+
page = 1;
|
|
561
|
+
}
|
|
562
|
+
return this.scrapeCardPage(`${this.baseUrl}/subbed-anime?page=${page}`);
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* @param page number
|
|
566
|
+
*/
|
|
567
|
+
fetchDubbedAnime(page = 1) {
|
|
568
|
+
if (0 >= page) {
|
|
569
|
+
page = 1;
|
|
570
|
+
}
|
|
571
|
+
return this.scrapeCardPage(`${this.baseUrl}/dubbed-anime?page=${page}`);
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* @param page number
|
|
575
|
+
*/
|
|
576
|
+
fetchMovie(page = 1) {
|
|
577
|
+
if (0 >= page) {
|
|
578
|
+
page = 1;
|
|
579
|
+
}
|
|
580
|
+
return this.scrapeCardPage(`${this.baseUrl}/movie?page=${page}`);
|
|
581
|
+
}
|
|
582
|
+
/**
|
|
583
|
+
* @param page number
|
|
584
|
+
*/
|
|
585
|
+
fetchTV(page = 1) {
|
|
586
|
+
if (0 >= page) {
|
|
587
|
+
page = 1;
|
|
588
|
+
}
|
|
589
|
+
return this.scrapeCardPage(`${this.baseUrl}/tv?page=${page}`);
|
|
590
|
+
}
|
|
591
|
+
/**
|
|
592
|
+
* @param page number
|
|
593
|
+
*/
|
|
594
|
+
fetchOVA(page = 1) {
|
|
595
|
+
if (0 >= page) {
|
|
596
|
+
page = 1;
|
|
597
|
+
}
|
|
598
|
+
return this.scrapeCardPage(`${this.baseUrl}/ova?page=${page}`);
|
|
599
|
+
}
|
|
600
|
+
/**
|
|
601
|
+
* @param page number
|
|
602
|
+
*/
|
|
603
|
+
fetchONA(page = 1) {
|
|
604
|
+
if (0 >= page) {
|
|
605
|
+
page = 1;
|
|
606
|
+
}
|
|
607
|
+
return this.scrapeCardPage(`${this.baseUrl}/ona?page=${page}`);
|
|
608
|
+
}
|
|
609
|
+
/**
|
|
610
|
+
* @param page number
|
|
611
|
+
*/
|
|
612
|
+
fetchSpecial(page = 1) {
|
|
613
|
+
if (0 >= page) {
|
|
614
|
+
page = 1;
|
|
615
|
+
}
|
|
616
|
+
return this.scrapeCardPage(`${this.baseUrl}/special?page=${page}`);
|
|
617
|
+
}
|
|
618
|
+
async fetchGenres() {
|
|
619
|
+
try {
|
|
620
|
+
const res = [];
|
|
621
|
+
const { data } = await this.client.get(`${this.baseUrl}/home`);
|
|
622
|
+
const $ = (0, cheerio_1.load)(data);
|
|
623
|
+
const sideBar = $('#main-sidebar');
|
|
624
|
+
sideBar.find('ul.sb-genre-list li a').each((i, ele) => {
|
|
625
|
+
const genres = $(ele);
|
|
626
|
+
res.push(genres.text().toLowerCase());
|
|
627
|
+
});
|
|
628
|
+
return res;
|
|
629
|
+
}
|
|
630
|
+
catch (err) {
|
|
631
|
+
throw new Error('Something went wrong. Please try again later.');
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* @param page number
|
|
636
|
+
*/
|
|
637
|
+
genreSearch(genre, page = 1) {
|
|
638
|
+
if (genre == '') {
|
|
639
|
+
throw new Error('genre is empty');
|
|
640
|
+
}
|
|
641
|
+
if (0 >= page) {
|
|
642
|
+
page = 1;
|
|
643
|
+
}
|
|
644
|
+
return this.scrapeCardPage(`${this.baseUrl}/genre/${genre}?page=${page}`);
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Fetches the schedule for a given date.
|
|
648
|
+
* @param date The date in format 'YYYY-MM-DD'. Defaults to the current date.
|
|
649
|
+
* @returns A promise that resolves to an object containing the search results.
|
|
650
|
+
*/
|
|
651
|
+
async fetchSchedule(date = new Date().toISOString().slice(0, 10)) {
|
|
652
|
+
try {
|
|
653
|
+
const res = {
|
|
654
|
+
results: [],
|
|
655
|
+
};
|
|
656
|
+
const { data: { html }, } = await this.client.get(`${this.baseUrl}/ajax/schedule/list?tzOffset=360&date=${date}`);
|
|
657
|
+
const $ = (0, cheerio_1.load)(html);
|
|
658
|
+
$('li').each((i, ele) => {
|
|
659
|
+
var _a;
|
|
660
|
+
const card = $(ele);
|
|
661
|
+
const title = card.find('.film-name');
|
|
662
|
+
const id = (_a = card.find('a.tsl-link').attr('href')) === null || _a === void 0 ? void 0 : _a.split('/')[1].split('?')[0];
|
|
663
|
+
const airingTime = card.find('div.time').text().replace('\n', '').trim();
|
|
664
|
+
const airingEpisode = card.find('div.film-detail div.fd-play button').text().replace('\n', '').trim();
|
|
665
|
+
res.results.push({
|
|
666
|
+
id: id,
|
|
667
|
+
title: title.text(),
|
|
668
|
+
japaneseTitle: title.attr('data-jname'),
|
|
669
|
+
url: `${this.baseUrl}/${id}`,
|
|
670
|
+
airingEpisode: airingEpisode,
|
|
671
|
+
airingTime: airingTime,
|
|
672
|
+
});
|
|
673
|
+
});
|
|
674
|
+
return res;
|
|
675
|
+
}
|
|
676
|
+
catch (err) {
|
|
677
|
+
throw new Error('Something went wrong. Please try again later.');
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
async fetchSpotlight() {
|
|
681
|
+
try {
|
|
682
|
+
const res = { results: [] };
|
|
683
|
+
const { data } = await this.client.get(`${this.baseUrl}/home`);
|
|
684
|
+
const $ = (0, cheerio_1.load)(data);
|
|
685
|
+
$('#slider div.swiper-wrapper div.swiper-slide').each((i, el) => {
|
|
686
|
+
var _a, _b, _c;
|
|
687
|
+
const card = $(el);
|
|
688
|
+
const titleElement = card.find('div.desi-head-title');
|
|
689
|
+
const id = ((_b = (_a = card
|
|
690
|
+
.find('div.desi-buttons .btn-secondary')
|
|
691
|
+
.attr('href')) === null || _a === void 0 ? void 0 : _a.match(/\/([^/]+)$/)) === null || _b === void 0 ? void 0 : _b[1]) || null;
|
|
692
|
+
const img = card.find('img.film-poster-img');
|
|
693
|
+
res.results.push({
|
|
694
|
+
id: id,
|
|
695
|
+
title: titleElement.text(),
|
|
696
|
+
japaneseTitle: titleElement.attr('data-jname'),
|
|
697
|
+
banner: img.attr('data-src') || img.attr('src') || null,
|
|
698
|
+
rank: parseInt((_c = card.find('.desi-sub-text').text().match(/(\d+)/g)) === null || _c === void 0 ? void 0 : _c[0]),
|
|
699
|
+
url: `${this.baseUrl}/${id}`,
|
|
700
|
+
type: card.find('div.sc-detail .scd-item:nth-child(1)').text().trim(),
|
|
701
|
+
duration: card.find('div.sc-detail > div:nth-child(2)').text().trim(),
|
|
702
|
+
releaseDate: card.find('div.sc-detail > div:nth-child(3)').text().trim(),
|
|
703
|
+
quality: card.find('div.sc-detail > div:nth-child(4)').text().trim(),
|
|
704
|
+
sub: parseInt(card.find('div.sc-detail div.tick-sub').text().trim()) || 0,
|
|
705
|
+
dub: parseInt(card.find('div.sc-detail div.tick-dub').text().trim()) || 0,
|
|
706
|
+
episodes: parseInt(card.find('div.sc-detail div.tick-eps').text()) || 0,
|
|
707
|
+
description: card.find('div.desi-description').text().trim(),
|
|
708
|
+
});
|
|
709
|
+
});
|
|
710
|
+
return res;
|
|
711
|
+
}
|
|
712
|
+
catch (error) {
|
|
713
|
+
throw new Error('Something went wrong. Please try again later.');
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
async fetchSearchSuggestions(query) {
|
|
717
|
+
try {
|
|
718
|
+
const encodedQuery = encodeURIComponent(query);
|
|
719
|
+
const { data } = await this.client.get(`${this.baseUrl}/ajax/search/suggest?keyword=${encodedQuery}`);
|
|
720
|
+
const $ = (0, cheerio_1.load)(data.html);
|
|
721
|
+
const res = {
|
|
722
|
+
results: [],
|
|
723
|
+
};
|
|
724
|
+
$('.nav-item').each((i, el) => {
|
|
725
|
+
var _a;
|
|
726
|
+
const card = $(el);
|
|
727
|
+
if (!card.hasClass('nav-bottom')) {
|
|
728
|
+
const image = card.find('.film-poster img').attr('data-src');
|
|
729
|
+
const title = card.find('.film-name');
|
|
730
|
+
const id = (_a = card.attr('href')) === null || _a === void 0 ? void 0 : _a.split('/')[1].split('?')[0];
|
|
731
|
+
const duration = card.find('.film-infor span').last().text().trim();
|
|
732
|
+
const releaseDate = card.find('.film-infor span:nth-child(1)').text().trim();
|
|
733
|
+
const type = card.find('.film-infor').find('span, i').remove().end().text().trim();
|
|
734
|
+
res.results.push({
|
|
735
|
+
image: image,
|
|
736
|
+
id: id,
|
|
737
|
+
title: title.text(),
|
|
738
|
+
japaneseTitle: title.attr('data-jname'),
|
|
739
|
+
aliasTitle: card.find('.alias-name').text(),
|
|
740
|
+
releaseDate: releaseDate,
|
|
741
|
+
type: type,
|
|
742
|
+
duration: duration,
|
|
743
|
+
url: `${this.baseUrl}/${id}`,
|
|
744
|
+
});
|
|
745
|
+
}
|
|
746
|
+
});
|
|
747
|
+
return res;
|
|
748
|
+
}
|
|
749
|
+
catch (error) {
|
|
750
|
+
throw new Error('Something went wrong. Please try again later.');
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Fetches the list of episodes that the user is currently watching.
|
|
755
|
+
* @param connectSid The session ID of the user. Note: This can be obtained from the browser cookies (needs to be signed in)
|
|
756
|
+
* @returns A promise that resolves to an array of anime episodes.
|
|
757
|
+
*/
|
|
758
|
+
async fetchContinueWatching(connectSid) {
|
|
759
|
+
try {
|
|
760
|
+
if (!(await this.verifyLoginState(connectSid))) {
|
|
761
|
+
throw new Error('Invalid session ID');
|
|
762
|
+
}
|
|
763
|
+
const res = [];
|
|
764
|
+
const { data } = await this.client.get(`${this.baseUrl}/user/continue-watching`, {
|
|
765
|
+
headers: {
|
|
766
|
+
Cookie: `connect.sid=${connectSid}`,
|
|
767
|
+
},
|
|
768
|
+
});
|
|
769
|
+
const $ = (0, cheerio_1.load)(data);
|
|
770
|
+
$('.flw-item').each((i, ele) => {
|
|
771
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
772
|
+
const card = $(ele);
|
|
773
|
+
const atag = card.find('.film-name a');
|
|
774
|
+
const id = (_b = (_a = atag.attr('href')) === null || _a === void 0 ? void 0 : _a.replace('/watch/', '')) === null || _b === void 0 ? void 0 : _b.replace('?ep=', '$episode$');
|
|
775
|
+
const timeText = (_e = (_d = (_c = card.find('.fdb-time')) === null || _c === void 0 ? void 0 : _c.text()) === null || _d === void 0 ? void 0 : _d.split('/')) !== null && _e !== void 0 ? _e : [];
|
|
776
|
+
const duration = (_g = (_f = timeText.pop()) === null || _f === void 0 ? void 0 : _f.trim()) !== null && _g !== void 0 ? _g : '';
|
|
777
|
+
const watchedTime = timeText.length > 0 ? timeText[0].trim() : '';
|
|
778
|
+
res.push({
|
|
779
|
+
id: id,
|
|
780
|
+
title: atag.text(),
|
|
781
|
+
number: parseInt(card.find('.fdb-type').text().replace('EP', '').trim()),
|
|
782
|
+
duration: duration,
|
|
783
|
+
watchedTime: watchedTime,
|
|
784
|
+
url: `${this.baseUrl}${atag.attr('href')}`,
|
|
785
|
+
image: (_h = card.find('img')) === null || _h === void 0 ? void 0 : _h.attr('data-src'),
|
|
786
|
+
japaneseTitle: atag.attr('data-jname'),
|
|
787
|
+
nsfw: ((_j = card.find('.tick-rate')) === null || _j === void 0 ? void 0 : _j.text()) === '18+' ? true : false,
|
|
788
|
+
sub: parseInt((_k = card.find('.tick-item.tick-sub')) === null || _k === void 0 ? void 0 : _k.text()) || 0,
|
|
789
|
+
dub: parseInt((_l = card.find('.tick-item.tick-dub')) === null || _l === void 0 ? void 0 : _l.text()) || 0,
|
|
790
|
+
episodes: parseInt((_m = card.find('.tick-item.tick-eps')) === null || _m === void 0 ? void 0 : _m.text()) || 0,
|
|
791
|
+
});
|
|
792
|
+
});
|
|
793
|
+
return res;
|
|
794
|
+
}
|
|
795
|
+
catch (err) {
|
|
796
|
+
throw new Error(err.message);
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
async fetchWatchList(connectSid, page = 1, sortListType) {
|
|
800
|
+
if (!(await this.verifyLoginState(connectSid))) {
|
|
801
|
+
throw new Error('Invalid session ID');
|
|
802
|
+
}
|
|
803
|
+
if (0 >= page) {
|
|
804
|
+
page = 1;
|
|
805
|
+
}
|
|
806
|
+
let type = 0;
|
|
807
|
+
switch (sortListType) {
|
|
808
|
+
case models_1.WatchListType.WATCHING:
|
|
809
|
+
type = 1;
|
|
810
|
+
case models_1.WatchListType.ONHOLD:
|
|
811
|
+
type = 2;
|
|
812
|
+
case models_1.WatchListType.PLAN_TO_WATCH:
|
|
813
|
+
type = 3;
|
|
814
|
+
case models_1.WatchListType.DROPPED:
|
|
815
|
+
type = 4;
|
|
816
|
+
case models_1.WatchListType.COMPLETED:
|
|
817
|
+
type = 5;
|
|
818
|
+
}
|
|
819
|
+
return this.scrapeCardPage(`${this.baseUrl}/user/watch-list?page=${page}${type != 0 ? '&type=' + type : ''}`, {
|
|
820
|
+
headers: { Cookie: `connect.sid=${connectSid}` },
|
|
821
|
+
});
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
exports.default = Hianime;
|
|
825
|
+
//# sourceMappingURL=hianime.js.map
|