feat(route): add 后续 (#8470)
* feat(route): add 后续 * fix: set limit to 30 * fix typo
This commit is contained in:
parent
b6a36f1e61
commit
c9ccd6bb9f
|
|
@ -1780,20 +1780,20 @@ others = 热点新闻 + 滚动新闻
|
|||
|
||||
## 后续
|
||||
|
||||
### Live
|
||||
### 分类
|
||||
|
||||
<Route author="ciaranchen sanmmm" example="/houxu/live/5" path="/houxu/live/:id" :paramsDesc="['Live ID']" />
|
||||
<Route author="nczitzk" example="/houxu" path="/houxu/:category?" :paramsDesc="['分类,见下表,默认为首页']">
|
||||
|
||||
### 最新 Live
|
||||
|
||||
<Route author="ciaranchen" example="/houxu/lives/new" path="/houxu/lives/:type" :paramsDesc="['类型']">
|
||||
|
||||
| 往事进展 | 最新添加 |
|
||||
| -------- | -------- |
|
||||
| realtime | new |
|
||||
| 首页 | 热点 | 跟踪 | 事件 |
|
||||
| ----- | -------- | ------ | ------ |
|
||||
| index | featured | memory | events |
|
||||
|
||||
</Route>
|
||||
|
||||
### Lives
|
||||
|
||||
<Route author="ciaranchen sanmmm nczitzk" example="/houxu/lives/33899" path="/houxu/:category?" :paramsDesc="['编号,可在对应 Live 页面的 URL 中找到']"/>
|
||||
|
||||
### 最新专栏
|
||||
|
||||
<Route author="ciaranchen" example="/houxu/events" path="/houxu/events"/>
|
||||
|
|
|
|||
|
|
@ -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'));
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
};
|
||||
|
|
@ -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}<br/><img src="${media.avatar_url}" />`,
|
||||
link: url,
|
||||
pubDate: new Date(publish_at).toUTCString(),
|
||||
author: media.name,
|
||||
};
|
||||
});
|
||||
|
||||
ctx.state.data = {
|
||||
title,
|
||||
description: desc,
|
||||
link: `${baseUrl}/lives/${id}`,
|
||||
item,
|
||||
};
|
||||
};
|
||||
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
|
@ -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: `<p>${item.link?.description ?? item.object?.summary ?? item.last?.link.description ?? item.description}</p>`,
|
||||
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: `<p>${item.link.description}</p>`,
|
||||
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,
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
module.exports = {
|
||||
'/lives/:id?': ['nczitzk'],
|
||||
'/:category?': ['nczitzk'],
|
||||
};
|
||||
|
|
@ -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',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
module.exports = function (router) {
|
||||
router.get('/:category?/:id?', require('./index'));
|
||||
};
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<div>
|
||||
<h3>
|
||||
<a href="{{ link }}">{{ title }}</a>
|
||||
</h3>
|
||||
<p>{{ description }}</p>
|
||||
<small><b>来源</b> {{ author }}</small>
|
||||
<br>
|
||||
<small><b>时间</b> {{ pubDate }}</small>
|
||||
</div>
|
||||
Loading…
Reference in New Issue