SteveCelticus commited on
Commit
ab32af0
·
verified ·
1 Parent(s): c888a42

Upload 9 files

Browse files
Files changed (6) hide show
  1. episodes.js +87 -57
  2. main.js +41 -15
  3. package-lock.json +0 -0
  4. package.json +23 -22
  5. rama_series.js +118 -30
  6. streams.js +69 -61
episodes.js CHANGED
@@ -1,57 +1,87 @@
1
- import axios from 'axios';
2
- import cloudscraper from 'cloudscraper';
3
- import * as cheerio from 'cheerio';
4
- import ProxyAgent from 'proxy-agent';
5
- import { getEpisodes } from './streams.js';
6
-
7
- const proxyUrl = process.env.PROXY_URL;
8
-
9
- const axiosInstance = axios.create({
10
- headers: {
11
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36',
12
- 'Referer': 'https://ramaorientalfansub.tv/paese/corea-del-sud/',
13
- 'Accept-Language': 'en-US,en;q=0.9',
14
- },
15
- httpAgent: proxyUrl ? new ProxyAgent(proxyUrl) : undefined,
16
- httpsAgent: proxyUrl ? new ProxyAgent(proxyUrl) : undefined,
17
- });
18
-
19
- async function fetchWithCloudscraper(url) {
20
- try {
21
- const options = {
22
- uri: url,
23
- agent: proxyUrl ? new ProxyAgent(proxyUrl) : undefined,
24
- };
25
- const data = await cloudscraper.get(options);
26
- return data;
27
- } catch (error) {
28
- console.error("Errore con Cloudscraper:", error);
29
- return null;
30
- }
31
- }
32
-
33
- async function getMeta(id) {
34
- const meta = { id, type: 'series', name: '', poster: '', episodes: [] };
35
- const cleanId = id.replace(/,/g, '-').toLowerCase();
36
- const baseId = cleanId.replace(/-\d{4}$/, '');
37
- const seriesLink = `https://ramaorientalfansub.tv/drama/${baseId}/`;
38
-
39
- try {
40
- const { data } = await axiosInstance.get(seriesLink);
41
- const $ = cheerio.load(data);
42
-
43
- meta.name = $('a.text-accent').text().trim();
44
- meta.poster = $('img.wp-post-image').attr('src');
45
- meta.description = $('div.font-light > div:nth-child(1)').text().trim();
46
- console.log('Chiamata a getEpisodes con URL:', seriesLink);
47
- meta.episodes = await getEpisodes(seriesLink);
48
- console.log('Episodi trovati:', meta.episodes);
49
- } catch (error) {
50
- console.error('Errore nel caricamento dei dettagli della serie:', error);
51
- }
52
-
53
- console.log('Meta finale:', meta);
54
- return { meta };
55
- }
56
-
57
- export { axiosInstance, getMeta, fetchWithCloudscraper };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import axios from 'axios';
2
+ import cloudscraper from 'cloudscraper';
3
+ import * as cheerio from 'cheerio';
4
+ import { getStream, getEpisodes } from './streams.js'; // Importa sia getStream che getEpisodes
5
+
6
+ // Lista di User-Agent
7
+ const userAgents = [
8
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.3',
9
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0',
10
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1 Safari/605.1.15'
11
+ ];
12
+
13
+ // Funzione per ottenere headers casuali
14
+ function getRandomHeaders() {
15
+ const userAgent = userAgents[Math.floor(Math.random() * userAgents.length)];
16
+ return {
17
+ 'User-Agent': userAgent,
18
+ 'Referer': 'https://ramaorientalfansub.tv/paese/corea-del-sud/',
19
+ 'Accept-Language': 'en-US,en;q=0.9'
20
+ };
21
+ }
22
+
23
+ // Istanza di Axios con headers casuali
24
+ const axiosInstance = axios.create({
25
+ headers: getRandomHeaders()
26
+ });
27
+ export { axiosInstance, axios, cloudscraper, cheerio };
28
+ // Cache per i metadati delle serie
29
+ const metaCache = new Map();
30
+
31
+ async function fetchWithCloudscraper(url) {
32
+ try {
33
+ const data = await cloudscraper.get({
34
+ uri: url,
35
+ headers: getRandomHeaders() // Aggiungi headers casuali anche qui
36
+ });
37
+ return data;
38
+ } catch (error) {
39
+ console.error("Errore con Cloudscraper:", error);
40
+ return null;
41
+ }
42
+ }
43
+
44
+ async function getMeta(id) {
45
+ const meta = { id, type: 'series', name: '', poster: '', episodes: [] };
46
+ const cleanId = id.replace(/,/g, '').replace(/\s+/g, '-').toLowerCase();
47
+ const baseId = cleanId.replace(/-\d{4}$/, '');
48
+ const seriesLink = `https://ramaorientalfansub.tv/drama/${baseId}/`;
49
+ // Verifica se i metadati sono in cache
50
+ if (metaCache.has(id)) {
51
+ console.log(`Caricamento metadati dalla cache per ${id}`);
52
+ return { meta: metaCache.get(id) }; // Restituisci direttamente i metadati dalla cache
53
+ }
54
+
55
+ try {
56
+ const data = await fetchWithCloudscraper(seriesLink);
57
+ if (!data) {
58
+ console.warn(`Nessun dato ricevuto per ${seriesLink}`);
59
+ return { meta };
60
+ }
61
+
62
+ const $ = cheerio.load(data);
63
+ // Carica i metadati (name, poster, description)
64
+ meta.name = $('a.text-accent').text().trim();
65
+ meta.poster = $('img.wp-post-image').attr('src');
66
+ let description = $('div.font-light > div:nth-child(1)').text().trim(); // Recupera la descrizione
67
+ // Aggiungi il tag alla descrizione se presente
68
+ if (meta.extra && meta.extra.tag) {
69
+ description += ` [${meta.extra.tag.toUpperCase()}]`;
70
+ }
71
+
72
+ meta.description = description; // Assegna la descrizione modificata a meta.description
73
+ // Carica gli episodi
74
+ meta.episodes = await getEpisodes(seriesLink, $); // Passa l'oggetto cheerio
75
+ console.log('Episodi trovati:', meta.episodes);
76
+ // Salva i metadati nella cache (CON gli episodi)
77
+ metaCache.set(id, meta);
78
+ console.log(`Metadati salvati nella cache per ${id}`);
79
+ } catch (error) {
80
+ console.error('Errore nel caricamento dei dettagli della serie:', error);
81
+ }
82
+
83
+ console.log('Meta finale:', meta);
84
+ return { meta };
85
+ }
86
+
87
+ export { getMeta };
main.js CHANGED
@@ -2,7 +2,6 @@ import pkg from 'stremio-addon-sdk';
2
  import seriesCatalog from './rama_series.js';
3
  import filmsCatalog from './rama_films.js';
4
  import { getMeta } from './episodes.js';
5
- import { getEpisodes } from './streams.js';
6
 
7
  const { addonBuilder, serveHTTP } = pkg;
8
 
@@ -16,46 +15,59 @@ const manifest = {
16
  "type": "series",
17
  "id": "rama_series",
18
  "name": "Serie Coreane",
19
- "extra": [{"name": "skip"}]
20
  },
21
  {
22
  "type": "movie",
23
  "id": "rama_films",
24
  "name": "Film Coreani",
25
- "extra": [{"name": "skip"}]
26
  }
27
  ],
28
- "resources": ["catalog", "meta", "stream"], // Aggiunto stream
29
  "types": ["series", "movie"],
30
  "logo": "https://ramaorientalfansub.tv/wp-content/uploads/2023/10/cropped-Logo-1.png",
31
  "background": "https://ramaorientalfansub.tv/wp-content/uploads/2023/10/2860055-e1696595653601.jpg"
32
  };
33
 
34
  const builder = new addonBuilder(manifest);
 
35
 
36
- // **GESTORE STREAM**
37
  builder.defineStreamHandler(async ({ type, id }) => {
38
  if (type !== "series") {
39
  return Promise.resolve({ streams: [] });
40
  }
41
 
42
  console.log(`Richiesta stream per ID: ${id}`);
 
43
 
44
- const episodes = await getEpisodes(`https://ramaorientalfansub.tv/drama/${id}/`);
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
- if (!episodes || episodes.length === 0) {
47
  console.warn(`Nessun episodio trovato per ${id}`);
48
  return Promise.resolve({ streams: [] });
49
  }
50
 
51
- const streams = episodes.flatMap(ep =>
52
  ep.streams.map(stream => ({
53
  title: `${ep.title} - ${stream.title}`,
54
  url: stream.url,
55
  type: "video/mp4",
56
  behaviorHints: {
57
- bingeGroup: id,
58
- notWebReady: false
59
  }
60
  }))
61
  );
@@ -63,8 +75,6 @@ builder.defineStreamHandler(async ({ type, id }) => {
63
  return Promise.resolve({ streams });
64
  });
65
 
66
-
67
- // **GESTORE CATALOGHI**
68
  builder.defineCatalogHandler(async (args) => {
69
  if (args.type === 'series' && args.id === 'rama_series') {
70
  return seriesCatalog(args);
@@ -73,11 +83,27 @@ builder.defineCatalogHandler(async (args) => {
73
  }
74
  });
75
 
76
- // **GESTORE METADATI**
77
- builder.defineMetaHandler(async (args) => getMeta(args.id));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
 
79
  export default builder.getInterface();
80
 
81
- // **AVVIA IL SERVER**
82
  serveHTTP(builder.getInterface(), { port: 7000 });
83
  console.log(`Addon server is running at http://localhost:7000/manifest.json`);
 
2
  import seriesCatalog from './rama_series.js';
3
  import filmsCatalog from './rama_films.js';
4
  import { getMeta } from './episodes.js';
 
5
 
6
  const { addonBuilder, serveHTTP } = pkg;
7
 
 
15
  "type": "series",
16
  "id": "rama_series",
17
  "name": "Serie Coreane",
18
+ "extra": [{ "name": "skip" }]
19
  },
20
  {
21
  "type": "movie",
22
  "id": "rama_films",
23
  "name": "Film Coreani",
24
+ "extra": [{ "name": "skip" }]
25
  }
26
  ],
27
+ "resources": ["catalog", "meta", "stream"],
28
  "types": ["series", "movie"],
29
  "logo": "https://ramaorientalfansub.tv/wp-content/uploads/2023/10/cropped-Logo-1.png",
30
  "background": "https://ramaorientalfansub.tv/wp-content/uploads/2023/10/2860055-e1696595653601.jpg"
31
  };
32
 
33
  const builder = new addonBuilder(manifest);
34
+ const metaCache = new Map();
35
 
 
36
  builder.defineStreamHandler(async ({ type, id }) => {
37
  if (type !== "series") {
38
  return Promise.resolve({ streams: [] });
39
  }
40
 
41
  console.log(`Richiesta stream per ID: ${id}`);
42
+ let meta = null;
43
 
44
+ if (metaCache.has(id)) {
45
+ console.log(`Caricamento metadati dalla cache per ${id}`);
46
+ meta = metaCache.get(id);
47
+ } else {
48
+ try {
49
+ const metaResult = await getMeta(id);
50
+ meta = metaResult.meta;
51
+ metaCache.set(id, meta);
52
+ } catch (error) {
53
+ console.error(`Errore nel caricamento dei metadati per ${id}:`, error);
54
+ return Promise.resolve({ streams: [] });
55
+ }
56
+ }
57
 
58
+ if (!meta || !meta.episodes || meta.episodes.length === 0) {
59
  console.warn(`Nessun episodio trovato per ${id}`);
60
  return Promise.resolve({ streams: [] });
61
  }
62
 
63
+ const streams = meta.episodes.flatMap(ep =>
64
  ep.streams.map(stream => ({
65
  title: `${ep.title} - ${stream.title}`,
66
  url: stream.url,
67
  type: "video/mp4",
68
  behaviorHints: {
69
+ bingeGroup: id,
70
+ notWebReady: false
71
  }
72
  }))
73
  );
 
75
  return Promise.resolve({ streams });
76
  });
77
 
 
 
78
  builder.defineCatalogHandler(async (args) => {
79
  if (args.type === 'series' && args.id === 'rama_series') {
80
  return seriesCatalog(args);
 
83
  }
84
  });
85
 
86
+ builder.defineMetaHandler(async (args) => {
87
+ let meta = null;
88
+
89
+ if (metaCache.has(args.id)) {
90
+ console.log(`Caricamento metadati dalla cache per ${args.id}`);
91
+ meta = { meta: metaCache.get(args.id) };
92
+ } else {
93
+ try {
94
+ const metaResult = await getMeta(args.id);
95
+ meta = metaResult.meta;
96
+ metaCache.set(args.id, meta);
97
+ } catch (error) {
98
+ console.error(`Errore nel caricamento dei metadati per ${args.id}:`, error);
99
+ return { meta: null };
100
+ }
101
+ }
102
+
103
+ return { meta: { ...meta, extra: meta.extra } };
104
+ });
105
 
106
  export default builder.getInterface();
107
 
 
108
  serveHTTP(builder.getInterface(), { port: 7000 });
109
  console.log(`Addon server is running at http://localhost:7000/manifest.json`);
package-lock.json ADDED
The diff for this file is too large to render. See raw diff
 
package.json CHANGED
@@ -1,22 +1,23 @@
1
- {
2
- "name": "stremio-rama-addon",
3
- "version": "1.0.5",
4
- "description": "Addon per visualizzare serie e film coreani dal sito Rama Oriental Fansub",
5
- "main": "main.js",
6
- "scripts": {
7
- "start": "node main.js"
8
- },
9
- "dependencies": {
10
- "axios": "^1.7.7",
11
- "cheerio": "^1.0.0-rc.12",
12
- "cloudscraper": "4.6.0",
13
- "proxy-agent": "^6.5.0",
14
- "stremio-addon-sdk": "^1.6.10",
15
- "puppeteer": "24.3.1",
16
- "puppeteer-core": "^24.3.1",
17
- "puppeteer-extra": "^3.3.6",
18
- "puppeteer-extra-plugin-recaptcha": "^3.6.8",
19
- "puppeteer-extra-plugin-stealth": "^2.11.2"
20
- },
21
- "type": "module"
22
- }
 
 
1
+ {
2
+ "name": "stremio-rama-addon",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "description": "Addon per Stremio per visualizzare serie e film coreani dal sito Rama Oriental Fansub",
6
+ "main": "main.js",
7
+ "scripts": {
8
+ "start": "node main.js"
9
+ },
10
+ "author": "Il tuo nome",
11
+ "license": "ISC",
12
+ "dependencies": {
13
+ "axios": "^1.5.0",
14
+ "cheerio": "^1.0.0-rc.12",
15
+ "cloudscraper": "4.6.0",
16
+ "puppeteer": "24.3.1",
17
+ "puppeteer-core": "^24.3.1",
18
+ "puppeteer-extra": "^3.3.6",
19
+ "puppeteer-extra-plugin-recaptcha": "^3.6.8",
20
+ "puppeteer-extra-plugin-stealth": "^2.11.2",
21
+ "stremio-addon-sdk": "^1.6.10"
22
+ }
23
+ }
rama_series.js CHANGED
@@ -1,34 +1,122 @@
1
- import { axiosInstance } from './episodes.js';
2
  import * as cheerio from 'cheerio';
3
 
4
- async function seriesCatalog(args) {
5
- const catalog = {
6
- metas: [],
7
- };
8
-
9
- try {
10
- const url = 'https://ramaorientalfansub.tv/paese/corea-del-sud/';
11
- const res = await axiosInstance.get(url); // Usa axiosInstance
12
- const $ = cheerio.load(res.data);
13
-
14
- $('.element').each((i, el) => {
15
- const element = $(el);
16
- const title = element.find('.title a').text();
17
- const id = element.find('.title a').attr('href').split('/')[4];
18
- const poster = element.find('.poster img').attr('src');
19
-
20
- catalog.metas.push({
21
- id: id,
22
- type: 'series',
23
- name: title,
24
- poster: poster,
25
- });
26
- });
27
- } catch (e) {
28
- console.log(e);
29
- }
30
-
31
- return Promise.resolve(catalog);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  }
33
 
34
- export default seriesCatalog;
 
 
 
 
1
+ import cloudscraper from 'cloudscraper';
2
  import * as cheerio from 'cheerio';
3
 
4
+ const userAgents = [
5
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.3',
6
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0',
7
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1 Safari/605.1.15'
8
+ ];
9
+
10
+ function getRandomHeaders() {
11
+ const userAgent = userAgents[Math.floor(Math.random() * userAgents.length)];
12
+ return {
13
+ 'User-Agent': userAgent,
14
+ 'Referer': 'https://ramaorientalfansub.tv/paese/corea-del-sud/',
15
+ 'Accept-Language': 'en-US,en;q=0.9'
16
+ };
17
+ }
18
+
19
+ async function fetchWithCloudscraper(url) {
20
+ try {
21
+ const data = await cloudscraper.get({
22
+ uri: url,
23
+ headers: getRandomHeaders()
24
+ });
25
+ return data;
26
+ } catch (error) {
27
+ console.error("Errore con Cloudscraper:", error);
28
+ return null;
29
+ }
30
+ }
31
+
32
+ const BASE_URL = 'https://ramaorientalfansub.tv/paese/corea-del-sud/';
33
+ const ITEMS_PER_PAGE = 25;
34
+ const MAX_PAGES = 35;
35
+ const catalogCache = new Map();
36
+
37
+ async function getCatalog(skip = 0) {
38
+ const catalog = [];
39
+ let pageNumber = Math.floor(skip / ITEMS_PER_PAGE) + 1;
40
+ let itemsToLoad = ITEMS_PER_PAGE;
41
+
42
+ while (catalog.length < itemsToLoad && pageNumber <= MAX_PAGES) {
43
+ const pageUrl = `${BASE_URL}page/${pageNumber}/`;
44
+ console.log(`Richiedendo pagina: ${pageNumber}`);
45
+
46
+ let data;
47
+ if (catalogCache.has(pageUrl)) {
48
+ console.log(`Caricamento pagina ${pageNumber} dalla cache.`);
49
+ data = catalogCache.get(pageUrl);
50
+ } else {
51
+ try {
52
+ data = await fetchWithCloudscraper(pageUrl);
53
+ if (!data) {
54
+ console.warn(`Nessun dato ricevuto per ${pageUrl}`);
55
+ pageNumber++;
56
+ continue;
57
+ }
58
+ catalogCache.set(pageUrl, data);
59
+ } catch (error) {
60
+ console.error(`Errore nel caricamento della pagina ${pageNumber}:`, error);
61
+ pageNumber++;
62
+ continue;
63
+ }
64
+ }
65
+
66
+ const $ = cheerio.load(data);
67
+ let foundItemsOnPage = 0;
68
+
69
+ $('div.w-full.bg-gradient-to-t.from-primary').each((index, element) => {
70
+ if (catalog.length >= itemsToLoad) {
71
+ return false; // Interrompe il ciclo .each()
72
+ }
73
+
74
+ const titleElement = $(element).find('a.text-sm.line-clamp-2.font-medium.leading-snug.lg\\:leading-normal');
75
+ const title = titleElement.text().trim();
76
+ const link = titleElement.attr('href');
77
+ const poster = $(element).find('img').attr('src');
78
+ const tagElement = $(element).find('.inline-block.md\\:my-3.uppercase');
79
+ const tagText = tagElement.text().trim().toLowerCase();
80
+ let extraTag = null;
81
+
82
+ if (tagText.includes('completed')) {
83
+ extraTag = 'completed';
84
+ } else if (tagText.includes('simulcast')) {
85
+ extraTag = 'simulcast';
86
+ }
87
+
88
+ if (tagText.includes('tv')) {
89
+ if (title && link) {
90
+ const formattedTitle = title.replace(/\s+/g, '-').toLowerCase().replace(/[()]/g, '');
91
+ const meta = {
92
+ id: formattedTitle,
93
+ type: 'series',
94
+ name: title,
95
+ poster,
96
+ description: title,
97
+ imdbRating: "N/A",
98
+ released: 2024,
99
+ };
100
+
101
+ if (extraTag) {
102
+ meta.extra = { tag: extraTag };
103
+ }
104
+
105
+ catalog.push(meta);
106
+ foundItemsOnPage++;
107
+ }
108
+ }
109
+ });
110
+
111
+ console.log(`Pagina ${pageNumber}: trovati ${foundItemsOnPage} elementi.`);
112
+ pageNumber++;
113
+ }
114
+
115
+ console.log(`Totale elementi raccolti: ${catalog.length}`);
116
+ return catalog;
117
  }
118
 
119
+ export default async function (args) {
120
+ const skip = args.extra?.skip || 0;
121
+ return { metas: await getCatalog(skip) };
122
+ };
streams.js CHANGED
@@ -1,32 +1,35 @@
1
- import axios from 'axios';
2
  import cloudscraper from 'cloudscraper';
3
  import * as cheerio from 'cheerio';
4
- import puppeteer from 'puppeteer';
5
 
6
- const axiosInstance = axios.create({
7
- headers: {
8
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36',
9
- 'Referer': 'https://ramaorientalfansub.tv/',
10
- 'Accept-Language': 'en-US,en;q=0.9',
11
- }
12
- });
13
- export { axiosInstance, axios, puppeteer, cheerio };
14
-
15
-
16
- async function fetchSeriesData(seriesLink) {
17
- if (!seriesLink) {
18
- throw new Error("seriesLink non definito!");
19
- }
 
 
20
 
21
- // const data = await fetchWithCloudscraper(seriesLink);
22
-
23
- // Controllo se data è una stringa valida
24
- if (typeof data !== "string" || !data.trim()) {
25
- console.error("Errore: Il contenuto della pagina non è valido.");
 
 
 
 
 
26
  return null;
27
  }
28
-
29
- return cheerio.load(data);
30
  }
31
 
32
  /**
@@ -35,17 +38,27 @@ async function fetchSeriesData(seriesLink) {
35
  * @returns {string|null} - URL dello stream o null se non trovato.
36
  */
37
  async function getStream(episodeLink) {
 
38
  try {
39
- const { data } = await axios.get(episodeLink);
40
- const $ = cheerio.load(data);
41
-
42
- const iframeSrc = encodeURI($('iframe').attr('src'));
43
- console.log(`Stream trovato: ${decodeURI(iframeSrc)}`);
44
 
45
- if (iframeSrc && iframeSrc.startsWith('https://server1.streamingrof.online/02-DRAMACOREANI')) {
46
- return iframeSrc;
 
 
 
 
 
 
 
 
 
47
  } else {
48
- console.warn(`Stream non valido per ${episodeLink}: ${iframeSrc}`);
49
  return null;
50
  }
51
  } catch (err) {
@@ -59,27 +72,21 @@ async function getStream(episodeLink) {
59
  /**
60
  * Recupera la lista degli episodi e i rispettivi stream per una serie.
61
  * @param {string} seriesLink - URL della pagina della serie.
 
62
  * @returns {Array} - Lista di episodi con titolo, thumbnail e link allo stream.
63
  */
64
- async function getEpisodes(seriesLink) {
65
  try {
66
  const episodes = [];
67
  const baseEpisodeUrl = seriesLink.replace('/drama/', '/watch/');
68
-
69
  console.log('Chiamata a getEpisodes con URL:', seriesLink);
70
-
71
  let seriesId = seriesLink.split('/').filter(Boolean).pop();
72
  console.log('ID della serie estratto prima della pulizia:', seriesId);
73
-
74
  seriesId = seriesId.replace(/,/g, '').replace(/\s+/g, '-').toLowerCase();
75
  console.log('ID della serie dopo la pulizia:', seriesId);
76
-
77
  let seriesYear = null;
78
-
79
  try {
80
- const { data } = await axiosInstance.get(seriesLink);
81
- const $ = cheerio.load(data);
82
-
83
  const titleText = $('title').text();
84
  const yearMatch = titleText.match(/\b(19|20)\d{2}\b/);
85
  if (yearMatch) {
@@ -90,34 +97,40 @@ async function getEpisodes(seriesLink) {
90
  }
91
 
92
  console.log('Anno serie:', seriesYear);
93
-
94
- for (let episodeNumber = 1; episodeNumber <= 30; episodeNumber++) {
 
95
  const episodeId = seriesYear ? `${seriesId}-${seriesYear}` : seriesId;
96
  const episodeLink = `https://ramaorientalfansub.tv/watch/${episodeId}-episodio-${episodeNumber}/`;
97
  console.log(`URL dell'episodio generato: ${episodeLink}`);
98
-
99
  try {
100
  const stream = await getStream(episodeLink);
101
- if (!stream) continue;
 
 
 
102
 
103
  episodes.push({
104
  id: `episodio-${episodeNumber}`,
105
- title: `Episodio ${episodeNumber}`,
106
- thumbnail: 'https://ramaorientalfansub.tv/wp-content/uploads/2023/10/cropped-Logo-1.png',
107
- streams: [
108
- {
109
- title: `Episodio ${episodeNumber}`,
110
- url: stream,
111
- type: "video/mp4"
112
- }
113
- ]
114
  });
115
- } catch (err) {
116
- console.log('Episodi trovati:', JSON.stringify(episodes, null, 2));
 
117
  console.error(`Errore durante il recupero dello stream per ${episodeLink}:`, err);
 
118
  }
 
 
119
  }
120
 
 
121
  return episodes;
122
  } catch (err) {
123
  console.error('Errore durante il recupero degli episodi:', err);
@@ -125,9 +138,4 @@ async function getEpisodes(seriesLink) {
125
  }
126
  }
127
 
128
- export { getEpisodes };
129
-
130
- (async () => {
131
- const seriesLink = "https://ramaorientalfansub.tv/drama/";
132
- const $ = await fetchSeriesData(seriesLink);
133
- })();
 
 
1
  import cloudscraper from 'cloudscraper';
2
  import * as cheerio from 'cheerio';
 
3
 
4
+ // Lista di User-Agent
5
+ const userAgents = [
6
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.3',
7
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0',
8
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1 Safari/605.1.15'
9
+ ];
10
+
11
+ // Funzione per ottenere headers casuali
12
+ function getRandomHeaders() {
13
+ const userAgent = userAgents[Math.floor(Math.random() * userAgents.length)];
14
+ return {
15
+ 'User-Agent': userAgent,
16
+ 'Referer': 'https://ramaorientalfansub.tv', // Assicurati che il referer sia corretto
17
+ 'Accept-Language': 'en-US,en;q=0.9'
18
+ };
19
+ }
20
 
21
+ async function fetchWithCloudscraper(url) {
22
+ try {
23
+ const data = await cloudscraper.get({
24
+ uri: url,
25
+ headers: getRandomHeaders() // Aggiungi headers casuali
26
+ });
27
+ return data;
28
+ } catch (error) {
29
+ console.error("Errore con Cloudscraper:", error);
30
+ // Gestisci l'errore e restituisci null o un valore appropriato
31
  return null;
32
  }
 
 
33
  }
34
 
35
  /**
 
38
  * @returns {string|null} - URL dello stream o null se non trovato.
39
  */
40
  async function getStream(episodeLink) {
41
+ let iframeSrc = null;
42
  try {
43
+ const data = await fetchWithCloudscraper(episodeLink);
44
+ if (!data) {
45
+ console.warn(`Nessun dato ricevuto per ${episodeLink}`);
46
+ return null;
47
+ }
48
 
49
+ const $ = cheerio.load(data);
50
+ iframeSrc = $('iframe').attr('src');
51
+ if (iframeSrc) {
52
+ iframeSrc = encodeURI(iframeSrc);
53
+ console.log(`Stream trovato: ${decodeURI(iframeSrc)}`);
54
+ if (iframeSrc.startsWith('https://server1.streamingrof.online/02-DRAMACOREANI')) {
55
+ return iframeSrc;
56
+ } else {
57
+ console.warn(`Stream non valido per ${episodeLink}: ${iframeSrc}`);
58
+ return null;
59
+ }
60
  } else {
61
+ console.warn(`Nessun iframe trovato per ${episodeLink}`);
62
  return null;
63
  }
64
  } catch (err) {
 
72
  /**
73
  * Recupera la lista degli episodi e i rispettivi stream per una serie.
74
  * @param {string} seriesLink - URL della pagina della serie.
75
+ * @param {CheerioStatic} $ - Oggetto Cheerio caricato con la pagina della serie.
76
  * @returns {Array} - Lista di episodi con titolo, thumbnail e link allo stream.
77
  */
78
+ async function getEpisodes(seriesLink, $) {
79
  try {
80
  const episodes = [];
81
  const baseEpisodeUrl = seriesLink.replace('/drama/', '/watch/');
 
82
  console.log('Chiamata a getEpisodes con URL:', seriesLink);
 
83
  let seriesId = seriesLink.split('/').filter(Boolean).pop();
84
  console.log('ID della serie estratto prima della pulizia:', seriesId);
 
85
  seriesId = seriesId.replace(/,/g, '').replace(/\s+/g, '-').toLowerCase();
86
  console.log('ID della serie dopo la pulizia:', seriesId);
 
87
  let seriesYear = null;
88
+ // Estrai l'anno dalla pagina della serie (se presente)
89
  try {
 
 
 
90
  const titleText = $('title').text();
91
  const yearMatch = titleText.match(/\b(19|20)\d{2}\b/);
92
  if (yearMatch) {
 
97
  }
98
 
99
  console.log('Anno serie:', seriesYear);
100
+ // Invece di cercare il numero massimo di episodi, proviamo semplicemente a caricarli in sequenza
101
+ let episodeNumber = 1;
102
+ while (true) {
103
  const episodeId = seriesYear ? `${seriesId}-${seriesYear}` : seriesId;
104
  const episodeLink = `https://ramaorientalfansub.tv/watch/${episodeId}-episodio-${episodeNumber}/`;
105
  console.log(`URL dell'episodio generato: ${episodeLink}`);
 
106
  try {
107
  const stream = await getStream(episodeLink);
108
+ if (!stream) {
109
+ console.log(`Stream non trovato per l'episodio ${episodeNumber}, interrompendo la ricerca.`);
110
+ break; // Interrompi il ciclo se lo stream non viene trovato
111
+ }
112
 
113
  episodes.push({
114
  id: `episodio-${episodeNumber}`,
115
+ title: `${episodeNumber}`,
116
+ thumbnail: 'div.swiper-slide:nth-child(1) > a:nth-child(1) > div:nth-child(1)',
117
+ streams: [{
118
+ title: `Episodio ${episodeNumber}`,
119
+ url: stream,
120
+ type: "video/mp4"
121
+ }]
 
 
122
  });
123
+ // Aggiungi un ritardo tra le richieste per ogni episodio
124
+ await new Promise(resolve => setTimeout(resolve, 1000)); // Aspetta 1 secondo
125
+ } catch (error) {
126
  console.error(`Errore durante il recupero dello stream per ${episodeLink}:`, err);
127
+ break; // Interrompi il ciclo anche in caso di errore
128
  }
129
+
130
+ episodeNumber++;
131
  }
132
 
133
+ console.log('Episodi trovati:', JSON.stringify(episodes, null, 2));
134
  return episodes;
135
  } catch (err) {
136
  console.error('Errore durante il recupero degli episodi:', err);
 
138
  }
139
  }
140
 
141
+ export { getEpisodes, getStream }; // Esporta anche getStream