5.1 KiB
bsky2tg
A real-time bridge that forwards Bluesky posts to Telegram. Monitor your Bluesky account and automatically send posts to a Telegram channel with full media support, quote posts, and more.
Features
- 🦋 Real-time sync - Posts appear on Telegram seconds after posting on Bluesky
- 📸 Full media support - Images, videos, GIFs (from Tenor)
- 💬 Quote posts - Properly formatted with links to original posts
- ✏️ Edit support - Updates Telegram message when you edit a Bluesky post
- 🗑️ Delete sync - Removes from Telegram when you delete from Bluesky
- 🔗 Rich links - @mentions, hashtags, and custom aliases converted to clickable links
- ⏰ Time filtering - Ignore old posts and replies if desired
- 🎬 Video metadata - Includes duration, dimensions, and thumbnail
Setup
Prerequisites
- Go 1.21+
- A Bluesky account
- A Telegram bot and channel
Installation
-
Clone the repository
git clone https://git.zio.sh/astra/bsky2tg cd bsky2tg -
Build the project
go build -
Set environment variables
export BSKY_HANDLE="your.bsky.handle" export BSKY_PASSWORD="your-app-password" # NOT your main password export TG_TOKEN="your-telegram-bot-token" export TG_CHANNEL_ID="your-channel-id"Optional:
export TG_API_ENDPOINT="https://api.telegram.org/bot%s/%s" # Custom Telegram API endpoint export OLDPOSTTIME="1" # Ignore posts older than this many hours (default: 1) -
Run the daemon
./bsky2tg
Running with Podman
Run the bot in a container using Podman:
With .env file
podman run -it --name bsky2tg_<profile> \
--env-file /path/to/.env \
git.zio.sh/astra/bsky2tg:latest
With environment variables
podman run -it --name bsky2tg_<profile> \
--env TG_TOKEN=<your-token> \
--env TG_CHANNEL_ID=<your-channel-id> \
--env BSKY_HANDLE=<your.handle> \
--env BSKY_PASSWORD=<your-app-password> \
git.zio.sh/astra/bsky2tg:latest
Getting Your Credentials
Bluesky App Password:
- Go to Settings → Privacy and Security → App Passwords
- Create a new app password (NOT your main Bluesky password)
Telegram Bot Token:
- Message @BotFather on Telegram
- Create a new bot with
/newbot - Copy the token
Telegram Channel ID:
- Create a channel (can also be private)
- Add your bot as an admin
- Use
@userinfobotto get the channel ID
Usage
Daemon Mode
The bot runs continuously and syncs new posts in real-time:
./bsky2tg
One-Shot Post Sync
Send a specific post to Telegram:
./bsky2tg -post "https://bsky.app/profile/user.bsky/post/abc123"
Delete a Post
Remove a post from Telegram (delete from Bluesky first):
./bsky2tg -post "https://bsky.app/profile/user.bsky/post/abc123" -delete
Ignore Old Posts
Ignore posts created more than 2 hours ago:
./bsky2tg -oldposttime 2
How It Works
- Authentication - Logs into Bluesky via ATProto and stores the session
- Jetstream Connection - Subscribes to real-time post events from your account
- Post Processing - Parses posts, extracts media, processes facets (links/mentions)
- Telegram Delivery - Sends formatted messages with media to your channel
- Metadata Storage - Records post mapping (Bluesky → Telegram) for edits/deletes
Configuration
Post Format
Posts are sent with this format:
[Post text with @mentions and #hashtags]
—
🦋 @your.handle
Quote posts include the quoted post above in a blockquote.
Custom Aliases
You can set up custom link replacements by creating entries in the blue.zio.bsky2tg.alias collection on your PDS.
Troubleshooting
Auth errors
- Verify
BSKY_HANDLEandBSKY_PASSWORDare correct - Use an app password, not your main Bluesky password
- Check
auth-session.jsonfile permissions
Posts not syncing
- Ensure the bot is admin in the channel
- Check
TG_CHANNEL_IDis correct - Verify Jetstream connection with logs
Video errors
- FFmpeg must be installed for video processing
- Check that video file can be read
Project Structure
.
├── main.go # Event handler, post processing, Telegram sender
├── bsky/
│ ├── client.go # Bluesky session management, handle resolution
│ ├── bluesky.go # ATProto API calls (posts, records, sessions)
│ └── parse.go # Post parsing, facet processing
├── auth-session.json # Stored auth session (auto-created)
└── README.md # This file
API Integration
- Bluesky ATProto - Session creation, post fetching, record management
- Jetstream - Real-time firehose subscription
- Telegram Bot API - Message/media sending, editing, deleting
Notes
- Auth sessions are persisted in
auth-session.json - Tokens are automatically refreshed when expired
- Posts are deduplicated to prevent duplicates on sync restart
- Media is fetched from your PDS via blob endpoints
License
See LICENSE file