Skip to main content

Declarative thread sync for Slack, Discord, and Bluesky

Project description

thrds

Declarative thread sync for Slack, Discord, and Bluesky.

Given a desired thread state (list of message contents), diffs against existing messages and applies minimal edits/posts/deletes to converge.

Install

pip install thrds            # Core only (zero deps)
pip install thrds[bsky]      # + Bluesky (atproto)

Slack and Discord clients use only stdlib (urllib) and curl subprocess respectively — no extra deps needed.

Usage

from thrds import SlackClient, Thread

slack = SlackClient(token="xoxb-...", channel="C0AQC2VKEJF")
thread = Thread(messages=["OP text", "Reply 1", "Reply 2"])

# Create new thread
result = slack.sync(thread)

# Update existing thread (edits changed messages, appends new, deletes extras)
result = slack.sync(thread, thread_ts="1775516040.743629")

Discord

from thrds import DiscordClient, Thread

discord = DiscordClient(token="your-bot-token", channel_id="1489279547689140505")
thread = Thread(messages=["OP text", "Reply 1", "Reply 2"])
result = discord.sync(thread, thread_id="1490821926288097503")

Bluesky

from thrds import BskyClient, Thread

bsky = BskyClient(handle="you.bsky.social", password="app-password")
thread = Thread(messages=["Root post", "Reply 1"])
result = bsky.sync(thread)

Bluesky doesn't support editing posts — the sync algorithm automatically falls back to delete+repost when content changes.

Dry run

result = slack.sync(thread, thread_ts="...", dry_run=True)
for action in result.actions:
    print(action.type, action.index, action.content)

Sync algorithm

Given desired messages M and existing thread messages N:

  1. Delete extras from the end (backwards — replies before OP)
  2. Edit overlapping messages where content changed (skip unchanged)
  3. Post new messages at the end

This ensures minimal API calls, preserved ordering, and no orphaned thread parents.

Features

  • Rate limit handling: Slack 429 retry with Retry-After, configurable pacing between API calls
  • Edit rate limit fallback: Discord's 30046 error (edit limit on old messages) triggers automatic delete+repost
  • Unfurl suppression: Slack link previews suppressed by default
  • Discord system message filtering: Thread starter messages filtered from list_messages
  • Bot token prefix: Discord Bot prefix auto-prepended
  • Metadata support: Slack message metadata passthrough

Used by

API

SyncResult

@dataclass
class SyncResult:
    thread_id: str          # thread_ts (Slack), thread channel ID (Discord), AT URI (Bluesky)
    message_ids: list[str]  # Per-message IDs
    actions: list[Action]   # What was done: Edit, Post, Delete, Skip

SyncOptions

Option Default Description
dry_run False Print actions without executing
pace 0.0 Seconds between mutating API calls
suppress_embeds False Discord: suppress link previews
suppress_unfurls True Slack: suppress link previews

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

thrds-0.1.2.tar.gz (19.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

thrds-0.1.2-py3-none-any.whl (10.6 kB view details)

Uploaded Python 3

File details

Details for the file thrds-0.1.2.tar.gz.

File metadata

  • Download URL: thrds-0.1.2.tar.gz
  • Upload date:
  • Size: 19.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for thrds-0.1.2.tar.gz
Algorithm Hash digest
SHA256 c9d8611e776541dece5f3f80ed84317e3a76883ae1eae43a4f9dfbcf51c06f3d
MD5 2cdec68f4420cc369bd6b22f58f42a63
BLAKE2b-256 81e685194028e80775ec9ad961fddee413c2c146ec9cbee3223945ea6ba335af

See more details on using hashes here.

Provenance

The following attestation bundles were made for thrds-0.1.2.tar.gz:

Publisher: release.yml on runsascoded/thrds

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file thrds-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: thrds-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 10.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for thrds-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 1ad5bea669465535f987733e893a08a1e2198c085652ddbd023d57ea6a086e15
MD5 6b2a287373e568d6b6054df8cfc74e47
BLAKE2b-256 39f7be1cdd790c7e531b01e48edb42ba3b387b7a87b369d848819679abdb2ff8

See more details on using hashes here.

Provenance

The following attestation bundles were made for thrds-0.1.2-py3-none-any.whl:

Publisher: release.yml on runsascoded/thrds

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page