# 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 1. **Clone the repository** ```bash git clone https://git.zio.sh/astra/bsky2tg cd bsky2tg ``` 2. **Build the project** ```bash go build ``` 3. **Set environment variables** ```bash 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:** ```bash 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) ``` 4. **Run the daemon** ```bash ./bsky2tg ``` ## Running with Podman Run the bot in a container using Podman: ### With `.env` file ```bash podman run -it --name bsky2tg_ \ --env-file /path/to/.env \ git.zio.sh/astra/bsky2tg:latest ``` ### With environment variables ```bash podman run -it --name bsky2tg_ \ --env TG_TOKEN= \ --env TG_CHANNEL_ID= \ --env BSKY_HANDLE= \ --env BSKY_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](https://t.me/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 `@userinfobot` to get the channel ID ## Usage ### Daemon Mode The bot runs continuously and syncs new posts in real-time: ```bash ./bsky2tg ``` ### One-Shot Post Sync Send a specific post to Telegram: ```bash ./bsky2tg -post "https://bsky.app/profile/user.bsky/post/abc123" ``` ### Delete a Post Remove a post from Telegram (delete from Bluesky first): ```bash ./bsky2tg -post "https://bsky.app/profile/user.bsky/post/abc123" -delete ``` ### Ignore Old Posts Ignore posts created more than 2 hours ago: ```bash ./bsky2tg -oldposttime 2 ``` ## How It Works 1. **Authentication** - Logs into Bluesky via ATProto and stores the session 2. **Jetstream Connection** - Subscribes to real-time post events from your account 3. **Post Processing** - Parses posts, extracts media, processes facets (links/mentions) 4. **Telegram Delivery** - Sends formatted messages with media to your channel 5. **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_HANDLE` and `BSKY_PASSWORD` are correct - Use an app password, not your main Bluesky password - Check `auth-session.json` file permissions ### Posts not syncing - Ensure the bot is admin in the channel - Check `TG_CHANNEL_ID` is 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