ani-web 1.5.8
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.
Potentially problematic release.
This version of ani-web might be problematic. Click here for more details.
- package/LICENSE +21 -0
- package/README.md +174 -0
- package/client/dist/assets/AnimeInfo-C7DQp7Oo.js +1 -0
- package/client/dist/assets/AnimeInfo-Sb3YiXHJ.css +1 -0
- package/client/dist/assets/AnimeInfoPage-DJA7AJQ8.js +2 -0
- package/client/dist/assets/Button-Fq9KaUOg.css +1 -0
- package/client/dist/assets/Button-o0l9V_NG.js +1 -0
- package/client/dist/assets/ErrorMessage-Ddf2zmRx.js +1 -0
- package/client/dist/assets/ErrorMessage-FOxXyZC9.css +1 -0
- package/client/dist/assets/Home-CKHJA97j.css +1 -0
- package/client/dist/assets/Home-Dey0azy1.js +1 -0
- package/client/dist/assets/Insights-BSRcCkDs.css +1 -0
- package/client/dist/assets/Insights-CogjPOd_.js +1 -0
- package/client/dist/assets/MAL-CYArH4yf.js +1 -0
- package/client/dist/assets/MAL-DeQNXXPx.css +1 -0
- package/client/dist/assets/Player-BWFN9gud.js +9 -0
- package/client/dist/assets/Player-CBCYW7uG.css +1 -0
- package/client/dist/assets/PlayerSettings-BgStUrrP.css +1 -0
- package/client/dist/assets/PlayerSettings-rWZuATQf.js +1 -0
- package/client/dist/assets/RemoveConfirmationModal-BBiogSdf.css +1 -0
- package/client/dist/assets/RemoveConfirmationModal-CLYqyGOv.js +1 -0
- package/client/dist/assets/Search-DZAWgKwq.js +1 -0
- package/client/dist/assets/Search-lWsVQ0Ke.css +1 -0
- package/client/dist/assets/Settings-Bv9fX-x3.css +1 -0
- package/client/dist/assets/Settings-DyisJGeD.js +1 -0
- package/client/dist/assets/ToggleSwitch-CLnWnAuY.js +1 -0
- package/client/dist/assets/ToggleSwitch-DInRb7iM.css +1 -0
- package/client/dist/assets/Watchlist-2dVYksxq.css +1 -0
- package/client/dist/assets/Watchlist-CuqJISI3.js +1 -0
- package/client/dist/assets/hls.light-DcbkToIY.js +27 -0
- package/client/dist/assets/index-BK_Zaqaw.css +1 -0
- package/client/dist/assets/index-CHVF4D4L.js +178 -0
- package/client/dist/assets/useAnimeInfoData-Cr58brCY.js +1 -0
- package/client/dist/assets/useIsMobile-gHo4t6g6.js +1 -0
- package/client/dist/assets/vendor-DdbgYKo4.js +3 -0
- package/client/dist/favicon.ico +0 -0
- package/client/dist/index.html +35 -0
- package/client/dist/logo.png +0 -0
- package/client/dist/placeholder.svg +4 -0
- package/client/dist/robots.txt +3 -0
- package/client/package.json +54 -0
- package/orchestrator.js +302 -0
- package/package.json +69 -0
- package/server/dist/config.js +86 -0
- package/server/dist/constants.json +1359 -0
- package/server/dist/controllers/auth.controller.js +213 -0
- package/server/dist/controllers/data.controller.js +126 -0
- package/server/dist/controllers/insights.controller.js +125 -0
- package/server/dist/controllers/proxy.controller.js +235 -0
- package/server/dist/controllers/settings.controller.js +147 -0
- package/server/dist/controllers/watchlist.controller.js +499 -0
- package/server/dist/db.js +231 -0
- package/server/dist/github-sync.js +279 -0
- package/server/dist/google.js +274 -0
- package/server/dist/logger.js +21 -0
- package/server/dist/providers/123anime.provider.js +229 -0
- package/server/dist/providers/allanime.provider.js +773 -0
- package/server/dist/providers/animepahe.provider.js +313 -0
- package/server/dist/providers/animeya.provider.js +799 -0
- package/server/dist/providers/provider.interface.js +2 -0
- package/server/dist/rclone.js +126 -0
- package/server/dist/repositories/insights.repository.js +30 -0
- package/server/dist/repositories/notifications.repository.js +22 -0
- package/server/dist/repositories/settings.repository.js +13 -0
- package/server/dist/repositories/shows-meta.repository.js +39 -0
- package/server/dist/repositories/watched-episodes.repository.js +60 -0
- package/server/dist/repositories/watchlist.repository.js +49 -0
- package/server/dist/routes/auth.routes.js +23 -0
- package/server/dist/routes/data.routes.js +43 -0
- package/server/dist/routes/insights.routes.js +11 -0
- package/server/dist/routes/proxy.routes.js +13 -0
- package/server/dist/routes/settings.routes.js +26 -0
- package/server/dist/routes/watchlist.routes.js +26 -0
- package/server/dist/server.js +179 -0
- package/server/dist/sync-config.js +28 -0
- package/server/dist/sync.js +383 -0
- package/server/dist/utils/db-utils.js +36 -0
- package/server/dist/utils/env.utils.js +70 -0
- package/server/package.json +54 -0
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.AnimePaheProvider = void 0;
|
|
40
|
+
const cheerio = __importStar(require("cheerio"));
|
|
41
|
+
const logger_1 = __importDefault(require("../logger"));
|
|
42
|
+
class AnimePaheProvider {
|
|
43
|
+
name = 'AnimePahe';
|
|
44
|
+
base = 'https://animepahe.pw';
|
|
45
|
+
apiBase = 'https://animepahe.pw/api';
|
|
46
|
+
cache;
|
|
47
|
+
constructor(cache) {
|
|
48
|
+
this.cache = cache;
|
|
49
|
+
}
|
|
50
|
+
getHeaders(isApi = false) {
|
|
51
|
+
const cookies = {
|
|
52
|
+
__ddg1_: '5H0114JE1p0wQHdJiV2O',
|
|
53
|
+
__ddg2_: 'FxnuwLkvPnXSQtPE',
|
|
54
|
+
__ddg8_: 'j55RhixQcxVPfvqt',
|
|
55
|
+
__ddg9_: '51.158.195.12',
|
|
56
|
+
__ddg10_: '1769167572',
|
|
57
|
+
__ddgid_: 'ExAWs3AJTzpAKb8m',
|
|
58
|
+
__ddgmark_: 'slbgrX6Jj2jTxuo2',
|
|
59
|
+
};
|
|
60
|
+
const cookieString = Object.entries(cookies)
|
|
61
|
+
.map(([key, val]) => `${key}=${val}`)
|
|
62
|
+
.join('; ');
|
|
63
|
+
const headers = {
|
|
64
|
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36',
|
|
65
|
+
Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
|
|
66
|
+
'Accept-Language': 'en-US,en;q=0.9',
|
|
67
|
+
Referer: 'https://animepahe.pw/',
|
|
68
|
+
Origin: 'https://animepahe.pw',
|
|
69
|
+
Cookie: cookieString,
|
|
70
|
+
};
|
|
71
|
+
if (isApi) {
|
|
72
|
+
headers['X-Requested-With'] = 'XMLHttpRequest';
|
|
73
|
+
headers['Accept'] = 'application/json, text/javascript, */*; q=0.01';
|
|
74
|
+
}
|
|
75
|
+
return headers;
|
|
76
|
+
}
|
|
77
|
+
async get(url, isApi = false) {
|
|
78
|
+
try {
|
|
79
|
+
const response = await fetch(url, {
|
|
80
|
+
method: 'GET',
|
|
81
|
+
headers: this.getHeaders(isApi),
|
|
82
|
+
});
|
|
83
|
+
const text = await response.text();
|
|
84
|
+
if (!response.ok) {
|
|
85
|
+
if (response.status === 403 || text.includes('DDoS-Guard')) {
|
|
86
|
+
logger_1.default.error('DDoS-Guard blocked the request! Your ANIMEPAHE_COOKIES in .env are likely expired.');
|
|
87
|
+
}
|
|
88
|
+
throw new Error(`HTTP ${response.status}`);
|
|
89
|
+
}
|
|
90
|
+
return text;
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
const err = error;
|
|
94
|
+
logger_1.default.error({ url, err: err.message }, 'AnimePahe Fetch failed');
|
|
95
|
+
throw error;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
async getJson(url) {
|
|
99
|
+
const data = await this.get(url, true);
|
|
100
|
+
try {
|
|
101
|
+
return JSON.parse(data);
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
logger_1.default.error({ url }, 'Failed to parse JSON (likely blocked by bot protection)');
|
|
105
|
+
return {};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
async search(options) {
|
|
109
|
+
try {
|
|
110
|
+
const query = options.query || '';
|
|
111
|
+
const url = `${this.apiBase}?m=search&q=${encodeURIComponent(query)}`;
|
|
112
|
+
const data = (await this.getJson(url));
|
|
113
|
+
const animeRows = (data.data || data.results || data.items || []);
|
|
114
|
+
return animeRows.map((a) => ({
|
|
115
|
+
_id: a.session,
|
|
116
|
+
id: a.session,
|
|
117
|
+
name: a.title || a.name || '',
|
|
118
|
+
englishName: a.title,
|
|
119
|
+
thumbnail: a.poster || a.image,
|
|
120
|
+
type: a.type,
|
|
121
|
+
year: a.year,
|
|
122
|
+
session: a.session,
|
|
123
|
+
}));
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
return [];
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
async getEpisodes(showId) {
|
|
130
|
+
try {
|
|
131
|
+
const firstPageUrl = `${this.apiBase}?m=release&id=${showId}&sort=episode_asc&page=1`;
|
|
132
|
+
const firstPageData = (await this.getJson(firstPageUrl));
|
|
133
|
+
let episodes = (firstPageData.data || firstPageData.results || []);
|
|
134
|
+
const lastPage = Number(firstPageData.last_page || firstPageData.lastPage || 1);
|
|
135
|
+
for (let p = 2; p <= lastPage; p++) {
|
|
136
|
+
const pageUrl = `${this.apiBase}?m=release&id=${showId}&sort=episode_asc&page=${p}`;
|
|
137
|
+
const pageData = (await this.getJson(pageUrl));
|
|
138
|
+
episodes = episodes.concat((pageData.data || pageData.results || []));
|
|
139
|
+
}
|
|
140
|
+
const episodeMap = {};
|
|
141
|
+
const episodeNumbers = [];
|
|
142
|
+
episodes.forEach((ep) => {
|
|
143
|
+
const epNum = (ep.episode ?? ep.number ?? '').toString();
|
|
144
|
+
if (epNum) {
|
|
145
|
+
episodeMap[epNum] = ep.session || ep.release_session || '';
|
|
146
|
+
episodeNumbers.push(epNum);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
this.cache.set(`animepahe_epmap_${showId}`, episodeMap, 86400);
|
|
150
|
+
return {
|
|
151
|
+
episodes: episodeNumbers.sort((a, b) => Number(a) - Number(b)),
|
|
152
|
+
description: '',
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
async getEpisodeSession(showId, episodeNumber) {
|
|
160
|
+
const cacheKey = `animepahe_epmap_${showId}`;
|
|
161
|
+
let cachedMap = this.cache.get(cacheKey);
|
|
162
|
+
if (!cachedMap) {
|
|
163
|
+
await this.getEpisodes(showId);
|
|
164
|
+
cachedMap = this.cache.get(cacheKey);
|
|
165
|
+
}
|
|
166
|
+
if (!cachedMap)
|
|
167
|
+
return null;
|
|
168
|
+
if (cachedMap[episodeNumber]) {
|
|
169
|
+
return cachedMap[episodeNumber];
|
|
170
|
+
}
|
|
171
|
+
const requestedNum = parseFloat(episodeNumber);
|
|
172
|
+
const keys = Object.keys(cachedMap);
|
|
173
|
+
for (const key of keys) {
|
|
174
|
+
if (parseFloat(key) === requestedNum) {
|
|
175
|
+
return cachedMap[key];
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
const sortedKeys = keys.sort((a, b) => Number(a) - Number(b));
|
|
179
|
+
const minEp = Number(sortedKeys[0]);
|
|
180
|
+
if (requestedNum < minEp) {
|
|
181
|
+
const index = Math.floor(requestedNum) - 1;
|
|
182
|
+
if (index >= 0 && index < sortedKeys.length) {
|
|
183
|
+
const actualEpNum = sortedKeys[index];
|
|
184
|
+
return cachedMap[actualEpNum];
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
async getStreamUrls(showId, episodeNumber) {
|
|
190
|
+
try {
|
|
191
|
+
const epSession = await this.getEpisodeSession(showId, episodeNumber);
|
|
192
|
+
if (!epSession)
|
|
193
|
+
return null;
|
|
194
|
+
const sources = await this.getSources(showId, epSession);
|
|
195
|
+
const videoSources = [];
|
|
196
|
+
for (const src of sources) {
|
|
197
|
+
const label = src.fansub
|
|
198
|
+
? `${src.quality || 'Auto'} - ${src.fansub} (${src.audio || 'jpn'})`
|
|
199
|
+
: `${src.quality || 'Auto'} - ${src.audio || 'jpn'}`;
|
|
200
|
+
videoSources.push({
|
|
201
|
+
sourceName: label,
|
|
202
|
+
links: [
|
|
203
|
+
{
|
|
204
|
+
resolutionStr: src.quality || 'Auto',
|
|
205
|
+
link: src.url,
|
|
206
|
+
hls: false,
|
|
207
|
+
},
|
|
208
|
+
],
|
|
209
|
+
type: 'iframe',
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
return videoSources.length > 0 ? videoSources : null;
|
|
213
|
+
}
|
|
214
|
+
catch {
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
async getSources(animeSession, episodeSession) {
|
|
219
|
+
try {
|
|
220
|
+
const playUrl = `${this.base}/play/${animeSession}/${episodeSession}`;
|
|
221
|
+
const html = await this.get(playUrl);
|
|
222
|
+
const $ = cheerio.load(html);
|
|
223
|
+
const sources = [];
|
|
224
|
+
$('[data-src]').each((_, el) => {
|
|
225
|
+
const src = $(el).attr('data-src')?.trim();
|
|
226
|
+
if (!src || !/kwik/i.test(src))
|
|
227
|
+
return;
|
|
228
|
+
const resolution = $(el).attr('data-resolution') || $(el).attr('data-res');
|
|
229
|
+
sources.push({
|
|
230
|
+
url: src,
|
|
231
|
+
quality: resolution ? (resolution.endsWith('p') ? resolution : `${resolution}p`) : null,
|
|
232
|
+
fansub: $(el).attr('data-fansub') ?? null,
|
|
233
|
+
audio: $(el).attr('data-audio') ?? null,
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
const unique = Array.from(new Map(sources.map((s) => [s.url, s])).values());
|
|
237
|
+
unique.sort((a, b) => {
|
|
238
|
+
const qa = a.quality ? parseInt(a.quality) || 0 : 0;
|
|
239
|
+
const qb = b.quality ? parseInt(b.quality) || 0 : 0;
|
|
240
|
+
return qb - qa;
|
|
241
|
+
});
|
|
242
|
+
return unique;
|
|
243
|
+
}
|
|
244
|
+
catch {
|
|
245
|
+
return [];
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
async resolveKwik(kwikUrl) {
|
|
249
|
+
try {
|
|
250
|
+
const fetchUrl = kwikUrl.replace('/e/', '/f/');
|
|
251
|
+
const response = await fetch(fetchUrl, {
|
|
252
|
+
headers: {
|
|
253
|
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
|
|
254
|
+
Referer: 'https://animepahe.pw/',
|
|
255
|
+
},
|
|
256
|
+
});
|
|
257
|
+
const html = await response.text();
|
|
258
|
+
if (html.includes('Just a moment')) {
|
|
259
|
+
throw new Error('Kwik triggered a Cloudflare challenge.');
|
|
260
|
+
}
|
|
261
|
+
const directMatch = html.match(/(?:source|file)\s*:\s*['"]([^'"]+\.m3u8)['"]/);
|
|
262
|
+
if (directMatch)
|
|
263
|
+
return { m3u8: directMatch[1], referer: kwikUrl };
|
|
264
|
+
const packedMatch = html.match(/'([^']{50,})'\.split\('\|'\)/);
|
|
265
|
+
if (packedMatch) {
|
|
266
|
+
const parts = packedMatch[1].split('|');
|
|
267
|
+
const hash = parts.find((p) => p.length === 64 && /^[a-f0-9]+$/.test(p));
|
|
268
|
+
const domain = parts.find((p) => p.includes('owocdn'));
|
|
269
|
+
if (hash) {
|
|
270
|
+
const cdn = domain || 'na.owocdn.top';
|
|
271
|
+
return { m3u8: `https://${cdn}/stream/01/${hash}/uwu.m3u8`, referer: kwikUrl };
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
throw new Error('Could not regex m3u8 link from Kwik HTML');
|
|
275
|
+
}
|
|
276
|
+
catch (err) {
|
|
277
|
+
const error = err;
|
|
278
|
+
logger_1.default.error({ err: error.message }, 'Kwik Resolve failed');
|
|
279
|
+
return { m3u8: '', referer: kwikUrl };
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
async getShowMeta(showId) {
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
285
|
+
async getPopular() {
|
|
286
|
+
return [];
|
|
287
|
+
}
|
|
288
|
+
async getSchedule() {
|
|
289
|
+
return [];
|
|
290
|
+
}
|
|
291
|
+
async getSeasonal() {
|
|
292
|
+
return [];
|
|
293
|
+
}
|
|
294
|
+
async getLatestReleases() {
|
|
295
|
+
return [];
|
|
296
|
+
}
|
|
297
|
+
async getSkipTimes() {
|
|
298
|
+
return { found: false, results: [] };
|
|
299
|
+
}
|
|
300
|
+
async getShowDetails() {
|
|
301
|
+
return { status: 'Unknown' };
|
|
302
|
+
}
|
|
303
|
+
async getAllmangaDetails() {
|
|
304
|
+
return {
|
|
305
|
+
Rating: 'N/A',
|
|
306
|
+
Season: 'N/A',
|
|
307
|
+
Episodes: 'N/A',
|
|
308
|
+
Date: 'N/A',
|
|
309
|
+
'Original Broadcast': 'N/A',
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
exports.AnimePaheProvider = AnimePaheProvider;
|