From 52fddfca4f6b7d76732203f5ae6f9c59fbb66a0f Mon Sep 17 00:00:00 2001 From: alaska <75046310+sweetbbak@users.noreply.github.com> Date: Mon, 19 Aug 2024 07:45:13 -0800 Subject: [PATCH] add rainofsnow english (#1147) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add rainofsnow explicitly * Update src/plugins/english/rainofsnow.ts Co-authored-by: K1ngfish3r * Update src/plugins/english/rainofsnow.ts Co-authored-by: K1ngfish3r * rainofsnow: done 🎉 - fixed pagination parsing, plugin type is now correct, parsing chapter no longer crashes the server, now using 'this.site', and cleaned a few things up. --------- Co-authored-by: K1ngfish3r --- public/static/src/en/rainofsnow/icon.png | Bin 0 -> 7176 bytes src/plugins/english/rainofsnow.ts | 186 +++++++++++++++++++++++ 2 files changed, 186 insertions(+) create mode 100644 public/static/src/en/rainofsnow/icon.png create mode 100644 src/plugins/english/rainofsnow.ts diff --git a/public/static/src/en/rainofsnow/icon.png b/public/static/src/en/rainofsnow/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..43c8de8b7483bd9a3f16f35b263a43193247be34 GIT binary patch literal 7176 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 literal 0 HcmV?d00001 diff --git a/src/plugins/english/rainofsnow.ts b/src/plugins/english/rainofsnow.ts new file mode 100644 index 0000000..84e1270 --- /dev/null +++ b/src/plugins/english/rainofsnow.ts @@ -0,0 +1,186 @@ +import { fetchApi } from '@libs/fetch'; +import { Plugin } from '@typings/plugin'; +import { Filters } from '@libs/filterInputs'; +import { CheerioAPI, load as parseHTML } from 'cheerio'; +import { NovelStatus } from '@libs/novelStatus'; + +class Rainofsnow implements Plugin.PagePlugin { + id = 'rainofsnow'; + name = 'Rainofsnow'; + icon = 'src/en/rainofsnow/icon.png'; + site = 'https://rainofsnow.com/'; + version = '1.0.0'; + filters: Filters | undefined = undefined; + imageRequestInit?: Plugin.ImageRequestInit | undefined = undefined; + + parseNovels(loadedCheerio: CheerioAPI, searchTerm?: string) { + let novels: Plugin.NovelItem[] = []; + + loadedCheerio('.minbox').each((index, element) => { + const name = loadedCheerio(element).find('h3').text(); + const cover = loadedCheerio(element).find('img').attr('data-src'); + const path = loadedCheerio(element) + .find('h3 > a') + .attr('href') + ?.replace(this.site, '') + .replace(/\/+$/, ''); + + if (!path) { + return; + } + + novels.push({ name, cover, path }); + }); + + if (searchTerm) { + novels = novels.filter(novel => + novel.name.toLowerCase().includes(searchTerm.toLowerCase()), + ); + } + + return novels; + } + + async popularNovels( + pageNo: number, + { + showLatestNovels, + filters, + }: Plugin.PopularNovelsOptions, + ): Promise { + let url = this.site + 'novels/page/' + pageNo; + const body = await fetchApi(url).then(res => res.text()); + const loadedCheerio = parseHTML(body); + + return this.parseNovels(loadedCheerio); + } + + async parseNovel( + novelPath: string, + ): Promise { + const novel: Plugin.SourceNovel & { totalPages: number } = { + path: novelPath, + name: '', + totalPages: 0, + }; + + const body = await fetchApi(this.site + novelPath).then(res => res.text()); + const loadedCheerio = parseHTML(body); + + novel.name = loadedCheerio('div.text > h2').text().trim(); + + novel.cover = loadedCheerio('.imagboca1 > img').attr('data-src'); + + novel.summary = loadedCheerio('#synop').text().trim(); + + novel.genres = loadedCheerio( + 'body > div.queen > div > div > div.row > div.col-md-12.col-lg-7 > div > div.backcolor1 > ul > li:nth-child(5) > small', + ) + .text() + .trim(); + + novel.author = loadedCheerio( + 'body > div.queen > div > div > div.row > div.col-md-12.col-lg-7 > div > div.backcolor1 > ul > li:nth-child(2) > small', + ).text(); + + let x = 1; + loadedCheerio('.page-numbers') + .find('li') + .each(function (i, el) { + const num = loadedCheerio(el).find('a').text().trim().match(/(\d+)/); + + let n = Number(num?.[1] || '0'); + if (n > x) { + x = n; + } + }); + + novel.totalPages = x; + + novel.status = status ? NovelStatus.Completed : NovelStatus.Ongoing; + novel.chapters = this.parseChapters(loadedCheerio); + return novel; + } + + // parse paged chapters + async parsePage(novelPath: string, page: string): Promise { + const url = this.site + novelPath + '/page/' + page + '/#chapter'; + const body = await fetchApi(url).then(res => res.text()); + const loadedCheerio = parseHTML(body); + const chapters = this.parseChapters(loadedCheerio); + return { chapters }; + } + + // helper to parse a novel + parseChapters(loadedCheerio: CheerioAPI) { + const chapter: Plugin.ChapterItem[] = []; + + loadedCheerio('#chapter') + .find('li') + .each((i, el) => { + const name = loadedCheerio(el).find('.chapter').first().text().trim(); + const releaseTime = loadedCheerio(el).find('small').text(); + const path = loadedCheerio(el) + .find('a') + .attr('href') + ?.slice(this.site.length); + + if (path && name) { + chapter.push({ name, path, releaseTime }); + } + }); + + return chapter; + } + + async parseChapter(chapterPath: string): Promise { + // parse chapter text here + const result = await fetch(this.site + chapterPath); + const body = await result.text(); + + const loadedCheerio = parseHTML(body); + + let chapterName = loadedCheerio('.content > h2').text(); + let chapterText = loadedCheerio('.content').html(); + if (!chapterText) return ''; + return chapterName + '\n' + chapterText; + } + + async searchNovels( + searchTerm: string, + pageNo: number, + ): Promise { + const novels: Plugin.NovelItem[] = []; + // get novels using the search term + // no page number, infinite scroll + + const newSearch = searchTerm.replace(/\s+/g, '+'); + let url = this.site + '?s=' + newSearch; + + console.log('SERCH URL: ', url); + + const result = await fetch(url); + const body = await result.text(); + const loadedCheerio = parseHTML(body); + + loadedCheerio('.minbox').each((index, element) => { + const name = loadedCheerio(element).find('h3').text(); + const cover = loadedCheerio(element).find('img').attr('data-src'); + const path = loadedCheerio(element) + .find('h3 > a') + .attr('href') + ?.slice(this.site.length) + .replace(/\/+$/, ''); + + if (!path) { + return; + } + + novels.push({ name, cover, path }); + }); + + return novels; + } +} + +export default new Rainofsnow();