James Griffin 932d7a5f0e
All checks were successful
CI / test (push) Successful in 1m41s
Add PHPUnit test suite, Gitea CI, and fix broken URL pattern
- Add 22 unit tests covering feed parsing, thread rendering, facets,
  needsRefetch staleness windows, and handleConfigureAction
- Add FreshRSS class stubs so tests run without a full FreshRSS install
- Add RSS feed fixture (hockeyviz.com snapshot) and thread API fixture
  for post 3mhtk7awhrp26 (1 root + 2 replies)
- Add Gitea Actions workflow (.gitea/workflows/ci.yml) running on PHP 8.2
- Fix POST_URL_PATTERN: using '#' as PCRE delimiter with '#' inside a
  character class caused PHP to close the pattern early, so no Bluesky
  URL ever matched; switch delimiter to '~'

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 15:41:07 -03:00
2026-03-25 20:50:17 -03:00
2026-03-25 20:50:17 -03:00
2026-03-25 20:50:17 -03:00
2026-03-25 20:50:17 -03:00
2026-03-25 20:50:17 -03:00

Bluesky Threads — FreshRSS Extension

A FreshRSS extension that enriches Bluesky posts in your RSS feeds by fetching the full reply thread and embedded content via the Bluesky public API, collapsing everything into a single article.

Features

  • Fetches full reply threads when a post is first saved, so API sync clients (Fever, GReader, etc.) receive enriched content immediately
  • Automatically refreshes thread content as it ages, with progressively relaxed refresh intervals
  • Renders rich text with working links, mentions, and hashtags
  • Renders all embed types: images, external link cards, quoted posts, and videos
  • No Bluesky account or API credentials required

Installation

  1. Download or clone this repository into FreshRSS's extensions/ directory. The folder must be named xExtension-BlueskyThreads.
  2. In FreshRSS, go to Extensions and enable Bluesky Threads.

Configuration

In the extension settings, you can set Thread depth (default: 10, max: 1000) — how many levels of replies to fetch per post.

How it works

Hooks

Two hooks work in tandem so both the web UI and API sync clients receive enriched content:

  • EntryBeforeInsert — fires once when a new entry is first saved. Fetches the thread immediately and stores the rendered HTML.
  • EntryBeforeDisplay — fires on every web render. Checks if the cached thread is stale; if so, re-fetches and writes the updated HTML back to the database.

Cache & staleness

Thread HTML is cached as JSON files in DATA_PATH/BlueskyThreads/{md5(url)}.json. Staleness is determined by the post's age:

Post age Cache refresh interval
< 1 hour Every 10 minutes
< 24 hours Every 1 hour
< 7 days Every 12 hours
7+ days Never (frozen)

On API failure, the stale cache is served as a fallback.

API endpoints used

All requests go to public.api.bsky.app — no authentication required.

  • Handle resolution: com.atproto.identity.resolveHandle
  • Thread fetch: app.bsky.feed.getPostThread
Description
A FreshRSS extension that enriches Bluesky posts in your RSS feeds by fetching the full reply thread and emb edded content via the Bluesky public API, collapsing everything into a single article.
Readme 118 KiB
Languages
PHP 98.3%
HTML 1.7%