better-ani-scraped 1.6.7 → 1.6.81

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.
@@ -3,7 +3,7 @@ import { getVideoUrlFromEmbed } from "../../index.js"; // REPLACE BY "from 'bett
3
3
  const main = async () => {
4
4
  const embedUrlSibnet = "https://video.sibnet.ru/shell.php?videoid=4291083";
5
5
  const embedUrlSendvid = "https://sendvid.com/embed/4vzpcb0q";
6
- const embedUrlVidmoly = "https://vidmoly.to/embed-vt374ef2joph.html";
6
+ const embedUrlVidmoly = "https://vidmoly.to/embed-rvqrwg5zk37w.html";
7
7
  const embedUrlOneupload = "https://oneupload.net/embed-axdrxh1y3p37.html";
8
8
 
9
9
  const videoUrlSibnet = await getVideoUrlFromEmbed("sibnet", embedUrlSibnet)
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "better-ani-scraped",
3
- "version": "1.6.7",
4
- "description": "Scrape anime data from different sources (only anime-sama.fr for the moment)",
3
+ "version": "1.6.81",
4
+ "description": "Scrape anime data from different sources (only anime-sama.fr, animepahe and crunchyroll for the moment)",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
7
  "test": "echo \"Error: no test specified\" && exit 1"
@@ -36,13 +36,19 @@ async function ensureChromiumInstalled(customPath) {
36
36
  }
37
37
 
38
38
  function getHeaders(referer = BASE_URL) {
39
+ const userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ' + '(KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36';
39
40
  return {
40
- "User-Agent": "Mozilla/5.0",
41
- "Accept-Language": "fr-FR,fr;q=0.9,en;q=0.8",
42
- Referer: referer,
41
+ headers: {
42
+ "User-Agent": userAgent,
43
+ "Accept-Language": "fr-FR,fr;q=0.9,en;q=0.8",
44
+ "Referer": referer,
45
+ },
46
+ userAgent
43
47
  };
44
48
  }
45
49
 
50
+
51
+
46
52
  export async function searchAnime(
47
53
  query,
48
54
  limit = 10,
@@ -53,6 +59,7 @@ export async function searchAnime(
53
59
  const languages = Array.isArray(wantedLanguages) ? wantedLanguages : ["vostfr", "vf", "vastfr"];
54
60
  const types = Array.isArray(wantedTypes) ? wantedTypes : ["Anime", "Film"];
55
61
 
62
+ const { headers } = getHeaders(CATALOGUE_URL);
56
63
  const isWanted = (text, list) =>
57
64
  list.length === 0 || list.some(item => text.toLowerCase().includes(item.toLowerCase()));
58
65
 
@@ -64,7 +71,7 @@ export async function searchAnime(
64
71
  ? `${CATALOGUE_URL}/?search=${encodeURIComponent(query)}`
65
72
  : `${CATALOGUE_URL}/?search=${encodeURIComponent(query)}&page=${pageNum}`;
66
73
 
67
- const res = await axios.get(url, { headers: getHeaders(CATALOGUE_URL) });
74
+ const res = await axios.get(url, { headers: headers });
68
75
  const $ = cheerio.load(res.data);
69
76
 
70
77
  const containers = $("a.flex.divide-x");
@@ -125,7 +132,9 @@ export async function searchAnime(
125
132
  }
126
133
 
127
134
  export async function getSeasons(animeUrl, languagePriority = ["vostfr", "vf", "va", "vkr", "vcn", "vqc", "vf1", "vf2"]) {
128
- const res = await axios.get(animeUrl, { headers: getHeaders(CATALOGUE_URL) });
135
+ const { headersCatalog } = getHeaders(CATALOGUE_URL);
136
+ const { headersAnime } = getHeaders(animeUrl);
137
+ const res = await axios.get(animeUrl, { headers: headersCatalog });
129
138
  const html = res.data;
130
139
 
131
140
  const mainAnimeOnly = html.split("Anime Version Kai")[0];
@@ -155,19 +164,19 @@ export async function getSeasons(animeUrl, languagePriority = ["vostfr", "vf", "
155
164
  const href = match[2].split("/")[0];
156
165
  const fullUrl = `${CATALOGUE_URL}/${animeName}/${href}/${language}`;
157
166
 
158
- try {
159
- const check = await axios.head(fullUrl, {
160
- headers: getHeaders(animeUrl),
161
- });
162
- if (check.status === 200) {
163
- languageAvailable = true;
164
- seasons.push({ title, url: fullUrl });
165
- }
166
- } catch (err) {
167
- // Ignore invalid URLs
167
+ try {
168
+ const check = await axios.head(fullUrl, {
169
+ headers: headersAnime,
170
+ });
171
+ if (check.status === 200) {
172
+ languageAvailable = true;
173
+ seasons.push({ title, url: fullUrl });
168
174
  }
175
+ } catch (err) {
176
+ // Ignore missing URLs
169
177
  }
170
178
  }
179
+ }
171
180
 
172
181
  if (languageAvailable) {
173
182
  return { language, seasons };
@@ -179,6 +188,7 @@ export async function getSeasons(animeUrl, languagePriority = ["vostfr", "vf", "
179
188
 
180
189
 
181
190
  export async function getEpisodeTitles(seasonUrl, customChromiumPath) {
191
+ const { headers, userAgent } = getHeaders(seasonUrl);
182
192
  let browser;
183
193
  try {
184
194
  const puppeteer = await import('puppeteer');
@@ -187,11 +197,15 @@ export async function getEpisodeTitles(seasonUrl, customChromiumPath) {
187
197
  browser = await puppeteer.launch({
188
198
  headless: true,
189
199
  executablePath,
190
- args: ['--no-sandbox', '--disable-setuid-sandbox'],
200
+ args: [
201
+ '--no-sandbox',
202
+ '--disable-setuid-sandbox',
203
+ ]
204
+
191
205
  });
192
206
 
193
207
  const page = await browser.newPage();
194
-
208
+ await page.setExtraHTTPHeaders(headers);
195
209
  await page.setRequestInterception(true);
196
210
  page.on('request', (req) => {
197
211
  const blocked = ['image', 'stylesheet', 'font', 'media'];
@@ -201,9 +215,13 @@ export async function getEpisodeTitles(seasonUrl, customChromiumPath) {
201
215
  req.continue();
202
216
  }
203
217
  });
204
-
218
+ await page.setUserAgent(userAgent);
219
+ await page.evaluateOnNewDocument(() => {
220
+ Object.defineProperty(navigator, 'webdriver', { get: () => false });
221
+ });
205
222
  await page.goto(seasonUrl, { waitUntil: 'domcontentloaded' });
206
223
  await page.waitForSelector('#selectEpisodes');
224
+
207
225
 
208
226
  const titres = await page.$$eval('#selectEpisodes option', options =>
209
227
  options.map(o => o.textContent.trim())
@@ -226,8 +244,10 @@ export async function getEmbed(
226
244
  includeInfo = false,
227
245
  customChromiumPath
228
246
  ) {
247
+ const { headersSplit } = getHeaders(seasonUrl.split("/").slice(0, 5).join("/"));
248
+ const { headers } = getHeaders(seasonUrl);
229
249
  const res = await axios.get(seasonUrl, {
230
- headers: getHeaders(seasonUrl.split("/").slice(0, 5).join("/")),
250
+ headers: headersSplit,
231
251
  });
232
252
 
233
253
  const $ = cheerio.load(res.data);
@@ -245,7 +265,7 @@ export async function getEmbed(
245
265
  : seasonUrl + "/" + scriptTag;
246
266
 
247
267
  const episodesJs = await axios
248
- .get(scriptUrl, { headers: getHeaders(seasonUrl) })
268
+ .get(scriptUrl, { headers: headers })
249
269
  .then((r) => r.data);
250
270
 
251
271
  const matches = [...episodesJs.matchAll(/var\s+(eps\d+)\s*=\s*(\[[^\]]+\])/g)];
@@ -302,13 +322,13 @@ export async function getEmbed(
302
322
  if (selectedUrl) break;
303
323
  }
304
324
 
305
- finalEmbeds.push({
306
- title: null, // à remplir plus tard
307
- url: selectedUrl || null,
308
- host: selectedHost || null,
309
- });
310
- }
325
+ finalEmbeds.push({
326
+ title: null,
327
+ url: selectedUrl || null,
328
+ host: selectedHost || null
329
+ });
311
330
  }
331
+ }
312
332
 
313
333
  const titles = await getEpisodeTitles(seasonUrl, customChromiumPath);
314
334
  finalEmbeds.forEach((embed, i) => {
@@ -331,7 +351,8 @@ export async function getEmbed(
331
351
 
332
352
 
333
353
  export async function getAnimeInfo(animeUrl) {
334
- const res = await axios.get(animeUrl, { headers: getHeaders(CATALOGUE_URL) });
354
+ const { headers } = getHeaders(CATALOGUE_URL);
355
+ const res = await axios.get(animeUrl, { headers: headers });
335
356
  const $ = cheerio.load(res.data);
336
357
 
337
358
  const cover = $("#coverOeuvre").attr("src");
@@ -367,6 +388,7 @@ export async function getAvailableLanguages(
367
388
  wantedLanguages = ["vostfr", "vf", "va", "vkr", "vcn", "vqc", "vf1", "vf2"],
368
389
  numberEpisodes = false
369
390
  ) {
391
+ const { headers } = getHeaders(CATALOGUE_URL);
370
392
  const languageLinks = [];
371
393
 
372
394
  // Iterate over each possible language and check if the page exists
@@ -374,7 +396,7 @@ export async function getAvailableLanguages(
374
396
  const languageUrl = seasonUrl.split('/').map((s, i) => i === 6 ? language : s).join('/');
375
397
  try {
376
398
  const res = await axios.get(languageUrl, {
377
- headers: getHeaders(CATALOGUE_URL),
399
+ headers: headers,
378
400
  });
379
401
  if (res.status === 200) {
380
402
  if (numberEpisodes){
@@ -400,6 +422,7 @@ export async function getAllAnime(
400
422
  output = "anime_list.json",
401
423
  get_seasons = false
402
424
  ) {
425
+ const { headers } = getHeaders(CATALOGUE_URL);
403
426
  let animeLinks = [];
404
427
 
405
428
  const isWanted = (text, list) =>
@@ -407,7 +430,7 @@ export async function getAllAnime(
407
430
 
408
431
  const fetchPage = async (pageNum) => {
409
432
  const url = pageNum === 1 ? CATALOGUE_URL : `${CATALOGUE_URL}?page=${pageNum}`;
410
- const res = await axios.get(url, { headers: getHeaders(CATALOGUE_URL) });
433
+ const res = await axios.get(url, { headers: headers });
411
434
  const $ = cheerio.load(res.data);
412
435
 
413
436
  const containers = $("div.shrink-0.m-3.rounded.border-2");
@@ -486,7 +509,8 @@ export async function getAllAnime(
486
509
 
487
510
  export async function getLatestEpisodes(languageFilter = null) {
488
511
  try {
489
- const res = await axios.get(BASE_URL, { headers: getHeaders() });
512
+ const { headers } = getHeaders(BASE_URL);
513
+ const res = await axios.get(BASE_URL, { headers: headers });
490
514
  const $ = cheerio.load(res.data);
491
515
 
492
516
  const container = $("#containerAjoutsAnimes");
@@ -498,7 +522,7 @@ export async function getLatestEpisodes(languageFilter = null) {
498
522
  const cover = $(el).find("img").attr("src");
499
523
 
500
524
  const buttons = $(el).find("button");
501
- const language = $(buttons[0]).text().trim().toLowerCase(); // Normalisation
525
+ const language = $(buttons[0]).text().trim().toLowerCase();
502
526
  const episode = $(buttons[1]).text().trim();
503
527
 
504
528
  if (
@@ -532,10 +556,11 @@ export async function getRandomAnime(
532
556
  maxAttempts = null,
533
557
  attempt = 0
534
558
  ) {
559
+ const { headers } = getHeaders(CATALOGUE_URL);
535
560
  try {
536
561
  const res = await axios.get(
537
562
  `${CATALOGUE_URL}/?search=&random=1`,
538
- { headers: getHeaders(CATALOGUE_URL) }
563
+ { headers:headers }
539
564
  );
540
565
 
541
566
  const $ = cheerio.load(res.data);
@@ -53,6 +53,9 @@ export async function getSendvidVideo(embedUrl) {
53
53
 
54
54
  export async function getVidmolyOrOneuploadVideo(embedUrl) {
55
55
  try {
56
+ if (embedUrl.includes("vidmoly.to/")) {
57
+ embedUrl = embedUrl.replace("vidmoly.to/", "vidmoly.net/");
58
+ }
56
59
  console.log(embedUrl)
57
60
  const { data } = await axios.get(embedUrl, {
58
61
  headers: getHeaders(embedUrl),