better-ani-scraped 1.5.2 → 1.6.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/DOCUMENTATION.md CHANGED
@@ -316,10 +316,14 @@ Extracts information from all episodes of a season of an anime.
316
316
  Retrieves the video URL of the source's embed.
317
317
 
318
318
  - **Parameters:**
319
- - `source` *(string)*: The embed source (only "sibnet" available at the moment)
319
+ - `source` *(string)*: The embed source (only "sibnet", "sendvid", "vidmoly" and "oneupload" available at the moment)
320
320
  - `embedUrl` *(string)*: The embed url of the given source.
321
321
  - **Returns:**
322
- A video URL as a string.
322
+ A video URL as a string :
323
+ - `sibnet`: mp4
324
+ - `sendvid`: mp4
325
+ - `vidmoly`: m3u8
326
+ - `oneupload`: m3u8
323
327
 
324
328
  ---
325
329
  ---
@@ -1,11 +1,22 @@
1
1
  import { getVideoUrlFromEmbed } from "../../index.js"; // REPLACE BY "from 'better-ani-scraped';"
2
2
 
3
3
  const main = async () => {
4
- const embedUrl = "https://video.sibnet.ru/shell.php?videoid=4291083";
5
-
6
- const videoUrl = await getVideoUrlFromEmbed("sibnet", embedUrl)
7
- console.log("Video URL:", videoUrl);
4
+ const embedUrlSibnet = "https://video.sibnet.ru/shell.php?videoid=4291083";
5
+ const embedUrlSendvid = "https://sendvid.com/embed/4vzpcb0q";
6
+ const embedUrlVidmoly = "https://vidmoly.to/embed-vt374ef2joph.html";
7
+ const embedUrlOneupload = "https://oneupload.net/embed-axdrxh1y3p37.html";
8
+
9
+ const videoUrlSibnet = await getVideoUrlFromEmbed("sibnet", embedUrlSibnet)
10
+ console.log("Video URL Sibnet:", videoUrlSibnet);
8
11
 
12
+ const videoUrlSendvid = await getVideoUrlFromEmbed("sendvid", embedUrlSendvid)
13
+ console.log("Video URL Sendvid:", videoUrlSendvid);
14
+
15
+ const videoUrlVidmoly = await getVideoUrlFromEmbed("vidmoly", embedUrlVidmoly)
16
+ console.log("Video URL Vidmoly:", videoUrlVidmoly);
17
+
18
+ const videoUrlOneupload = await getVideoUrlFromEmbed("oneupload", embedUrlOneupload)
19
+ console.log("Video URL Oneupload:", videoUrlOneupload);
9
20
  };
10
21
 
11
22
  main().catch(console.error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "better-ani-scraped",
3
- "version": "1.5.2",
3
+ "version": "1.6.0",
4
4
  "description": "Scrape anime data from different sources (only anime-sama.fr for the moment)",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -21,7 +21,7 @@
21
21
  "axios": "^1.8.4",
22
22
  "cheerio": "^1.0.0",
23
23
  "playwright": "^1.52.0",
24
- "puppeteer": "^24.7.2",
24
+ "puppeteer": "^24.8.1",
25
25
  "puppeteer-extra": "^3.3.6",
26
26
  "puppeteer-extra-plugin-stealth": "^2.11.2"
27
27
  },
@@ -4,6 +4,12 @@ export async function getVideoUrlFromEmbed(source, embedUrl) {
4
4
  if (source === "sibnet") {
5
5
  return await extractor.getSibnetVideo(embedUrl);
6
6
  }
7
+ if (source === "sendvid") {
8
+ return await extractor.getSendvidVideo(embedUrl);
9
+ }
10
+ if (source === "vidmoly" || source === "oneupload" ) {
11
+ return await extractor.getVidmolyOrOneuploadVideo(embedUrl);
12
+ }
7
13
 
8
14
  throw new Error(`Unsupported embed source: ${source}`);
9
15
  }
@@ -1,67 +1,74 @@
1
1
  import axios from "axios";
2
2
  import * as cheerio from "cheerio";
3
3
 
4
- export async function getSibnetVideo(embedUrl) {
5
- let intermediaries = [];
6
- let realUrl = "";
7
-
8
- const getIntermediary = async () => {
9
- try {
10
- const { data } = await axios.get(embedUrl, { headers: getHeaders(embedUrl) });
11
- const $ = cheerio.load(data);
12
- const script = $("script")
13
- .toArray()
14
- .map((s) => $(s).html())
15
- .find((s) => s.includes("player.src"));
16
- const match = script?.match(/player\.src\(\[{src:\s*["']([^"']+)["']/);
17
- if (match) intermediaries.push(`https://video.sibnet.ru${match[1]}`);
18
- return !!match;
19
- } catch {
20
- return false;
21
- }
22
- };
23
4
 
24
- const followRedirection = async () => {
25
- if (!intermediaries.length) return false;
26
- try {
27
- const first = await axios.get(intermediaries[0], {
28
- headers: getHeaders(embedUrl),
29
- maxRedirects: 0,
30
- validateStatus: (s) => s >= 200 && s < 303,
31
- });
5
+ const getHeaders = (referer) => ({
6
+ Accept: "*/*",
7
+ Referer: referer,
8
+ "User-Agent":
9
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
10
+ });
11
+ export async function getSibnetVideo(embedUrl) {
12
+ try {
13
+ const { data } = await axios.get(embedUrl, {
14
+ headers: getHeaders(embedUrl),
15
+ });
16
+ const $ = cheerio.load(data);
17
+ const script = $("script")
18
+ .toArray()
19
+ .map((s) => $(s).html())
20
+ .find((s) => s.includes("player.src"));
21
+ const match = script?.match(/player\.src\(\[{src:\s*["']([^"']+)["']/);
22
+ if (!match || !match[1]) return null;
23
+ const intermediateUrl = `https://video.sibnet.ru${match[1]}`;
24
+ const res1 = await axios.get(intermediateUrl, {
25
+ headers: getHeaders(embedUrl),
26
+ maxRedirects: 0,
27
+ validateStatus: (s) => s >= 200 && s < 400,
28
+ });
29
+ const redirectUrl = res1.headers.location;
30
+ if (!redirectUrl) return null;
31
+ const finalUrl = redirectUrl.startsWith("http")
32
+ ? redirectUrl
33
+ : `https:${redirectUrl}`;
34
+ return finalUrl;
35
+ } catch (err) {
36
+ console.error("Erreur getSibnetVideo:", err.message);
37
+ return null;
38
+ }
39
+ }
32
40
 
33
- const redirect1 = correct(first.headers.location);
34
- intermediaries.push(redirect1);
41
+ export async function getSendvidVideo(embedUrl) {
42
+ try {
43
+ const { data } = await axios.get(embedUrl, {
44
+ headers: getHeaders(embedUrl),
45
+ });
46
+ const $ = cheerio.load(data);
47
+ const sourceTag = $("video source[type='video/mp4']").attr("src");
48
+ return sourceTag || null;
49
+ } catch (err) {
50
+ return null;
51
+ }
52
+ }
35
53
 
36
- const second = await axios.get(redirect1, {
37
- headers: getHeaders(intermediaries[0]),
38
- maxRedirects: 0,
39
- validateStatus: (s) => s >= 200 && s < 303,
40
- });
54
+ export async function getVidmolyOrOneuploadVideo(embedUrl) {
55
+ try {
56
+ const { data } = await axios.get(embedUrl, {
57
+ headers: getHeaders(embedUrl),
58
+ });
59
+ const $ = cheerio.load(data);
60
+ const scripts = $("script");
41
61
 
42
- realUrl =
43
- second.status === 302
44
- ? correct(second.headers.location)
45
- : second.status === 200
46
- ? intermediaries.pop()
47
- : "";
48
- return !!realUrl;
49
- } catch {
50
- return false;
62
+ for (let i = 0; i < scripts.length; i++) {
63
+ const content = $(scripts[i]).html();
64
+ const match = content && content.match(/file\s*:\s*"(https[^"]+\.m3u8[^"]*)"/);
65
+ if (match && match[1]) {
66
+ return match[1];
67
+ }
51
68
  }
52
- };
53
-
54
- const correct = (url) => (url.startsWith("https:") ? url : `https:${url}`);
55
-
56
- const getHeaders = (referer) => ({
57
- Accept: "*/*",
58
- Referer: referer,
59
- Range: "bytes=0-",
60
- "User-Agent":
61
- "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
62
- });
63
-
64
- return (await getIntermediary()) && (await followRedirection())
65
- ? realUrl
66
- : null;
69
+ return null;
70
+ } catch (err) {
71
+ console.error("Erreur getVidmolyVideo:", err.message);
72
+ return null;
73
+ }
67
74
  }