diff --git a/src/routes/v1/anime/animeflv/AnimeflvRoutes.ts b/src/routes/v1/anime/animeflv/AnimeflvRoutes.ts index 3c671f9..139eb54 100644 --- a/src/routes/v1/anime/animeflv/AnimeflvRoutes.ts +++ b/src/routes/v1/anime/animeflv/AnimeflvRoutes.ts @@ -6,6 +6,7 @@ import { StatusAnimeflv, OrderAnimeflv, } from "../../../../scraper/sites/anime/animeflv/animeflv_helper"; +import { ScraperErrorResponse } from "utils/ScraperError"; const r = Router(); //anime info @@ -16,8 +17,9 @@ r.get("/anime/flv/name/:name", async (req, res) => { const animeInfo = await flv.GetItemInfo(name); res.send(animeInfo); } catch (error) { - console.log(error); - res.status(500).send(error); + if (error instanceof ScraperErrorResponse) { + res.status(404).send(error); + } } }); @@ -29,8 +31,9 @@ r.get("/anime/flv/episode/:episode", async (req, res) => { const animeInfo = await flv.GetEpisodeServers(episode); res.send(animeInfo); } catch (error) { - console.log(error); - res.status(500).send(error); + if (error instanceof ScraperErrorResponse) { + res.status(404).send(error); + } } }); @@ -38,7 +41,7 @@ r.get("/anime/flv/episode/:episode", async (req, res) => { r.get("/anime/flv/filter", async (req, res) => { try { const gen = req.query.gen as Genres; - const date = req.query.date as string; + const year = req.query.year as string; const type = req.query.type as TypeAnimeflv; const status = req.query.status as StatusAnimeflv; const ord = req.query.ord as OrderAnimeflv; @@ -48,17 +51,18 @@ r.get("/anime/flv/filter", async (req, res) => { const flv = new AnimeFlv(); const animeInfo = await flv.GetItemByFilter( gen, - date, + year, type, status, ord, page, - title, + title ); res.send(animeInfo); } catch (error) { - console.log(error); - res.status(500).send(error); + if (error instanceof ScraperErrorResponse) { + res.status(404).send(error); + } } }); diff --git a/src/scraper/sites/anime/animeflv/AnimeFlv.ts b/src/scraper/sites/anime/animeflv/AnimeFlv.ts index eb65351..c89df66 100644 --- a/src/scraper/sites/anime/animeflv/AnimeFlv.ts +++ b/src/scraper/sites/anime/animeflv/AnimeFlv.ts @@ -1,4 +1,4 @@ -import axios from "axios"; +import axios, { AxiosResponse } from "axios"; import { load } from "cheerio"; import { AnimeMedia, Chronology } from "../../../../types/anime"; import { Episode } from "../../../../types/episode"; @@ -15,6 +15,7 @@ import { AnimeResult, } from "../../../../types/search"; import { AnimeScraperModel } from "../../../../models/AnimeScraperModel"; +import { ScraperErrorResponse } from "utils/ScraperError"; export class AnimeFlv extends AnimeScraperModel { readonly url = "https://m.animeflv.net"; @@ -72,7 +73,6 @@ export class AnimeFlv extends AnimeScraperModel { 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 @@ -89,7 +89,7 @@ export class AnimeFlv extends AnimeScraperModel { "An error occurred while getting the anime info: invalid name", error ); - throw new Error( + throw new ScraperErrorResponse( "An error occurred while getting the anime info: invalid name" ); } @@ -97,7 +97,7 @@ export class AnimeFlv extends AnimeScraperModel { async GetItemByFilter( gen?: Genres | string, - date?: string, + year?: string, type?: TypeAnimeflv, status?: StatusAnimeflv, ord?: OrderAnimeflv, @@ -105,29 +105,35 @@ export class AnimeFlv extends AnimeScraperModel { title?: string ): Promise> { try { - const { data } = await axios.get(`${this.url}/browse`, { - params: { - genres: gen || "all", - year: date || "all", - status: status || "all", - Tipo: type || "all", - order: ord || 1, - page: page || 1, - q: title, - }, - }); + const { data, request }: AxiosResponse = await axios.get( + `${this.url}/browse`, + { + params: { + page: page, + genre: gen, + year: year, + status: status, + type: type, + order: ord, + q: title, + }, + } + ); + console.log(request); const $ = load(data); - const infoList = $("ul.ListAnimes li"); + const infoList = $("ul.List-Animes li"); const data_filter = new ResultSearch(); data_filter.results = []; infoList.each((_i, e) => { const info = new AnimeResult(); - info.name = $(e).find("h3").text().trim(); - info.image = - $(e) - .find("a") - .attr("href") - .replace("/anime/", "https://img.animeflv.ws/cover/") + ".jpg"; + info.name = $(e).find("h2").text().trim(); + info.image = $(e) + .find("img") + .attr("src") + .replace( + "/uploads/animes/", + "https://m.animeflv.net/uploads/animes/" + ); info.url = `/anime/flv/name/${$(e) .find("a") .attr("href") @@ -138,13 +144,17 @@ export class AnimeFlv extends AnimeScraperModel { return data_filter; } catch (error) { console.log("An error occurred while getting the filter values", error); - throw new Error("An error occurred while getting the filter values"); + throw new ScraperErrorResponse("An error occurred while getting the filter values"); } } async GetEpisodeServers(episode: string): Promise { try { const { data } = await axios.get(`${this.url}/ver/${episode}`); + /* const test: AxiosResponse = await axios.get( + "https://streamtape.com/e/ybVywBZRXMheQ2/" + ); + const $t = load(test.data); */ const $ = load(data); const title = $("h1").text().trim(); const getLinks = $("script"); @@ -155,6 +165,10 @@ export class AnimeFlv extends AnimeScraperModel { episodeReturn.num = Number(numberEpisode); episodeReturn.servers = []; + /* const player = $t("div.plyr__video-wrapper").html(); + + console.log(player); */ + getLinks.each((_i, e) => { interface VideoObject { title: string; @@ -223,7 +237,7 @@ export class AnimeFlv extends AnimeScraperModel { return episodeReturn; } catch (error) { console.log("An error occurred while getting the episode servers", error); - throw new Error("An error occurred while getting the episode servers"); + throw new ScraperErrorResponse("An error occurred while getting the episode servers"); } } diff --git a/src/scraper/sites/anime/animeflv/animeflv_helper.ts b/src/scraper/sites/anime/animeflv/animeflv_helper.ts index 601b7f5..4ea4c5b 100644 --- a/src/scraper/sites/anime/animeflv/animeflv_helper.ts +++ b/src/scraper/sites/anime/animeflv/animeflv_helper.ts @@ -1,52 +1,63 @@ //genres animeflf export enum Genres { - Action = "Acción", - MartialArts = "Artes Marciales", - Adventure = "Aventuras", - Racing = "Carreras", - ScienceFiction = "Ciencia Ficción", - Comedy = "Comedia", - Dementia = "Demencia", - Demons = "Demonios", - Sports = "Deportes", - Drama = "Drama", - Ecchi = "Ecchi", - School = "Escolares", - Space = "Espacial", - Fantasy = "Fantasía", - Harem = "Harem", - Historical = "Histórico", - Kids = "Infantil", - Josei = "Josei", - Games = "Juegos", - Magic = "Magia", - Mecha = "Mecha", - Military = "Militar", - Mystery = "Misterio", - Music = "Música", - Parody = "Parodia", - Police = "Policía", - Psychological = "Psicológico", - SliceOfLife = "Recuentos de la vida", - Romance = "Romance", - Samurai = "Samurai", - Seinen = "Seinen", - Shoujo = "Shoujo", - Shounen = "Shounen", - Supernatural = "Sobrenatural", - Superpowers = "Superpoderes", - Suspense = "Suspenso", - Horror = "Terror", - Vampires = "Vampiros", - Yaoi = "Yaoi", - Yuri = "Yuri", + Action = "accion", + MartialArts = "artes-marciales", + Adventure = "aventura", + Racing = "carreras", + ScienceFiction = "ciencia-ficcion", + Comedy = "comedia", + Dementia = "demencia", + Demons = "demonios", + Sports = "deportes", + Drama = "drama", + Ecchi = "ecchi", + School = "escolares", + Space = "espacial", + Fantasy = "fantasia", + Harem = "harem", + Historical = "historico", + Kids = "infantil", + Josei = "josei", + Games = "juegos", + Magic = "magia", + Mecha = "mecha", + Military = "militar", + Mystery = "misterio", + Music = "musica", + Parody = "parodia", + Police = "policia", + Psychological = "psicologico", + SliceOfLife = "recuentos-de-la-vida", + Romance = "romance", + Samurai = "samurai", + Seinen = "seinen", + Shoujo = "shoujo", + Shounen = "shounen", + Supernatural = "sobrenatural", + Superpowers = "superpoderes", + Suspense = "suspenso", + Horror = "terror", + Vampires = "vampiros", + Yaoi = "yaoi", + Yuri = "yuri", } export enum StatusAnimeflv { - OnGoing = "En emision", - Finished = "Finalizado", - Upcoming = "Próximamente", + OnGoing = "1", + Finished = "2", + Upcoming = "3", } -export type TypeAnimeflv = "all" | 1 | 2 | 3 | 4; -export type OrderAnimeflv = "all" | 1 | 2 | 3 | 4 | 5; +export enum TypeAnimeflv { + TV = "tv", + MOVIE = "movie", + SPECIAL = "special", + OVA = "ova", +} +export enum OrderAnimeflv { + DEFAULT = "default", + UPDATED = "updated", + ADDED = "added", + TITLE = "title", + RATING = "rating", +} diff --git a/src/test/Animeflv.spec.ts b/src/test/Animeflv.spec.ts index 24b0987..d3fea66 100644 --- a/src/test/Animeflv.spec.ts +++ b/src/test/Animeflv.spec.ts @@ -1,29 +1,39 @@ import { AnimeFlv } from "../scraper/sites/anime/animeflv/AnimeFlv"; import { AnimeMedia } from "../types/anime"; -import { Episode } from "../types/episode"; +/* import { Episode } from "../types/episode"; +import { + Genres, + StatusAnimeflv, +} from "../scraper/sites/anime/animeflv/animeflv_helper"; */ import { Genres, StatusAnimeflv, } from "../scraper/sites/anime/animeflv/animeflv_helper"; -describe("AnimeFlv", () => { +describe("AnimeFlv test", () => { let animeFlv: AnimeFlv; beforeEach(() => { animeFlv = new AnimeFlv(); }); - it("should get anime info successfully", async () => { - const animeInfo: AnimeMedia = - await animeFlv.GetItemInfo("25jigen-no-ririsa"); - expect(animeInfo.name).toBe("Wonder Egg Priority"); - expect(animeInfo.alt_names).toContain("ワンダーエッグ・プライオリティ"); - expect(animeInfo.image.url).toContain(".jpg"); - 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); + test("should get anime info successfully", async () => { + const animeInfo: AnimeMedia = await animeFlv.GetItemInfo("horimiya-piece"); + + const alt_names_expected: string[] = ["Horimiya: Piece"]; + const genres_expected: string[] = ["Escolares", "Romance", "Shounen"]; + + expect(animeInfo.name).toBe("Horimiya: Piece"); + expect(animeInfo.alt_names).toEqual( + expect.arrayContaining(alt_names_expected) + ); + expect(animeInfo.image.url).toContain(".jp"); + expect(animeInfo.synopsis).toBe( + "Historias del manga no adaptadas en el anime principal." + ); + expect(animeInfo.chronology?.length).toBeGreaterThanOrEqual(0); + expect(animeInfo.genres).toEqual(expect.arrayContaining(genres_expected)); + expect(animeInfo.episodes?.length).toBeGreaterThanOrEqual(12); }); it("should filter anime successfully", async () => { @@ -38,6 +48,18 @@ describe("AnimeFlv", () => { expect(result.results.length).toBeGreaterThan(0); }); + /* it("should filter anime successfully", async () => { + const result = await animeFlv.GetItemByFilter( + Genres.Action, + "all", + "all", + StatusAnimeflv.OnGoing, + 1, + 1 + ); + expect(result.results.length).toBeGreaterThan(0); + }); + it("should get episode servers successfully", async () => { const episode: Episode = await animeFlv.GetEpisodeServers( "wonder-egg-priority-01" @@ -46,5 +68,5 @@ describe("AnimeFlv", () => { 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/utils/ScraperError.ts b/src/utils/ScraperError.ts new file mode 100644 index 0000000..86c0083 --- /dev/null +++ b/src/utils/ScraperError.ts @@ -0,0 +1,9 @@ +import { AxiosError } from "axios"; + +export class ScraperErrorResponse extends AxiosError { + constructor(message: string, name?: string) { + super(message); + this.name = name || "Server error"; + this.stack = null; + } +}