diff --git a/src/index.ts b/src/index.ts index 7b44335..60d178c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,8 +8,6 @@ import cors from "cors"; /* Anime */ import flv from "../src/routes/v1/anime/animeflv/AnimeflvRoutes"; import latinhd from "../src/routes/v1/anime/animelatinohd/AnimeLatinoHDRoutes"; -//import gogoanime from "../src/routes/v1/anime/gogoanime/GogoAnimeRoute"; -import zoro from "../src/routes/v1/anime/zoro/ZoroRoutes"; import monoschinos from "../src/routes/v1/anime/monoschinos/MonosChinosRoute"; import tioanime from "../src/routes/v1/anime/tioanime/TioAnimeRoute"; import WcoStream from "../src/routes/v1/anime/wcostream/wcostreamRoutes"; @@ -19,7 +17,6 @@ import Animevostfr from "../src/routes/v1/anime/animevostfr/AnimevostfrRoutes"; /* Manga */ import comick from "../src/routes/v1/manga/comick/ComickRoutes"; import inmanga from "../src/routes/v1/manga/inmanga/InmangaRoutes"; -import nhentai from "../src/routes/v1/manga/nhentai/NhentaiRoutes"; import mangareader from "../src/routes/v1/manga/mangareader/MangaReaderRoutes"; import manganelo from "../src/routes/v1/manga/manganelo/ManganeloRoutes"; @@ -40,9 +37,7 @@ app.use(cors()); /*anime*/ app.use(flv); app.use(latinhd); -//app.use(gogoanime); app.use(monoschinos); -app.use(zoro); app.use(tioanime); app.use(WcoStream); app.use(AnimeBlix); @@ -53,7 +48,6 @@ app.use(Animevostfr); /*Manga*/ app.use(comick); app.use(inmanga); -app.use(nhentai); app.use(mangareader); app.use(manganelo); /*Manga*/ diff --git a/src/scraper/sites/anime/animeflv/AnimeFlv.ts b/src/scraper/sites/anime/animeflv/AnimeFlv.ts index ab0330b..eb65351 100644 --- a/src/scraper/sites/anime/animeflv/AnimeFlv.ts +++ b/src/scraper/sites/anime/animeflv/AnimeFlv.ts @@ -1,7 +1,7 @@ import axios from "axios"; import { load } from "cheerio"; -import { Anime, Chronology } from "../../../../types/anime"; -import { Episode, EpisodeServer } from "../../../../types/episode"; +import { AnimeMedia, Chronology } from "../../../../types/anime"; +import { Episode } from "../../../../types/episode"; import { Genres, OrderAnimeflv, @@ -9,35 +9,45 @@ import { TypeAnimeflv, } from "./animeflv_helper"; import { - AnimeSearch, ResultSearch, type IResultSearch, - type IAnimeSearch, + type IAnimeResult, + AnimeResult, } from "../../../../types/search"; import { AnimeScraperModel } from "../../../../models/AnimeScraperModel"; export class AnimeFlv extends AnimeScraperModel { - readonly url = "https://animeflv.ws"; + readonly url = "https://m.animeflv.net"; - async GetItemInfo(anime: string): Promise { + async GetItemInfo(anime: string): Promise { try { const { data } = await axios.get(`${this.url}/anime/${anime}`); const $ = load(data); - const title = $("h2.Title").text().trim(); - const title_alt = $("span.TxtAlt").text().trim(); - const img = $("div.AnimeCover .Image figure img").attr("src"); - const status = $("p.AnmStts span").text().trim(); - const synopsis = $("div.Description").text().trim(); - const episodes = $(".ListCaps li a"); - const AnimeReturn = new Anime(); + + //relevant information + const title = $("h1.Title").text().trim(); + const title_alt = title; + const img = $("meta[property='og:image']").attr("content"); + const status = $("p strong.Anm-On").text(); + const synopsis = $("header p:contains(Sinopsis)") + .text() + .replace("Sinopsis:", "") + .trim(); + + //container of episodes + const episodesContainer = $("div.List-Episodes div.AACrdn"); + + const AnimeReturn = new AnimeMedia(); AnimeReturn.name = title; - AnimeReturn.alt_name = [...title_alt.split(",")]; + AnimeReturn.alt_names = [...title_alt.split(",")]; AnimeReturn.image = { url: img, }; AnimeReturn.status = status; AnimeReturn.synopsis = synopsis; AnimeReturn.chronology = []; + AnimeReturn.genres = []; + AnimeReturn.episodes = []; //getRelated $("ul.ListAnmRel li a").each((_i, e) => { @@ -46,23 +56,32 @@ export class AnimeFlv extends AnimeScraperModel { cro.url = `/anime/flv/name/${$(e).attr("href").replace("/anime/", "")}`; AnimeReturn.chronology.push(cro); }); + //get genres - $("nav.Nvgnrs a").each((_i, e) => { - const gen = $(e).text().trim(); + $("footer a").each((_i, e) => { + const gen = $(e).text().trim() as string; + AnimeReturn.genres.push(gen); }); + //get episodes - episodes.each((_i_, e) => { - const l = $(e).attr("href").replace("/", ""); - const episode = new Episode(); - episode.name = $(e).children(".Title").text().trim(); - episode.url = `/anime/flv/episode/${`${l}`.replace( - "/anime", - "/anime/flv" - )}`; - episode.number = $(e).children("p").last().text().trim(); - episode.image = $(e).children("figure").find(".lazy").attr("src"); - AnimeReturn.episodes.push(episode); + episodesContainer.each((_i_, e) => { + $(e) + .find("ul li") + .each((_i, e) => { + const link = $(e).find("a"); + const name = link.text().trim(); + const numberEpisode = Number(name.split(" ").slice(-1)); + console.log(numberEpisode); + const episode = new Episode(); + episode.name = name; + episode.url = `/anime/flv/episode/${link + .attr("href") + .replace("/ver/", "")}`; + episode.num = numberEpisode; + + AnimeReturn.episodes.push(episode); + }); }); return AnimeReturn; } catch (error) { @@ -84,7 +103,7 @@ export class AnimeFlv extends AnimeScraperModel { ord?: OrderAnimeflv, page?: number, title?: string - ): Promise> { + ): Promise> { try { const { data } = await axios.get(`${this.url}/browse`, { params: { @@ -99,10 +118,10 @@ export class AnimeFlv extends AnimeScraperModel { }); const $ = load(data); const infoList = $("ul.ListAnimes li"); - const data_filter = new ResultSearch(); + const data_filter = new ResultSearch(); data_filter.results = []; infoList.each((_i, e) => { - const info = new AnimeSearch(); + const info = new AnimeResult(); info.name = $(e).find("h3").text().trim(); info.image = $(e) @@ -125,24 +144,50 @@ export class AnimeFlv extends AnimeScraperModel { async GetEpisodeServers(episode: string): Promise { try { - const { data } = await axios.get(`${this.url}/${episode}`); + const { data } = await axios.get(`${this.url}/ver/${episode}`); const $ = load(data); - const title = $(".CapiTop").children("h1").text().trim(); - const getLinks = $(".CpCnA .anime_muti_link li"); + const title = $("h1").text().trim(); + const getLinks = $("script"); const numberEpisode = episode.substring(episode.lastIndexOf("-") + 1); const episodeReturn = new Episode(); episodeReturn.name = title; episodeReturn.url = `/anime/flv/episode/${episode}`; - episodeReturn.number = numberEpisode as unknown as string; + episodeReturn.num = Number(numberEpisode); episodeReturn.servers = []; - const promises = getLinks.map(async (_i, e) => { - const servers = new EpisodeServer(); - const title = $(e).attr("title"); + getLinks.each((_i, e) => { + interface VideoObject { + title: string; + code: string; + } + + const scriptContent = $(e).html(); + const regexVideoObject = /var videos = (\{.*?\});/; + + const matchObject = scriptContent.match(regexVideoObject); + + if (matchObject) { + const videoObject: VideoObject[] = JSON.parse(matchObject[1]).SUB; + + for (let index = 0; index < videoObject.length; index++) { + const element = videoObject[index]; + + episodeReturn.servers.push({ + name: element.title, + url: element.code, + }); + } + } + }); + /*const promises = getLinks.map(async (_i, e) => { + /* const servers = new EpisodeServer(); + const title = $(e).find("a").text().trim(); const videoData = $(e).attr("data-video"); servers.name = title; servers.url = videoData; - if (videoData.includes("streaming.php")) { + console.log(title); */ + + /* if (videoData.includes("streaming.php")) { await this.getM3U( `${videoData.replace("streaming.php", "ajax.php")}&refer=none` ).then((g) => { @@ -172,9 +217,9 @@ export class AnimeFlv extends AnimeScraperModel { default: break; } - episodeReturn.servers.push(servers); - }); - await Promise.all(promises); + episodeReturn.servers.push(servers); + })*/ + //await Promise.all(promises); return episodeReturn; } catch (error) { console.log("An error occurred while getting the episode servers", error); @@ -182,7 +227,7 @@ export class AnimeFlv extends AnimeScraperModel { } } - private async getM3U(vidurl: string) { + /* private async getM3U(vidurl: string) { try { const res = await axios.get(vidurl); @@ -190,5 +235,5 @@ export class AnimeFlv extends AnimeScraperModel { } catch (error) { console.log(error); } - } + } */ } diff --git a/src/test/Animeflv.spec.ts b/src/test/Animeflv.spec.ts index adcee4f..24b0987 100644 --- a/src/test/Animeflv.spec.ts +++ b/src/test/Animeflv.spec.ts @@ -1,8 +1,11 @@ import { AnimeFlv } from "../scraper/sites/anime/animeflv/AnimeFlv"; +import { AnimeMedia } from "../types/anime"; +import { Episode } from "../types/episode"; import { - StatusAnimeflv, Genres, + StatusAnimeflv, } from "../scraper/sites/anime/animeflv/animeflv_helper"; + describe("AnimeFlv", () => { let animeFlv: AnimeFlv; @@ -11,15 +14,16 @@ describe("AnimeFlv", () => { }); it("should get anime info successfully", async () => { - const animeInfo = await animeFlv.GetItemInfo("wonder-egg-priority"); + const animeInfo: AnimeMedia = + await animeFlv.GetItemInfo("25jigen-no-ririsa"); expect(animeInfo.name).toBe("Wonder Egg Priority"); - expect(animeInfo.alt_name).toContain("ワンダーエッグ・プライオリティ"); + expect(animeInfo.alt_names).toContain("ワンダーエッグ・プライオリティ"); expect(animeInfo.image.url).toContain(".jpg"); - expect(animeInfo.status).toBe("En emision"); - expect(animeInfo.synopsis.length).toBeGreaterThan(0); + expect(animeInfo.status).toBe("Finalizado"); + expect(animeInfo.synopsis?.length).toBeGreaterThan(0); expect(animeInfo.chronology?.length).toBeGreaterThan(0); - expect(animeInfo.genres.length).toBeGreaterThan(0); - expect(animeInfo.episodes.length).toBeGreaterThan(0); + expect(animeInfo.genres?.length).toBeGreaterThan(0); + expect(animeInfo.episodes?.length).toBeGreaterThan(0); }); it("should filter anime successfully", async () => { @@ -33,4 +37,14 @@ describe("AnimeFlv", () => { ); expect(result.results.length).toBeGreaterThan(0); }); + + it("should get episode servers successfully", async () => { + const episode: Episode = await animeFlv.GetEpisodeServers( + "wonder-egg-priority-01" + ); + expect(episode.name).toBeTruthy(); + expect(episode.url).toContain("/anime/flv/episode/wonder-egg-priority-01"); + expect(episode.num).toBe(1); + expect(episode?.servers?.length).toBeGreaterThan(0); + }); }); diff --git a/src/test/Nhentai.spec.ts b/src/test/Nhentai.spec.ts deleted file mode 100644 index b405de9..0000000 --- a/src/test/Nhentai.spec.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { Nhentai } from "../../src/scraper/sites/manga/nhentai/Nhentai"; -import { IMangaChapter, IMangaResult, Manga } from "../types/manga"; - -describe("It returns a list of animes related that name filter", () => { - it("it should match that fields", async () => { - const mangasHentai: IMangaResult[] = await new Nhentai().filter( - "Evangelion", - ); - - expect(mangasHentai[0].id).toBe("403447"); - expect(mangasHentai[0].title).toBe( - "[Cassino (Magarikouji Lily)] Playboys (2) – Neon Genesis Evangelion dj [Eng]", - ); - }); -}); - -describe("Manga info tests", () => { - it("it should return a manga information from manga id", async () => { - const getMangaInfo: Manga = await new Nhentai().getMangaInfo("403447"); - - expect(getMangaInfo.title).toEqual( - "[Cassino (Magarikouji Lily)] Playboys (2) – Neon Genesis Evangelion dj [Eng]", - ); - expect(getMangaInfo.id).toEqual("403447"); - }); -}); - -describe("Manga chapters", () => { - it("it should return a manga chapters from manga id", async () => { - const getMangaChapters: IMangaChapter[] = - await new Nhentai().getMangaChapters("403447"); - expect(getMangaChapters[0].images[0]).toEqual( - "https://t7.nhentai.net/galleries/2223278/1t.jpg", - ); - }); -}); diff --git a/src/test/Zoro.spec.ts b/src/test/Zoro.spec.ts deleted file mode 100644 index 5e4d165..0000000 --- a/src/test/Zoro.spec.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Zoro } from "../scraper/sites/anime/zoro/Zoro"; - -describe("Zoro", () => { - let zoro: Zoro; - - beforeEach(() => { - zoro = new Zoro(); - }); - it("should get anime info successfully", async () => { - const animeInfo = await zoro.GetItemInfo("tokyo-ghoul-790"); - expect(animeInfo.name).toBe("Tokyo Ghoul"); - expect(animeInfo.alt_name).toContain("東京喰種-トーキョーグール-"); - expect(animeInfo.image.url).toContain(".jpg"); - expect(animeInfo.synopsis.length).toBeGreaterThan(0); - expect(animeInfo.chronology?.length).toBeGreaterThan(0); - expect(animeInfo.genres.length).toBeGreaterThan(0); - }); - it("should filter anime successfully", async () => { - const result = await zoro.GetItemByFilter("2"); - expect(result.results.length).toBeGreaterThan(0); - }); -});