mirror of
https://github.com/DIYgod/RSSHub.git
synced 2026-09-24 23:12:34 +08:00
@@ -46,6 +46,8 @@ RSSHub 是一个轻量、易于扩展的 RSS 生成器,可以给任何奇奇
|
||||
- 所有专题
|
||||
- 专题详情
|
||||
- 详情
|
||||
- Pixiv
|
||||
- 用户动态
|
||||
|
||||
## 参与我们
|
||||
|
||||
|
||||
@@ -3,4 +3,10 @@ module.exports = {
|
||||
cacheType: 'memory', // support memory and redis, set empty to disable cache
|
||||
cacheExpire: 5 * 60,
|
||||
ua: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36',
|
||||
// pixiv: {
|
||||
// client_id: 'XXXXXXXXXXXXXXXXXXX',
|
||||
// client_secret: 'XXXXXXXXXXXXXXXXX',
|
||||
// username: 'xxxx@xxx.xx',
|
||||
// password: 'xxxxx'
|
||||
// }
|
||||
};
|
||||
@@ -26,6 +26,7 @@
|
||||
"cheerio": "1.0.0-rc.2",
|
||||
"crypto": "1.0.1",
|
||||
"eslint": "4.19.1",
|
||||
"form-data": "^2.3.2",
|
||||
"koa": "2.5.0",
|
||||
"koa-redis-cache": "3.0.0",
|
||||
"koa-router": "7.4.0",
|
||||
|
||||
@@ -57,4 +57,7 @@ router.get('/mzitu/category/:category', require('./routes/mzitu/category'));
|
||||
router.get('/mzitu/post/:id', require('./routes/mzitu/post'));
|
||||
router.get('/mzitu/tag/:tag', require('./routes/mzitu/tag'));
|
||||
|
||||
// // Pixiv
|
||||
router.get('/pixiv/user/:id', require('./routes/pixiv/user'));
|
||||
|
||||
module.exports = router;
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
const axios = require('axios');
|
||||
const art = require('art-template');
|
||||
const path = require('path');
|
||||
const config = require('../../config');
|
||||
const logger = require('../../utils/logger');
|
||||
const FormData = require('form-data');
|
||||
|
||||
const pixivConfig = config.pixiv;
|
||||
|
||||
if (!pixivConfig) {
|
||||
logger.info('Pixiv RSS disable.');
|
||||
module.exports = () => {};
|
||||
return;
|
||||
}
|
||||
|
||||
const authorizationInfo = {
|
||||
client_id: pixivConfig.client_id,
|
||||
client_secret: pixivConfig.client_secret,
|
||||
username: pixivConfig.username,
|
||||
password: pixivConfig.password
|
||||
};
|
||||
|
||||
const maskHeader = {
|
||||
'App-OS': 'ios',
|
||||
'App-OS-Version': '10.3.1',
|
||||
'App-Version': '6.7.1',
|
||||
'User-Agent': 'PixivIOSApp/6.7.1 (iOS 10.3.1; iPhone8,1)'
|
||||
};
|
||||
|
||||
let token = null;
|
||||
|
||||
async function getToken() {
|
||||
const data = new FormData();
|
||||
const jsonData = {
|
||||
...authorizationInfo,
|
||||
get_secure_url: 1,
|
||||
grant_type: 'password'
|
||||
};
|
||||
for (const key in jsonData) {
|
||||
if (jsonData.hasOwnProperty(key)) {
|
||||
const element = jsonData[key];
|
||||
data.append(key,element);
|
||||
}
|
||||
}
|
||||
const response = await axios.post('https://oauth.secure.pixiv.net/auth/token', data, {
|
||||
headers: {
|
||||
...maskHeader,
|
||||
...data.getHeaders()
|
||||
}
|
||||
});
|
||||
return response.data.response;
|
||||
}
|
||||
|
||||
async function refreshToken(refresh_token) {
|
||||
const data = new FormData();
|
||||
const jsonData = {
|
||||
...authorizationInfo,
|
||||
get_secure_url: 1,
|
||||
grant_type: 'refresh_token',
|
||||
refresh_token: refresh_token
|
||||
};
|
||||
for (const key in jsonData) {
|
||||
if (jsonData.hasOwnProperty(key)) {
|
||||
const element = jsonData[key];
|
||||
data.append(key,element);
|
||||
}
|
||||
}
|
||||
const response = await axios.post('https://oauth.secure.pixiv.net/auth/token', data, {
|
||||
headers: {
|
||||
...maskHeader,
|
||||
...data.getHeaders()
|
||||
}
|
||||
});
|
||||
return response.data.response;
|
||||
}
|
||||
|
||||
function wait(ms) {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(resolve, ms);
|
||||
});
|
||||
}
|
||||
|
||||
async function tokenLoop() {
|
||||
const res = await getToken();
|
||||
logger.info('Pixiv login success.');
|
||||
token = res.access_token;
|
||||
let refresh_token = res.refresh_token;
|
||||
let expires_in = res.expires_in * 0.9;
|
||||
while (true) {
|
||||
await wait(expires_in * 1000);
|
||||
try {
|
||||
const refresh_res = await refreshToken(refresh_token);
|
||||
logger.debug('Pixiv refresh token success.');
|
||||
token = refresh_res.access_token;
|
||||
refresh_token = refresh_res.refresh_token;
|
||||
expires_in = refresh_res.expires_in * 0.9;
|
||||
} catch (err) {
|
||||
expires_in = 30;
|
||||
logger.err('Pixiv refresh token failed, retry in ${expires_in} seconds.', err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tokenLoop();
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const id = ctx.params.id;
|
||||
|
||||
if (typeof token === 'null') {
|
||||
ctx.throw(500);
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await axios({
|
||||
method: 'get',
|
||||
url: 'https://app-api.pixiv.net/v1/user/illusts',
|
||||
headers: {
|
||||
...maskHeader,
|
||||
'Authorization': 'Bearer ' + token
|
||||
},
|
||||
params: {
|
||||
user_id: id,
|
||||
filter: 'for_ios',
|
||||
type: 'illust'
|
||||
},
|
||||
});
|
||||
|
||||
const illusts = response.data.illusts;
|
||||
const username = illusts[0].user.name
|
||||
|
||||
ctx.body = art(path.resolve(__dirname, '../../views/rss.art'), {
|
||||
title: `${username} 的 Pixiv 动态`,
|
||||
link: `https://music.163.com/#/playlist?id=${id}`,
|
||||
description: `${username} 的 Pixiv 最新动态`,
|
||||
lastBuildDate: new Date().toUTCString(),
|
||||
item: illusts.map((illust) => {
|
||||
const images = [];
|
||||
if (illust.page_count === 1) {
|
||||
images.push(`<p><img src="https://pixiv.cat/${illust.id}.jpg"/></p>`);
|
||||
} else {
|
||||
for (let i = 0; i < illust.page_count; i++) {
|
||||
images.push(`<p><img src="https://pixiv.cat/${illust.id}-${i+1}.jpg"/></p>`);
|
||||
}
|
||||
}
|
||||
return {
|
||||
title: illust.title,
|
||||
description: `<p>画师:${username} - 上传于:${new Date(illust.create_date).toLocaleString('zh-cn')} - 阅览数:${illust.total_view} - 收藏数:${illust.total_bookmarks}</p>${images.join('')}`,
|
||||
link: `https://www.pixiv.net/member_illust.php?mode=medium&illust_id=${illust.id}`
|
||||
};
|
||||
})
|
||||
});
|
||||
};
|
||||
@@ -106,6 +106,10 @@ async@^2.6.0:
|
||||
dependencies:
|
||||
lodash "^4.14.0"
|
||||
|
||||
asynckit@^0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||
|
||||
axios@0.18.0:
|
||||
version "0.18.0"
|
||||
resolved "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz#32d53e4851efdc0a11993b6cd000789d70c05102"
|
||||
@@ -262,6 +266,12 @@ colorspace@1.0.x:
|
||||
color "0.8.x"
|
||||
text-hex "0.0.x"
|
||||
|
||||
combined-stream@1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818"
|
||||
dependencies:
|
||||
delayed-stream "~1.0.0"
|
||||
|
||||
commander@2.15.x, commander@~2.15.0:
|
||||
version "2.15.1"
|
||||
resolved "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f"
|
||||
@@ -353,6 +363,10 @@ del@^2.0.2:
|
||||
pinkie-promise "^2.0.0"
|
||||
rimraf "^2.2.8"
|
||||
|
||||
delayed-stream@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
||||
|
||||
delegates@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
|
||||
@@ -618,6 +632,14 @@ follow-redirects@^1.3.0:
|
||||
dependencies:
|
||||
debug "^3.1.0"
|
||||
|
||||
form-data@^2.3.2:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099"
|
||||
dependencies:
|
||||
asynckit "^0.4.0"
|
||||
combined-stream "1.0.6"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
fresh@^0.5.2:
|
||||
version "0.5.2"
|
||||
resolved "http://registry.npm.taobao.org/fresh/download/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
|
||||
@@ -957,7 +979,7 @@ mime-db@~1.33.0:
|
||||
version "1.33.0"
|
||||
resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db"
|
||||
|
||||
mime-types@^2.0.7, mime-types@~2.1.18:
|
||||
mime-types@^2.0.7, mime-types@^2.1.12, mime-types@~2.1.18:
|
||||
version "2.1.18"
|
||||
resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8"
|
||||
dependencies:
|
||||
|
||||
Reference in New Issue
Block a user