From ac8bca7f03ebf78d8f64e97c2e0f397f9bf74eac Mon Sep 17 00:00:00 2001 From: Bread Genie <63963181+BreadGenie@users.noreply.github.com> Date: Sun, 25 Jul 2021 21:38:33 +0530 Subject: [PATCH] feat(sources): Add ReaperScans Novels (#59) --- src/sources/en/reaperscans.js | 185 ++++++++++++++++++++++++++++++++++ src/sources/sources.js | 2 + src/sources/sources.json | 7 ++ 3 files changed, 194 insertions(+) create mode 100644 src/sources/en/reaperscans.js diff --git a/src/sources/en/reaperscans.js b/src/sources/en/reaperscans.js new file mode 100644 index 00000000..c65bc7a6 --- /dev/null +++ b/src/sources/en/reaperscans.js @@ -0,0 +1,185 @@ +import cheerio from "react-native-cheerio"; +import { htmlToText } from "../helpers/htmlToText"; + +const baseUrl = "https://reaperscans.com"; + +const sourceId = 67; + +const popularNovels = async (page) => { + let url = `${baseUrl}/all-series/novels/`; + let totalPages = 1; + + const result = await fetch(url); + const body = await result.text(); + + $ = cheerio.load(body); + + let novels = []; + + $(".page-item-detail").each(function (result) { + const novelName = $(this).find(".item-summary h3").text(); + const novelCover = $(this).find(".img-responsive").attr("data-src"); + + let novelUrl = $(this).find("div > a").attr("href"); + novelUrl = novelUrl.replace(`${baseUrl}/`, ""); + + const novel = { + sourceId, + novelName, + novelCover, + novelUrl, + }; + + novels.push(novel); + }); + + return { totalPages, novels }; +}; + +const parseNovelAndChapters = async (novelUrl) => { + const url = `${baseUrl}/${novelUrl}`; + + const result = await fetch(url); + const body = await result.text(); + + $ = cheerio.load(body); + + let novel = {}; + + $(".post-title > h3 > span").remove(); + + novel.sourceId = 67; + + novel.sourceName = "ReaperScans"; + + novel.url = url; + + novel.novelUrl = novelUrl; + + novel.novelName = $(".post-title > h3") + .text() + .replace(/[\t\n]/g, "") + .trim(); + + novel.novelCover = $(".summary_image > a > img").attr("src"); + + $(".post-content_item").each(function (result) { + detailName = $(this) + .find(".summary-heading > h5") + .text() + .replace(/[\t\n]/g, "") + .trim(); + detail = $(this) + .find(".summary-content") + .text() + .replace(/[\t\n]/g, "") + .trim(); + + switch (detailName) { + case "Genre(s)": + novel.genre = detail.trim().replace(/[\t\n]/g, ","); + break; + case "Author(s)": + novel.author = detail.trim(); + break; + case "Status": + novel.status = detail.trim(); + break; + } + }); + + $(".description-summary > div.summary__content").find("em").remove(); + $(".premium-block").remove(); + + novel.summary = $(".description-summary > div.summary__content") + .text() + .replace(/[\t\n]|Description|Summary/g, ""); + + let novelChapters = []; + + $(".wp-manga-chapter").each(function (result) { + const chapterName = $(this) + .find("a") + .text() + .replace(/[\t\n]/g, "") + .trim(); + + const releaseDate = $(this) + .find(".chapter-release-date") + .text() + .replace(/[\t\n]/g, "") + .trim(); + + const chapterUrl = $(this).find("a").attr("href").replace(url, ""); + + const chapter = { chapterName, releaseDate, chapterUrl }; + + novelChapters.push(chapter); + }); + + novel.chapters = novelChapters.reverse(); + + return novel; +}; + +const parseChapter = async (novelUrl, chapterUrl) => { + const url = `${baseUrl}/${novelUrl}/${chapterUrl}`; + + const result = await fetch(url); + const body = await result.text(); + + $ = cheerio.load(body); + + const chapterName = $("#chapter-heading").text(); + let chapterText = $(".reading-content").html(); + chapterText = htmlToText(chapterText); + + const chapter = { + sourceId, + novelUrl, + chapterUrl, + chapterName, + chapterText, + }; + + return chapter; +}; + +const searchNovels = async (searchTerm) => { + const url = `${baseUrl}?s=${searchTerm}&post_type=wp-manga`; + + const result = await fetch(url); + const body = await result.text(); + + $ = cheerio.load(body); + + let novels = []; + + $(".c-tabs-item__content").each(function (result) { + const novelName = $(this).find(".post-title > h3").text(); + const novelCover = $(this).find("div > div > a > img").attr("data-src"); + + let novelUrl = $(this).find("div > div > a").attr("href"); + novelUrl = novelUrl.replace(`${baseUrl}/`, ""); + + const novel = { + sourceId, + novelName, + novelCover, + novelUrl, + }; + + novels.push(novel); + }); + + return novels; +}; + +const ReaperScansScraper = { + popularNovels, + parseNovelAndChapters, + parseChapter, + searchNovels, +}; + +export default ReaperScansScraper; diff --git a/src/sources/sources.js b/src/sources/sources.js index 03b95d13..0f49cdad 100644 --- a/src/sources/sources.js +++ b/src/sources/sources.js @@ -67,6 +67,7 @@ import { RewayatArScraper, } from "./multisrc/wpmangastream/WPMangaStreamGenerator"; import WLNUpdatesScraper from "./en/wlnupdates"; +import ReaperScansScraper from "./en/reaperscans"; export const getSource = (sourceId) => { const scrapers = { @@ -135,6 +136,7 @@ export const getSource = (sourceId) => { 64: ClickNovelScraper, 65: ReadWebNovelsScraper, 66: WBNovelScraper, + 67: ReaperScansScraper, }; return scrapers[sourceId]; diff --git a/src/sources/sources.json b/src/sources/sources.json index 549b94eb..f5717d7d 100644 --- a/src/sources/sources.json +++ b/src/sources/sources.json @@ -453,5 +453,12 @@ "sourceName": "WBNovel", "icon": "https://github.com/LNReader/lnreader-sources/blob/main/multisrc/madara/icons/wbnovel.png?raw=true", "lang": "English" + }, + { + "sourceId": 67, + "url": "https://reaperscans.com/all-series/novels/", + "sourceName": "ReaperScans", + "icon": "https://github.com/LNReader/lnreader-sources/blob/main/src/en/reaperscans/icon.png?raw=true", + "lang": "English" } ]