Skip to content

Social publishing plugins

cb-social-plugin packages three independent Call Baxter plugin entry points:

Plugin Native actions Telegram mirror
bluesky create/update/delete post, upload blob bluesky.mirror_telegram_message
mastodon create/update/delete post, upload media mastodon.mirror_telegram_message
x create/update/delete post, upload image x.mirror_telegram_message

Each provider also exposes <provider>.flush_due_media_groups for Telegram albums staged through media_group_wait_seconds.

Provider references:

Shared mirror contract

The mirror layer deliberately follows the existing WordPress operator shape without forcing the three remote protocols into identical semantics:

  • update or message accepts Telegram raw update/message objects.
  • required_hashtag optionally gates publication.
  • dry_run renders the source decision without making a remote request.
  • state_db_path persists (provider, Telegram source) mappings and source versions.
  • media_group_wait_seconds stages Telegram albums before publication.
  • telegram_gateway_factory or telegram_bot_token supplies Telegram file access for images.
  • media_required: true turns otherwise reported media omissions into hard failures.

The initial media contract is image-only. This keeps the mirror deterministic while provider video and GIF APIs have materially different asynchronous/chunked processing models.

Provider-specific behavior

Bluesky

Configuration accepts either access_token + repo, or identifier + app_password. The latter creates an AT Protocol session and uses the returned DID as the repository.

Mirrors derive a stable record key from the Telegram source key and publish with putRecord. Telegram edits therefore update the same AT Protocol record. URL facets are generated with UTF-8 byte offsets, and up to four downloaded images are embedded. The plugin currently enforces a 1,000,000-byte per-image mirror limit before upload.

Mastodon

Configuration requires base_url and a user access_token. Creates use POST /api/v1/statuses with a deterministic Idempotency-Key; Telegram edits use the mapped status ID with the status edit endpoint. Visibility, sensitivity, content warning, and language can be supplied in config or action arguments. Images upload through /api/v2/media.

X

Configuration requires a user access_token; base_url defaults to https://api.x.com. Posts use the v2 create/delete endpoints and images use the v2 media upload endpoint. Current X API post edits are represented as another POST /2/tweets request with edit_options.previous_post_id; the returned post ID becomes the current durable mapping.

edit_policy: native is the default. ignore retains the existing remote post, while replace explicitly deletes and recreates it. Native edits remain subject to X's own eligibility/window rules; replacement remains non-atomic.

Idempotency boundary

Use state_db_path in production. Bluesky has an additional remote safety property because the mirror targets a deterministic record key. Mastodon sends an idempotency key on creates, but remote retention is bounded by the server implementation. X has no create idempotency key in this plugin, so a crash after remote creation but before local mapping persistence can still duplicate a post on retry.