mirror of
https://github.com/DIYgod/RSSHub.git
synced 2025-12-05 20:27:52 +08:00
feat: 增加单读的栏目选择支持 (#2822)
This commit is contained in:
@@ -438,7 +438,13 @@ type 为 all 时,category 参数不支持 cost 和 free
|
|||||||
|
|
||||||
### 单读
|
### 单读
|
||||||
|
|
||||||
<Route author="KeNorizon" example="/owspace/read" path="/owspace/read" />
|
<Route author="KeNorizon" example="/owspace/read/0" path="/owspace/read/:type?" :paramsDesc="['栏目分类,不填则默认为首页']">
|
||||||
|
|
||||||
|
| 首页 | 文字 | 影像 | 声音 | 单向历 | 谈论 |
|
||||||
|
| ---- | ---- | ---- | ---- | ------ | ---- |
|
||||||
|
| 0 | 1 | 2 | 3 | 4 | 6 |
|
||||||
|
|
||||||
|
</Route>
|
||||||
|
|
||||||
## 电商在线
|
## 电商在线
|
||||||
|
|
||||||
|
|||||||
@@ -1633,6 +1633,6 @@ router.get('/gouhuo/news/:category', require('./routes/gouhuo'));
|
|||||||
router.get('/gouhuo/strategy', require('./routes/gouhuo/strategy'));
|
router.get('/gouhuo/strategy', require('./routes/gouhuo/strategy'));
|
||||||
|
|
||||||
// 单向空间
|
// 单向空间
|
||||||
router.get('/owspace/read', require('./routes/owspace/read'));
|
router.get('/owspace/read/:type?', require('./routes/owspace/read'));
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|||||||
@@ -4,11 +4,21 @@ const qs = require('querystring');
|
|||||||
const cheerio = require('cheerio');
|
const cheerio = require('cheerio');
|
||||||
|
|
||||||
const secret = 'fk4iy@98(*Y98fh-^o)re+wg=';
|
const secret = 'fk4iy@98(*Y98fh-^o)re+wg=';
|
||||||
|
|
||||||
|
const typeMap = {
|
||||||
|
1: '文字',
|
||||||
|
2: '影像',
|
||||||
|
3: '声音',
|
||||||
|
4: '单向历',
|
||||||
|
6: '谈论',
|
||||||
|
};
|
||||||
|
|
||||||
const signQuery = (query) => {
|
const signQuery = (query) => {
|
||||||
query.sign = md5(['apiname=', query.a, 'device_id=', query.device_id, 'time=', query.time, secret].join(''));
|
query.sign = md5(['apiname=', query.a, 'device_id=', query.device_id, 'time=', query.time, secret].join(''));
|
||||||
};
|
};
|
||||||
|
|
||||||
const generateFullText = async (item) => {
|
const generateFullText = async (item) => {
|
||||||
|
const model = parseInt(item.model);
|
||||||
const fullTextResponse = await got.get(item.html5);
|
const fullTextResponse = await got.get(item.html5);
|
||||||
const $ = cheerio.load(fullTextResponse.data);
|
const $ = cheerio.load(fullTextResponse.data);
|
||||||
|
|
||||||
@@ -17,29 +27,88 @@ const generateFullText = async (item) => {
|
|||||||
|
|
||||||
let intro = '';
|
let intro = '';
|
||||||
|
|
||||||
|
if (item.excerpt) {
|
||||||
|
intro += '<p>' + item.excerpt + '</p>';
|
||||||
|
}
|
||||||
|
|
||||||
if (item.thumbnail) {
|
if (item.thumbnail) {
|
||||||
intro += `<p><img src="${item.thumbnail}"></p>`;
|
intro += `<p><img src="${item.thumbnail}"></p>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.excerpt) {
|
|
||||||
intro += '<blockquote>' + item.excerpt + '</blockquote><br>';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (describe.length > 0) {
|
if (describe.length > 0) {
|
||||||
intro += '<p>' + describe.html() + '</p><hr>';
|
intro += '<blockquote>' + describe.html() + '</blockquote>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (intro) {
|
||||||
|
intro += '<hr>';
|
||||||
|
}
|
||||||
|
|
||||||
|
// hide redundant meta
|
||||||
content.find('.articleTit').remove();
|
content.find('.articleTit').remove();
|
||||||
|
|
||||||
|
if (model === 2) {
|
||||||
|
// make video visible
|
||||||
|
content.find('.vBox').removeAttr('style');
|
||||||
|
|
||||||
|
content.find('.vBox video').attr('preload', 'metadata');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (model === 3) {
|
||||||
|
// make audio visible
|
||||||
|
const audioContainer = content.find('.fmCon').removeAttr('style');
|
||||||
|
|
||||||
|
// generate audio player
|
||||||
|
$('<audio controls="controls"></audio>')
|
||||||
|
.attr('src', item.fm)
|
||||||
|
.attr('preload', 'metadata')
|
||||||
|
.prependTo(audioContainer);
|
||||||
|
|
||||||
|
content.find('.fmCon>.graphic').remove();
|
||||||
|
content.find('.fmCon>.fmDetail').remove();
|
||||||
|
}
|
||||||
|
|
||||||
return intro + content.html();
|
return intro + content.html();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleItem = (ctx) => async (item) => {
|
||||||
|
if (parseInt(item.model) === 4) {
|
||||||
|
const result = {
|
||||||
|
title: item.title.substring(0, 4) + '年' + parseInt(item.title.substring(4, 6)) + '月' + parseInt(item.title.substring(6, 8)) + '日',
|
||||||
|
link: item.html5,
|
||||||
|
description: `<img src="${item.thumbnail}">`,
|
||||||
|
pubDate: new Date(Number(item.create_time) * 1000).toUTCString(),
|
||||||
|
author: item.author,
|
||||||
|
};
|
||||||
|
|
||||||
|
return Promise.resolve(result);
|
||||||
|
} else {
|
||||||
|
const url = item.html5;
|
||||||
|
const cache = await ctx.cache.get(url);
|
||||||
|
if (cache) {
|
||||||
|
return Promise.resolve(JSON.parse(cache));
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = {
|
||||||
|
title: item.title.replace('\r\n', ''),
|
||||||
|
link: item.html5,
|
||||||
|
description: await generateFullText(item),
|
||||||
|
pubDate: new Date(Number(item.create_time) * 1000).toUTCString(),
|
||||||
|
author: item.author,
|
||||||
|
};
|
||||||
|
|
||||||
|
ctx.cache.set(url, JSON.stringify(result));
|
||||||
|
return Promise.resolve(result);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = async (ctx) => {
|
module.exports = async (ctx) => {
|
||||||
|
const selectedType = ctx.params.type !== undefined ? parseInt(ctx.params.type) : 0;
|
||||||
|
|
||||||
const queryData = {
|
const queryData = {
|
||||||
c: 'api2',
|
c: 'api2',
|
||||||
a: 'getList',
|
a: 'getList',
|
||||||
p: '1',
|
p: '1',
|
||||||
model: '0',
|
model: selectedType,
|
||||||
client: 'android',
|
client: 'android',
|
||||||
version: '1.6.3',
|
version: '1.6.3',
|
||||||
time: Math.round(Date.now() / 1000),
|
time: Math.round(Date.now() / 1000),
|
||||||
@@ -61,32 +130,15 @@ module.exports = async (ctx) => {
|
|||||||
throw response.data.msg ? 'api error: ' + response.data.msg : 'api error';
|
throw response.data.msg ? 'api error: ' + response.data.msg : 'api error';
|
||||||
}
|
}
|
||||||
|
|
||||||
const itemArray = await Promise.all(
|
const responseItemArray = response.data.datas.filter((item) => parseInt(item.model) !== 5);
|
||||||
response.data.datas
|
|
||||||
.filter((item) => item.model !== 5)
|
|
||||||
.map(async (item) => {
|
|
||||||
const url = item.html5;
|
|
||||||
const cache = await ctx.cache.get(url);
|
|
||||||
if (cache) {
|
|
||||||
return Promise.resolve(JSON.parse(cache));
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = {
|
const feedItemArray = await Promise.all(responseItemArray.map(handleItem(ctx)));
|
||||||
title: item.title.replace('\r\n', ''),
|
|
||||||
link: item.html5,
|
|
||||||
description: await generateFullText(item),
|
|
||||||
pubDate: new Date(Number(item.create_time) * 1000).toUTCString(),
|
|
||||||
author: item.author,
|
|
||||||
};
|
|
||||||
|
|
||||||
ctx.cache.set(url, JSON.stringify(result));
|
const selectedTypeName = typeMap[selectedType];
|
||||||
return Promise.resolve(result);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
ctx.state.data = {
|
ctx.state.data = {
|
||||||
title: '单读',
|
title: selectedTypeName ? `${selectedTypeName} - 单读` : '单读',
|
||||||
link: 'http://www.owspace.com/read.html',
|
link: 'http://www.owspace.com/read.html',
|
||||||
item: itemArray,
|
item: feedItemArray,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user