Bluesky provider¶
Configuration¶
Use either an existing access token and repository DID, or an identifier/app-password pair:
- module: cb_social_plugin.bluesky
config:
identifier: "publisher.example"
app_password: "${BLUESKY_APP_PASSWORD}"
state_db_path: "/srv/data/social-publications.db"
media_group_wait_seconds: 2
Equivalent direct credentials are access_token + repo. service_url defaults to
https://bsky.social.
Actions and API contracts¶
| Action | Remote operation |
|---|---|
bluesky.create_post |
com.atproto.repo.createRecord |
bluesky.update_post |
com.atproto.repo.putRecord |
bluesky.delete_post |
com.atproto.repo.deleteRecord |
bluesky.upload_blob |
com.atproto.repo.uploadBlob |
bluesky.mirror_telegram_message |
deterministic putRecord mirror |
For app-password authentication the plugin first calls com.atproto.server.createSession and uses
the returned DID as the repository.
Mirror behavior¶
The mirror derives a deterministic AT Protocol record key from the Telegram publication key. Both
initial publication and later edits use putRecord, so a retry targets the same record instead of
creating a new one. The original source creation time is retained across edits.
HTTP links become Bluesky facets. Facet offsets are calculated in UTF-8 bytes, not Python character indexes, so text before a URL may safely contain non-ASCII characters.
Up to four downloaded images are embedded. The mirror currently enforces a 1,000,000-byte limit per
image before upload; with media_required: true, an oversized image fails the action instead of
being omitted.
Limitations¶
- The shared mirror path handles images, not video/GIF uploads.
- The provider-level deterministic record key improves retry behavior, but generic Call Baxter action replay remains fail-closed until complete idempotency/authorization evidence is recorded.
- HTTP/provider errors, including rate limiting, propagate as action failures.