diff --git a/docs/en/finance.md b/docs/en/finance.md
index 935b14710b..2e63d0d0cf 100644
--- a/docs/en/finance.md
+++ b/docs/en/finance.md
@@ -16,6 +16,28 @@ pageClass: routes
+## TokenInsight
+
+### Blogs
+
+
+
+### Latest
+
+
+
+### Research
+
+
+
+Language:
+
+| Chinese | English |
+| ------- | ------- |
+| zh | en |
+
+
+
## World Economic Forum
### Report
diff --git a/docs/finance.md b/docs/finance.md
index 423e7cd1ef..e0442b6e15 100644
--- a/docs/finance.md
+++ b/docs/finance.md
@@ -38,6 +38,28 @@ pageClass: routes
+## TokenInsight
+
+### 博客
+
+
+
+### 快讯
+
+
+
+### 报告
+
+
+
+语言
+
+| 中文 | 英文 |
+| -- | -- |
+| zh | en |
+
+
+
## WEEX 华尔街见闻旗下全球投资线上品牌
### 资讯
diff --git a/lib/v2/tokeninsight/blog.js b/lib/v2/tokeninsight/blog.js
new file mode 100644
index 0000000000..f2c72a1871
--- /dev/null
+++ b/lib/v2/tokeninsight/blog.js
@@ -0,0 +1,52 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const { parseDate } = require('@/utils/parse-date');
+const baseURL = 'https://www.tokeninsight.com/';
+const title = 'TokenInsight';
+const link = 'https://www.tokeninsight.com/';
+
+module.exports = async (ctx) => {
+ const lang = ctx.params.lang ?? 'zh';
+
+ const getBlogs = async () => {
+ const url = `${baseURL}api/user/search/getAllList`;
+ const response = (
+ await got.post(url, {
+ form: {
+ isRecommend: 2,
+ language: lang === 'zh' ? 'cn' : lang,
+ },
+ })
+ ).data;
+ return response.data.blogsList;
+ };
+
+ const getBlogInfomation = async (blog) => {
+ const { publishDate, title, id } = blog;
+ const blogUrl = `${baseURL}${lang}/blogs/${id}`;
+ const description = await ctx.cache.tryGet(blogUrl, async () => {
+ const res = await got(blogUrl);
+ const $ = cheerio.load(res.data);
+ const description = $('.detail_html_box').html();
+ return description;
+ });
+ return {
+ // 文章标题
+ title,
+ // 文章正文
+ description,
+ // 文章发布时间
+ pubDate: parseDate(publishDate),
+ // 文章链接
+ link: blogUrl,
+ };
+ };
+ const limit = ctx.query.limit ? parseInt(ctx.query.limit) : 30;
+ const blogs = (await getBlogs()).slice(0, limit);
+ const list = await Promise.all(blogs.map(getBlogInfomation));
+ ctx.state.data = {
+ title: `${lang === 'zh' ? '博客' : 'Blogs'} | ${title}`,
+ link: `${link}${lang}/blogs`,
+ item: list,
+ };
+};
diff --git a/lib/v2/tokeninsight/bulletin.js b/lib/v2/tokeninsight/bulletin.js
new file mode 100644
index 0000000000..ed09b93c46
--- /dev/null
+++ b/lib/v2/tokeninsight/bulletin.js
@@ -0,0 +1,44 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const { parseDate } = require('@/utils/parse-date');
+const baseURL = 'https://www.tokeninsight.com/';
+const title = 'TokenInsight';
+const link = 'https://www.tokeninsight.com/';
+const get_articles = async () => {
+ const url = `${baseURL}api/bulletin/selectBulletinList`;
+ const response = (await got.get(url)).data;
+ const { data } = response;
+ return data;
+};
+
+module.exports = async (ctx) => {
+ const lang = ctx.params.lang ?? 'zh';
+
+ const get_article_info = async (article) => {
+ const { updateDate, titleEn, id, title } = article;
+ const articleUrl = `${baseURL}${lang}/latest/${id}`;
+ const description = await ctx.cache.tryGet(articleUrl, async () => {
+ const res = await got(articleUrl);
+ const $ = cheerio.load(res.data);
+ return $('.detail_html_box').html();
+ });
+ return {
+ // 文章标题
+ title: lang === 'zh' ? title : titleEn,
+ // 文章正文
+ description,
+ // 文章发布时间
+ pubDate: parseDate(updateDate),
+ // 文章链接
+ link: articleUrl,
+ };
+ };
+
+ const articles = await get_articles();
+ const list = await Promise.all(articles.map(get_article_info));
+ ctx.state.data = {
+ title: `${lang === 'zh' ? '快讯' : 'Latest'} | ${title}`,
+ link: `${link}${lang}/latest`,
+ item: list,
+ };
+};
diff --git a/lib/v2/tokeninsight/maintainer.js b/lib/v2/tokeninsight/maintainer.js
new file mode 100644
index 0000000000..24fc185a6b
--- /dev/null
+++ b/lib/v2/tokeninsight/maintainer.js
@@ -0,0 +1,5 @@
+module.exports = {
+ '/blog/:lang?': ['fuergaosi233'],
+ '/bulletin:lang?': ['fuergaosi233'],
+ '/report:lang?': ['fuergaosi233'],
+};
diff --git a/lib/v2/tokeninsight/radar.js b/lib/v2/tokeninsight/radar.js
new file mode 100644
index 0000000000..e3e33dcc6a
--- /dev/null
+++ b/lib/v2/tokeninsight/radar.js
@@ -0,0 +1,25 @@
+module.exports = {
+ 'tokeninsight.com': {
+ _name: 'TokenInsight',
+ '.': [
+ {
+ title: '博客',
+ docs: 'https://docs.rsshub.app/new-media.html#tokeninsight',
+ source: ['/:lang/blogs'],
+ target: '/tokeninsight/blog/:lang',
+ },
+ {
+ title: '快讯',
+ docs: 'https://docs.rsshub.app/new-media.html#tokeninsight',
+ source: ['/:lang/latest'],
+ target: '/tokeninsight/bulletin/:lang',
+ },
+ {
+ title: '报告',
+ docs: 'https://docs.rsshub.app/new-media.html#tokeninsight',
+ source: ['/:lang/report'],
+ target: '/tokeninsight/report/:lang',
+ },
+ ],
+ },
+};
diff --git a/lib/v2/tokeninsight/report.js b/lib/v2/tokeninsight/report.js
new file mode 100644
index 0000000000..ef7e6b39c7
--- /dev/null
+++ b/lib/v2/tokeninsight/report.js
@@ -0,0 +1,52 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const { parseDate } = require('@/utils/parse-date');
+const baseURL = 'https://www.tokeninsight.com/';
+const title = 'TokenInsight';
+const link = 'https://www.tokeninsight.com/';
+
+module.exports = async (ctx) => {
+ const lang = ctx.params.lang ?? 'zh';
+
+ const getReports = async () => {
+ const url = `${baseURL}api/user/search/getAllList`;
+ const response = (
+ await got.post(url, {
+ form: {
+ isRecommend: 2,
+ language: lang === 'zh' ? 'cn' : lang,
+ },
+ })
+ ).data;
+ return response.data.reportList;
+ };
+
+ const getReportInfomation = async (report) => {
+ const { publishDate, title, id } = report;
+ const reportUrl = `${baseURL}${lang}/report/${id}`;
+ const description = await ctx.cache.tryGet(reportUrl, async () => {
+ const res = await got(reportUrl);
+ const $ = cheerio.load(res.data);
+ const description = $('.detail_html_box').html();
+ return description;
+ });
+ return {
+ // 文章标题
+ title,
+ // 文章正文
+ description,
+ // 文章发布时间
+ pubDate: parseDate(publishDate),
+ // 文章链接
+ link: reportUrl,
+ };
+ };
+ const limit = ctx.query.limit ? parseInt(ctx.query.limit) : 30;
+ const reports = (await getReports()).slice(0, limit);
+ const list = await Promise.all(reports.map(getReportInfomation));
+ ctx.state.data = {
+ title: `${lang === 'zh' ? '报告' : 'Research'} | ${title}`,
+ link: `${link}${lang}/report`,
+ item: list,
+ };
+};
diff --git a/lib/v2/tokeninsight/router.js b/lib/v2/tokeninsight/router.js
new file mode 100644
index 0000000000..c6b6c9fa3e
--- /dev/null
+++ b/lib/v2/tokeninsight/router.js
@@ -0,0 +1,5 @@
+module.exports = (router) => {
+ router.get('/blog/:lang?', require('./blog.js'));
+ router.get('/bulletin/:lang?', require('./bulletin.js'));
+ router.get('/report/:lang?', require('./report.js'));
+};