diff --git a/docs/new-media.md b/docs/new-media.md index 98f0cc7e2..791a94bb6 100644 --- a/docs/new-media.md +++ b/docs/new-media.md @@ -719,6 +719,36 @@ Edition +## LVV2 + +### 频道 + + + +| 热门 | 最新 | 得分 | 24 小时榜 | +| :------: | :------: | :--------: | :-----------: | +| sort-hot | sort-new | sort-score | sort-realtime | + +| 排序方式 | 一小时内 | 一天内 | 一个周内 | 一个月内 | +| :--: | :----: | :---: | :----: | :-----: | +| | t-hour | t-day | t-week | t-month | + + + +### 24 小时点击排行 Top 10 + + + +| 热门 | 最新 | 得分 | 24 小时榜 | +| :------: | :------: | :--------: | :-----------: | +| sort-hot | sort-new | sort-score | sort-realtime | + +| 排序方式 | 一小时内 | 一天内 | 一个周内 | 一个月内 | +| :--: | :----: | :---: | :----: | :-----: | +| | t-hour | t-day | t-week | t-month | + + + ## MakeUseOf diff --git a/lib/v2/lvv2/maintainer.js b/lib/v2/lvv2/maintainer.js new file mode 100644 index 000000000..3b7dd702e --- /dev/null +++ b/lib/v2/lvv2/maintainer.js @@ -0,0 +1,4 @@ +module.exports = { + '/news/:channel/:sort?': ['Fatpandac'], + '/top/:channel/:sort?': ['Fatpandac'], +}; diff --git a/lib/v2/lvv2/news.js b/lib/v2/lvv2/news.js new file mode 100644 index 000000000..ef6e2aba8 --- /dev/null +++ b/lib/v2/lvv2/news.js @@ -0,0 +1,75 @@ +const got = require('@/utils/got'); +const cheerio = require('cheerio'); +const { parseDate } = require('@/utils/parse-date'); +const timezone = require('@/utils/timezone'); +const { art } = require('@/utils/render'); +const path = require('path'); + +const rootUrl = 'https://lvv2.com'; + +const titleMap = { + 'sort-realtime': { + 't-month': '24小时榜 一月内', + 't-week': '24小时榜 一周内', + 't-day': '24小时榜 一天内', + 't-hour': '24小时榜 一小时内', + }, + 'sort-hot': '热门', + 'sort-new': '最新', + 'sort-score': { + 't-month': '得分 一月内', + 't-week': '得分 一周内', + 't-day': '得分 一天内', + 't-hour': '得分 一小时内', + }, +}; + +module.exports = async (ctx) => { + const channel = ctx.params.channel; + const sort = (channel === 'sort-realtime' || channel === 'sort-score') && !ctx.params.sort ? 't-week' : ctx.params.sort; + const url = `${rootUrl}/${channel}/${sort}`; + + const response = await got(url); + const $ = cheerio.load(response.data); + const list = $('div.spacer > div') + .map((_, item) => ({ + title: $(item).find('h3 > a.title').text().trim(), + author: $(item).find('a.author').text().trim(), + link: new URL($(item).find('h3.title > a.title').attr('href'), rootUrl).href.replace(/(https:\/\/lvv2\.com.*?)\/title.*/, '$1'), + pubDate: timezone(parseDate($(item).find('a.dateline > time').attr('datetime')), +8), + })) + .filter((_, item) => item.title !== '') + .get(); + + const items = await Promise.all( + list.map((item) => + ctx.cache.tryGet(item.link, async () => { + if (item.link.indexOf('instant.lvv2.com') !== -1) { + item.description = await ctx.cache.tryGet(item.link, async () => { + const articleResponse = await got(item.link); + const article = cheerio.load(articleResponse.data); + + const description = article('#_tl_editor') + .html() + .replace(/src=['|"]data.*?['|"]/g, '') + .replace(/()/g, '$1src$2'); + + return description; + }); + } else { + item.description = art(path.join(__dirname, 'templates/outlink.art'), { + outlink: item.link, + }); + } + + return item; + }) + ) + ); + + ctx.state.data = { + title: `lvv2 - ${sort ? titleMap[channel][sort] : titleMap[channel]}`, + link: url, + item: items, + }; +}; diff --git a/lib/v2/lvv2/radar.js b/lib/v2/lvv2/radar.js new file mode 100644 index 000000000..d4be95817 --- /dev/null +++ b/lib/v2/lvv2/radar.js @@ -0,0 +1,79 @@ +module.exports = { + 'lvv2.com': { + _name: 'LVV2', + '.': [ + { + title: '热门', + docs: 'https://docs.rsshub.app/new-media.html#lvv2', + source: ['/sort-hot'], + target: '/lvv2/news/sort-hot', + }, + { + title: '最新', + docs: 'https://docs.rsshub.app/new-media.html#lvv2', + source: ['/sort-new'], + target: '/lvv2/news/sort-new', + }, + { + title: '得分', + docs: 'https://docs.rsshub.app/new-media.html#lvv2', + source: ['/sort-score', '/sort-score/:sort'], + target: (params) => { + if (!params.sort) { + return '/lvv2/news/sort-score'; + } else { + return `/lvv2/news/sort-score/${params.sort}`; + } + }, + }, + { + title: '24小时榜', + docs: 'https://docs.rsshub.app/new-media.html#lvv2', + source: ['/sort-realtime', '/sort-realtime/:sort'], + target: (params) => { + if (!params.sort) { + return '/lvv2/news/sort-realtime'; + } else { + return `/lvv2/news/sort-realtime/${params.sort}`; + } + }, + }, + { + title: '热门 24小时 Top 10', + docs: 'https://docs.rsshub.app/new-media.html#lvv2', + source: ['/', '/sort-hot'], + target: '/lvv2/top/sort-hot', + }, + { + title: '最新 24小时 Top 10', + docs: 'https://docs.rsshub.app/new-media.html#lvv2', + source: ['/sort-new'], + target: '/lvv2/top/sort-new', + }, + { + title: '得分 24小时 Top 10', + docs: 'https://docs.rsshub.app/new-media.html#lvv2', + source: ['/sort-score', '/sort-score/:sort'], + target: (params) => { + if (!params.sort) { + return '/lvv2/top/sort-score'; + } else { + return `/lvv2/top/sort-score/${params.sort}`; + } + }, + }, + { + title: '24小时榜 24小时 Top 10', + docs: 'https://docs.rsshub.app/new-media.html#lvv2', + source: ['/sort-realtime', '/sort-realtime/:sort'], + target: (params) => { + if (!params.sort) { + return '/lvv2/top/sort-realtime'; + } else { + return `/lvv2/top/sort-realtime/${params.sort}`; + } + }, + }, + ], + }, +}; diff --git a/lib/v2/lvv2/router.js b/lib/v2/lvv2/router.js new file mode 100644 index 000000000..870b12a43 --- /dev/null +++ b/lib/v2/lvv2/router.js @@ -0,0 +1,4 @@ +module.exports = function (router) { + router.get('/news/:channel/:sort?', require('./news')); + router.get('/top/:channel/:sort?', require('./top')); +}; diff --git a/lib/v2/lvv2/templates/outlink.art b/lib/v2/lvv2/templates/outlink.art new file mode 100644 index 000000000..e89a59ec1 --- /dev/null +++ b/lib/v2/lvv2/templates/outlink.art @@ -0,0 +1 @@ +文章链接 diff --git a/lib/v2/lvv2/top.js b/lib/v2/lvv2/top.js new file mode 100644 index 000000000..5df85527b --- /dev/null +++ b/lib/v2/lvv2/top.js @@ -0,0 +1,77 @@ +const got = require('@/utils/got'); +const cheerio = require('cheerio'); +const { parseDate } = require('@/utils/parse-date'); +const timezone = require('@/utils/timezone'); +const { art } = require('@/utils/render'); +const path = require('path'); + +const rootUrl = 'https://lvv2.com'; + +const titleMap = { + 'sort-realtime': { + 't-month': '24小时榜 一月内', + 't-week': '24小时榜 一周内', + 't-day': '24小时榜 一天内', + 't-hour': '24小时榜 一小时内', + }, + 'sort-hot': '热门', + 'sort-new': '最新', + 'sort-score': { + 't-month': '得分 一月内', + 't-week': '得分 一周内', + 't-day': '得分 一天内', + 't-hour': '得分 一小时内', + }, +}; + +module.exports = async (ctx) => { + const channel = ctx.params.channel; + const sort = (channel === 'sort-realtime' || channel === 'sort-score') && !ctx.params.sort ? 't-week' : ctx.params.sort; + const url = `${rootUrl}/${channel}/${sort}`; + + const response = await got(url); + const $ = cheerio.load(response.data); + const list = $('#top-content-news > div') + .map((_, item) => ({ + title: $(item).find('div.md > a').text(), + link: new URL($(item).find('div.md > a').attr('href'), rootUrl).href.replace(/(https:\/\/lvv2\.com.*?)\/title.*/, '$1'), + })) + .get(); + + const items = await Promise.all( + list.map((item) => + ctx.cache.tryGet(item.link, async () => { + const detailResponse = await got.get(item.link); + const content = cheerio.load(detailResponse.data); + + item.pubDate = timezone(parseDate(content('time').attr('datetime')), +8); + item.author = content('a.author').text(); + const link = content('h2.title > a.title').attr('href'); + if (link.indexOf('instant.lvv2.com') !== -1) { + item.description = await ctx.cache.tryGet(link, async () => { + const articleResponse = await got(link); + const article = cheerio.load(articleResponse.data); + + const description = article('#_tl_editor') + .html() + .replace(/()/g, '$1src$2'); + + return description; + }); + } else { + item.description = art(path.join(__dirname, 'templates/outlink.art'), { + outlink: link, + }); + } + + return item; + }) + ) + ); + + ctx.state.data = { + title: `lvv2 - ${sort ? titleMap[channel][sort] : titleMap[channel]} 24小时点击 Top 10`, + link: url, + item: items, + }; +};