feat(source): Add MTNovel (Closes LNReader/lnreader-sources#197)

This commit is contained in:
Rajarshee Chatterjee
2022-05-03 12:55:58 +05:30
parent ae16cc70f5
commit aee3126e6c
3 changed files with 194 additions and 0 deletions
+185
View File
@@ -0,0 +1,185 @@
import * as cheerio from 'cheerio';
import {
SourceChapter,
SourceChapterItem,
SourceNovel,
SourceNovelItem,
} from '../types';
const sourceId = 120;
const sourceName = 'MT Novel';
const baseUrl = 'https://mtnovel.com';
const popularNovels = async (page: number) => {
let totalPages = 22;
const url = `${baseUrl}/most-popular?page=${page}`;
const result = await fetch(url);
const body = await result.text();
const loadedCheerio = cheerio.load(body);
let novels: SourceNovelItem[] = [];
loadedCheerio('.list-truyen .row').each(function () {
const novelName = loadedCheerio(this).find('h3.truyen-title > a').text();
const novelCover =
baseUrl + loadedCheerio(this).find('img.cover').attr('src');
const novelUrl =
baseUrl + loadedCheerio(this).find('h3.truyen-title > a').attr('href');
const novel = {
sourceId,
novelUrl,
novelName,
novelCover,
};
novels.push(novel);
});
return { totalPages, novels };
};
const parseNovelAndChapters = async (novelUrl: string) => {
const url = novelUrl;
const result = await fetch(url);
const body = await result.text();
let loadedCheerio = cheerio.load(body);
let novel: SourceNovel = {
sourceId,
sourceName,
url: novelUrl,
novelUrl,
};
novel.novelName = loadedCheerio('div.book > img').attr('alt');
novel.novelCover = baseUrl + loadedCheerio('div.book > img').attr('src');
novel.summary = loadedCheerio('div.desc-text').text().trim();
novel.author = loadedCheerio('div.info > div > h3')
.filter(function () {
return loadedCheerio(this).text().trim() === 'Author:';
})
.siblings()
.text();
novel.genre = loadedCheerio('div.info > div')
.filter(function () {
return loadedCheerio(this).find('h3').text().trim() === 'Genre:';
})
.text()
.replace('Genre:', '');
novel.status = loadedCheerio('div.info > div > h3')
.filter(function () {
return loadedCheerio(this).text().trim() === 'Status:';
})
.next()
.text();
const novelId = loadedCheerio('#rating').attr('data-novel-id');
const getChapters = async (id: string) => {
const chapterListUrl = baseUrl + '/ajax/chapter-option?novelId=' + id;
const data = await fetch(chapterListUrl);
const chapters = await data.text();
loadedCheerio = cheerio.load(chapters);
let novelChapters: SourceChapterItem[] = [];
loadedCheerio('select > option').each(function () {
let chapterName = loadedCheerio(this).text();
let releaseDate = null;
let chapterUrl = loadedCheerio(this)
.attr('value')
?.replace(`/${novelUrl}`, '');
if (chapterUrl) {
novelChapters.push({
chapterName,
releaseDate,
chapterUrl,
});
}
});
return novelChapters;
};
if (novelId) {
novel.chapters = await getChapters(novelId);
}
return novel;
};
const parseChapter = async (novelUrl: string, chapterUrl: string) => {
const url = baseUrl + chapterUrl;
const result = await fetch(url);
const body = await result.text();
const loadedCheerio = cheerio.load(body);
const chapterName = loadedCheerio('.chapter-title').attr('title');
const chapterText = loadedCheerio('#chapter-content').html() || '';
const chapter: SourceChapter = {
sourceId,
novelUrl,
chapterUrl,
chapterName,
chapterText,
};
return chapter;
};
const searchNovels = async (searchTerm: string) => {
const url = `${baseUrl}/search?keyword=${searchTerm}`;
const result = await fetch(url);
const body = await result.text();
const loadedCheerio = cheerio.load(body);
let novels: SourceNovelItem[] = [];
loadedCheerio('div.col-truyen-main > div.list-truyen > .row').each(
function () {
const novelUrl =
baseUrl + loadedCheerio(this).find('h3.truyen-title > a').attr('href');
const novelName = loadedCheerio(this).find('h3.truyen-title > a').text();
const novelCover = baseUrl + loadedCheerio(this).find('img').attr('src');
if (novelUrl) {
novels.push({
sourceId,
novelUrl,
novelName,
novelCover,
});
}
},
);
return novels;
};
const MTNovelScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default MTNovelScraper;
+2
View File
@@ -119,6 +119,7 @@ import FreeNovelUpdatesScraper from './en/freenovelupdates';
import NovelsCafeScraper from './en/NovelsCafe';
import LightNovelReaderScraper from './en/LightNovelReader';
import HakoLightNovelScraper from './vi/HakoLightNovel';
import MTNovelScraper from './en/mtnovel';
interface PopularNovelsResponse {
totalPages: number;
@@ -252,6 +253,7 @@ export const sourceManager = (sourceId: number): Scraper => {
117: JaomixScraper,
118: RulateScraper,
119: RanobeRFScraper,
120: MTNovelScraper,
};
return scrapers[sourceId];
+7
View File
@@ -803,5 +803,12 @@
"url": "https://ранобэ.рф",
"lang": "Russian",
"icon": "https://github.com/LNReader/lnreader-sources/blob/main/src/ru/ranoberf/icon.png?raw=true"
},
{
"sourceId": 120,
"url": "https://mtnovel.com/",
"sourceName": "MT Novel",
"icon": "https://github.com/LNReader/lnreader-sources/blob/main/src/en/allnovelfull/icon.png?raw=true",
"lang": "English"
}
]