diff --git a/assets/radar-rules.js b/assets/radar-rules.js index 8587f6ace..73be642ab 100644 --- a/assets/radar-rules.js +++ b/assets/radar-rules.js @@ -97,9 +97,6 @@ 'ishuhui.com': { _name: '鼠绘漫画', www: [{ title: '鼠绘漫画', docs: 'https://docs.rsshub.app/anime.html#shu-hui-man-hua', source: '/comics/anime/:id', target: '/shuhui/comics/:id' }] }, 'www.chicagotribune.com': { _name: 'Chicago Tribune', www: [{ title: 'Chicago Tribune', docs: 'https://docs.rsshub.app/traditional_media.html#chicago-tribune', source: '/' }] }, 'haimaoba.com': { _name: '海猫吧', www: [{ title: '漫画更新', docs: 'https://docs.rsshub.app/anime.html#hai-mao-ba', source: '/catalog/:id', target: '/haimaoba/:id' }] }, - 'manhuagui.com': { _name: '漫画柜', www: [{ title: '漫画更新', docs: 'https://docs.rsshub.app/anime.html#kan-man-hua', source: '/comic/:id/', target: '/manhuagui/comic/:id/5' }] }, - 'mhgui.com': { _name: '漫画柜镜像站', www: [{ title: '漫画更新', docs: 'https://docs.rsshub.app/anime.html#kan-man-hua-jing-xiang-zhan', source: '/comic/:id/', target: '/mhgui/comic/:id/5' }] }, - 'tw.manhuagui.com': { _name: '漫画柜台湾', www: [{ title: '漫画更新', docs: 'https://docs.rsshub.app/anime.html#kan-man-hua-tai-wan', source: '/comic/:id/', target: '/twmanhuagui/comic/:id' }] }, 'copymanga.com': { _name: '拷贝漫画', www: [{ title: '漫画更新', docs: 'https://docs.rsshub.app/anime.html#kao-bei-man-hua', source: '/comic/:id/', target: '/manhuagui/comic/:id/5' }] }, 'pgyer.com': { _name: '蒲公英应用分发', www: [{ title: 'app更新', docs: 'https://docs.rsshub.app/program-update.html#pu-gong-ying-ying-yong-fen-fa', source: '/:app', target: '/pgyer/:app' }] }, 'wineyun.com': { _name: '酒云网', www: [{ title: '最新商品', docs: 'https://docs.rsshub.app/other.html#jiu-yun-wang', source: ['/:category'], target: '/wineyun/:category' }] }, diff --git a/docs/anime.md b/docs/anime.md index 456d15560..388be1180 100644 --- a/docs/anime.md +++ b/docs/anime.md @@ -567,17 +567,26 @@ Sources -## 看漫画镜像站 +### 漫画个人订阅 -### 漫画更新 + - +::: tip 提示 -## 看漫画台湾 +个人订阅需要自建 +环境变量需要添加 MHGUI_COOKIE -### 漫画更新 +::: - + + +### 镜像站 - 漫画更新 + + + +### 台湾站 - 漫画更新 + + ## 拷贝漫画 diff --git a/lib/config.js b/lib/config.js index 7771b9d21..0faecc77f 100644 --- a/lib/config.js +++ b/lib/config.js @@ -185,6 +185,9 @@ const calculateValue = () => { lastfm: { api_key: envs.LASTFM_API_KEY, }, + manhuagui: { + cookie: envs.MHGUI_COOKIE, + }, mastodon: { apiHost: envs.MASTODON_API_HOST, accessToken: envs.MASTODON_API_ACCESS_TOKEN, diff --git a/lib/radar-rules.js b/lib/radar-rules.js index 62c922e2e..befac161f 100644 --- a/lib/radar-rules.js +++ b/lib/radar-rules.js @@ -167,39 +167,6 @@ module.exports = { }, ], }, - 'manhuagui.com': { - _name: '漫画柜', - www: [ - { - title: '漫画更新', - docs: 'https://docs.rsshub.app/anime.html#kan-man-hua', - source: '/comic/:id/', - target: '/manhuagui/comic/:id', - }, - ], - }, - 'mhgui.com': { - _name: '漫画柜镜像站', - www: [ - { - title: '漫画更新', - docs: 'https://docs.rsshub.app/anime.html#kan-man-hua-jing-xiang-zhan', - source: '/comic/:id/', - target: '/mhgui/comic/:id', - }, - ], - }, - 'tw.manhuagui.com': { - _name: '漫画柜台湾', - www: [ - { - title: '漫画更新', - docs: 'https://docs.rsshub.app/anime.html#kan-man-hua-tai-wan', - source: '/comic/:id/', - target: '/twmanhuagui/comic/:id', - }, - ], - }, 'pgyer.com': { _name: '蒲公英应用分发', www: [ diff --git a/lib/router.js b/lib/router.js index 22808d3df..81329ec7e 100644 --- a/lib/router.js +++ b/lib/router.js @@ -996,10 +996,11 @@ router.get('/eeo/:column?/:category?', lazyloadRouteHandler('./routes/eeo/index' // 腾讯视频 router.get('/tencentvideo/playlist/:id', lazyloadRouteHandler('./routes/tencent/video/playlist')); -// 看漫画 -router.get('/manhuagui/comic/:id/:chapterCnt?', lazyloadRouteHandler('./routes/manhuagui/comic')); -router.get('/mhgui/comic/:id/:chapterCnt?', lazyloadRouteHandler('./routes/mhgui/comic')); -router.get('/twmanhuagui/comic/:id/:chapterCnt?', lazyloadRouteHandler('./routes/twmanhuagui/comic')); +// 看漫画 migrated to v2 +// router.get('/manhuagui/comic/:id/:chapterCnt?', lazyloadRouteHandler('./routes/manhuagui/comic')); +// router.get('/mhgui/comic/:id/:chapterCnt?', lazyloadRouteHandler('./routes/mhgui/comic')); +// router.get('/twmanhuagui/comic/:id/:chapterCnt?', lazyloadRouteHandler('./routes/twmanhuagui/comic')); + // 拷贝漫画 router.get('/copymanga/comic/:id/:chapterCnt?', lazyloadRouteHandler('./routes/copymanga/comic')); diff --git a/lib/routes/mhgui/comic.js b/lib/routes/mhgui/comic.js deleted file mode 100644 index daf52eb7e..000000000 --- a/lib/routes/mhgui/comic.js +++ /dev/null @@ -1,99 +0,0 @@ -const { resolve } = require('url'); -const cheerio = require('cheerio'); -const got = require('@/utils/got'); -const LZString = require('lz-string'); - -const getChapters = ($) => { - let time_mark = 0; - // 用于一次更新多个新章节的排序 - let new_time_mark = 0; - return $('h4') - .toArray() - .map((ele) => { - const categoryName = $(ele).text(); - while (!$(ele.next).hasClass('chapter-list')) { - ele = ele.next; - } - ele = ele.next; - return $(ele) - .children('ul') - .toArray() - .reverse() - .reduce((acc, curr) => acc.concat($(curr).children('li').toArray()), []) - .map((ele) => { - const a = $(ele).children('a'); - // 通过操作发布时间来对章节进行排序,如果是刚刚更新的单行本或者番外,保留最新更新时间 - let pDate = new Date(new Date($.pubDate) - time_mark++ * 1000); - if (a.find('em').length > 0) { - // 对更新的章节也进行排序 - pDate = new Date(new Date($.pubDate) - new_time_mark++ * 1000); - $.newChapterCnt++; - } - return { - link: resolve('https://www.mhgui.com/', a.attr('href')), - title: a.attr('title'), - pub_date: pDate, - num: a.find('i').text(), - guid: resolve('https://www.mhgui.com/', a.attr('href')), - category: categoryName, - }; - }); - }) - .reduce((acc, curr) => acc.concat(curr)); -}; -module.exports = async (ctx) => { - const { id } = ctx.params; - const chapterCnt = Number(ctx.params.chapterCnt || 0); - const { data } = await got.get(`https://www.mhgui.com/comic/${id}/`); - const $ = cheerio.load(data); - - if ($('#__VIEWSTATE').length > 0) { - const n = LZString.decompressFromBase64($('#__VIEWSTATE').val()); - if (n) { - $('#erroraudit_show').replaceWith(n); - $('#__VIEWSTATE').remove(); - } - } - const bookTitle = $('.book-title > h1').text(); - const bookIntro = $('#intro-all').text(); - const coverImgSrc = $('.book-cover img').attr('src'); - // 对最新更新的章节增加了pubDate - const reg = new RegExp('最近于.+更新至'); - // 处理已下架的漫画 - if ($('.status > span').text().indexOf('已下架') > 0) { - ctx.state.data = { - title: `看漫画 - ${bookTitle} 已下架`, - link: `https://www.mhgui.com/comic/${id}/`, - description: bookIntro, - item: [{ link: `https://www.mhgui.com/comic/${id}/`, title: bookTitle, description: '已下架' }], - }; - } else { - const pub_date_str = $('.status > span').text().match(reg)[0].replace('最近于 [', '').replace('] 更新至', ''); - // 为了能在闭包内访问到这个日期而不是每次需要处理这个最近更新日期 - $.pubDate = new Date(pub_date_str).toUTCString(); - $.newChapterCnt = 0; - const chapters = getChapters($); - const genResult = (chapter) => ({ - link: chapter.link, - title: chapter.title, - pubDate: chapter.pub_date, - guid: chapter.guid, - category: chapter.category, - description: ` -

${chapter.num}

- - `.trim(), - }); - const items = chapters.map(genResult); - let itemsLen = items.length; - if (chapterCnt > 0) { - itemsLen = chapterCnt < $.newChapterCnt ? $.newChapterCnt : chapterCnt; - } - ctx.state.data = { - title: `看漫画 - ${bookTitle}`, - link: `https://www.mhgui.com/comic/${id}/`, - description: bookIntro, - item: items.slice(0, itemsLen), - }; - } -}; diff --git a/lib/routes/twmanhuagui/comic.js b/lib/routes/twmanhuagui/comic.js deleted file mode 100644 index 9629a1464..000000000 --- a/lib/routes/twmanhuagui/comic.js +++ /dev/null @@ -1,99 +0,0 @@ -const { resolve } = require('url'); -const cheerio = require('cheerio'); -const got = require('@/utils/got'); -const LZString = require('lz-string'); - -const getChapters = ($) => { - let time_mark = 0; - // 用于一次更新多个新章节的排序 - let new_time_mark = 0; - return $('h4') - .toArray() - .map((ele) => { - const categoryName = $(ele).text(); - while (!$(ele.next).hasClass('chapter-list')) { - ele = ele.next; - } - ele = ele.next; - return $(ele) - .children('ul') - .toArray() - .reverse() - .reduce((acc, curr) => acc.concat($(curr).children('li').toArray()), []) - .map((ele) => { - const a = $(ele).children('a'); - // 通过操作发布时间来对章节进行排序,如果是刚刚更新的单行本或者番外,保留最新更新时间 - let pDate = new Date(new Date($.pubDate) - time_mark++ * 1000); - if (a.find('em').length > 0) { - // 对更新的章节也进行排序 - pDate = new Date(new Date($.pubDate) - new_time_mark++ * 1000); - $.newChapterCnt++; - } - return { - link: resolve('https://tw.manhuagui.com/', a.attr('href')), - title: a.attr('title'), - pub_date: pDate, - num: a.find('i').text(), - guid: resolve('https://tw.manhuagui.com/', a.attr('href')), - category: categoryName, - }; - }); - }) - .reduce((acc, curr) => acc.concat(curr)); -}; -module.exports = async (ctx) => { - const { id } = ctx.params; - const chapterCnt = Number(ctx.params.chapterCnt || 0); - const { data } = await got.get(`https://tw.manhuagui.com/comic/${id}/`); - const $ = cheerio.load(data); - - if ($('#__VIEWSTATE').length > 0) { - const n = LZString.decompressFromBase64($('#__VIEWSTATE').val()); - if (n) { - $('#erroraudit_show').replaceWith(n); - $('#__VIEWSTATE').remove(); - } - } - const bookTitle = $('.book-title > h1').text(); - const bookIntro = $('#intro-all').text(); - const coverImgSrc = $('.book-cover img').attr('src'); - // 对最新更新的章节增加了pubDate - const reg = new RegExp('最近於.+更新至'); - // 处理已下架的漫画 - if ($('.status > span').text().indexOf('已下架') > 0) { - ctx.state.data = { - title: `看漫画 - ${bookTitle} 已下架`, - link: `https://tw.manhuagui.com/comic/${id}/`, - description: bookIntro, - item: [{ link: `https://tw.manhuagui.com/comic/${id}/`, title: bookTitle, description: '已下架' }], - }; - } else { - const pub_date_str = $('.status > span').text().match(reg)[0].replace('最近於 [', '').replace('] 更新至', ''); - // 为了能在闭包内访问到这个日期而不是每次需要处理这个最近更新日期 - $.pubDate = new Date(pub_date_str).toUTCString(); - $.newChapterCnt = 0; - const chapters = getChapters($); - const genResult = (chapter) => ({ - link: chapter.link, - title: chapter.title, - pubDate: chapter.pub_date, - guid: chapter.guid, - category: chapter.category, - description: ` -

${chapter.num}

- - `.trim(), - }); - const items = chapters.map(genResult); - let itemsLen = items.length; - if (chapterCnt > 0) { - itemsLen = chapterCnt < $.newChapterCnt ? $.newChapterCnt : chapterCnt; - } - ctx.state.data = { - title: `看漫画 - ${bookTitle}`, - link: `https://tw.manhuagui.com/comic/${id}/`, - description: bookIntro, - item: items.slice(0, itemsLen), - }; - } -}; diff --git a/lib/routes/manhuagui/comic.js b/lib/v2/manhuagui/comic.js similarity index 77% rename from lib/routes/manhuagui/comic.js rename to lib/v2/manhuagui/comic.js index 72643133e..321708b7b 100644 --- a/lib/routes/manhuagui/comic.js +++ b/lib/v2/manhuagui/comic.js @@ -1,7 +1,9 @@ -const { resolve } = require('url'); const cheerio = require('cheerio'); const got = require('@/utils/got'); const LZString = require('lz-string'); +const { parseDate } = require('@/utils/parse-date'); + +let baseUrl = ''; const getChapters = ($) => { let time_mark = 100; @@ -30,21 +32,29 @@ const getChapters = ($) => { $.newChapterCnt++; } return { - link: resolve('https://www.manhuagui.com/', a.attr('href')), + link: new URL(a.attr('href'), baseUrl).href, title: a.attr('title'), pub_date: pDate, num: a.find('i').text(), - guid: resolve('https://www.manhuagui.com/', a.attr('href')), category: categoryName, }; }); }) .reduce((acc, curr) => acc.concat(curr)); }; + module.exports = async (ctx) => { - const { id } = ctx.params; + const { id, domain } = ctx.params; + if (domain === 'mhgui') { + baseUrl = 'https://www.mhgui.com'; + } else if (domain === 'twmanhuagui') { + baseUrl = 'https://tw.manhuagui.com'; + } else { + baseUrl = 'https://www.manhuagui.com'; + } + const chapterCnt = Number(ctx.params.chapterCnt || 0); - const { data } = await got.get(`https://www.manhuagui.com/comic/${id}/`); + const { data } = await got(`${baseUrl}/comic/${id}/`); const $ = cheerio.load(data); if ($('#__VIEWSTATE').length > 0) { @@ -54,30 +64,34 @@ module.exports = async (ctx) => { $('#__VIEWSTATE').remove(); } } + const bookTitle = $('.book-title > h1').text(); const bookIntro = $('#intro-all').text(); const coverImgSrc = $('.book-cover img').attr('src'); // 对最新更新的章节增加了pubDate - const reg = new RegExp('最近于.+更新至'); + const reg = new RegExp('最近(?:于|於).+更新至'); // 处理已下架的漫画 if ($('.status > span').text().indexOf('已下架') > 0) { ctx.state.data = { title: `看漫画 - ${bookTitle} 已下架`, - link: `https://www.manhuagui.com/comic/${id}/`, + link: `${baseUrl}/comic/${id}/`, description: bookIntro, - item: [{ link: `https://www.manhuagui.com/comic/${id}/`, title: bookTitle, description: '已下架' }], + item: [{ link: `${baseUrl}/comic/${id}/`, title: bookTitle, description: '已下架' }], }; } else { - const pub_date_str = $('.status > span').text().match(reg)[0].replace('最近于 [', '').replace('] 更新至', ''); + const pub_date_str = $('.status > span') + .text() + .match(reg)[0] + .replace(/最近(?:于|於) \[/, '') + .replace('] 更新至', ''); // 为了能在闭包内访问到这个日期而不是每次需要处理这个最近更新日期 - $.pubDate = new Date(pub_date_str).toUTCString(); + $.pubDate = parseDate(pub_date_str); $.newChapterCnt = 0; const chapters = getChapters($); const genResult = (chapter) => ({ link: chapter.link, title: chapter.title, pubDate: chapter.pub_date, - guid: chapter.guid, category: chapter.category, description: `

${chapter.num}

@@ -89,9 +103,10 @@ module.exports = async (ctx) => { if (chapterCnt > 0) { itemsLen = chapterCnt < $.newChapterCnt ? $.newChapterCnt : chapterCnt; } + ctx.state.data = { title: `看漫画 - ${bookTitle}`, - link: `https://www.manhuagui.com/comic/${id}/`, + link: `${baseUrl}/comic/${id}/`, description: bookIntro, item: items.slice(0, itemsLen), }; diff --git a/lib/v2/manhuagui/maintainer.js b/lib/v2/manhuagui/maintainer.js new file mode 100644 index 000000000..cd0d3a8e3 --- /dev/null +++ b/lib/v2/manhuagui/maintainer.js @@ -0,0 +1,6 @@ +module.exports = { + '/comic/:id/:chapterCnt?': ['MegrezZhu'], + '/mhgui/comic/:id/:chapterCnt?': ['btdwv'], + '/subscribe': ['shininome'], + '/twmanhuagui/comic/:id/:chapterCnt?': ['btdwv'], +}; diff --git a/lib/v2/manhuagui/radar.js b/lib/v2/manhuagui/radar.js new file mode 100644 index 000000000..5d138c4b9 --- /dev/null +++ b/lib/v2/manhuagui/radar.js @@ -0,0 +1,33 @@ +const rules = [ + { + title: '漫画柜个人订阅', + docs: 'https://docs.rsshub.app/anime.html#kan-man-hua', + source: '/user/book/shelf', + target: '/manhuagui/subscribe', + }, + { + title: '漫画更新', + docs: 'https://docs.rsshub.app/anime.html#kan-man-hua', + source: '/comic/:id/', + target: '/manhuagui/comic/:id', + }, +]; + +module.exports = { + 'manhuagui.com': { + _name: '漫画柜', + www: rules, + tw: [ + { + title: '漫画更新', + docs: 'https://docs.rsshub.app/anime.html#kan-man-hua', + source: '/comic/:id/', + target: '/manhuagui/twmanhuagui/comic/:id', + }, + ], + }, + 'mhgui.com': { + _name: '漫画柜镜像站', + www: rules, + }, +}; diff --git a/lib/v2/manhuagui/router.js b/lib/v2/manhuagui/router.js new file mode 100644 index 000000000..29cafb256 --- /dev/null +++ b/lib/v2/manhuagui/router.js @@ -0,0 +1,5 @@ +module.exports = function (router) { + router.get('/comic/:id/:chapterCnt?', require('./comic')); + router.get('/:domain?/comic/:id/:chapterCnt?', require('./comic')); + router.get('/subscribe', require('./subscribe')); +}; diff --git a/lib/v2/manhuagui/subscribe.js b/lib/v2/manhuagui/subscribe.js new file mode 100644 index 000000000..2a01f0e20 --- /dev/null +++ b/lib/v2/manhuagui/subscribe.js @@ -0,0 +1,54 @@ +const got = require('@/utils/got'); +const { parseRelativeDate } = require('@/utils/parse-date'); +const cheerio = require('cheerio'); +const { art } = require('@/utils/render'); +const path = require('path'); +const config = require('@/config').value; +const web_url = 'https://www.manhuagui.com/user/book/shelf/1'; + +module.exports = async (ctx) => { + if (!config.manhuagui || !config.manhuagui.cookie) { + throw 'manhuagui RSS is disabled due to the lack of relevant config'; + } + const cookie = config.manhuagui.cookie; + const response = await got({ + method: 'get', + url: web_url, + headers: { + Cookie: cookie, + }, + }); + const $ = cheerio.load(response.data); + const user_name = $('.avatar-box').find('h3').text(); + const title = `${user_name} 的 漫画订阅`; + const link = web_url; + const description = `${user_name} 的 漫画订阅`; + + const item = $('.dy_content_li') + .map(function () { + const img_src = $(this).find('img').attr('src'); // 漫画的封面 + const manga_title = $(this).find('.co_1.c_space').first().text(); // 最新的一话题目 + const title = $(this).find('img').attr('alt'); // 漫画的名字 + const link = $(this).find('.co_1.c_space').first().children().attr('href'); // 漫画最新的链接 + const description = art(path.join(__dirname, 'templates/manga.art'), { + manga_title, + img_src, + }); + const pubDate = $(this).find('.co_1.c_space').first().next().text(); + const publishDate = parseRelativeDate(pubDate); // 处理相对时间 + const single = { + title, + link, + description, + pubDate: publishDate, + }; + return single; + }) + .get(); // 这里获取数组= = + ctx.state.data = { + title, + link, + description, + item, + }; +}; diff --git a/lib/v2/manhuagui/templates/manga.art b/lib/v2/manhuagui/templates/manga.art new file mode 100644 index 000000000..a6f0d14d5 --- /dev/null +++ b/lib/v2/manhuagui/templates/manga.art @@ -0,0 +1,2 @@ +

{{manga_title}}

+