* feat: add shanxi museum temporary exhibition route
* chore: trigger ci
* fix: remove pubDate if no return information
* fix: remove redundancy
* fix:fix the timezone error and refactor the resData and list
* fix: remove ! check for imgurl
* fix: remove empty message and add trycatch
* feat(route/sjtu): add CS school academic activities
* refactor(route/sjtu/cs/xshd): use JSX for description and respect dedicated item fields
- Switch to .tsx with renderToString (Rule 25)
- Move 时间→pubDate (with HH:mm), 报告人→author, 封面→image (Rule 11)
- Drop hand-written referrerpolicy attributes (Rule 39)
- pubDate now preserves hour/minute when source provides it
* fix(route/sjtu/cs/xshd): separate publish date from event time
- pubDate now reflects announcement publish date:
- in-site articles: detail page 发布日期 (authoritative)
- WeChat-redirect items: extracted from image URL path /upload/image/YYYYMMDD/
- 举办时间 (event time) moved back into description (no longer duplicates pubDate)
* fix(route/sjtu/cs/xshd): remove manual title trimming (Rule 16)
* fix(route/sjtu/cs/xshd): address review comments
- Use response URL to detect WeChat redirect
- Fetch WeChat MP content via fetchArticle
- Remove try-catch around detail requests
- Remove dangerouslySetInnerHTML from JSX rendering
* fix(route/sjtu/cs/xshd): use ofetch consistently
* fix(route/sjtu/cs/xshd): fallback on WeChat MP WAF errors
* fix(route/sjtu/cs/xshd): fallback when detail enrichment fails
The route enriches list items by fetching detail pages, but some SJTU
detail URLs are redirect stubs to WeChat MP. In CI, those intermediate
detail requests can fail with no response before the route reaches the
WeChat MP parser, causing Promise.all to reject and the whole feed to
return 503.
Switch detail enrichment aggregation from Promise.all to
Promise.allSettled and fall back to list-page metadata for only the
failed item. Successful items are still enriched with in-site article
content or WeChat MP content.
This follows the existing resilient detail-fetching pattern in
lib/routes/usenix/usenix.ts and keeps the scoped WeChatMpError fallback
around fetchArticle(), similar to lib/routes/wechat/sogou.ts.
* feat(route): add the Palace Museum route
* fix: fix trailing space, array and radar target
* fix: fix array
* fix: follow rule22
* refactor(dpm): migrate exhibitions route to JSX format (.tsx)
* fix(dpm): use arrow function in cheerio filter
* fix: update example
* fix: remove redundancy and fix error for endDate and fullduration
* chore: trigger gh actions retry
* fix: remove trim for fullduration
* fix:remove ! check for imgurl and fullduration
* fix: remove exhibition_item
* feat: add China National Museum exhibition route
* Update route.ts
* Update zl.ts
* Update zl.ts
* Update zl.ts
* fix: refactor to JSX and fix cache import
* fix: refactor to JSX, fix duration and fix import
* fix: replaceAll, if and regualr expression range
* Update zl.ts
* fix: refactor extra output and import namespace
* fix: fix error
* fix: adjust fullduration logic
* feat: refactor route file with type and subtype used
* fix: reduce the complexity
* fix: remove trim() for title
* fix: remove redundancy and fix error
* fix: remove toLowerCase redundancy
* fix: remove trim for title
* fix: Apply suggestions from code review and error fix
Co-authored-by: Tony <TonyRL@users.noreply.github.com>
---------
Here is a page with description-box:
https://www.cna.com.tw/news/aipl/202605070117.aspx
Explanation for the term 憲法第130條 is injected in the middle of a
paragraph and makes that paragraph hard to read. This change fixes that.
* route(gigazine): add English news full-text feed
Adds /gigazine/en route that fetches full article content from
GIGAZINE's English news listing. Uses sequential fetching with
delays to respect Cloudflare rate limits; subsequent loads are
served from cache.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* route(gigazine): improve english feed resilience
* test(gigazine): add english route coverage
* test(gigazine): move route coverage out of route tree
* test(api): cover route status cache fallbacks
* refactor(gigazine): apply PR review feedback to english route
- Use ofetch built-in auto-retry instead of hand-rolled circuit breaker
- Remove config.trueUA; let request-rewriter inject random browser UA
- Simplify Number.parseInt call (drop redundant ?? '' fallback)
- Update tests to match new retry and UA behaviour
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: remove unrelated changes and unnecessary test file
* refactor(gigazine): simplify selectors and cleanup logic per review
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(route): support fulltext mode for nyaa
* feat(route): replace parameter name
* feat(route): migrate from query parameters to route paths
* feat(route): use mode=fulltext as trigger and update namespace
* delete fulltext routes
* feat(route): add /humanlayer/blog route
Add RSS feed for HumanLayer blog (www.humanlayer.dev/blog), scraping
blog listing and full article content with cheerio.
via [HAPI](https://hapi.run)
Co-Authored-By: HAPI <noreply@hapi.run>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor(route): use CSS :not() selector instead of JS filter for humanlayer blog
Address PR review feedback: move /blog/tags/ exclusion into the CSS selector
instead of using a separate .filter() call.
via [HAPI](https://hapi.run)
Co-Authored-By: HAPI <noreply@hapi.run>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(route): extract tags into category field for humanlayer blog
Parse #-prefixed tags from the meta line and populate the category field.
via [HAPI](https://hapi.run)
Co-Authored-By: HAPI <noreply@hapi.run>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(route): address review feedback for humanlayer blog
- Remove redundant :not() selector (tag links use different class)
- Simplify tag extraction from parts.slice(3).join() to parts[3]
- Fix tag regex to match hyphenated tags like best-practices
via [HAPI](https://hapi.run)
Co-Authored-By: HAPI <noreply@hapi.run>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(route): remove custom limit for humanlayer blog, use built-in
via [HAPI](https://hapi.run)
Co-Authored-By: HAPI <noreply@hapi.run>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: HAPI <noreply@hapi.run>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: zj1123581321 <zj1123581321@users.noreply.github.com>
* feat(route): make GitHub pulls title and docs consistent with issues
I'm not really a coder, but I use RSSHub to bridge GitHub updates into IRC for my community. I noticed that the `pulls.ts` route didn't show the "Open/Closed" state in the feed title like the `issues.ts` route does, which was making my users a bit confused!
I tried my best to replicate the logic and metadata structure from `issues.ts` over to `pulls.ts`.
Changes:
- Updated the feed title to dynamically show the state (Open/Closed/All) and any labels.
- Updated the parameter metadata so the documentation looks as clean and organized as the Issues page.
I've tested this locally and it’s working perfectly for my IRC tracker. Hopefully, this helps keep things consistent across the GitHub routes!
Closes#21902
* Fix title formatting in pull request response
* Comment out media object in rss_item
Comment out media object in rss_item construction
* Disable voiceInfo handling in RSS item
Comment out voiceInfo handling logic in RSS item creation.
* Update description extraction to exclude report view
* Refactor description logic in common.tsx
Refactor description extraction to remove specific images and report view paragraphs.
* Handle missing featured image in description logic
* Improve description extraction in common.tsx
Refactor description extraction logic to handle cases without a featured image more cleanly.
* feat(route): add 国际能源网 (in-en.com) news route
Add RSS route for in-en.com (国际能源网), a major Chinese energy news portal.
Supported channels via /in-en/news/:type:
- solar — 光伏太阳能
- wind — 风电
- chuneng — 储能
- h2 — 氢能
- chd — 充换电
- newenergy — 新能源综合
- power — 电力
- huanbao — 环保
Features: fetches article list from each subdomain's news page,
then retrieves full article body via detail page (cached).
Handles Chinese relative timestamps (X分钟/小时/天前).
* fix(in-en): add maintainer, fix timezone double-shift, translate comments to English
* fix(in-en): correct news paths for h2/chd/huanbao, drop date-only pubDate override
* fix(in-en): sort imports, fix numeric separators, add category field, use trueUA
* fix(in-en): address review comments
- Remove config.trueUA, use default UA
- Remove custom parseRelTime, use parseDate directly
- Fix title text extraction without cloning element
- Remove unnecessary .first() on pubDate
- Fix author: handle both em.ly and plain-text source via .prompt > span
- Simplify category field (remove redundant length check)
- Fix description selector: .article-body → #article
- Fix detail author selector: .article-meta .source a → p.source a
- Remove try-catch around detail fetch
* fix(in-en): fix author including category text and handle relative pubDate formats
* fix(in-en): use parseRelativeDate, simplify selectors, drop redundant fallbacks
- Replace hand-rolled relative-date logic with parseRelativeDate (covers
"刚刚 / N分钟前 / N小时前 / 今天 HH:MM / 昨天 HH:MM / YYYY-MM-DD"). Fixes
Invalid Date on the first few entries and resolves the two oxlint findings
(no-useless-undefined, numeric-separators-style).
- Drop the `.first()` on `.listTxt .prompt i` — each `ul.infoList > li` carries
exactly one `<i>` (date), confirmed against https://solar.in-en.com/news/.
- Author selector: `.prompt > span:first-of-type`, then strip leading "来源:".
Cheerio's `.text()` flattens `<em class="ly">…</em>` into the same string,
so this matches both shapes shown on https://solar.in-en.com/news/
(plain text vs. wrapped in em.ly).
- Category selector: `.prompt > span:not(:first-of-type) em a`, scoped to the
second span so author text never leaks in.
- Drop `|| undefined` on author and `?? ''` on description (redundant —
DataItem already accepts undefined).
- Add an HTML-shape comment pointing to the live sample URL so future
reviewers can verify the layout assumptions.
* fix(in-en): drop dead default + use new-media category
- Hono treats `:type` as compulsory (path is `/news/:type`), so users without
it never reach the handler — the `?? 'solar'` fallback was unreachable.
Replace with a non-null assertion to keep the type narrow.
- categories: 'traditional-media' → 'new-media' per review suggestion.
* feat(route/fjrb): add Fujian Daily route and namespace configuration
* feat(route/fjrb): update route to support date parameter and improve error handling
* fix(route/fjrb): standardize root URL constant usage
* fix(route/fjrb): address review comments for Fujian Daily route
* fix(route/fjrb): refactor media source retrieval to use getNodeSrc function
* fix(route/fjrb): update Fujian Daily URL to use the second level domain
* feat(route/fjdaily): add Fujian Daily route and namespace configuration
* fix(route/fjdaily): add Fujian Daily route and namespace configuration
* fix(cache): call JSON.stringify when storing value in cache.tryGet
The value is returned as-is, so we may assume that it's not JSON
stringified inside `getValueFunc`. Otherwise, the caller already needs
to distinguish between values that are either JSON parsed or not.
* Revert "fix(routes/mastodon): don't refresh account ID cache (#20663)"
This reverts commit c2cff410fa.
* test: add test
* test: lint
* feat(route/bilibili): add video-browser route using Puppeteer for video list extraction
Replace broken real-browser API dependency with getPuppeteerPage + browserless
to render Bilibili space pages and extract video data via DOM parsing. Includes
username extraction from page title and cover image detection.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(route/bilibili): fix video title extraction picking stats over actual titles
The candidate selection logic was preferring longer text (e.g. "8.3万23907:45")
over real titles (e.g. "爆肝三天,我总结了 GPT Image 2 全网最实用的玩法")
because stats strings passed the hasTitle check. Now prefer candidates that
contain Chinese characters and don't start with digits, falling back to
longest hasTitle candidate. Fixes 11/35 UIDs returning empty results.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* feat(route/bilibili): add /user/video-browser route using Puppeteer + XHR interception
Close#20406
Bilibili upgraded anti-crawler (WBI signing) on /x/space/wbi/arc/search
in Nov 2025, causing existing /user/video/:uid to return 412.
This new route bypasses it by intercepting the browser's own API response
via Puppeteer, extracting structured JSON data (title, bvid, pic, created
timestamp, author, play/comment counts) instead of fragile DOM scraping.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* feat(route/bilibili): fold browser mode into video route
---------
Co-authored-by: gqy20 <qingyu_ge@foxmail.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>