mirror of
https://github.com/DIYgod/RSSHub.git
synced 2026-09-24 23:12:34 +08:00
feat(route): add ainvest (#13348)
* feat(route): add ainvest * style: fix code style * fix: feed title
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
const got = require('@/utils/got');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
const { getHeaders, randomString, encryptAES, decryptAES } = require('./utils');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const key = randomString(16);
|
||||
|
||||
const { data: response } = await got.post('https://api.ainvest.com/gw/socialcenter/v1/edu/article/listArticle', {
|
||||
headers: getHeaders(key),
|
||||
searchParams: {
|
||||
timestamp: Date.now(),
|
||||
},
|
||||
data: encryptAES(
|
||||
JSON.stringify({
|
||||
batch: ctx.query.limit ? parseInt(ctx.query.limit, 10) : 30,
|
||||
startId: null,
|
||||
tags: {
|
||||
in: ['markettrends', 'premarket', 'companyinsights', 'macro'],
|
||||
and: ['web', 'creationplatform'],
|
||||
},
|
||||
}),
|
||||
key
|
||||
),
|
||||
});
|
||||
|
||||
const { data } = JSON.parse(decryptAES(response, key));
|
||||
|
||||
const items = data.map((item) => ({
|
||||
title: item.title,
|
||||
description: item.content,
|
||||
link: item.sourceUrl,
|
||||
pubDate: parseDate(item.postDate, 'x'),
|
||||
category: [item.nickName, ...item.tags.map((tag) => tag.code)],
|
||||
}));
|
||||
|
||||
ctx.state.data = {
|
||||
title: 'AInvest - Latest Articles',
|
||||
link: 'https://www.ainvest.com/news',
|
||||
language: 'en',
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
'/article': ['TonyRL'],
|
||||
'/news': ['TonyRL'],
|
||||
};
|
||||
@@ -0,0 +1,39 @@
|
||||
const got = require('@/utils/got');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
const { getHeaders, randomString, decryptAES } = require('./utils');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const key = randomString(16);
|
||||
|
||||
const { data: response } = await got('https://api.ainvest.com/gw/news_f10/v1/newsFlash/getNewsData', {
|
||||
headers: getHeaders(key),
|
||||
searchParams: {
|
||||
terminal: 'web',
|
||||
tab: 'all',
|
||||
page: 1,
|
||||
size: ctx.query.limit ? parseInt(ctx.query.limit, 10) : 50,
|
||||
lastId: '',
|
||||
timestamp: Date.now(),
|
||||
},
|
||||
});
|
||||
|
||||
const { data } = JSON.parse(decryptAES(response, key));
|
||||
|
||||
const items = data.content.map((item) => ({
|
||||
title: item.title,
|
||||
description: item.content,
|
||||
link: item.sourceUrl,
|
||||
pubDate: parseDate(item.publishTime, 'x'),
|
||||
category: item.tagList.map((tag) => tag.nameEn),
|
||||
author: item.userInfo.nickname,
|
||||
upvotes: item.likeCount,
|
||||
comments: item.commentCount,
|
||||
}));
|
||||
|
||||
ctx.state.data = {
|
||||
title: 'AInvest - Latest News',
|
||||
link: 'https://www.ainvest.com/news',
|
||||
language: 'en',
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
module.exports = {
|
||||
'ainvest.com': {
|
||||
_name: 'AInvest',
|
||||
'.': [
|
||||
{
|
||||
title: 'Latest Article',
|
||||
docs: 'https://docs.rsshub.app/finance#ainvest',
|
||||
source: ['/news'],
|
||||
target: '/ainvest/article',
|
||||
},
|
||||
{
|
||||
title: 'Latest News',
|
||||
docs: 'https://docs.rsshub.app/finance#ainvest',
|
||||
source: ['/news'],
|
||||
target: '/ainvest/news',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
module.exports = (router) => {
|
||||
router.get('/article', require('./article'));
|
||||
router.get('/news', require('./news'));
|
||||
};
|
||||
@@ -0,0 +1,73 @@
|
||||
const crypto = require('crypto');
|
||||
const CryptoJS = require('crypto-js');
|
||||
const { KJUR, KEYUTIL, hextob64 } = require('jsrsasign');
|
||||
|
||||
const publicKey =
|
||||
'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCARnxLlrhTK28bEV7s2IROjT73KLSjfqpKIvV8L+Yhe4BrF0Ut4oOH728HZlbSF0C3N0vXZjLAFesoS4v1pYOjVCPXl920Lh2seCv82m0cK78WMGuqZTfA44Nv7JsQMHC3+J6IZm8YD53ft2d8mYBFgKektduucjx8sObe7eRyoQIDAQAB';
|
||||
|
||||
const randomString = (length) => {
|
||||
if (length > 32) {
|
||||
throw Error('Max length is 32.');
|
||||
}
|
||||
return uuidv4().replace(/-/g, '').substring(0, length);
|
||||
};
|
||||
|
||||
const uuidv4 = () => crypto.randomUUID();
|
||||
|
||||
/**
|
||||
* @param {string} str
|
||||
* @returns {CryptoJS.lib.WordArray}
|
||||
*/
|
||||
const MD5 = (str) => CryptoJS.MD5(str);
|
||||
|
||||
const encryptAES = (data, key) => {
|
||||
if (typeof key === 'string') {
|
||||
key = MD5(key);
|
||||
}
|
||||
return CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(data), key, {
|
||||
mode: CryptoJS.mode.ECB,
|
||||
padding: CryptoJS.pad.Pkcs7,
|
||||
}).toString();
|
||||
};
|
||||
|
||||
const decryptAES = (data, key) => {
|
||||
if (typeof key === 'string') {
|
||||
key = MD5(key);
|
||||
}
|
||||
return CryptoJS.AES.decrypt(data, key, {
|
||||
mode: CryptoJS.mode.ECB,
|
||||
padding: CryptoJS.pad.Pkcs7,
|
||||
}).toString(CryptoJS.enc.Utf8);
|
||||
};
|
||||
|
||||
const encryptRSA = (data) => {
|
||||
// Original code:
|
||||
// var n = new JSEncrypt();
|
||||
// n.setPublicKey(pubKey);
|
||||
// return n.encrypt(message);
|
||||
// Note: Server will reject the public key if it's encrypted using crypto.publicEncrypt().
|
||||
let pubKey = `-----BEGIN PUBLIC KEY-----${publicKey}-----END PUBLIC KEY-----`;
|
||||
pubKey = KEYUTIL.getKey(pubKey);
|
||||
return hextob64(KJUR.crypto.Cipher.encrypt(data, pubKey));
|
||||
};
|
||||
|
||||
const getHeaders = (key) => {
|
||||
const fingerPrint = uuidv4();
|
||||
|
||||
return {
|
||||
'content-type': 'application/json',
|
||||
'ovse-trace': uuidv4(),
|
||||
callertype: 'USER',
|
||||
fingerprint: encryptAES(fingerPrint, MD5(key)),
|
||||
onetimeskey: encryptRSA(key),
|
||||
timestamp: encryptAES(Date.now(), key),
|
||||
referer: 'https://www.ainvest.com/',
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
randomString,
|
||||
encryptAES,
|
||||
decryptAES,
|
||||
getHeaders,
|
||||
};
|
||||
@@ -113,6 +113,7 @@
|
||||
"jsdom": "22.1.0",
|
||||
"json-bigint": "1.0.0",
|
||||
"json5": "2.2.3",
|
||||
"jsrsasign": "10.8.6",
|
||||
"koa": "2.14.2",
|
||||
"koa-basic-auth": "4.0.0",
|
||||
"koa-favicon": "2.1.0",
|
||||
|
||||
Generated
+7
@@ -95,6 +95,9 @@ dependencies:
|
||||
json5:
|
||||
specifier: 2.2.3
|
||||
version: 2.2.3
|
||||
jsrsasign:
|
||||
specifier: 10.8.6
|
||||
version: 10.8.6
|
||||
koa:
|
||||
specifier: 2.14.2
|
||||
version: 2.14.2
|
||||
@@ -5096,6 +5099,10 @@ packages:
|
||||
verror: 1.10.0
|
||||
dev: false
|
||||
|
||||
/jsrsasign@10.8.6:
|
||||
resolution: {integrity: sha512-bQmbVtsfbgaKBTWCKiDCPlUPbdlRIK/FzSwT3BzIgZl/cU6TqXu6pZJsCI/dJVrZ9Gir5GC4woqw9shH/v7MBw==}
|
||||
dev: false
|
||||
|
||||
/jwa@2.0.0:
|
||||
resolution: {integrity: sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==}
|
||||
dependencies:
|
||||
|
||||
@@ -38,6 +38,16 @@
|
||||
|
||||
</Route>
|
||||
|
||||
## AInvest {#ainvest}
|
||||
|
||||
### Latest Article {#ainvest-latest-article}
|
||||
|
||||
<Route author="TonyRL" example="/ainvest/article" path="/ainvest/article" radar="1"/>
|
||||
|
||||
### Latest News {#ainvest-latest-news}
|
||||
|
||||
<Route author="TonyRL" example="/ainvest/news" path="/ainvest/news" radar="1"/>
|
||||
|
||||
## BigQuant {#bigquant}
|
||||
|
||||
### 专题报告 {#bigquant-zhuan-ti-bao-gao}
|
||||
|
||||
Reference in New Issue
Block a user