diff --git a/.gitignore b/.gitignore index a5c841183ab023..368a4c547ba8e7 100644 --- a/.gitignore +++ b/.gitignore @@ -30,5 +30,3 @@ package-lock.json # pnpm-lock.yaml yarn.lock yarn-error.log - -scripts/twitter-token/accounts.* diff --git a/README.md b/README.md index 8eb2654555ec1d..debaf1bff5cd97 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ [![test](https://img.shields.io/github/actions/workflow/status/DIYgod/RSSHub/test.yml?branch=master&label=test&logo=github&style=flat-square)](https://github.com/DIYgod/RSSHub/actions/workflows/test.yml?query=event%3Apush+branch%3Amaster) [![Test coverage](https://img.shields.io/codecov/c/github/DIYgod/RSSHub.svg?style=flat-square&logo=codecov)](https://app.codecov.io/gh/DIYgod/RSSHub/branch/master) -[![Telegram group](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.swo.moe%2Fstats%2Ftelegram%2Frsshub&query=count&color=2CA5E0&label=Telegram%20Group&logo=telegram&cacheSeconds=3600&style=flat-square)](https://t.me/rsshub) [![Telegram channel](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.swo.moe%2Fstats%2Ftelegram%2FawesomeRSSHub&query=count&color=2CA5E0&label=Telegram%20Channel&logo=telegram&cacheSeconds=3600&style=flat-square)](https://t.me/awesomeRSSHub) [![Twitter](https://img.shields.io/badge/any_text-Follow-blue?color=2CA5E0&label=Twitter&logo=twitter&cacheSeconds=3600&style=flat-square)](https://twitter.com/intent/follow?screen_name=_RSSHub) +[![Telegram group](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.swo.moe%2Fstats%2Ftelegram%2Frsshub&query=count&color=2CA5E0&label=Telegram%20Group&logo=telegram&cacheSeconds=3600&style=flat-square)](https://t.me/rsshub) [![Telegram channel](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.swo.moe%2Fstats%2Ftelegram%2FawesomeRSSHub&query=count&color=2CA5E0&label=Telegram%20Channel&logo=telegram&cacheSeconds=3600&style=flat-square)](https://t.me/awesomeRSSHub) [![Twitter](https://img.shields.io/badge/any_text-Follow-blue?color=2CA5E0&label=Twitter&logo=twitter&cacheSeconds=3600&style=flat-square)](https://x.com/intent/follow?screen_name=_RSSHub) ## Introduction @@ -21,18 +21,10 @@ RSSHub delivers millions of contents aggregated from all kinds of sources, our v RSSHub can be used with browser extension [RSSHub Radar](https://github.com/DIYgod/RSSHub-Radar) and mobile auxiliary app [RSSBud](https://github.com/Cay-Zhang/RSSBud) (iOS) and [RSSAid](https://github.com/LeetaoGoooo/RSSAid) (Android) -[English docs](https://docs.rsshub.app) | [Telegram Group](https://t.me/rsshub) | [Telegram Channel](https://t.me/awesomeRSSHub) | [Twitter](https://twitter.com/intent/follow?screen_name=_RSSHub) | [中文文档](https://docs.rsshub.app/zh/) +[English docs](https://docs.rsshub.app) | [Telegram Group](https://t.me/rsshub) | [Telegram Channel](https://t.me/awesomeRSSHub) | [Twitter](https://x.com/intent/follow?screen_name=_RSSHub) | [中文文档](https://docs.rsshub.app/zh/) ## Special Thanks -### Special Sponsors - -

-        -

- -[![](https://opencollective.com/static/images/become_sponsor.svg)](https://docs.rsshub.app/sponsor/) - ### Contributors [![](https://opencollective.com/RSSHub/contributors.svg?width=890)](https://github.com/DIYgod/RSSHub/graphs/contributors) @@ -99,4 +91,4 @@ Open source is a very expensive thing. RSSHub would not be possible without the **RSSHub** © [DIYgod](https://github.com/DIYgod), Released under the [MIT](./LICENSE) License.
Authored and maintained by DIYgod with help from contributors ([list](https://github.com/DIYgod/RSSHub/contributors)). -> Blog [@DIYgod](https://diygod.cc) · GitHub [@DIYgod](https://github.com/DIYgod) · Twitter [@DIYgod](https://twitter.com/DIYgod) · Telegram Channel [@awesomeDIYgod](https://t.me/awesomeDIYgod) +> Blog [@DIYgod](https://diygod.cc) · GitHub [@DIYgod](https://github.com/DIYgod) · Twitter [@DIYgod](https://x.com/DIYgod) · Telegram Channel [@awesomeDIYgod](https://t.me/awesomeDIYgod) diff --git a/lib/routes-deprecated/universities/bjtu/gs/index.js b/lib/routes-deprecated/universities/bjtu/gs/index.js deleted file mode 100644 index 742c56bb985fa7..00000000000000 --- a/lib/routes-deprecated/universities/bjtu/gs/index.js +++ /dev/null @@ -1,130 +0,0 @@ -const got = require('@/utils/got'); -const cheerio = require('cheerio'); - -module.exports = async (ctx) => { - const type = ctx.params.type; - const struct = { - zs: { - selector: { - list: '.mainleft_box li', - }, - url: 'https://gs.bjtu.edu.cn/cms/zszt/item/?tag=1', - name: '招生 - 北京交通大学研究生院', - }, - noti: { - selector: { - list: '.tab-content li', - }, - url: 'https://gs.bjtu.edu.cn/cms/item/?tag=2', - name: '通知公告 - 北京交通大学研究生院', - }, - news: { - selector: { - list: '.tab-content li', - }, - url: 'https://gs.bjtu.edu.cn/cms/item/?tag=3', - name: '新闻动态 - 北京交通大学研究生院', - }, - zsxc: { - selector: { - list: '.tab-content li', - }, - url: 'https://gs.bjtu.edu.cn/cms/item/?tag=4', - name: '招生宣传 - 北京交通大学研究生院', - }, - py: { - selector: { - list: '.tab-content li', - }, - url: 'https://gs.bjtu.edu.cn/cms/item/?tag=5', - name: '培养 - 北京交通大学研究生院', - }, - xw: { - selector: { - list: '.tab-content li', - }, - url: 'https://gs.bjtu.edu.cn/cms/item/?tag=7', - name: '学位 - 北京交通大学研究生院', - }, - ygbtzgg: { - selector: { - list: '.tab-content li', - }, - url: 'https://gs.bjtu.edu.cn/cms/item/?tag=9', - name: '通知公告 - 研工部 - 北京交通大学研究生院', - }, - ygbnews: { - selector: { - list: '.tab-content li', - }, - url: 'https://gs.bjtu.edu.cn/cms/item/?tag=10', - name: '新闻动态 - 研工部 - 北京交通大学研究生院', - }, - all: { - selector: { - list: '.tab-content li', - }, - url: 'https://gs.bjtu.edu.cn/cms/item/?tag=12', - name: '所有文章 - 北京交通大学研究生院', - }, - bszs: { - selector: { - list: '.mainleft_box li', - }, - url: 'https://gs.bjtu.edu.cn/cms/zszt/item/?cat=2', - name: '博士招生 - 北京交通大学研究生院', - }, - sszs: { - selector: { - list: '.mainleft_box li', - }, - url: 'https://gs.bjtu.edu.cn/cms/zszt/item/?cat=3', - name: '硕士招生 - 北京交通大学研究生院', - }, - zsjz: { - selector: { - list: '.mainleft_box li', - }, - url: 'https://gs.bjtu.edu.cn/cms/zszt/item/?cat=4', - name: '招生简章 - 北京交通大学研究生院', - }, - zcfg: { - selector: { - list: '.mainleft_box li', - }, - url: 'https://gs.bjtu.edu.cn/cms/zszt/item/?cat=5', - name: '政策法规 - 北京交通大学研究生院', - }, - }; - - const url = struct[type].url; - const response = await got({ - method: 'get', - url, - }); - - const data = response.data; - - const $ = cheerio.load(data); - const list = $(struct[type].selector.list); - - ctx.state.data = { - title: struct[type].name, - link: url, - description: '北京交通大学研究生院', - item: - list && - list - .map((index, item) => { - item = $(item); - const date = new Date(Date.parse(item.find('li span').text().slice(1, 11).replaceAll('-', '/'))); - const bj_date = date.getTime() / 1000 + 8 * 60 * 60; - const title = item - .find('li a') - .text() - .replaceAll(/\[.*?]/g, ''); - return { title, description: title, link: item.find('li a').attr('href'), pubDate: new Date(Number.parseInt(bj_date) * 1000) }; - }) - .get(), - }; -}; diff --git a/lib/routes/apnews/rss.ts b/lib/routes/apnews/rss.ts index edf24f65b74bec..3b5f3cc8f0576d 100644 --- a/lib/routes/apnews/rss.ts +++ b/lib/routes/apnews/rss.ts @@ -5,7 +5,7 @@ const HOME_PAGE = 'https://apnews.com'; export const route: Route = { path: '/rss/:rss?', - categories: ['traditional-media'], + categories: ['traditional-media', 'popular'], example: '/apnews/rss/business', parameters: { rss: 'Route name from the first segment of the corresponding site, or `index` for the front page(default).' }, features: { diff --git a/lib/routes/bilibili/dynamic.ts b/lib/routes/bilibili/dynamic.ts index 487a41e53aafa8..8ec42a6ed1a2c8 100644 --- a/lib/routes/bilibili/dynamic.ts +++ b/lib/routes/bilibili/dynamic.ts @@ -10,7 +10,7 @@ import { BilibiliWebDynamicResponse, Item2, Modules } from './api-interface'; export const route: Route = { path: '/user/dynamic/:uid/:routeParams?', - categories: ['social-media'], + categories: ['social-media', 'popular'], example: '/bilibili/user/dynamic/2267573', parameters: { uid: '用户 id, 可在 UP 主主页中找到', routeParams: '额外参数;请参阅以下说明和表格' }, features: { diff --git a/lib/routes/bilibili/ranking.ts b/lib/routes/bilibili/ranking.ts index 800ecbb3a43255..a2c1967804b252 100644 --- a/lib/routes/bilibili/ranking.ts +++ b/lib/routes/bilibili/ranking.ts @@ -6,7 +6,7 @@ export const route: Route = { path: '/ranking/:rid?/:day?/:arc_type?/:disableEmbed?', name: '排行榜', maintainers: ['DIYgod'], - categories: ['social-media'], + categories: ['social-media', 'popular'], example: '/bilibili/ranking/0/3/1', parameters: { rid: '排行榜分区 id, 默认 0', diff --git a/lib/routes/bilibili/video.ts b/lib/routes/bilibili/video.ts index 8c8a7d5ed1e044..7059a2a1870b50 100644 --- a/lib/routes/bilibili/video.ts +++ b/lib/routes/bilibili/video.ts @@ -6,7 +6,7 @@ import logger from '@/utils/logger'; export const route: Route = { path: '/user/video/:uid/:disableEmbed?', - categories: ['social-media'], + categories: ['social-media', 'popular'], example: '/bilibili/user/video/2267573', parameters: { uid: '用户 id, 可在 UP 主主页中找到', disableEmbed: '默认为开启内嵌视频, 任意值为关闭' }, features: { diff --git a/lib/routes/bjtu/gs.ts b/lib/routes/bjtu/gs.ts new file mode 100644 index 00000000000000..833eae04dd8939 --- /dev/null +++ b/lib/routes/bjtu/gs.ts @@ -0,0 +1,224 @@ +import { Route } from '@/types'; +import cache from '@/utils/cache'; +import ofetch from '@/utils/ofetch'; +import { load } from 'cheerio'; +import { parseDate } from '@/utils/parse-date'; + +const rootURL = 'https://gs.bjtu.edu.cn'; +const urlCms = `${rootURL}/cms/item/?tag=`; +const urlZszt = `${rootURL}/cms/zszt/item/?cat=`; +const title = ' - 北京交通大学研究生院'; +const zsztRegex = /_zszt/; +const struct = { + noti_zs: { + selector: { + list: '.tab-content li', + }, + tag: 1, + name: '通知公告_招生', + }, + noti: { + selector: { + list: '.tab-content li', + }, + tag: 2, + name: '通知公告', + }, + news: { + selector: { + list: '.tab-content li', + }, + tag: 3, + name: '新闻动态', + }, + zsxc: { + selector: { + list: '.tab-content li', + }, + tag: 4, + name: '招生宣传', + }, + py: { + selector: { + list: '.tab-content li', + }, + tag: 5, + name: '培养', + }, + zs: { + selector: { + list: '.tab-content li', + }, + tag: 6, + name: '招生', + }, + xw: { + selector: { + list: '.tab-content li', + }, + tag: 7, + name: '学位', + }, + ygb: { + selector: { + list: '.tab-content li', + }, + tag: 8, + name: '研工部', + }, + ygbtzgg: { + selector: { + list: '.tab-content li', + }, + tag: 9, + name: '通知公告 - 研工部', + }, + ygbnews: { + selector: { + list: '.tab-content li', + }, + tag: 10, + name: '新闻动态 - 研工部', + }, + ygbnewscover: { + selector: { + list: '.tab-content li', + }, + tag: 11, + name: '新闻封面 - 研工部', + }, + all: { + selector: { + list: '.tab-content li', + }, + tag: 12, + name: '文章列表', + }, + bszs_zszt: { + selector: { + list: '.mainleft_box li', + }, + tag: 2, + name: '博士招生 - 招生专题', + }, + sszs_zszt: { + selector: { + list: '.mainleft_box li', + }, + tag: 3, + name: '硕士招生 - 招生专题', + }, + zsjz_zszt: { + selector: { + list: '.mainleft_box li', + }, + tag: 4, + name: '招生简章 - 招生专题', + }, + zcfg_zszt: { + selector: { + list: '.mainleft_box li', + }, + tag: 5, + name: '政策法规 - 招生专题', + }, +}; + +const getItem = (item, selector) => { + const newsInfo = item.find('a'); + const newsDate = item + .find('span') + .text() + .match(/\d{4}(-|\/|.)\d{1,2}\1\d{1,2}/)[0]; + + const infoTitle = newsInfo.text(); + const link = rootURL + newsInfo.attr('href'); + return cache.tryGet(link, async () => { + const resp = await ofetch(link); + const $$ = load(resp); + const infoText = $$(selector).html(); + + return { + title: infoTitle, + pubDate: parseDate(newsDate), + link, + description: infoText, + }; + }) as any; +}; + +export const route: Route = { + path: '/gs/:type?', + categories: ['university'], + example: '/bjtu/gs/noti', + parameters: { type: 'Article type' }, + features: { + requireConfig: false, + requirePuppeteer: false, + antiCrawler: true, + supportBT: false, + supportPodcast: false, + supportScihub: false, + }, + radar: [ + { + source: ['gs.bjtu.edu.cn'], + }, + ], + name: '研究生院', + maintainers: ['E1nzbern'], + handler, + description: ` + | 文章来源 | 参数 | + | ----------------- | ------------ | + | 通知公告_招生 | noti_zs | + | 通知公告 | noti | + | 新闻动态 | news | + | 招生宣传 | zsxc | + | 培养 | py | + | 招生 | zs | + | 学位 | xw | + | 研工部 | ygb | + | 通知公告 - 研工部 | ygbtzgg | + | 新闻动态 - 研工部 | ygbnews | + | 新闻封面 - 研工部 | ygbnewscover | + | 文章列表 | all | + | 博士招生 - 招生专题 | bszs_zszt | + | 硕士招生 - 招生专题 | sszs_zszt | + | 招生简章 - 招生专题 | zsjz_zszt | + | 政策法规 - 招生专题 | zcfg_zszt | + + :::tip 文章来源 + 文章来源的命名均来自研究生院网站标题。 + 最常用的几项有“通知公告_招生”、“通知公告”、“博士招生 - 招生专题”、“硕士招生 - 招生专题”。 + :::`, +}; + +async function handler(ctx) { + const { type = 'noti' } = ctx.req.param(); + let url = urlCms; + let selectorArticle = 'div.main_left.main_left_list'; + if (zsztRegex.test(type)) { + url = urlZszt; + selectorArticle = 'div.mainleft_box'; + } + const urlAddr = `${url}${struct[type].tag}`; + const resp = await ofetch(urlAddr); + const $ = load(resp); + + const list = $(struct[type].selector.list); + + const items = await Promise.all( + list.toArray().map((i) => { + const item = $(i); + return getItem(item, selectorArticle); + }) + ); + + return { + title: `${struct[type].name}${title}`, + link: urlAddr, + item: items, + allowEmpty: true, + }; +} diff --git a/lib/routes/bjtu/namespace.ts b/lib/routes/bjtu/namespace.ts new file mode 100644 index 00000000000000..74f3a9a242c099 --- /dev/null +++ b/lib/routes/bjtu/namespace.ts @@ -0,0 +1,8 @@ +import type { Namespace } from '@/types'; +export const namespace: Namespace = { + name: 'Beijing Jiaotong University', + url: 'bjtu.edu.cn', + zh: { + name: '北京交通大学', + }, +}; diff --git a/lib/routes/dockerhub/build.ts b/lib/routes/dockerhub/build.ts index ebbc86d8a0636f..3b3d432b18d9c9 100644 --- a/lib/routes/dockerhub/build.ts +++ b/lib/routes/dockerhub/build.ts @@ -4,7 +4,7 @@ import { hash } from './utils'; export const route: Route = { path: '/build/:owner/:image/:tag?', - categories: ['program-update'], + categories: ['program-update', 'popular'], example: '/dockerhub/build/wangqiru/ttrss', parameters: { owner: 'Image owner', image: 'Image name', tag: 'Image tag,default to latest' }, features: { diff --git a/lib/routes/douban/other/group.ts b/lib/routes/douban/other/group.ts index d7105995112bfb..5360275fdd4e01 100644 --- a/lib/routes/douban/other/group.ts +++ b/lib/routes/douban/other/group.ts @@ -5,7 +5,7 @@ import { load } from 'cheerio'; export const route: Route = { path: '/group/:groupid/:type?', - categories: ['social-media'], + categories: ['social-media', 'popular'], example: '/douban/group/648102', parameters: { groupid: '豆瓣小组的 id', type: '缺省 最新,essence 最热,elite 精华' }, features: { diff --git a/lib/routes/github/issue.ts b/lib/routes/github/issue.ts index 6f39650c9360d6..1d6eb384acb53c 100644 --- a/lib/routes/github/issue.ts +++ b/lib/routes/github/issue.ts @@ -11,7 +11,7 @@ import { parseDate } from '@/utils/parse-date'; export const route: Route = { path: '/issue/:user/:repo/:state?/:labels?', - categories: ['programming'], + categories: ['programming', 'popular'], example: '/github/issue/vuejs/core/all/wontfix', parameters: { user: 'GitHub username', repo: 'GitHub repo name', state: 'the state of the issues. Can be either `open`, `closed`, or `all`. Default: `open`.', labels: 'a list of comma separated label names' }, radar: [ diff --git a/lib/routes/instagram/private-api/index.ts b/lib/routes/instagram/private-api/index.ts index b42a8beda7752c..137c873f696762 100644 --- a/lib/routes/instagram/private-api/index.ts +++ b/lib/routes/instagram/private-api/index.ts @@ -58,7 +58,7 @@ async function loadContent(category, nameOrId, tryGet) { export const route: Route = { path: '/:category/:key', - categories: ['social-media'], + categories: ['social-media', 'popular'], example: '/instagram/user/stefaniejoosten', parameters: { category: 'Feed category, see table above', key: 'Username / Hashtag name' }, features: { diff --git a/lib/routes/javbus/index.ts b/lib/routes/javbus/index.ts index 37ed73efa21bd7..c2ff9015ff2d05 100644 --- a/lib/routes/javbus/index.ts +++ b/lib/routes/javbus/index.ts @@ -20,17 +20,18 @@ const toSize = (raw) => { const allowDomain = new Set(['javbus.com', 'javbus.org', 'javsee.icu', 'javsee.one']); export const route: Route = { - path: '*', + path: '/:path{.+}?', radar: [ { - source: ['www.seejav.pw/'], - target: '', + source: ['www.javbus.com/:path*'], + target: '/:path', }, ], - name: 'Unknown', - maintainers: [], + name: 'Works', + maintainers: ['MegrezZhu', 'CoderTonyChan', 'nczitzk', 'Felix2yu'], + categories: ['multimedia', 'popular'], handler, - url: 'www.seejav.pw/', + url: 'www.javbus.com', }; async function handler(ctx) { diff --git a/lib/routes/jike/topic.ts b/lib/routes/jike/topic.ts index d1b84bd0b91520..88382b42e580e7 100644 --- a/lib/routes/jike/topic.ts +++ b/lib/routes/jike/topic.ts @@ -9,7 +9,7 @@ const urlRegex = /(https?:\/\/[^\s"'<>]+)/g; export const route: Route = { path: '/topic/:id/:showUid?', - categories: ['social-media'], + categories: ['social-media', 'popular'], example: '/jike/topic/556688fae4b00c57d9dd46ee', parameters: { id: '圈子 id, 可在即刻 web 端圈子页或 APP 分享出来的圈子页 URL 中找到', showUid: '是否在内容中显示用户信息,设置为 1 则开启' }, features: { diff --git a/lib/routes/jike/user.ts b/lib/routes/jike/user.ts index 42441a9ac0925c..d2736d10e806f4 100644 --- a/lib/routes/jike/user.ts +++ b/lib/routes/jike/user.ts @@ -5,7 +5,7 @@ import { parseDate } from '@/utils/parse-date'; export const route: Route = { path: '/user/:id', - categories: ['social-media'], + categories: ['social-media', 'popular'], example: '/jike/user/3EE02BC9-C5B3-4209-8750-4ED1EE0F67BB', parameters: { id: '用户 id, 可在即刻分享出来的单条动态页点击用户头像进入个人主页,然后在个人主页的 URL 中找到,或者在单条动态页使用 RSSHub Radar 插件' }, features: { diff --git a/lib/routes/lofter/user.ts b/lib/routes/lofter/user.ts index 65cc415f051356..a9f0a6dc1b8db0 100644 --- a/lib/routes/lofter/user.ts +++ b/lib/routes/lofter/user.ts @@ -6,7 +6,7 @@ import { isValidHost } from '@/utils/valid-host'; export const route: Route = { path: '/user/:name?', - categories: ['social-media'], + categories: ['social-media', 'popular'], example: '/lofter/user/i', parameters: { name: 'Lofter user name, can be found in the URL' }, features: { diff --git a/lib/routes/pixiv/ranking.ts b/lib/routes/pixiv/ranking.ts index 2b231df377e318..4c70dd3d3a0d53 100644 --- a/lib/routes/pixiv/ranking.ts +++ b/lib/routes/pixiv/ranking.ts @@ -60,7 +60,7 @@ const alias = { export const route: Route = { path: '/ranking/:mode/:date?', - categories: ['social-media'], + categories: ['social-media', 'popular'], example: '/pixiv/ranking/week', parameters: { mode: 'rank type', date: 'format: `2018-4-25`' }, features: { diff --git a/lib/routes/pixiv/search.ts b/lib/routes/pixiv/search.ts index 8d9dda5fa73b0b..3823ae1d023397 100644 --- a/lib/routes/pixiv/search.ts +++ b/lib/routes/pixiv/search.ts @@ -10,7 +10,7 @@ import ConfigNotFoundError from '@/errors/types/config-not-found'; export const route: Route = { path: '/search/:keyword/:order?/:mode?', - categories: ['social-media'], + categories: ['social-media', 'popular'], example: '/pixiv/search/Nezuko/popular/2', parameters: { keyword: 'keyword', order: 'rank mode, empty or other for time order, popular for popular order', mode: 'filte R18 content' }, features: { diff --git a/lib/routes/pixiv/user.ts b/lib/routes/pixiv/user.ts index 08243ad2e38c33..2678c1aa85c06a 100644 --- a/lib/routes/pixiv/user.ts +++ b/lib/routes/pixiv/user.ts @@ -9,7 +9,7 @@ import ConfigNotFoundError from '@/errors/types/config-not-found'; export const route: Route = { path: '/user/:id', - categories: ['social-media'], + categories: ['social-media', 'popular'], example: '/pixiv/user/15288095', parameters: { id: "user id, available in user's homepage URL" }, features: { diff --git a/lib/routes/rsshub/routes.ts b/lib/routes/rsshub/routes.ts index 26e4cb9af04814..f755d8de2e824a 100644 --- a/lib/routes/rsshub/routes.ts +++ b/lib/routes/rsshub/routes.ts @@ -4,7 +4,7 @@ import { load } from 'cheerio'; export const route: Route = { path: '/routes/:lang?', - categories: ['program-update'], + categories: ['program-update', 'popular'], example: '/rsshub/routes/en', parameters: { lang: 'Language, `zh` means Chinese docs, other values or null means English docs, `en` by default' }, radar: [ diff --git a/lib/routes/sehuatang/user.ts b/lib/routes/sehuatang/user.ts index 7046f2f933e64a..26dd329f21cb56 100644 --- a/lib/routes/sehuatang/user.ts +++ b/lib/routes/sehuatang/user.ts @@ -11,7 +11,7 @@ const baseUrl = 'https://sehuatang.org/'; export const route: Route = { path: '/user/:uid', - categories: ['multimedia'], + categories: ['multimedia', 'popular'], example: '/sehuatang/user/411096', parameters: { uid: '用户 uid, 可在用户主页 URL 中找到' }, features: { diff --git a/lib/routes/swjtu/gsee/yjs.ts b/lib/routes/swjtu/gsee/yjs.ts new file mode 100644 index 00000000000000..4c747778c3815e --- /dev/null +++ b/lib/routes/swjtu/gsee/yjs.ts @@ -0,0 +1,76 @@ +import { Route } from '@/types'; +import cache from '@/utils/cache'; +import ofetch from '@/utils/ofetch'; +import { load } from 'cheerio'; +import { parseDate } from '@/utils/parse-date'; + +const rootURL = 'https://gsee.swjtu.edu.cn'; +const urlAddr = `${rootURL}/xwzx/tzgg.htm`; + +const getItem = (item) => { + const newsInfo = item.find('dt'); + const newsDate = item + .find('dd') + .text() + .match(/\d{4}(-|\/|.)\d{1,2}\1\d{1,2}/)[0]; + + const infoTitle = newsInfo.text(); + const link = rootURL + newsInfo.find('a').last().attr('href').slice(2); + return cache.tryGet(link, async () => { + const resp = await ofetch(link); + const $$ = load(resp); + const infoText = $$('.article').html(); + + return { + title: infoTitle, + pubDate: parseDate(newsDate), + link, + description: infoText, + }; + }) as any; +}; + +export const route: Route = { + path: '/gsee/yjs', + categories: ['university'], + example: '/swjtu/gsee/yjs', + parameters: {}, + features: { + requireConfig: false, + requirePuppeteer: false, + antiCrawler: true, + supportBT: false, + supportPodcast: false, + supportScihub: false, + }, + radar: [ + { + source: ['gsee.swjtu.edu.cn/'], + }, + ], + name: '地球科学与工程学院', + maintainers: ['E1nzbern'], + handler, + description: `研究生教育通知公告`, +}; + +async function handler() { + const resp = await ofetch(urlAddr); + const $ = load(resp); + + const list = $('dl'); + + const items = await Promise.all( + list.toArray().map((i) => { + const item = $(i); + return getItem(item); + }) + ); + + return { + title: '西南交大地学学院-研究生通知', + link: urlAddr, + item: items, + allowEmpty: true, + }; +} diff --git a/lib/routes/telegram/channel.ts b/lib/routes/telegram/channel.ts index ea7c3bdfa8c561..b36b5670537129 100644 --- a/lib/routes/telegram/channel.ts +++ b/lib/routes/telegram/channel.ts @@ -57,7 +57,7 @@ const mediaTagDict = { export const route: Route = { path: '/channel/:username/:routeParams?', - categories: ['social-media'], + categories: ['social-media', 'popular'], example: '/telegram/channel/awesomeDIYgod/searchQuery=twitter', parameters: { username: 'channel username', routeParams: 'extra parameters, see the table below' }, features: { diff --git a/lib/routes/twitter/api/developer-api/search.ts b/lib/routes/twitter/api/developer-api/search.ts index 5a9fc81b47ee1d..484b93cd115b41 100644 --- a/lib/routes/twitter/api/developer-api/search.ts +++ b/lib/routes/twitter/api/developer-api/search.ts @@ -13,7 +13,7 @@ const handler = async (ctx) => { return { title: `Twitter Keyword - ${keyword}`, - link: `https://twitter.com/search?q=${encodeURIComponent(keyword)}`, + link: `https://x.com/search?q=${encodeURIComponent(keyword)}`, item: utils.ProcessFeed(ctx, { data: data.statuses, }), diff --git a/lib/routes/twitter/api/developer-api/user.ts b/lib/routes/twitter/api/developer-api/user.ts index 2d94a7165533f6..94954de30d982b 100644 --- a/lib/routes/twitter/api/developer-api/user.ts +++ b/lib/routes/twitter/api/developer-api/user.ts @@ -27,7 +27,7 @@ const handler = async (ctx) => { return { title: `Twitter @${userInfo.name}`, - link: `https://twitter.com/${screen_name}`, + link: `https://x.com/${screen_name}`, image: profileImageUrl, description: userInfo.description, item: utils.ProcessFeed(ctx, { diff --git a/lib/routes/twitter/api/mobile-api/api.ts b/lib/routes/twitter/api/mobile-api/api.ts index 199f21c6e217a8..1d6d26cb38af47 100644 --- a/lib/routes/twitter/api/mobile-api/api.ts +++ b/lib/routes/twitter/api/mobile-api/api.ts @@ -28,7 +28,7 @@ const twitterGot = async (url, params) => { connection: 'keep-alive', 'content-type': 'application/json', 'x-twitter-active-user': 'yes', - authority: 'api.twitter.com', + authority: 'api.x.com', 'accept-encoding': 'gzip', 'accept-language': 'en-US,en;q=0.9', accept: '*/*', diff --git a/lib/routes/twitter/api/mobile-api/constants.ts b/lib/routes/twitter/api/mobile-api/constants.ts index c4bedb05fb169c..cd9b92bbbf36a4 100644 --- a/lib/routes/twitter/api/mobile-api/constants.ts +++ b/lib/routes/twitter/api/mobile-api/constants.ts @@ -1,4 +1,4 @@ -const baseUrl = 'https://api.twitter.com'; +const baseUrl = 'https://api.x.com'; const consumerKey = '3nVuSoBZnx6U4vzUxf5w'; const consumerSecret = 'Bcs59EFbbsdF6Sl9Ng71smgStWEGwXXKSjYvPVt7qys'; diff --git a/lib/routes/twitter/api/mobile-api/login.ts b/lib/routes/twitter/api/mobile-api/login.ts index fe7feb9a3cc2f0..3bf1ac688fff5f 100644 --- a/lib/routes/twitter/api/mobile-api/login.ts +++ b/lib/routes/twitter/api/mobile-api/login.ts @@ -51,7 +51,7 @@ async function login() { headers['x-guest-token'] = guestToken.data.guest_token; const task1 = await ofetch.raw( - 'https://api.twitter.com/1.1/onboarding/task.json?' + + 'https://api.x.com/1.1/onboarding/task.json?' + new URLSearchParams({ flow_name: 'login', api_version: '1', @@ -84,7 +84,7 @@ async function login() { headers.att = task1.headers.get('att'); - const task2 = await got.post('https://api.twitter.com/1.1/onboarding/task.json', { + const task2 = await got.post('https://api.x.com/1.1/onboarding/task.json', { headers, json: { flow_token: task1._data.flow_token, @@ -102,7 +102,7 @@ async function login() { }); logger.debug('Twitter login 3 finished: LoginEnterUserIdentifier.'); - const task3 = await got.post('https://api.twitter.com/1.1/onboarding/task.json', { + const task3 = await got.post('https://api.x.com/1.1/onboarding/task.json', { headers, json: { flow_token: task2.data.flow_token, @@ -119,7 +119,7 @@ async function login() { }); logger.debug('Twitter login 4 finished: LoginEnterPassword.'); - const task4 = await got.post('https://api.twitter.com/1.1/onboarding/task.json', { + const task4 = await got.post('https://api.x.com/1.1/onboarding/task.json', { headers, json: { flow_token: task3.data.flow_token, @@ -142,7 +142,7 @@ async function login() { } else if (subtask.subtask_id === 'LoginTwoFactorAuthChallenge') { const token = authenticator.generate(authenticationSecret); - const task5 = await got.post('https://api.twitter.com/1.1/onboarding/task.json', { + const task5 = await got.post('https://api.x.com/1.1/onboarding/task.json', { headers, json: { flow_token: task4.data.flow_token, diff --git a/lib/routes/twitter/api/web-api/constants.ts b/lib/routes/twitter/api/web-api/constants.ts index f0500752ea5b47..dc4a2f2a80b55f 100644 --- a/lib/routes/twitter/api/web-api/constants.ts +++ b/lib/routes/twitter/api/web-api/constants.ts @@ -1,4 +1,4 @@ -const baseUrl = 'https://twitter.com/i/api'; +const baseUrl = 'https://x.com/i/api'; const graphQLEndpointsPlain = [ '/graphql/eS7LO5Jy3xgmd3dbL044EA/UserTweets', diff --git a/lib/routes/twitter/api/web-api/utils.ts b/lib/routes/twitter/api/web-api/utils.ts index 7cf210f5b84c31..20bdd99633906c 100644 --- a/lib/routes/twitter/api/web-api/utils.ts +++ b/lib/routes/twitter/api/web-api/utils.ts @@ -23,7 +23,7 @@ export const twitterGot = async (url, params) => { url: `${url}?${queryString.stringify(params)}`, method: 'GET', headers: { - authority: 'twitter.com', + authority: 'x.com', accept: '*/*', 'accept-language': 'en-US,en;q=0.9', authorization: bearerToken, @@ -32,7 +32,7 @@ export const twitterGot = async (url, params) => { cookie: config.twitter.cookie, dnt: '1', pragma: 'no-cache', - referer: 'https://twitter.com/narendramodi', + referer: 'https://x.com/narendramodi', 'x-csrf-token': jsonCookie.ct0, 'x-twitter-active-user': 'yes', 'x-twitter-auth-type': 'OAuth2Session', diff --git a/lib/routes/twitter/home.ts b/lib/routes/twitter/home.ts index 4b8b1254c9c7b9..f666a2e191a3ce 100644 --- a/lib/routes/twitter/home.ts +++ b/lib/routes/twitter/home.ts @@ -32,7 +32,7 @@ export const route: Route = { handler, radar: [ { - source: ['twitter.com/home'], + source: ['x.com/home'], target: '/home', }, ], @@ -51,7 +51,7 @@ async function handler(ctx) { return { title: `Twitter following timeline`, - link: `https://twitter.com/home`, + link: `https://x.com/home`, // description: userInfo?.description, item: utils.ProcessFeed(ctx, { data, diff --git a/lib/routes/twitter/keyword.ts b/lib/routes/twitter/keyword.ts index 2954a0ab6b5cdb..d458989879123e 100644 --- a/lib/routes/twitter/keyword.ts +++ b/lib/routes/twitter/keyword.ts @@ -4,7 +4,7 @@ import utils from './utils'; export const route: Route = { path: '/keyword/:keyword/:routeParams?', - categories: ['social-media'], + categories: ['social-media', 'popular'], example: '/twitter/keyword/RSSHub', parameters: { keyword: 'keyword', routeParams: 'extra parameters, see the table above' }, features: { @@ -33,7 +33,7 @@ export const route: Route = { handler, radar: [ { - source: ['twitter.com/search'], + source: ['x.com/search'], }, ], }; @@ -45,7 +45,7 @@ async function handler(ctx) { return { title: `Twitter Keyword - ${keyword}`, - link: `https://twitter.com/search?q=${encodeURIComponent(keyword)}`, + link: `https://x.com/search?q=${encodeURIComponent(keyword)}`, item: utils.ProcessFeed(ctx, { data, }), diff --git a/lib/routes/twitter/likes.ts b/lib/routes/twitter/likes.ts index 27d1c013f96a25..b14677d3996531 100644 --- a/lib/routes/twitter/likes.ts +++ b/lib/routes/twitter/likes.ts @@ -38,7 +38,7 @@ async function handler(ctx) { return { title: `Twitter Likes - ${id}`, - link: `https://twitter.com/${id}/likes`, + link: `https://x.com/${id}/likes`, item: utils.ProcessFeed(ctx, { data, }), diff --git a/lib/routes/twitter/list.ts b/lib/routes/twitter/list.ts index 645c17c0cc8018..af1250c0531855 100644 --- a/lib/routes/twitter/list.ts +++ b/lib/routes/twitter/list.ts @@ -33,7 +33,7 @@ export const route: Route = { handler, radar: [ { - source: ['twitter.com/i/lists/:id'], + source: ['x.com/i/lists/:id'], target: '/list/:id', }, ], @@ -49,7 +49,7 @@ async function handler(ctx) { return { title: `Twitter List - ${id}`, - link: `https://twitter.com/i/lists/${id}`, + link: `https://x.com/i/lists/${id}`, item: utils.ProcessFeed(ctx, { data, }), diff --git a/lib/routes/twitter/media.ts b/lib/routes/twitter/media.ts index c43ad10c289f7d..979160dcf5ad9b 100644 --- a/lib/routes/twitter/media.ts +++ b/lib/routes/twitter/media.ts @@ -4,7 +4,7 @@ import utils from './utils'; export const route: Route = { path: '/media/:id/:routeParams?', - categories: ['social-media'], + categories: ['social-media', 'popular'], example: '/twitter/media/DIYgod', parameters: { id: 'username; in particular, if starts with `+`, it will be recognized as a [unique ID](https://github.com/DIYgod/RSSHub/issues/12221), e.g. `+44196397`', routeParams: 'extra parameters, see the table above.' }, features: { @@ -33,7 +33,7 @@ export const route: Route = { handler, radar: [ { - source: ['twitter.com/:id/media'], + source: ['x.com/:id/media'], target: '/media/:id', }, ], @@ -51,7 +51,7 @@ async function handler(ctx) { return { title: `Twitter @${userInfo?.name}`, - link: `https://twitter.com/${userInfo?.screen_name}/media`, + link: `https://x.com/${userInfo?.screen_name}/media`, image: profileImageUrl.replace(/_normal.jpg$/, '.jpg'), description: userInfo?.description, item: utils.ProcessFeed(ctx, { diff --git a/lib/routes/twitter/namespace.ts b/lib/routes/twitter/namespace.ts index 38f1269e0db080..6ef292d9273ba3 100644 --- a/lib/routes/twitter/namespace.ts +++ b/lib/routes/twitter/namespace.ts @@ -1,8 +1,8 @@ import type { Namespace } from '@/types'; export const namespace: Namespace = { - name: 'Twitter', - url: 'twitter.com', + name: 'X (Twitter)', + url: 'x.com', description: `Specify options (in the format of query string) in parameter \`routeParams\` to control some extra features for Tweets | Key | Description | Accepts | Defaults to | diff --git a/lib/routes/twitter/trends.ts b/lib/routes/twitter/trends.ts index 37d28812d45731..5bfb1d56e1310c 100644 --- a/lib/routes/twitter/trends.ts +++ b/lib/routes/twitter/trends.ts @@ -32,7 +32,7 @@ async function handler(ctx) { return { title: `Twitter Trends on ${data[0].locations[0].name}`, - link: `https://twitter.com/i/trends`, + link: `https://x.com/i/trends`, item: trends .filter((t) => !t.promoted_content) .map((t) => ({ diff --git a/lib/routes/twitter/tweet.ts b/lib/routes/twitter/tweet.ts index 1883869ce5392c..d921e2dc25d892 100644 --- a/lib/routes/twitter/tweet.ts +++ b/lib/routes/twitter/tweet.ts @@ -57,7 +57,7 @@ async function handler(ctx) { return { title: `Twitter @${userInfo.name}`, - link: `https://twitter.com/${userInfo.screen_name}/status/${status}`, + link: `https://x.com/${userInfo.screen_name}/status/${status}`, image: profileImageUrl.replace(/_normal.jpg$/, '.jpg'), description: userInfo.description, item, diff --git a/lib/routes/twitter/user.ts b/lib/routes/twitter/user.ts index 6d78b8f152c191..7b35743991f35b 100644 --- a/lib/routes/twitter/user.ts +++ b/lib/routes/twitter/user.ts @@ -4,7 +4,7 @@ import api from './api'; export const route: Route = { path: '/user/:id/:routeParams?', - categories: ['social-media'], + categories: ['social-media', 'popular'], example: '/twitter/user/DIYgod', parameters: { id: 'username; in particular, if starts with `+`, it will be recognized as a [unique ID](https://github.com/DIYgod/RSSHub/issues/12221), e.g. `+44196397`', @@ -42,7 +42,7 @@ export const route: Route = { handler, radar: [ { - source: ['twitter.com/:id'], + source: ['x.com/:id'], target: '/user/:id', }, ], @@ -66,7 +66,7 @@ async function handler(ctx) { return { title: `Twitter @${userInfo?.name}`, - link: `https://twitter.com/${userInfo?.screen_name}`, + link: `https://x.com/${userInfo?.screen_name}`, image: profileImageUrl.replace(/_normal.jpg$/, '.jpg'), description: userInfo?.description, item: utils.ProcessFeed(ctx, { diff --git a/lib/routes/twitter/utils.ts b/lib/routes/twitter/utils.ts index d6a8e3815d6ab8..5bd33ae3e1c7b8 100644 --- a/lib/routes/twitter/utils.ts +++ b/lib/routes/twitter/utils.ts @@ -114,7 +114,7 @@ const ProcessFeed = (ctx, { data = [] }, params = {}) => { let img = ''; if (item.extended_entities) { for (const media of item.extended_entities.media) { - // https://developer.twitter.com/en/docs/tweets/data-dictionary/overview/extended-entities-object + // https://developer.x.com/en/docs/tweets/data-dictionary/overview/extended-entities-object let content = ''; let style = ''; let originalImg; @@ -211,7 +211,7 @@ const ProcessFeed = (ctx, { data = [] }, params = {}) => { } if (readable) { - quote += ``; + quote += ``; } if (showQuotedAuthorAvatarInDesc) { @@ -244,7 +244,7 @@ const ProcessFeed = (ctx, { data = [] }, params = {}) => { quoteInTitle += `${author.name}: ${formatText(quoteData)}`; if (readable) { - quote += `
Link:
https://twitter.com/${ + quote += `
Link:
https://x.com/${ author.screen_name }/status/${quoteData.id_str || quoteData.conversation_id_str}`; } @@ -298,7 +298,7 @@ const ProcessFeed = (ctx, { data = [] }, params = {}) => { if (showAuthorInDesc) { if (readable) { description += ''; - description += ``; + description += ``; } if (authorNameBold) { description += ``; @@ -316,7 +316,7 @@ const ProcessFeed = (ctx, { data = [] }, params = {}) => { if (!showAuthorInDesc) { description += ' '; if (readable) { - description += ``; + description += ``; } if (authorNameBold) { description += ``; @@ -336,7 +336,7 @@ const ProcessFeed = (ctx, { data = [] }, params = {}) => { } if (showAuthorInDesc) { if (readable) { - description += ``; + description += ``; } if (showAuthorAvatarInDesc) { @@ -376,14 +376,15 @@ const ProcessFeed = (ctx, { data = [] }, params = {}) => { const authorName = originalItem.user.name; const link = originalItem.user.screen_name && (originalItem.id_str || originalItem.conversation_id_str) - ? `https://twitter.com/${originalItem.user.screen_name}/status/${originalItem.id_str || originalItem.conversation_id_str}` - : `https://twitter.com/${item.user.screen_name}/status/${item.id_str || item.conversation_id_str}`; + ? `https://x.com/${originalItem.user.screen_name}/status/${originalItem.id_str || originalItem.conversation_id_str}` + : `https://x.com/${item.user.screen_name}/status/${item.id_str || item.conversation_id_str}`; return { title, author: authorName, description, pubDate: parseDate(item.created_at), link, + guid: link.replace('x.com', 'twitter.com'), _extra: (isRetweet && { @@ -396,7 +397,7 @@ const ProcessFeed = (ctx, { data = [] }, params = {}) => { (item.is_quote_status && { links: [ { - url: `https://twitter.com/${item.quoted_status?.user?.screen_name}/status/${item.quoted_status?.id_str || item.quoted_status?.conversation_id_str}`, + url: `https://x.com/${item.quoted_status?.user?.screen_name}/status/${item.quoted_status?.id_str || item.quoted_status?.conversation_id_str}`, type: 'quote', }, ], @@ -405,7 +406,7 @@ const ProcessFeed = (ctx, { data = [] }, params = {}) => { item.in_reply_to_status_id_str && { links: [ { - url: `https://twitter.com/${item.in_reply_to_screen_name}/status/${item.in_reply_to_status_id_str}`, + url: `https://x.com/${item.in_reply_to_screen_name}/status/${item.in_reply_to_status_id_str}`, type: 'reply', }, ], diff --git a/lib/routes/weibo/keyword.ts b/lib/routes/weibo/keyword.ts index df8b1b2cd27bab..8eb2619c3bfae2 100644 --- a/lib/routes/weibo/keyword.ts +++ b/lib/routes/weibo/keyword.ts @@ -9,7 +9,7 @@ import { config } from '@/config'; export const route: Route = { path: '/keyword/:keyword/:routeParams?', - categories: ['social-media'], + categories: ['social-media', 'popular'], example: '/weibo/keyword/DIYgod', parameters: { keyword: '你想订阅的微博关键词', routeParams: '额外参数;请参阅上面的说明和表格' }, features: { diff --git a/lib/routes/weibo/user.ts b/lib/routes/weibo/user.ts index 153baaad4fe494..07e508fb876655 100644 --- a/lib/routes/weibo/user.ts +++ b/lib/routes/weibo/user.ts @@ -10,7 +10,7 @@ import { fallback, queryToBoolean } from '@/utils/readable-social'; export const route: Route = { path: '/user/:uid/:routeParams?', - categories: ['social-media'], + categories: ['social-media', 'popular'], example: '/weibo/user/1195230310', parameters: { uid: '用户 id, 博主主页打开控制台执行 `$CONFIG.oid` 获取', routeParams: '额外参数;请参阅上面的说明和表格;特别地,当 `routeParams=1` 时开启微博视频显示' }, features: { diff --git a/lib/routes/xiaoyuzhou/podcast.ts b/lib/routes/xiaoyuzhou/podcast.ts index c208e89d9c951a..d4493aa354d709 100644 --- a/lib/routes/xiaoyuzhou/podcast.ts +++ b/lib/routes/xiaoyuzhou/podcast.ts @@ -5,7 +5,7 @@ import { parseDate } from '@/utils/parse-date'; export const route: Route = { path: '/podcast/:id', - categories: ['multimedia'], + categories: ['multimedia', 'popular'], example: '/xiaoyuzhou/podcast/6021f949a789fca4eff4492c', parameters: { id: '播客id,可以在小宇宙播客的 URL 中找到' }, features: { diff --git a/lib/routes/ximalaya/album.ts b/lib/routes/ximalaya/album.ts index 519d5a7e3cef5b..ffde92729c0213 100644 --- a/lib/routes/ximalaya/album.ts +++ b/lib/routes/ximalaya/album.ts @@ -82,8 +82,8 @@ function judgeTrue(str, ...validStrings) { } export const route: Route = { - path: ['/:type/:id/:all?', '/:type/:id/:all/:shownote?'], - categories: ['multimedia'], + path: ['/:type/:id/:all/:shownote?'], + categories: ['multimedia', 'popular'], example: '/ximalaya/album/299146', parameters: { type: '专辑类型, 通常可以使用 `album`,可在对应专辑页面的 URL 中找到', id: '专辑 id, 可在对应专辑页面的 URL 中找到', all: '是否需要获取全部节目,填入 `1`、`true`、`all` 视为获取所有节目,填入其他则不获取。' }, features: { @@ -99,10 +99,10 @@ export const route: Route = { supportPodcast: true, supportScihub: false, }, - name: '专辑(不输出 ShowNote)', + name: '专辑', maintainers: ['lengthmin', 'jjeejj', 'prnake'], handler, - description: `目前喜马拉雅的 API 只能一集一集的获取各节目上的 ShowNote,会极大的占用系统资源,所以默认为不获取节目的 ShowNote。下方有一个新的路径可选获取 ShowNote。 + description: `目前喜马拉雅的 API 只能一集一集的获取各节目上的 ShowNote,会极大的占用系统资源,所以默认为不获取节目的 ShowNote。 :::warning 专辑类型即 url 中的分类拼音,使用通用分类 \`album\` 通常是可行的,专辑 id 是跟在**分类拼音**后的那个 id, 不要输成某集的 id 了 diff --git a/lib/routes/youtube/user.ts b/lib/routes/youtube/user.ts index 71893c868ded00..e3a3127accd070 100644 --- a/lib/routes/youtube/user.ts +++ b/lib/routes/youtube/user.ts @@ -9,7 +9,7 @@ import ConfigNotFoundError from '@/errors/types/config-not-found'; export const route: Route = { path: '/user/:username/:embed?', - categories: ['social-media'], + categories: ['social-media', 'popular'], example: '/youtube/user/@JFlaMusic', parameters: { username: 'YouTuber username with @', embed: 'Default to embed the video, set to any value to disable embedding' }, features: { diff --git a/lib/routes/zhihu/activities.ts b/lib/routes/zhihu/activities.ts index 9ab887444d219e..ee3738e1cb3c57 100644 --- a/lib/routes/zhihu/activities.ts +++ b/lib/routes/zhihu/activities.ts @@ -5,7 +5,7 @@ import { parseDate } from '@/utils/parse-date'; export const route: Route = { path: '/people/activities/:id', - categories: ['social-media'], + categories: ['social-media', 'popular'], example: '/zhihu/people/activities/diygod', parameters: { id: '作者 id,可在用户主页 URL 中找到' }, features: { diff --git a/lib/types.ts b/lib/types.ts index a45dc653710495..67f20d420bf9b7 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -3,6 +3,7 @@ import type { Context } from 'hono'; // Make sure it's synchronise with scripts/workflow/data.ts // and lib/routes/rsshub/routes.ts type Category = + | 'popular' | 'social-media' | 'new-media' | 'traditional-media' diff --git a/lib/views/error.tsx b/lib/views/error.tsx index 50e724b8f50e43..3d532136aacc78 100644 --- a/lib/views/error.tsx +++ b/lib/views/error.tsx @@ -81,7 +81,7 @@ const Index: FC<{ Telegram channel {' '} and{' '} - + Twitter {' '} to get community support and news. @@ -96,7 +96,7 @@ const Index: FC<{ Telegram 频道 和{' '} - + Twitter {' '} 获取社区支持和新闻。 @@ -115,7 +115,7 @@ const Index: FC<{ telegram channel - + github

diff --git a/lib/views/index.tsx b/lib/views/index.tsx index cc5394000c06e9..9293815af22fd5 100644 --- a/lib/views/index.tsx +++ b/lib/views/index.tsx @@ -176,7 +176,7 @@ const Index: FC<{ debugQuery: string | undefined }> = ({ debugQuery }) => { telegram channel - + github

diff --git a/scripts/workflow/data.ts b/scripts/workflow/data.ts index dcf4cf8ffe5b87..24726828f79818 100644 --- a/scripts/workflow/data.ts +++ b/scripts/workflow/data.ts @@ -1,4 +1,10 @@ export const categories = [ + { + icon: '🌟', + link: '/routes/popular', + en: 'Popular', + zh: '热门', + }, { icon: '💬', link: '/routes/social-media',