diff --git a/docs/new-media.md b/docs/new-media.md index 06b523eb0..79ddf9f90 100644 --- a/docs/new-media.md +++ b/docs/new-media.md @@ -1780,20 +1780,20 @@ others = 热点新闻 + 滚动新闻 ## 后续 -### Live +### 分类 - + -### 最新 Live - - - -| 往事进展 | 最新添加 | -| -------- | -------- | -| realtime | new | +| 首页 | 热点 | 跟踪 | 事件 | +| ----- | -------- | ------ | ------ | +| index | featured | memory | events | +### Lives + + + ### 最新专栏 diff --git a/lib/router.js b/lib/router.js index 6fa6dd0d3..02c2011cb 100644 --- a/lib/router.js +++ b/lib/router.js @@ -1002,9 +1002,9 @@ router.get('/miniapp/article/:category', lazyloadRouteHandler('./routes/miniapp/ router.get('/miniapp/store/newest', lazyloadRouteHandler('./routes/miniapp/store/newest')); // 后续 -router.get('/houxu/live/:id/:timeline?', lazyloadRouteHandler('./routes/houxu/live')); -router.get('/houxu/events', lazyloadRouteHandler('./routes/houxu/events')); -router.get('/houxu/lives/:type', lazyloadRouteHandler('./routes/houxu/lives')); +// router.get('/houxu/live/:id/:timeline?', lazyloadRouteHandler('./routes/houxu/live')); +// router.get('/houxu/events', lazyloadRouteHandler('./routes/houxu/events')); +// router.get('/houxu/lives/:type', lazyloadRouteHandler('./routes/houxu/lives')); // 老司机 router.get('/laosiji/hot', lazyloadRouteHandler('./routes/laosiji/hot')); diff --git a/lib/routes/houxu/events.js b/lib/routes/houxu/events.js deleted file mode 100644 index 0d669e871..000000000 --- a/lib/routes/houxu/events.js +++ /dev/null @@ -1,27 +0,0 @@ -const got = require('@/utils/got'); -const cheerio = require('cheerio'); - -module.exports = async (ctx) => { - const baseUrl = `https://houxu.app/events`; - const res = await got.get(baseUrl); - const $ = cheerio.load(res.data); - - const list = $('div.list > div'); - const descriptionSelector = '.summary'; - const out = list - .map((_, el) => { - const each = $(el); - return { - title: each.find('a').first().text().trim() + ' | ' + each.find('h3').text().trim(), - description: each.find(descriptionSelector).text().trim(), - link: 'https://houxu.app' + each.find('a').first().attr('href'), - }; - }) - .get(); - ctx.state.data = { - title: $('title').text().trim(), - description: $('title').text().trim(), - link: baseUrl, - item: out, - }; -}; diff --git a/lib/routes/houxu/live.js b/lib/routes/houxu/live.js deleted file mode 100644 index d2240c120..000000000 --- a/lib/routes/houxu/live.js +++ /dev/null @@ -1,39 +0,0 @@ -const got = require('@/utils/got'); - -module.exports = async (ctx) => { - const { id } = ctx.params; - const baseUrl = 'https://houxu.app'; - const baseInfoApi = `${baseUrl}/api/1/lives/${id}`; - const { desc, title } = await ctx.cache.tryGet(baseInfoApi, async () => { - const res = await got.get(baseInfoApi); - const { summary: desc, title } = res.data; - return { - title, - desc, - }; - }); - - const itemsRes = await got(`${baseUrl}/api/1/lives/${id}/threads`, { - searchParams: { - limit: 40, - }, - }); - - const item = itemsRes.data.results.map((i) => { - const { media, url, title, description, publish_at } = i.link; - return { - title, - description: `${description}
`, - link: url, - pubDate: new Date(publish_at).toUTCString(), - author: media.name, - }; - }); - - ctx.state.data = { - title, - description: desc, - link: `${baseUrl}/lives/${id}`, - item, - }; -}; diff --git a/lib/routes/houxu/lives.js b/lib/routes/houxu/lives.js deleted file mode 100644 index 110be5765..000000000 --- a/lib/routes/houxu/lives.js +++ /dev/null @@ -1,58 +0,0 @@ -const got = require('@/utils/got'); - -const getLiveUrlById = (liveId) => `https://houxu.app/lives/${liveId}`; - -const realtimeHandler = async () => { - const res = await got.get('https://houxu.app/api/1/lives/updated/'); - - const out = res.data.results.map((el) => ({ - title: el.last.link.title, - description: el.last.link.description, - author: el.last.link.media ? el.last.link.media.name : null, - link: getLiveUrlById(el.id), - guid: 'realtime-' + el.id + '-' + el.last.id, - pubDate: new Date(el.news_update_at).toUTCString(), - })); - - return { - title: '往事进展 - 后续', - description: 'Live 往事进展', - link: 'https://houxu.app/lives/realtime', - item: out, - }; -}; - -const newHandler = async () => { - const res = await got.get('https://houxu.app/api/1/records/index/'); - const out = res.data.results - .filter((el) => el.type === 'live') - .map((el) => ({ - title: el.object.title, - description: el.object.summary, - link: getLiveUrlById(el.object.id), - guid: 'new-' + el.object.id, - pubDate: new Date(el.publish_at).toUTCString(), - })); - return { - title: '最新添加 - 后续', - description: 'Live 最新添加', - link: 'https://houxu.app/lives/new', - item: out, - }; -}; - -module.exports = async (ctx) => { - const { type } = ctx.params; - - switch (type) { - case 'realtime': - ctx.state.data = await realtimeHandler(); - break; - case 'new': - ctx.state.data = await newHandler(); - break; - default: - ctx.throw(404, 'Unknown lives type'); - return; - } -}; diff --git a/lib/v2/houxu/index.js b/lib/v2/houxu/index.js new file mode 100644 index 000000000..2e6cf1400 --- /dev/null +++ b/lib/v2/houxu/index.js @@ -0,0 +1,85 @@ +const got = require('@/utils/got'); +const path = require('path'); +const { art } = require('@/utils/render'); +const { parseDate } = require('@/utils/parse-date'); + +const categories = { + index: '首页', + featured: '热点', + updated: '跟踪', + memory: '跟踪', + events: '事件', +}; + +module.exports = async (ctx) => { + const category = ctx.params.category ?? 'index'; + const id = ctx.params.id ?? ''; + let title, + description, + author = ''; + + const rootUrl = 'https://houxu.app'; + const currentUrl = `${rootUrl}/api/1/${id ? `lives/${id}/threads` : category === 'events' ? category : category === 'updated' || category === 'memory' ? 'lives/updated' : `records/${category}`}/?limit=${ctx.query.limit ?? 30}`; + + const response = await got({ + method: 'get', + url: currentUrl, + }); + + let items = response.data.results.map((item) => ({ + guid: item.object?.id ?? item.id, + title: item.link?.title ?? item.object?.title ?? item.title, + link: item.link?.url ?? `${rootUrl}/lives/${item.object?.id ?? item.id}`, + pubDate: parseDate(item.create_at ?? item.object?.create_at ?? item.publish_at), + description: `

${item.link?.description ?? item.object?.summary ?? item.last?.link.description ?? item.description}

`, + author: item.link?.source ?? item.link?.media?.name ?? item.object?.creator?.username ?? item.object?.creator?.name ?? item.creator?.username ?? item.creator?.name ?? '', + })); + + if (id) { + const detailResponse = await got({ + method: 'get', + url: `${rootUrl}/api/1/lives/${id}`, + }); + + title = detailResponse.data.title; + description = detailResponse.data.summary; + author = detailResponse.data.creator.name; + } else { + items = await Promise.all( + items.map((item) => + ctx.cache.tryGet(item.guid, async () => { + try { + const detailResponse = await got({ + method: 'get', + url: `${rootUrl}/api/1/lives/${item.guid}/threads/?limit=1000`, + }); + + const feeds = detailResponse.data.results.map((item) => + art(path.join(__dirname, 'templates/description.art'), { + title: item.link.title, + link: item.link.url, + pubDate: parseDate(item.create_at), + description: `

${item.link.description}

`, + author: item.link.source ?? item.link.media?.name ?? '', + }) + ); + + item.description = feeds.join(''); + + return item; + } catch (e) { + return Promise.resolve(''); + } + }) + ) + ); + } + + ctx.state.data = { + title: `${title || categories[category]} - 后续`, + link: currentUrl, + item: items, + description, + author, + }; +}; diff --git a/lib/v2/houxu/maintainer.js b/lib/v2/houxu/maintainer.js new file mode 100644 index 000000000..c854b393e --- /dev/null +++ b/lib/v2/houxu/maintainer.js @@ -0,0 +1,4 @@ +module.exports = { + '/lives/:id?': ['nczitzk'], + '/:category?': ['nczitzk'], +}; diff --git a/lib/v2/houxu/radar.js b/lib/v2/houxu/radar.js new file mode 100644 index 000000000..344e683f8 --- /dev/null +++ b/lib/v2/houxu/radar.js @@ -0,0 +1,19 @@ +module.exports = { + 'houxu.app': { + _name: '后续', + '.': [ + { + title: '分类', + docs: 'https://docs.rsshub.app/new-media.html#hou-xu-fen-lei', + source: ['/:category', '/'], + target: '/houxu/:category?', + }, + { + title: 'Lives', + docs: 'https://docs.rsshub.app/new-media.html#hou-xu-lives', + source: ['/lives/:id', '/'], + target: '/houxu/lives/:id', + }, + ], + }, +}; diff --git a/lib/v2/houxu/router.js b/lib/v2/houxu/router.js new file mode 100644 index 000000000..3ceee154c --- /dev/null +++ b/lib/v2/houxu/router.js @@ -0,0 +1,3 @@ +module.exports = function (router) { + router.get('/:category?/:id?', require('./index')); +}; diff --git a/lib/v2/houxu/templates/description.art b/lib/v2/houxu/templates/description.art new file mode 100644 index 000000000..2003f293e --- /dev/null +++ b/lib/v2/houxu/templates/description.art @@ -0,0 +1,9 @@ +
+

+ {{ title }} +

+

{{ description }}

+ 来源 {{ author }} +
+ 时间 {{ pubDate }} +
\ No newline at end of file