diff --git a/src/sources/ru/jaomix.js b/src/sources/ru/jaomix.js index b0dbb58e..d3af025e 100644 --- a/src/sources/ru/jaomix.js +++ b/src/sources/ru/jaomix.js @@ -1,4 +1,5 @@ import * as cheerio from 'cheerio'; +import { Status } from '../helpers/constants'; const sourceId = 117; const sourceName = 'Jaomix'; @@ -48,6 +49,19 @@ const parseNovelAndChapters = async novelUrl => { novel.novelCover = loadedCheerio('div[class="img-book"] > img').attr('src'); novel.summary = loadedCheerio('div[id="desc-tab"]').text().trim(); + loadedCheerio('#info-book > p').each(function () { + let text = loadedCheerio(this).text().replace(/,/g, '').split(' '); + if (text[0] === 'Автор:') { + novel.author = text.splice(1).join(' '); + } else if (text[0] === 'Жанры:') { + novel.genre = text.splice(1).join(','); + } else if (text[0] === 'Статус:') { + novel.status = text.includes('продолжается') + ? Status.ONGOING + : Status.COMPLETED; + } + }); + const termid = loadedCheerio('div[class="like-but"]').attr('id'); const chapters = []; @@ -103,12 +117,6 @@ const parseChapter = async (novelUrl, chapterUrl) => { const body = await result.text(); const loadedCheerio = cheerio.load(body); - loadedCheerio('img').each(function () { - if (!loadedCheerio(this).attr('src')?.startsWith('http')) { - let src = loadedCheerio(this).attr('src'); - loadedCheerio(this).attr('src', baseUrl + src); - } - }); loadedCheerio('div[class="adblock-service"]').remove(); const chapterName = loadedCheerio('h1[class="entry-title"]').html(); const chapterText = loadedCheerio('div[class="entry-content"]').html(); diff --git a/src/sources/ru/ranobehub.js b/src/sources/ru/ranobehub.js index 2fc73706..67d9a4e3 100644 --- a/src/sources/ru/ranobehub.js +++ b/src/sources/ru/ranobehub.js @@ -49,12 +49,30 @@ const parseNovelAndChapters = async novelUrl => { novel.summary = loadedCheerio('.book-description__text').text().trim(); - novel.genre = ''; - - novel.status = Status.UNKNOWN; - novel.author = loadedCheerio('.book-author').text().trim(); + loadedCheerio('div[class="book-meta-table"] > div').each(function () { + let name = loadedCheerio(this) + .find('div[class="book-meta-key"]') + .text() + .trim(); + + if (name === 'Статус перевода') { + novel.status = loadedCheerio(this) + .find('div[class="book-meta-value"]') + .text() + .includes('процессе') + ? Status.ONGOING + : Status.COMPLETED; + } else if (name === 'Жанр') { + novel.genre = loadedCheerio(this) + .find('div[class="book-meta-value book-tags"]') + .text() + .trim() + .replace(/[\n\r]+/g, ','); + } + }); + let novelChapters = []; const novelId = novelUrl.split('-')[0]; diff --git a/src/sources/ru/ranobelib.js b/src/sources/ru/ranobelib.js index e05fa8ef..ad627f1d 100644 --- a/src/sources/ru/ranobelib.js +++ b/src/sources/ru/ranobelib.js @@ -1,4 +1,5 @@ import * as cheerio from 'cheerio'; +import { Status } from '../helpers/constants'; const sourceId = 93; const sourceName = 'RanobeLib'; @@ -49,11 +50,31 @@ const parseNovelAndChapters = async novelUrl => { novel.summary = loadedCheerio('.media-description__text').text().trim(); - novel.author = loadedCheerio( - '#main-page > div > div.container.container_responsive > div > div.media-sidebar > div.media-info-list.paper > a:nth-child(4) > div.media-info-list__value', - ) + novel.genre = loadedCheerio('div[class="media-tags"]') .text() - .trim(); + .trim() + .replace(/[\n\r]+/g, ',') + .replace(/ /g, ''); + + loadedCheerio( + 'div[class="media-info-list paper"] > [class="media-info-list__item"]', + ).each(function () { + let name = loadedCheerio(this) + .find('div[class="media-info-list__title"]') + .text(); + + if (name === 'Статус перевода') { + novel.status = + loadedCheerio(this).find('div:nth-child(2)').text().trim() === + 'Продолжается' + ? Status.ONGOING + : Status.COMPLETED; + } else if (name === 'Автор') { + novel.author = loadedCheerio(this).find('div:nth-child(2)').text().trim(); + } else if (name === 'Художник') { + novel.artist = loadedCheerio(this).find('div:nth-child(2)').text().trim(); + } + }); let chapters = []; diff --git a/src/sources/ru/ranoberf.js b/src/sources/ru/ranoberf.js index f07beb6b..4e74af82 100644 --- a/src/sources/ru/ranoberf.js +++ b/src/sources/ru/ranoberf.js @@ -1,5 +1,6 @@ import * as cheerio from 'cheerio'; import { htmlToText } from '../helpers/htmlToText'; +import { Status } from '../helpers/constants'; const sourceId = 119; const sourceName = 'РанобэРФ'; @@ -42,8 +43,13 @@ const parseNovelAndChapters = async novelUrl => { novelName: json.props.pageProps.book.title, novelCover: baseUrl + json.props.pageProps.book.verticalImage.url, summary: htmlToText(json.props.pageProps.book.description), - author: json.props.pageProps.book?.author || null, + author: json.props.pageProps.book?.author, + genre: json.props.pageProps.book.genres.map(item => item.title).join(','), + status: json.props.pageProps.book.additionalInfo.includes('Активен') + ? Status.ONGOING + : Status.COMPLETED, }; + let chapters = []; json.props.pageProps.book.chapters.map(item => { diff --git a/src/sources/ru/renovels.js b/src/sources/ru/renovels.js index cff8c36e..f42a62a1 100644 --- a/src/sources/ru/renovels.js +++ b/src/sources/ru/renovels.js @@ -1,14 +1,14 @@ import { htmlToText } from '../helpers/htmlToText'; +import { Status } from '../helpers/constants'; const sourceId = 116; const sourceName = 'Renovels'; -const baseUrl = 'https://renovels.org/'; +const baseUrl = 'https://renovels.org'; const popularNovels = async page => { const totalPages = 20; - const url = - 'https://api.renovels.org/api/titles/last-chapters/?&count=20&page=' + page; + const url = baseUrl + '/api/titles/last-chapters/?&count=20&page=' + page; const result = await fetch(url); let body = await result.json(); @@ -16,7 +16,7 @@ const popularNovels = async page => { body.content.map(item => { const novelName = item.rus_name; - const novelCover = 'https://api.renovels.org' + item.img.mid; + const novelCover = baseUrl + item.img.mid; const novelUrl = item.dir; novels.push({ sourceId, novelName, novelCover, novelUrl }); }); @@ -25,29 +25,41 @@ const popularNovels = async page => { }; const parseNovelAndChapters = async novelUrl => { - const result = await fetch('https://api.renovels.org/api/titles/' + novelUrl); + const result = await fetch(baseUrl + '/api/titles/' + novelUrl); let body = await result.json(); let novel = { sourceId, sourceName, - url: baseUrl + 'novel/' + body.content.dir, - novelName: body.content.rus_name, - novelCover: - 'https://api.renovels.org' + body.content.img?.high || - body.content.img?.low, - summary: htmlToText(body.content.description), novelUrl, + url: baseUrl + '/novel/' + body.content.dir, + novelName: body.content.rus_name, + novelCover: baseUrl + (body.content.img?.high || body.content.img.low), + summary: htmlToText(body.content.description), + status: + body.content.status.name === 'Продолжается' + ? Status.ONGOING + : Status.COMPLETED, }; + let tags = [] + .concat(body.content.genres, body.content.categories, []) + .map(item => item.name); + + if (tags.length > 0) { + novel.genre = tags.join(','); + } + let all = (body.content.count_chapters / 100 + 1) ^ 0; let chapters = []; for (let i = 0; i < all; i++) { let chapterResult = await fetch( - `https://api.renovels.org/api/titles/chapters/?branch_id=${ - body.content.branches[0].id - }&count=100&page=${i + 1}`, + baseUrl + + '/api/titles/chapters/?branch_id=' + + body.content.branches[0].id + + '&count=100&page=' + + (i + 1), ); let volumes = await chapterResult.json(); @@ -55,8 +67,7 @@ const parseNovelAndChapters = async novelUrl => { const chapterName = `Том ${item.tome} Глава ${item.chapter} ${item.name}`?.trim(); const releaseDate = item.upload_date; - const chapterUrl = - 'https://api.renovels.org/api/titles/chapters/' + item.id + '/'; + const chapterUrl = baseUrl + '/api/titles/chapters/' + item.id + '/'; if (!item.is_paid) { chapters.push({ chapterName, releaseDate, chapterUrl }); @@ -64,7 +75,7 @@ const parseNovelAndChapters = async novelUrl => { }); } - novel.chapters = chapters; + novel.chapters = chapters.reverse(); return novel; }; @@ -84,14 +95,14 @@ const parseChapter = async (novelUrl, chapterUrl) => { }; const searchNovels = async searchTerm => { - const url = `https://api.renovels.org/api/search/?query=${searchTerm}&count=100&field=titles`; + const url = `${baseUrl}/api/search/?query=${searchTerm}&count=100&field=titles`; const result = await fetch(url); let body = await result.json(); let novels = []; body.content.map(item => { const novelName = item.rus_name; - const novelCover = 'https://api.renovels.org' + item.img.mid; + const novelCover = baseUrl + item.img.mid; const novelUrl = item.dir; const novel = { sourceId, novelName, novelCover, novelUrl }; novels.push(novel); diff --git a/src/sources/ru/rulate.js b/src/sources/ru/rulate.js index c10640d9..e2f3e71d 100644 --- a/src/sources/ru/rulate.js +++ b/src/sources/ru/rulate.js @@ -1,4 +1,5 @@ import * as cheerio from 'cheerio'; +import { Status } from '../helpers/constants'; const sourceId = 118; const sourceName = 'Rulate'; @@ -6,11 +7,15 @@ const sourceName = 'Rulate'; const baseUrl = 'https://tl.rulate.ru'; const popularNovels = async page => { - const totalPages = 50; - const result = await fetch(`${baseUrl}/site/login?page=${page}`); + const result = await fetch(baseUrl + '/site/login?page=' + page); const body = await result.text(); const loadedCheerio = cheerio.load(body); + const totalPages = parseInt( + loadedCheerio('li[class="last"] > a').attr('href')?.replace(/[^\d]/g, '') || + '250', + 10, + ); let novels = []; loadedCheerio('.imged > li').each(function () { @@ -44,8 +49,44 @@ const parseNovelAndChapters = async novelUrl => { novel.novelCover = baseUrl + loadedCheerio('div[class="images"] > div img').attr('src'); novel.summary = loadedCheerio('#Info > div:nth-child(3)').text().trim(); + novel.genre = []; + let chapters = []; + loadedCheerio('div[class="span5"] > p').each(function () { + switch (loadedCheerio(this).find('strong').text()) { + case 'Автор:': + novel.author = loadedCheerio(this).find('em > a').text().trim(); + break; + case 'Выпуск:': + novel.status = + loadedCheerio(this).find('em').text().trim() === 'продолжается' + ? Status.ONGOING + : Status.COMPLETED; + break; + case 'Тэги:': + loadedCheerio(this) + .find('em > a') + .each(function () { + novel.genre.push(loadedCheerio(this).text()); + }); + break; + case 'Жанры:': + loadedCheerio(this) + .find('em > a') + .each(function () { + novel.genre.push(loadedCheerio(this).text()); + }); + break; + } + }); + + if (novel.genre.length > 0) { + novel.genre = novel.genre.reverse().join(','); + } else { + novel.genre = ''; + } + loadedCheerio('table > tbody > tr.chapter_row').each(function () { const chapterName = loadedCheerio(this) .find('td[class="t"] > a')