diff --git a/src/screens/source/SourceScreen.js b/src/screens/source/SourceScreen.js index 536172b1..e1f48443 100644 --- a/src/screens/source/SourceScreen.js +++ b/src/screens/source/SourceScreen.js @@ -46,30 +46,15 @@ const SourceScreen = ({navigation, route}) => { const isMounted = useRef(true); const getNovels = async () => { - try { - if (page <= totalPages) { - const source = getSource(sourceId); - const res = await source.popularNovels(page); - setNovels(prevState => [...prevState, ...res.novels]); - setTotalPages(res.totalPages); - setLoading(false); - } - } catch (e) { - setError(e.message); - showToast(e.message); - setNovels([]); - setLoading(false); - } - }; - - const getSearchResults = async () => { if (isMounted.current === true) { try { - setLoading(true); - const source = getSource(sourceId); - const res = await source.searchNovels(searchText); - setNovels(res); - setLoading(false); + if (page <= totalPages) { + const source = getSource(sourceId); + const res = await source.popularNovels(page); + setNovels(prevState => [...prevState, ...res.novels]); + setTotalPages(res.totalPages); + setLoading(false); + } } catch (e) { setError(e.message); showToast(e.message); @@ -79,6 +64,21 @@ const SourceScreen = ({navigation, route}) => { } }; + const getSearchResults = async () => { + try { + setLoading(true); + const source = getSource(sourceId); + const res = await source.searchNovels(searchText); + setNovels(res); + setLoading(false); + } catch (e) { + setError(e.message); + showToast(e.message); + setNovels([]); + setLoading(false); + } + }; + const checkIFInLibrary = (novelSourceId, novelUrl) => library.some( obj => obj.novelUrl === novelUrl && obj.sourceId === novelSourceId, diff --git a/src/sources/id/novelringan.js b/src/sources/id/novelringan.js new file mode 100644 index 00000000..911f4df9 --- /dev/null +++ b/src/sources/id/novelringan.js @@ -0,0 +1,162 @@ +import cheerio from 'react-native-cheerio'; +import {Status} from '../helpers/constants'; + +const sourceId = 86; + +const sourceName = 'NovelRingan'; + +const baseUrl = 'https://novelringan.com/'; +const searchUrl = `${baseUrl}advanced-search`; + +const popularNovels = async page => { + let totalPages = 402; + const url = `${baseUrl}/top-novel/page/${page}`; + + const result = await fetch(url); + const body = await result.text(); + + const loadedCheerio = cheerio.load(body); + + const novels = []; + + loadedCheerio('article.post').each(function () { + const novelName = loadedCheerio(this).find('.entry-title').text()?.trim(); + const novelCover = loadedCheerio(this).find('img').attr('src'); + const novelUrl = loadedCheerio(this).find('h2 > a').attr('href'); + + const novel = { + sourceId, + novelName, + novelCover, + novelUrl, + }; + + novels.push(novel); + }); + + return {totalPages, novels}; +}; + +const parseNovelAndChapters = async novelUrl => { + const url = novelUrl; + + const result = await fetch(url); + const body = await result.text(); + + const loadedCheerio = cheerio.load(body); + + let novel = { + sourceId, + sourceName, + url, + novelUrl, + novelName: '', + novelCover: '', + genre: '', + author: '', + status: Status.UNKNOWN, + artist: '', + summary: '', + chapters: [], + }; + + novel.novelName = loadedCheerio('.entry-title').text()?.trim(); + novel.novelCover = loadedCheerio('img.ts-post-image').attr('src'); + novel.summary = loadedCheerio( + 'body > div.site-container > div > main > article > div > div.maininfo > span > p', + ).text(); + + let genreSelector = loadedCheerio( + 'body > div.site-container > div > main > article > div > div.maininfo > span > ul > li:nth-child(4)', + ).text(); + + novel.genre = genreSelector.includes('Genre') + ? genreSelector.replace('Genre:', '').trim() + : ''; + + let statusSelector = loadedCheerio( + 'body > div.site-container > div > main > article > div > div.maininfo > span > ul > li:nth-child(3)', + ).text(); + + novel.status = statusSelector.includes('Status') + ? statusSelector.replace('Status:', '').trim() + : Status.UNKNOWN; + + let chapters = []; + + loadedCheerio('.bxcl > ul > li').each(function () { + const chapterName = loadedCheerio(this).find('a').text(); + const releaseDate = null; + const chapterUrl = loadedCheerio(this).find('a').attr('href'); + + const chapter = { + chapterName, + releaseDate, + chapterUrl, + }; + + chapters.push(chapter); + }); + + novel.chapters = chapters.reverse(); + + return novel; +}; + +const parseChapter = async (novelUrl, chapterUrl) => { + const url = chapterUrl; + + const result = await fetch(url); + const body = await result.text(); + + const loadedCheerio = cheerio.load(body); + + const chapterName = loadedCheerio('.entry-title').text(); + const chapterText = loadedCheerio('.entry-content').html(); + + const chapter = { + sourceId, + novelUrl, + chapterUrl, + chapterName, + chapterText, + }; + + return chapter; +}; + +const searchNovels = async searchTerm => { + const url = baseUrl + '?s=' + searchTerm; + + const result = await fetch(url); + const body = await result.text(); + + const loadedCheerio = cheerio.load(body); + + let novels = []; + + loadedCheerio('article.post').each(function () { + const novelName = loadedCheerio(this).find('.entry-title').text(); + const novelCover = loadedCheerio(this).find('img').attr('src'); + const novelUrl = loadedCheerio(this).find('h2 > a').attr('href'); + + const novel = { + sourceId, + novelName, + novelCover, + novelUrl, + }; + + novels.push(novel); + }); + return novels; +}; + +const NovelRinganScraper = { + popularNovels, + parseNovelAndChapters, + parseChapter, + searchNovels, +}; + +export default NovelRinganScraper; diff --git a/src/sources/sources.js b/src/sources/sources.js index e4593f11..516459ea 100644 --- a/src/sources/sources.js +++ b/src/sources/sources.js @@ -86,6 +86,7 @@ import WoopReadScraper from './en/woopread'; import MTLReaderScraper from './en/mtlreader'; import MyLoveNovelScraper from './en/mylovenovel'; import RiwayatScraper from './ar/riwayat'; +import NovelRinganScraper from './id/novelringan'; export const getSource = sourceId => { const scrapers = { @@ -173,6 +174,7 @@ export const getSource = sourceId => { 83: MyLoveNovelScraper, 84: MoreNovelScraper, 85: RiwayatScraper, + 86: NovelRinganScraper, }; return scrapers[sourceId]; diff --git a/src/sources/sources.json b/src/sources/sources.json index 10bb3a4e..f3b7686a 100644 --- a/src/sources/sources.json +++ b/src/sources/sources.json @@ -586,5 +586,12 @@ "sourceName": "NovelSpace", "icon": "https://github.com/LNReader/lnreader-sources/blob/main/multisrc/madara/icons/riwayat.png?raw=true", "lang": "Arabic" + }, + { + "sourceId": 86, + "url": "https://novelringan.com/", + "sourceName": "NovelRingan", + "icon": "https://github.com/LNReader/lnreader-sources/blob/main/src/id/novelringan/icon.png?raw=true", + "lang": "Indonesian" } ]