Social & Community Channels

Social media and community platform integrations.


Reddit

Prerequisites

Reddit runs as an out-of-process Python sidecar adapter (librefang.sidecar.adapters.reddit, ships in librefang-sdk).

Setup

  1. Go to reddit.com/prefs/apps and create a new script application. Note the client ID (shown under the app name) and the client secret.
  2. Open the dashboard Channels page, pick Reddit, and fill the form — the dashboard writes REDDIT_CLIENT_SECRET and REDDIT_PASSWORD to ~/.librefang/secrets.env and the rest of the fields to the [sidecar_channels.env] table in ~/.librefang/config.toml. Equivalent manual config:
[[sidecar_channels]]
name = "reddit"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.reddit"]
channel_type = "reddit"
default_agent = "assistant"
[sidecar_channels.env]
REDDIT_CLIENT_ID = "abc123"
REDDIT_USERNAME = "librefang-bot"
REDDIT_SUBREDDITS = "mysubreddit,rust"
REDDIT_USER_AGENT = "myorg/1.0 (by /u/myactual-reddit-name)"   # REQUIRED, see below
# REDDIT_ACCOUNT_ID = "prod"               # optional, multi-bot routing key
# REDDIT_POLL_INTERVAL_SECS = "30"         # optional, default 30, floor 5

Ban-avoidance — read before going live

Reddit is strict about bot behaviour. The adapter enforces what it can:

  • REDDIT_USER_AGENT is required. Reddit's API rules require the UA to identify a real maintainer (by /u/<your-reddit-handle>). The literal default placeholder is rejected at startup to prevent IP+account bans. Use your own Reddit username.
  • Default 30 s polling. Lower than 5 s burns the 60 req/min/account budget fast. The floor is 5 s; raise REDDIT_POLL_INTERVAL_SECS for less-active subs.
  • Automatic throttling. When Reddit reports X-Ratelimit-Remaining < 10, the poller pre-emptively sleeps until the reset window. A 429 on polling backs off; a 429 on /api/comment honours Retry-After and retries once.

What the adapter cannot enforce — your responsibility:

  • Bot account should be at least 30 days old with >100 comment karma; new accounts get shadowbanned quickly.
  • Get mod approval before joining any subreddit. Reply-bots in unfamiliar subs are a common report-and-ban trigger.
  • Gate triggers via group_trigger_patterns in your agent's config so the bot only replies to /cmd or named-mention — replying to every new comment is the fastest way to a sitewide ban.
  1. Put the two secrets in ~/.librefang/secrets.env:
REDDIT_CLIENT_SECRET=your-client-secret
REDDIT_PASSWORD=your-reddit-password
  1. Restart the daemon.

How It Works

The Reddit sidecar adapter authenticates via OAuth2 (password grant for script-type apps), polls each configured subreddit's new-comments stream every five seconds, and posts replies as comments through POST /api/comment. Reddit allows one comment per parent, so a chunked reply joins with \n\n---\n\n rather than splitting into multiple comments.


Mastodon

Prerequisites

  • A Mastodon account on any instance
  • An application access token (from the instance's Preferences > Development page, see Mastodon API docs)

Mastodon runs as an out-of-process Python sidecar adapter (librefang.sidecar.adapters.mastodon, ships in librefang-sdk).

Setup

  1. On your Mastodon instance, go to Preferences > Development > New Application.
  2. Grant the scopes read and write.
  3. Copy the access token (this becomes MASTODON_ACCESS_TOKEN).
  4. Open the dashboard Channels page, pick Mastodon, and fill the instance URL and access token — the dashboard writes MASTODON_ACCESS_TOKEN to ~/.librefang/secrets.env and MASTODON_INSTANCE_URL to the [sidecar_channels.env] table in ~/.librefang/config.toml. Equivalent manual config:
[[sidecar_channels]]
name = "mastodon"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.mastodon"]
channel_type = "mastodon"
[sidecar_channels.env]
MASTODON_INSTANCE_URL = "https://mastodon.social"
# MASTODON_VISIBILITY = "unlisted"          # public | unlisted | private | direct
# MASTODON_MAX_MESSAGE_LEN = "500"          # raise for higher-limit instances
# MASTODON_ACCOUNT_ID = "prod"              # optional, multi-bot routing
  1. The daemon supervises the sidecar — no manual restart is needed; the kernel's hot-reload spawns or replaces the subprocess on config change.

How It Works

The Mastodon sidecar connects to the instance's user streaming API via Server-Sent Events (SSE) to receive mention notifications in real time. On SSE failure it falls back to REST polling of /api/v1/notifications. Outbound replies are posted as toots via POST /api/v1/statuses with in_reply_to_id chaining so a chunked reply stays as one thread.


Bluesky

Prerequisites

  • A Bluesky account (see Bluesky API docs)
  • An app password (generated in Bluesky Settings > App Passwords)

Bluesky runs as an out-of-process Python sidecar adapter (librefang.sidecar.adapters.bluesky, ships in librefang-sdk).

Setup

  1. In Bluesky, go to Settings > App Passwords and create a new app password.
  2. Add a [[sidecar_channels]] entry:
[[sidecar_channels]]
name = "bluesky"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.bluesky"]
channel_type = "bluesky"
[sidecar_channels.env]
BLUESKY_IDENTIFIER = "your-handle.bsky.social"
# BLUESKY_SERVICE_URL = "https://bsky.social"   # custom PDS
# BLUESKY_ACCOUNT_ID = "prod"                   # optional, multi-bot routing key
  1. Set the app password via the dashboard's Channels page (writes BLUESKY_APP_PASSWORD to ~/.librefang/secrets.env), or place it directly in your vault / .env.
  2. Restart the daemon.

How It Works

The sidecar authenticates with com.atproto.server.createSession and refreshes the session JWT before expiry. It polls app.bsky.notification.listNotifications every 5 s (filtering mention + reply reasons) and posts replies via com.atproto.repo.createRecord using the app.bsky.feed.post lexicon. An in-memory LRU cache (capacity 200) maps inbound notification URIs to their {root, parent} reply refs so outbound responses thread back to the originating post; on a chunked reply every chunk reuses the same reply ref to keep the thread tight.


Twitch

Prerequisites

Twitch runs as an out-of-process Python sidecar adapter (librefang.sidecar.adapters.twitch, ships in librefang-sdk).

Setup

  1. Register an application on the Twitch Developer Console.
  2. Generate an OAuth token with the chat:read and chat:edit scopes (use a tool like twitchtokengenerator.com).
  3. Open the dashboard Channels page, pick Twitch, and fill the form — the dashboard writes TWITCH_OAUTH_TOKEN to ~/.librefang/secrets.env and the rest of the fields to the [sidecar_channels.env] table in ~/.librefang/config.toml. Equivalent manual config:
[[sidecar_channels]]
name = "twitch"
command = "python3"
args = ["-m", "librefang.sidecar.adapters.twitch"]
channel_type = "twitch"
default_agent = "assistant"
[sidecar_channels.env]
TWITCH_NICK = "librefang-bot"
TWITCH_CHANNELS = "channel1,channel2"      # comma-separated, no '#'
# TWITCH_ACCOUNT_ID = "prod"                # optional, multi-bot routing
# TWITCH_RATE_LIMIT_MSGS = "20"             # 20/30s for unmodded; 100 if bot is mod
# TWITCH_RATE_LIMIT_SECS = "30"
  1. Put the OAuth token in ~/.librefang/secrets.env:
TWITCH_OAUTH_TOKEN=oauth:your-token

The oauth: prefix is auto-added if you leave it off. Restart the daemon.

Security — read before going live

  • TLS is the default. The sidecar connects to irc.chat.twitch.tv:6697 and wraps the socket with ssl.create_default_context(). The previous in-process Rust adapter used plaintext port 6667, which leaked the OAuth token on every connect / reconnect — operators upgrading from a pre-migration release immediately get this fix.
  • Per-message reply threading is enabled. The sidecar requests the twitch.tv/tags capability so every inbound PRIVMSG carries an @id tag; outbound replies attach @reply-parent-msg-id=<id> so Twitch renders the bot's response threaded under the source message.
  • Send rate-limiter. Twitch's anti-spam logic drops a non-mod account from chat above 20 msgs / 30 s (100 / 30 s if mod). The sidecar throttles every PRIVMSG through an in-process token bucket. Operators with a mod-status bot can raise via TWITCH_RATE_LIMIT_MSGS=100; multi-process operators should still keep one process per account because the throttle is local-only.

How It Works

The Twitch sidecar adapter holds a persistent TLS IRC connection to irc.chat.twitch.tv:6697, authenticates via PASS oauth:<token> / NICK, requests the twitch.tv/tags twitch.tv/commands capabilities, and joins every configured channel. It parses inbound PRIVMSG frames (including the IRCv3 @-tag block), surfaces the @id tag as thread_id for round-trip threading, dedupes by tag id, and routes /cmd / !cmd lines as Commands. Outbound on_send calls pass through the rate-limit bucket and emit PRIVMSG frames with the reply-parent tag when the daemon supplied a thread_id.