@@ -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,
|
||||
|
||||
@@ -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;
|
||||
@@ -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];
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user