diff --git a/docs/README.md b/docs/README.md index bcec671cc..1aa531ff6 100644 --- a/docs/README.md +++ b/docs/README.md @@ -974,6 +974,11 @@ GitHub 官方也提供了一些 RSS: +### Tits Guru + + + + ### nHentai @@ -1007,6 +1012,10 @@ GitHub 官方也提供了一些 RSS: +### 看漫画 + + + ### Anime1 diff --git a/router.js b/router.js index e4a083775..bd4bb6c13 100644 --- a/router.js +++ b/router.js @@ -790,6 +790,13 @@ router.get('/eeo/:category?', require('./routes/eeo/index')); // 腾讯视频 router.get('/tencentvideo/playlist/:id', require('./routes/tencent/video/playlist')); +// 看漫画 +router.get('/manhuagui/comic/:id', require('./routes/manhuagui/comic')); + +// Tits Guru +router.get('/tits-guru/home', require('./routes/titsguru/home')); +router.get('/tits-guru/daily', require('./routes/titsguru/daily')); + // typora router.get('/typora/changelog', require('./routes/typora/changelog')); diff --git a/routes/manhuagui/comic.js b/routes/manhuagui/comic.js new file mode 100644 index 000000000..e6eb999ac --- /dev/null +++ b/routes/manhuagui/comic.js @@ -0,0 +1,42 @@ +const { resolve } = require('url'); +const cheerio = require('cheerio'); +const axios = require('../../utils/axios'); + +const getChapters = ($) => + $('#chapter-list-0 > ul li') + .map((_, ele) => { + const a = $(ele).children('a'); + return { + link: resolve('https://www.manhuagui.com/', a.attr('href')), + title: a.attr('title'), + num: a.find('i').text(), + }; + }) + .toArray(); + +module.exports = async (ctx) => { + const { id } = ctx.params; + + const { data } = await axios.get(`https://www.manhuagui.com/comic/${id}/`); + const $ = cheerio.load(data); + + const bookTitle = $('.book-title > h1').text(); + const bookIntro = $('#intro-all').text(); + const coverImgSrc = $('.book-cover img').attr('src'); + const chapters = getChapters($); + + const genResult = (chapter) => ({ + link: chapter.link, + title: chapter.title, + description: ` +

${chapter.num}

+ + `.trim(), + }); + ctx.state.data = { + title: `看漫画 - ${bookTitle}`, + link: `https://www.manhuagui.com/comic/${id}/`, + description: bookIntro, + item: chapters.map(genResult), + }; +}; diff --git a/routes/titsguru/daily.js b/routes/titsguru/daily.js new file mode 100644 index 000000000..8f29346a4 --- /dev/null +++ b/routes/titsguru/daily.js @@ -0,0 +1,21 @@ +const cheerio = require('cheerio'); +const axios = require('../../utils/axios'); +const { mapDetail } = require('./util'); + +module.exports = async (ctx) => { + const { data } = await axios.get('https://tits-guru.com/thebest/perDay', { + headers: { Accept: '' }, + }); + const $ = cheerio.load(data); + + const items = $('.post-row') + .map((_, ele) => mapDetail($(ele))) + .toArray(); + + ctx.state.data = { + title: 'TitsGuru - Babe of The Day', + link: 'https://tits-guru.com/thebest/perDay', + description: 'TitsGuru - Babe of The Day', + item: items, + }; +}; diff --git a/routes/titsguru/home.js b/routes/titsguru/home.js new file mode 100644 index 000000000..778504fa5 --- /dev/null +++ b/routes/titsguru/home.js @@ -0,0 +1,21 @@ +const cheerio = require('cheerio'); +const axios = require('../../utils/axios'); +const { mapDetail } = require('./util'); + +module.exports = async (ctx) => { + const { data } = await axios.get('https://tits-guru.com', { + headers: { Accept: '' }, + }); + const $ = cheerio.load(data); + + const items = $('.post-row') + .map((_, ele) => mapDetail($(ele))) + .toArray(); + + ctx.state.data = { + title: 'TitsGuru', + link: 'https://tits-guru.com/', + description: 'TitsGuru', + item: items, + }; +}; diff --git a/routes/titsguru/util.js b/routes/titsguru/util.js new file mode 100644 index 000000000..730b111e4 --- /dev/null +++ b/routes/titsguru/util.js @@ -0,0 +1,42 @@ +const { resolve } = require('url'); +const day = require('dayjs'); + +exports.mapDetail = (ele) => { + const link = resolve('https://tits-guru.com', ele.find('.img-link').attr('href')); + const title = ele.find('.img-link > img').attr('title'); + const image = ele + .find('.horizontal-socials .socials-share-pinterest > span') + .attr('data-src') + .match(/media=(.+)&url=/)[1]; + const dateStr = ele.find('.post-time').text(); + return { + link, + title, + pubDate: exports.parseDate(dateStr.trim()).toUTCString(), + description: ` + + `.trim(), + }; +}; + +exports.parseDate = (str) => { + // 网页给的是一种很诡异的零时区表示 + const [, _dayStr, timeStr] = str.match(/^(.+) (.+)$/); + const current = day().add(new Date().getTimezoneOffset(), 'minute'); // offset date + let dayStr; + if (_dayStr === 'Today') { + dayStr = current.format('YYYY-MM-DD'); + } else if (_dayStr === 'Yesterday') { + dayStr = current.subtract(1, 'day').format('YYYY-MM-DD'); + } else if (_dayStr.match(/[a-z]+/)) { + // eg. '06 november' + dayStr = day(`${_dayStr} UTC`) + .set('year', day().year()) + .format('YYYY-MM-DD'); + } else { + // eg. '16.03.2014' + const [, dd, mm, yy] = _dayStr.match(/(\d+)\.(\d+)\.(\d+)/); + dayStr = `${yy}-${mm}-${dd}`; + } + return new Date(`${dayStr} ${timeStr} UTC`); +};