diff --git a/lib/middleware/sentry.ts b/lib/middleware/sentry.ts index 39818a3064..04d59e95e1 100644 --- a/lib/middleware/sentry.ts +++ b/lib/middleware/sentry.ts @@ -1,7 +1,7 @@ import { MiddlewareHandler } from 'hono'; import logger from '@/utils/logger'; import { config } from '@/config'; -import Sentry from '@sentry/node'; +import * as Sentry from '@sentry/node'; import { getRouteNameFromPath } from '@/utils/helpers'; if (config.sentry.dsn) { diff --git a/lib/router.js b/lib/router.js index b1a0e80697..80d0cfa6fc 100644 --- a/lib/router.js +++ b/lib/router.js @@ -155,7 +155,7 @@ router.get('/mafengwo/ziyouxing/:code', lazyloadRouteHandler('./routes/mafengwo/ router.get('/novel/uukanshu/:uid', lazyloadRouteHandler('./routes/novel/uukanshu')); // 中国气象网 -router.get('/weatheralarm/:province?', lazyloadRouteHandler('./routes/weatheralarm')); +// router.get('/weatheralarm/:province?', lazyloadRouteHandler('./routes/weatheralarm')); // Gitlab router.get('/gitlab/explore/:type/:host?', lazyloadRouteHandler('./routes/gitlab/explore')); diff --git a/lib/routes-deprecated/weatheralarm/index.js b/lib/routes-deprecated/weatheralarm/index.js deleted file mode 100644 index 88d0595378..0000000000 --- a/lib/routes-deprecated/weatheralarm/index.js +++ /dev/null @@ -1,26 +0,0 @@ -const got = require('@/utils/got'); - -module.exports = async (ctx) => { - const province = ctx.params.province || '&'; - const alarmInfoURL = `http://www.nmc.cn/rest/findAlarm?pageNo=1&pageSize=20&signaltype=&signallevel=&province=${province}`; - const response = await got({ - method: 'get', - url: alarmInfoURL, - }); - const data = response.data.data; - const list = data.page.list; - - ctx.state.data = { - title: '中央气象台全国气象预警', - link: `http://www.nmc.cn/publish/alarm.html`, - item: list.map((item) => { - const title = item.title; - const url = item.url; - return { - title, - link: `http://www.nmc.cn${url}`, - pubDate: item.issuetime, - }; - }), - }; -}; diff --git a/lib/routes/baidu/radar.ts b/lib/routes/baidu/radar.ts index 5d91512855..13e02d4527 100644 --- a/lib/routes/baidu/radar.ts +++ b/lib/routes/baidu/radar.ts @@ -75,7 +75,7 @@ module.exports = { const qw = searchParams.get('qw'); const kw = searchParams.get('kw'); if (qw) { - const route = `/baidu/tieba/user/${qw}`; + const route = `/baidu/tieba/search/${qw}`; return kw ? `${route}/kw=${kw}` : route; } }, diff --git a/lib/routes/baidu/tieba/forum.ts b/lib/routes/baidu/tieba/forum.ts index 27f81aca55..7c21caa648 100644 --- a/lib/routes/baidu/tieba/forum.ts +++ b/lib/routes/baidu/tieba/forum.ts @@ -16,7 +16,7 @@ export default async (ctx) => { // PC端:https://tieba.baidu.com/f?kw=${encodeURIComponent(kw)} // 移动端接口:https://tieba.baidu.com/mo/q/m?kw=${encodeURIComponent(kw)}&lp=5024&forum_recommend=1&lm=0&cid=0&has_url_param=1&pn=0&is_ajax=1 const params = { kw: encodeURIComponent(kw) }; - ctx._matchedRoute.includes('good') && (params.tab = 'good'); + ctx.req.path.includes('good') && (params.tab = 'good'); cid && (params.cid = cid); const { data } = await got(`https://tieba.baidu.com/f`, { headers: { diff --git a/lib/routes/baidu/tieba/post.ts b/lib/routes/baidu/tieba/post.ts index 9e5080e916..421418dd1a 100644 --- a/lib/routes/baidu/tieba/post.ts +++ b/lib/routes/baidu/tieba/post.ts @@ -34,7 +34,7 @@ async function getPost(id, lz = 0, pn = 7e6) { export default async (ctx) => { const id = ctx.req.param('id'); - const lz = ctx._matchedRoute.includes('lz') ? 1 : 0; + const lz = ctx.req.path.includes('lz') ? 1 : 0; const html = await getPost(id, lz); const $ = load(html); const title = $('.core_title_txt').attr('title'); diff --git a/lib/routes/bilibili/like.js b/lib/routes/bilibili/like.js new file mode 100644 index 0000000000..2b628aec41 --- /dev/null +++ b/lib/routes/bilibili/like.js @@ -0,0 +1,35 @@ +import got from '@/utils/got'; +const cache = require('./cache'); +const utils = require('./utils'); +import { parseDate } from '@/utils/parse-date'; + +module.exports = async (ctx) => { + const uid = ctx.req.param('uid'); + const disableEmbed = ctx.req.param('disableEmbed'); + + const name = await cache.getUsernameFromUID(ctx, uid); + + const response = await got({ + url: `https://api.bilibili.com/x/space/like/video?vmid=${uid}`, + headers: { + Referer: `https://space.bilibili.com/${uid}/`, + }, + }); + const { data, code, message } = response.data; + if (code) { + throw new Error(message ?? code); + } + + ctx.set('data', { + title: `${name} 的 bilibili 点赞视频`, + link: `https://space.bilibili.com/${uid}`, + description: `${name} 的 bilibili 点赞视频`, + item: data.list.map((item) => ({ + title: item.title, + description: `${item.desc}${disableEmbed ? '' : `

${utils.iframe(item.aid)}`}
`, + pubDate: parseDate(item.pubdate * 1000), + link: item.pubdate > utils.bvidTime && item.bvid ? `https://www.bilibili.com/video/${item.bvid}` : `https://www.bilibili.com/video/av${item.aid}`, + author: item.owner.name, + })), + }); +}; diff --git a/lib/routes/bilibili/maintainer.ts b/lib/routes/bilibili/maintainer.ts index 2cbb05bfe8..bfab17167d 100644 --- a/lib/routes/bilibili/maintainer.ts +++ b/lib/routes/bilibili/maintainer.ts @@ -31,6 +31,7 @@ module.exports = { '/user/fav/:uid/:disableEmbed?': ['DIYgod'], '/user/followers/:uid/:loginUid': ['Qixingchen'], '/user/followings/:uid/:loginUid': ['Qixingchen'], + '/user/like/:uid/:disableEmbed?': ['ygguorun'], '/user/video/:uid/:disableEmbed?': ['DIYgod'], '/video/danmaku/:bvid/:pid?': ['Qixingchen'], '/video/page/:bvid/:disableEmbed?': ['sxzz'], diff --git a/lib/routes/bilibili/radar.ts b/lib/routes/bilibili/radar.ts index 24fa549a60..91df8b0b90 100644 --- a/lib/routes/bilibili/radar.ts +++ b/lib/routes/bilibili/radar.ts @@ -102,6 +102,12 @@ module.exports = { source: '/:uid', target: '/bilibili/user/coin/:uid', }, + { + title: 'UP 主点赞视频', + docs: 'https://docs.rsshub.app/routes/social-media#bilibili', + source: '/:uid', + target: '/bilibili/user/like/:uid', + }, { title: 'UP 主粉丝', docs: 'https://docs.rsshub.app/routes/social-media#bilibili', diff --git a/lib/routes/bilibili/router.ts b/lib/routes/bilibili/router.ts index 739d7fa2ea..01c61b004a 100644 --- a/lib/routes/bilibili/router.ts +++ b/lib/routes/bilibili/router.ts @@ -31,6 +31,7 @@ export default (router) => { router.get('/user/fav/:uid/:disableEmbed?', './user-fav'); router.get('/user/followers/:uid/:loginUid', './followers'); router.get('/user/followings/:uid/:loginUid', './followings'); + router.get('/user/like/:uid/:disableEmbed?', './like'); router.get('/user/video/:uid/:disableEmbed?', './video'); router.get('/user/video-all/:uid/:disableEmbed?', './video-all'); router.get('/video/danmaku/:bvid/:pid?', './danmaku'); diff --git a/lib/routes/github/notifications.ts b/lib/routes/github/notifications.ts index 3d1ab7623b..36982f510c 100644 --- a/lib/routes/github/notifications.ts +++ b/lib/routes/github/notifications.ts @@ -20,13 +20,19 @@ export default async (ctx) => { }); const notifications = response.data; - const items = notifications.map((item) => ({ - title: item.subject.title, - description: item.subject.title, - pubDate: parseDate(item.updated_at), // item.updated_at follows ISO 8601. - guid: item.id, - link: item.subject.url, - })); + const items = notifications.map((item) => { + let originUrl = item.subject.url ? item.subject.url.replace('https://api.github.com/repos/', 'https://github.com/') : 'https://github.com/notifications'; + if (originUrl.includes('/releases/')) { + originUrl = originUrl.replace(/\/releases\/\d+$/, '/releases'); + } + return { + title: item.subject.title, + description: item.subject.title, + pubDate: parseDate(item.updated_at), // item.updated_at follows ISO 8601. + guid: item.id, + link: originUrl, + }; + }); ctx.set('data', { title: 'Github Notifications', diff --git a/lib/routes/mastodon/timeline-local.ts b/lib/routes/mastodon/timeline-local.ts index 8beb5f6fb3..5af1a3b0aa 100644 --- a/lib/routes/mastodon/timeline-local.ts +++ b/lib/routes/mastodon/timeline-local.ts @@ -12,7 +12,7 @@ export default async (ctx) => { const url = `http://${site}/api/v1/timelines/public?local=true&only_media=${only_media}`; - const response = await got.get(url); + const response = await got.get(url, { headers: utils.apiHeaders() }); const list = response.data; ctx.set('data', { diff --git a/lib/routes/mastodon/timeline-remote.ts b/lib/routes/mastodon/timeline-remote.ts index 4755f131bb..ac570da1ce 100644 --- a/lib/routes/mastodon/timeline-remote.ts +++ b/lib/routes/mastodon/timeline-remote.ts @@ -12,7 +12,7 @@ export default async (ctx) => { const url = `http://${site}/api/v1/timelines/public?remote=true&only_media=${only_media}`; - const response = await got.get(url); + const response = await got.get(url, { headers: utils.apiHeaders() }); const list = response.data; ctx.set('data', { diff --git a/lib/routes/mastodon/utils.ts b/lib/routes/mastodon/utils.ts index 836379d76d..8383b93845 100644 --- a/lib/routes/mastodon/utils.ts +++ b/lib/routes/mastodon/utils.ts @@ -6,6 +6,12 @@ import { config } from '@/config'; const allowSiteList = ['mastodon.social', 'pawoo.net']; +const apiHeaders = (site) => { + const { accessToken, apiHost } = config.mastodon; + // avoid sending API token to other sites + return accessToken && site === apiHost ? { Authorization: `Bearer ${accessToken}` } : {}; +}; + const mediaParse = (media_attachments) => media_attachments .map((item) => { @@ -60,6 +66,7 @@ async function getAccountStatuses(site, account_id, only_media) { const statuses_response = await got({ method: 'get', url: statuses_url, + headers: apiHeaders(site), }); const data = statuses_response.data; @@ -71,6 +78,7 @@ async function getAccountStatuses(site, account_id, only_media) { const account_response = await got({ method: 'get', url: account_url, + headers: apiHeaders(site), }); account_data = account_response.data; } @@ -96,9 +104,7 @@ async function getAccountIdByAcct(acct) { const search_response = await got({ method: 'get', url: search_url, - headers: { - ...(mastodonConfig.accessToken ? { Authorization: `Bearer ${mastodonConfig.accessToken}` } : {}), - }, + headers: apiHeaders(site), searchParams: { q: acct, type: 'accounts', @@ -124,6 +130,7 @@ async function getAccountIdByAcct(acct) { } module.exports = { + apiHeaders, parseStatuses, getAccountStatuses, getAccountIdByAcct, diff --git a/lib/routes/nlc/maintainer.js b/lib/routes/nlc/maintainer.js new file mode 100644 index 0000000000..2a5a4f02d7 --- /dev/null +++ b/lib/routes/nlc/maintainer.js @@ -0,0 +1,3 @@ +module.exports = { + '/read/:type?': ['nczitzk'], +}; diff --git a/lib/routes/nlc/radar.js b/lib/routes/nlc/radar.js new file mode 100644 index 0000000000..607df4da50 --- /dev/null +++ b/lib/routes/nlc/radar.js @@ -0,0 +1,66 @@ +module.exports = { + 'nlc.cn': { + _name: '中国国家图书馆', + read: [ + { + title: '读者云平台', + docs: 'https://docs.rsshub.app/routes/other#zhong-guo-guo-jia-tu-shu-guan-du-zhe-yun-ping-tai', + source: ['/outRes/outResList'], + target: (_, url) => { + url = new URL(url); + const type = url.searchParams.get('type'); + + return `/nlc/read/${type ? `/${type}` : ''}`; + }, + }, + { + title: '电子图书', + docs: 'https://docs.rsshub.app/routes/other#zhong-guo-guo-jia-tu-shu-guan-du-zhe-yun-ping-tai', + source: ['/outRes/outResList'], + target: '/nlc/read/电子图书', + }, + { + title: '电子期刊', + docs: 'https://docs.rsshub.app/routes/other#zhong-guo-guo-jia-tu-shu-guan-du-zhe-yun-ping-tai', + source: ['/outRes/outResList'], + target: '/nlc/read/电子期刊', + }, + { + title: '电子论文', + docs: 'https://docs.rsshub.app/routes/other#zhong-guo-guo-jia-tu-shu-guan-du-zhe-yun-ping-tai', + source: ['/outRes/outResList'], + target: '/nlc/read/电子论文', + }, + { + title: '电子报纸', + docs: 'https://docs.rsshub.app/routes/other#zhong-guo-guo-jia-tu-shu-guan-du-zhe-yun-ping-tai', + source: ['/outRes/outResList'], + target: '/nlc/read/电子报纸', + }, + { + title: '音视频', + docs: 'https://docs.rsshub.app/routes/other#zhong-guo-guo-jia-tu-shu-guan-du-zhe-yun-ping-tai', + source: ['/outRes/outResList'], + target: '/nlc/read/音视频', + }, + { + title: '标准专利', + docs: 'https://docs.rsshub.app/routes/other#zhong-guo-guo-jia-tu-shu-guan-du-zhe-yun-ping-tai', + source: ['/outRes/outResList'], + target: '/nlc/read/标准专利', + }, + { + title: '工具书', + docs: 'https://docs.rsshub.app/routes/other#zhong-guo-guo-jia-tu-shu-guan-du-zhe-yun-ping-tai', + source: ['/outRes/outResList'], + target: '/nlc/read/工具书', + }, + { + title: '少儿资源', + docs: 'https://docs.rsshub.app/routes/other#zhong-guo-guo-jia-tu-shu-guan-du-zhe-yun-ping-tai', + source: ['/outRes/outResList'], + target: '/nlc/read/少儿资源', + }, + ], + }, +}; diff --git a/lib/routes/nlc/read.js b/lib/routes/nlc/read.js new file mode 100644 index 0000000000..f9afd64681 --- /dev/null +++ b/lib/routes/nlc/read.js @@ -0,0 +1,71 @@ +import got from '@/utils/got'; +import { load } from 'cheerio'; +import { art } from '@/utils/render'; +import * as path from 'node:path'; + +export default async (ctx) => { + const { type = '电子图书' } = ctx.req.param(); + const limit = ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit'), 10) : 15; + + const author = '中国国家图书馆'; + + const rootUrl = 'http://read.nlc.cn'; + const currentUrl = new URL(`/outRes/outResList?type=${type}`, rootUrl).href; + + const { data: response } = await got(currentUrl); + + const $ = load(response); + + const items = $('ul.YMH2019_New_GRZX_list7 li a.aa') + .slice(0, limit) + .toArray() + .map((item) => { + item = $(item); + + const title = item.find('span').first().text(); + + return { + title, + link: item.prop('onclick').match(/openOutRes\('1','(.*?)','1',/)[1], + description: art(path.join(__dirname, 'templates/description.art'), { + images: item + .find('div.pic img') + .toArray() + .map((i) => { + i = $(i); + + return { + src: i.prop('src'), + alt: title, + }; + }), + intro: item.find('div.txt').prop('title'), + }), + author, + category: [type], + guid: `nlc-read#${ + item + .prev() + .prop('onclick') + .match(/\('(\d+)'\)/)[1] + }`, + }; + }); + + const image = new URL('static/style/css/images/YMH_home_main_logo.png', rootUrl).href; + const icon = new URL($('link[rel="shortcut icon"]').prop('href'), rootUrl).href; + + ctx.set('data', { + item: items, + title: `${$('title').text()} - ${type}`, + link: currentUrl, + description: type, + language: 'zh', + image, + icon, + logo: icon, + subtitle: type, + author, + allowEmpty: true, + }); +}; diff --git a/lib/routes/nlc/router.js b/lib/routes/nlc/router.js new file mode 100644 index 0000000000..87a34ad553 --- /dev/null +++ b/lib/routes/nlc/router.js @@ -0,0 +1,3 @@ +export default (router) => { + router.get('/read/:type?', './read'); +}; diff --git a/lib/routes/nlc/templates/description.art b/lib/routes/nlc/templates/description.art new file mode 100644 index 0000000000..a3f88c9b4d --- /dev/null +++ b/lib/routes/nlc/templates/description.art @@ -0,0 +1,17 @@ +{{ if images }} + {{ each images image }} + {{ if image?.src }} +
+ {{ image.alt }} +
+ {{ /if }} + {{ /each }} +{{ /if }} + +{{ if intro }} +

{{ intro }}

+{{ /if }} \ No newline at end of file diff --git a/lib/routes/nmc/maintainer.js b/lib/routes/nmc/maintainer.js new file mode 100644 index 0000000000..42f2f53ab7 --- /dev/null +++ b/lib/routes/nmc/maintainer.js @@ -0,0 +1,3 @@ +module.exports = { + '/weatheralarm/:province?': ['ylc395'], +}; diff --git a/lib/routes/nmc/radar.js b/lib/routes/nmc/radar.js new file mode 100644 index 0000000000..0e77a18f3e --- /dev/null +++ b/lib/routes/nmc/radar.js @@ -0,0 +1,13 @@ +module.exports = { + 'nmc.cn': { + _name: '中央气象台', + '.': [ + { + title: '全国气象预警', + docs: 'https://docs.rsshub.app/routes/forecast#zhong-yang-qi-xiang-tai', + source: ['/publish/alarm.html', '/'], + target: '/nmc/weatheralarm', + }, + ], + }, +}; diff --git a/lib/routes/nmc/router.js b/lib/routes/nmc/router.js new file mode 100644 index 0000000000..fde453364b --- /dev/null +++ b/lib/routes/nmc/router.js @@ -0,0 +1,3 @@ +export default (router) => { + router.get('/weatheralarm/:province?', './weatheralarm'); +}; diff --git a/lib/routes/nmc/weatheralarm.js b/lib/routes/nmc/weatheralarm.js new file mode 100644 index 0000000000..825d35650f --- /dev/null +++ b/lib/routes/nmc/weatheralarm.js @@ -0,0 +1,49 @@ +import cache from '@/utils/cache'; +import got from '@/utils/got'; +import { parseDate } from '@/utils/parse-date'; +import timezone from '@/utils/timezone'; +import * as cheerio from 'cheerio'; + +export default async (ctx) => { + const { province } = ctx.req.param(); + const alarmInfoURL = `http://www.nmc.cn/rest/findAlarm`; + const { data: response } = await got(alarmInfoURL, { + searchParams: { + pageNo: 1, + pageSize: 20, + signaltype: '', + signallevel: '', + province, + }, + }); + + const list = response.data.page.list.map((item) => ({ + title: item.title, + link: `http://www.nmc.cn${item.url}`, + pubDate: timezone(parseDate(item.issuetime), 8), + })); + + const items = await Promise.all( + list.map((item) => + cache.tryGet(item.link, async () => { + const { data: response } = await got(item.link); + const $ = cheerio.load(response); + + item.description = + $('#icon').html() + + $('#alarmtext') + .toArray() + .map((i) => $(i).html()) + .join(''); + + return item; + }) + ) + ); + + ctx.set('data', { + title: '中央气象台全国气象预警', + link: 'http://www.nmc.cn/publish/alarm.html', + item: items, + }); +}; diff --git a/lib/routes/npm/package.ts b/lib/routes/npm/package.ts index 58ab3ebf12..33ed1d6ba8 100644 --- a/lib/routes/npm/package.ts +++ b/lib/routes/npm/package.ts @@ -7,7 +7,7 @@ import { art } from '@/utils/render'; import * as path from 'node:path'; export default async (ctx) => { - const name = ctx.req.url.split('package/')[1]; + const name = ctx.req.param('name'); const packageDownloadLastMonthAPI = `https://api.npmjs.org/downloads/point/last-month/${name}`; // 按月统计 const packageDownloadLastWeekAPI = `https://api.npmjs.org/downloads/point/last-week/${name}`; // 按周统计 const packageDownloadLastDayAPI = `https://api.npmjs.org/downloads/point/last-day/${name}`; // 按天统计 @@ -19,14 +19,12 @@ export default async (ctx) => { const packageVersionRes = await got(packageVersionAPI).json(); const packageVersion = packageVersionRes.time; - const packageVersionList = []; - for (const key in packageVersion) { - packageVersionList.push({ + const packageVersionList = Object.keys(packageVersion) + .map((key) => ({ version: key, time: packageVersion[key], - }); - } - packageVersionList.reverse(); + })) + .toReversed(); ctx.set('data', { title: `${name} - npm`, diff --git a/lib/routes/npm/router.ts b/lib/routes/npm/router.ts index 03da709285..0b04076bb8 100644 --- a/lib/routes/npm/router.ts +++ b/lib/routes/npm/router.ts @@ -1,3 +1,4 @@ export default (router) => { - router.get('package/*', './package'); + // https://github.com/dword-design/package-name-regex/blob/master/src/index.js + router.get('package/:name{(@[a-z0-9-~][a-z0-9-._~]*\\/)?[a-z0-9-~][a-z0-9-._~]*}', './package'); }; diff --git a/lib/routes/radio-canada/latest.ts b/lib/routes/radio-canada/latest.ts index e0bdf987c8..c402a49d18 100644 --- a/lib/routes/radio-canada/latest.ts +++ b/lib/routes/radio-canada/latest.ts @@ -32,10 +32,10 @@ export default async (ctx) => { }); const $ = load(detailResponse.data); - const rcState = $('script:contains("window._rcState_ = JSON.parse")') + const rcState = $('script:contains("window._rcState_ = ")') .text() - .match(/JSON\.parse\((".*")\);/)[1]; - const rcStateJson = JSON.parse(JSON.parse(rcState)); + .match(/window\._rcState_ = (.*);/)[1]; + const rcStateJson = JSON.parse(rcState); const news = Object.values(rcStateJson.pagesV2.pages)[0]; item.description = news.data.newsStory.body.html.replaceAll('\\n', '
'); diff --git a/lib/routes/weibo/user.ts b/lib/routes/weibo/user.ts index 5343ac7b5f..48ea8f302b 100644 --- a/lib/routes/weibo/user.ts +++ b/lib/routes/weibo/user.ts @@ -1,6 +1,6 @@ // @ts-nocheck import cache from '@/utils/cache'; -const querystring = require('query-string'); +import querystring from 'querystring'; import got from '@/utils/got'; const weiboUtils = require('./utils'); import { config } from '@/config'; diff --git a/lib/routes/zhujiceping/maintainer.js b/lib/routes/zhujiceping/maintainer.js new file mode 100644 index 0000000000..387d961bfe --- /dev/null +++ b/lib/routes/zhujiceping/maintainer.js @@ -0,0 +1,3 @@ +module.exports = { + '/': ['cnkmmk'], +}; diff --git a/lib/routes/zhujiceping/radar.js b/lib/routes/zhujiceping/radar.js new file mode 100644 index 0000000000..5ea1b8e747 --- /dev/null +++ b/lib/routes/zhujiceping/radar.js @@ -0,0 +1,13 @@ +module.exports = { + 'zhujiceping.com': { + _name: '国外主机测评', + '.': [ + { + title: '最新发布', + docs: 'https://docs.rsshub.app/routes/blog#guo-wai-zhu-ji-ce-ping', + source: ['/'], + target: '/zhujiceping', + }, + ], + }, +}; diff --git a/lib/routes/zhujiceping/router.js b/lib/routes/zhujiceping/router.js new file mode 100644 index 0000000000..09c585b573 --- /dev/null +++ b/lib/routes/zhujiceping/router.js @@ -0,0 +1,3 @@ +export default (router) => { + router.get('/', './rss'); +}; diff --git a/lib/routes/zhujiceping/rss.js b/lib/routes/zhujiceping/rss.js new file mode 100644 index 0000000000..7c75304996 --- /dev/null +++ b/lib/routes/zhujiceping/rss.js @@ -0,0 +1,32 @@ +import { parseDate } from '@/utils/parse-date'; +import got from '@/utils/got'; +import { load } from 'cheerio'; + +export default async (ctx) => { + const url = 'https://www.zhujiceping.com/'; + const response = await got({ method: 'get', url }); + const $ = load(response.data); + + const list = $('article.excerpt') + .map((i, e) => { + const element = $(e); + const title = element.find('h2 > a').attr('title'); + const link = element.find('h2 > a').attr('href'); + const description = element.find('p.note').text(); + const dateraw = element.find('time').text(); + + return { + title, + description, + link, + pubDate: parseDate(dateraw, 'YYYY-MM-DD'), + }; + }) + .get(); + + ctx.set('data', { + title: '国外主机测评', + link: url, + item: list, + }); +}; diff --git a/website/docs/routes/blog.mdx b/website/docs/routes/blog.mdx index 84aa4d03b2..0ea8cd45e3 100644 --- a/website/docs/routes/blog.mdx +++ b/website/docs/routes/blog.mdx @@ -334,6 +334,12 @@ | news | blog | articles | about-influence | customers | +## 国外主机测评 {#guo-wai-zhu-ji-ce-ping} + +### 最新发布 {#guo-wai-zhu-ji-ce-ping-zui-xin-fa-bu} + + + ## 虎皮椒 {#hu-pi-jiao} ### 文章 {#hu-pi-jiao-wen-zhang} diff --git a/website/docs/routes/forecast.mdx b/website/docs/routes/forecast.mdx index 2f17b104ed..b3bd703fd8 100644 --- a/website/docs/routes/forecast.mdx +++ b/website/docs/routes/forecast.mdx @@ -316,6 +316,6 @@ ### 全国气象预警 {#zhong-yang-qi-xiang-tai-quan-guo-qi-xiang-yu-jing} - + 可通过全局过滤参数订阅您感兴趣的地区. diff --git a/website/docs/routes/other.mdx b/website/docs/routes/other.mdx index 5c0fcad4e9..cb9d1607fc 100644 --- a/website/docs/routes/other.mdx +++ b/website/docs/routes/other.mdx @@ -995,6 +995,18 @@ Specify options (in the format of query string) in parameter `routeParams` param | usd | gbp | hkd | chf | sek | dkk | nok | jpy | cad | aud | sgd | eur | mop | thb | nzd | krw | +## 中国国家图书馆 {#zhong-guo-guo-jia-tu-shu-guan} + +### 读者云平台 {#zhong-guo-guo-jia-tu-shu-guan-du-zhe-yun-ping-tai} + + + | [电子图书](http://read.nlc.cn/outRes/outResList?type=电子图书) | [电子期刊](http://read.nlc.cn/outRes/outResList?type=电子期刊) | [电子论文](http://read.nlc.cn/outRes/outResList?type=电子论文) | [电子报纸](http://read.nlc.cn/outRes/outResList?type=电子报纸) | [音视频](http://read.nlc.cn/outRes/outResList?type=音视频) | + | -------------------------------------------------------------- | -------------------------------------------------------------- | -------------------------------------------------------------- | -------------------------------------------------------------- | ---------------------------------------------------------- | + + | [标准专利](http://read.nlc.cn/outRes/outResList?type=标准专利) | [工具书](http://read.nlc.cn/outRes/outResList?type=工具书) | [少儿资源](http://read.nlc.cn/outRes/outResList?type=少儿资源) | + | -------------------------------------------------------------- | ---------------------------------------------------------- | -------------------------------------------------------------- | + + ## 中国互联网联合辟谣平台 {#zhong-guo-hu-lian-wang-lian-he-pi-yao-ping-tai} ### 今日辟谣 {#zhong-guo-hu-lian-wang-lian-he-pi-yao-ping-tai-jin-ri-pi-yao} diff --git a/website/docs/routes/social-media.mdx b/website/docs/routes/social-media.mdx index dcfd03b0fb..541f207c34 100644 --- a/website/docs/routes/social-media.mdx +++ b/website/docs/routes/social-media.mdx @@ -67,6 +67,10 @@ +### UP 主点赞视频 {#bilibili-up-zhu-dian-zan-shi-pin} + + + ### UP 主粉丝 {#bilibili-up-zhu-fen-si}