feat: add piapro (#3889)

This commit is contained in:
hoilc
2020-02-05 00:44:23 +08:00
committed by GitHub
parent d57ec815cc
commit 18b8856c49
5 changed files with 174 additions and 0 deletions
+10
View File
@@ -312,6 +312,16 @@ Tiny Tiny RSS 会给所有 iframe 元素添加 `sandbox="allow-scripts"` 属性
<Route author="hoilc" example="/mastodon/timeline/pawoo.net/true" path="/mastodon/timeline/:site/:only_media?" :paramsDesc="['实例地址, 仅域名, 不包括`http://`或`https://`协议头', '是否只显示包含媒体(图片或视频)的推文, 默认置空为否, 任意值为是']"/>
## piapro
### 用户最新作品
<Route author="hoilc" example="/piapro/user/shine_longer" path="/piapro/user/:pid" :paramsDesc="['用户 ID, 可在 URL 中找到']"/>
### 全站最新作品
<Route author="hoilc" example="/piapro/public/music/miku/2" path="/piapro/public/:type/:tag?/:category?" :paramsDesc="['作品类别, 可选`music`,`illust`,`text`','标签, 即 URL 中`tag`参数','分类 ID, 即 URL 中 `categoryId` 参数']"/>
## pixiv
### 用户收藏
+4
View File
@@ -2187,4 +2187,8 @@ router.get('/netease/ds/:id', require('./routes/netease/ds'));
// javlibrary
router.get('/javlibrary/userposts/:uid', require('./routes/javlibrary/userposts'));
// piapro
router.get('/piapro/user/:pid', require('./routes/piapro/user'));
router.get('/piapro/public/:type/:tag?/:category?', require('./routes/piapro/public'));
module.exports = router;
+62
View File
@@ -0,0 +1,62 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
const utils = require('./utils');
const base = 'https://piapro.jp';
const selectors = {
music: '.snd_list li .title',
illust: '#itemcont .i_main',
text: '.txt_list li .title',
};
module.exports = async (ctx) => {
const type = selectors[ctx.params.type] ? ctx.params.type : 'music';
const tag = ctx.params.tag ? ctx.params.tag : '';
const category = ctx.params.category ? ctx.params.category : '';
const url = `${base}/${type}/?tag=${encodeURIComponent(tag)}&categoryId=${category}`;
const list_response = await got.get(url);
const $ = cheerio.load(list_response.data);
const type_name = $('#top_titlebox img')
.first()
.attr('alt');
const category_name = $('#_filterbox_category .name').text();
const tag_name = $('#_filterbox_character .name').text();
const list = $(selectors[type])
.map(function() {
return (
base +
$(this)
.find('a')
.first()
.attr('href')
);
})
.toArray();
const out = await Promise.all(
list.slice(0, 10).map(async (url) => {
const cache = await ctx.cache.get(url);
if (cache) {
return Promise.resolve(JSON.parse(cache));
}
const response = await got.get(url);
const item = utils.parseContent(response.data);
item.link = url;
ctx.cache.set(url, JSON.stringify(item));
return Promise.resolve(item);
})
);
ctx.state.data = {
title: `piapro - ${type_name}${tag ? ' - ' + tag_name : ''}${category ? ' - ' + category_name : ''}`,
link: url,
item: out.filter((item) => item !== ''),
};
};
+53
View File
@@ -0,0 +1,53 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
const utils = require('./utils');
const base = 'https://piapro.jp';
module.exports = async (ctx) => {
const pid = ctx.params.pid;
const url = `${base}/my_page/?view=content&pid=${pid}`;
const list_response = await got.get(url);
const $ = cheerio.load(list_response.data);
const user_name = $('#main_name h2').text();
const user_description = $('#main_name p').text();
const list = $('#itemcont .i_main')
.map(function() {
return (
base +
$(this)
.find('a')
.last()
.attr('href')
);
})
.toArray();
const out = await Promise.all(
list.slice(0, 10).map(async (url) => {
const cache = await ctx.cache.get(url);
if (cache) {
return Promise.resolve(JSON.parse(cache));
}
const response = await got.get(url);
const item = utils.parseContent(response.data);
item.link = url;
ctx.cache.set(url, JSON.stringify(item));
return Promise.resolve(item);
})
);
ctx.state.data = {
title: `piapro - ${user_name}の投稿作品`,
description: user_description,
link: url,
item: out.filter((item) => item !== ''),
};
};
+45
View File
@@ -0,0 +1,45 @@
const cheerio = require('cheerio');
const parseContent = (htmlString) => {
const $ = cheerio.load(htmlString);
const title = $('h1.cd_works-title');
const author = $('.cd_user-box-main a.cd_user-name');
const time = $('.cd_dtl_data')
.text()
.match(/\d+\/\d+\/\d+ \d+:\d+:\d+/)[0];
const blank = cheerio.load('<div></div>');
const content = blank('div');
// description
$('p.cd_dtl_cap').appendTo(content);
// image
$('.illust-whole').appendTo(content);
// audio
const testAudio = htmlString.match(/initNotLoginAudioFunc\(([\s\S]*?)\);/m);
if (testAudio) {
const audioInfo = testAudio[1];
const contentId = audioInfo.match(/contentId:\s*'(.*?)',/)[1];
const createDate = audioInfo.match(/createDate:\s*'(.*?)',/)[1];
const audio_url = `https://cdn.piapro.jp/mp3_a/${contentId.substring(0, 2)}/${contentId}_${createDate}_audition.mp3`;
$(`<audio src="${audio_url}" controls loop></audio>`).appendTo(content);
$('img#bigJacket_1').appendTo(content);
}
// text
$('.main_txt').appendTo(content);
return {
title: title.text().trim(),
author: author.text().trim(),
description: content.html(),
pubDate: new Date(time),
};
};
module.exports = {
parseContent,
};