| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Self-hosted Telegram bot that turns forwarded messages into scheduled cross-posts across Buffer (X, LinkedIn, Threads, Bluesky, Mastodon, Facebook, Instagram, …) and Binance Square — with randomised scheduling so a single batch fills weeks of content. Photos, albums, video, inline menu, full CRUD over the queue, publication journal.
See CHANGELOG.md for the full history.
Forward a Telegram post into the bot — it picks a random dueAt in the configured window (default 1–240 hours / up to 10 days) and schedules the post on every enabled Buffer channel + Binance Square. Drop 50 posts at once → you have ~10 days of content auto-pacing itself across all your socials.
flowchart LR
A[You forward a post<br/>in Telegram] --> B{Album?}
B -- yes, 1.5s buffer --> C[Upload photos<br/>imgbb → catbox → 0x0]
B -- no --> C
C --> D[Generate random dueAt<br/>1–240h from now]
D --> E[Buffer GraphQL<br/>createPost]
D --> F[Binance queue<br/>SQLite + Telegram file_ids]
E --> G[X / LinkedIn / Threads<br/>Bluesky / Mastodon / FB / IG / ...]
F --> H[Background scheduler<br/>tick every 60s]
H --> I[Binance Square v2<br/>presignedUrl → PUT → imageStatus → content/add<br/>images: imageList · video: fileTicket]
I --> J[DM you the post URL]
You ▸ [forward post: "GM ☀️ shipping a new feature today"]
Bot ▸ Buffer ⏰ 23 May 2026 14:30 UTC
✅ 🐦 @yourhandle
✅ 💼 LinkedIn — Your Company
✅ 🧵 Threads
✅ 🦋 Bluesky
Binance Square ⏰ 23 May 2026 14:30 UTC
📥 queued #42 (1 photo)
────────
🖼 photo: 1
"GM ☀️ shipping a new feature today"
You ▸ /menu
Bot ▸ 👋 Buffer Poster Bot
Active Buffer channels (4):
🐦 @yourhandle
💼 LinkedIn — Your Company
🧵 Threads
🦋 Bluesky
Binance Square: ✅ active
in queue: 12 posts
next: 24 May 2026 09:15 UTC
Schedule: random 1–240 h
📊 history: 47 ✅ / 2 ❌ (total 49)
[📡 Channels] [📋 Queue]
[🪙 Binance Square] [📊 Logs]
[⚙️ Settings] [🔁 Refresh]
| Variable | Where to find it |
|---|---|
| TELEGRAM_BOT_TOKEN | @BotFather → /newbot |
| ALLOWED_USER_ID | @userinfobot — your numeric Telegram ID |
| BUFFER_ACCESS_TOKEN | publish.buffer.com/settings/api → API (Beta) |
| IMGBB_API_KEY | api.imgbb.com — free, recommended for reliable image hosting on Buffer |
| BINANCE_SQUARE_API_KEY | Binance Skills Hub → square-post → Creator Center (optional) |
git clone https://github.com/SMOService/buffer-poster-bot.git
cd buffer-poster-bot
cp .env.example .env
# fill in .env
docker compose up -dpython -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
export TELEGRAM_BOT_TOKEN=...
export ALLOWED_USER_ID=...
export BUFFER_ACCESS_TOKEN=...
python bot.py| Command | What it does |
|---|---|
| /start or /menu | Main menu with inline buttons |
| /channels | Toggle Buffer channels on/off; Refresh from Buffer to re-sync |
| /queue | Scheduled-post counts per Buffer channel + Binance summary |
| /binance | Binance Square queue with full CRUD on each post |
| /logs | Paginated journal of publish attempts (success + failures) |
To post: just forward (or send) a message to the bot. Supported: text, photo, photo + caption, album of up to 4 photos, video up to 20 MB (video goes to Binance Square; Buffer receives the text + photos).
Buffer. On each forward the bot generates a random dueAt in the [SCHEDULE_MIN_HOURS, SCHEDULE_MAX_HOURS] window from now (default 1–240 h). The post is created via Buffer GraphQL with mode: customScheduled — Buffer publishes it at the scheduled time.
Binance Square. Posts are stored in a SQLite queue on the mounted volume along with Telegram file_ids for any attached photos. The background scheduler ticks every 60 s, finds posts whose publish_at has elapsed, downloads fresh bytes from Telegram, runs them through the official Binance v2 media flow, and DMs you with a link to the published post.
Duplicate protection. Before scheduling, the bot computes md5(text.strip().lower()) and checks the published_hashes table. Repeat? Hard block + warning to user.
Albums. Telegram delivers album items as separate messages with the same media_group_id. The bot buffers them for 1.5 s, then ships them all in one Buffer post + one Binance Square image post (up to 4 images for X carousel compatibility).
Pause / batch. Need to freeze posting before a launch? Tap ⏸ Pause on the Binance screen. Want to flush the queue immediately (e.g. for a coordinated drop)? ⚡ Publish all now with a confirm.
Implementation follows binance/binance-skills-hub (post-image.mjs, post-video.mjs, lib.mjs). There is no separate OpenAPI doc on developers.binance.com — the skill source is the canonical reference.
| Step | URL | Body |
|---|---|---|
| 1. Presign | images: POST /v2/…/image/presignedUrl · video: POST /v2/…/video/preSign | images: {"imageName":"<name>.<ext>"} · video: {"fileName", "size"} → data.presignedUrl, data.fileTicket |
| 2. Upload | PUT <presignedUrl> | raw bytes, Content-Type: image/<ext> or video/<ext> |
| 3. Status | POST /bapi/composite/v2/public/pgc/openApi/image/imageStatus | {"fileTicket":...} polling: images 3s × 10, video 5s × 36 → status==1 |
| 4. Publish | POST /bapi/composite/v1/public/pgc/openApi/content/add | image post: {"contentType":1, "bodyTextOnly", "imageList":[imageUrl, …]} (up to 4) · video post: {"contentType":3, "fileTicket", "cover", "videoTimeSeconds", "isPublish":true} (+ bodyTextOnly only when text is non-empty) |
All JSON requests carry X-Square-OpenAPI-Key, Content-Type: application/json, clienttype: binanceSkill.
Quirks handled by services/binance.py:
Article-mode (contentType=2 with a cover image) is implemented in the SDK layer (publish_article) but not surfaced in the UI yet — see "Roadmap" below.
buffer-poster-bot/
├── bot.py # entry point: init_db, load channels, start scheduler, polling
├── bot_instance.py # aiogram Bot/Dispatcher singletons + download_telegram_file
├── config.py # env + constants (BUFFER_API, BINANCE_API_V1/V2, …)
├── db.py # sqlite + migrations via PRAGMA user_version (schema v5)
├── keyboards.py # every InlineKeyboardMarkup builder
├── scheduler.py # background Binance publisher (60s tick, pause-aware)
├── state.py # FSM states (EditBinance.waiting_text)
├── services/
│ ├── buffer.py # Buffer GraphQL: fetch_channels, create_post, count_scheduled_posts
│ ├── binance.py # v1 text + v2 media flow (presignedUrl → PUT → imageStatus → content/add)
│ └── uploader.py # imgbb (primary) / catbox / 0x0.st fallback chain for Buffer
├── handlers/
│ ├── menu.py # /start, /menu, home / settings callbacks
│ ├── channels.py # /channels + toggle + refresh
│ ├── queue.py # /queue summary
│ ├── binance.py # /binance + CRUD + pause/resume + flush
│ ├── logs.py # /logs + pagination + filter
│ ├── post.py # handle_post (forward → Buffer + Binance queue; text/photo/album/video)
│ └── common.py # is_me, fmt_ts, fmt_delta, preview, random_due_at
├── tests/ # pytest: migrations, video queue, TTL, dedup, retry states
├── Procfile # Railway worker entrypoint
├── Dockerfile # docker / docker-compose / Coolify / any VPS
├── docker-compose.yml # ready-to-go with volume mount
├── .env.example # all env vars documented
├── pyproject.toml # ruff config
└── .github/
├── workflows/ci.yml # ruff + py_compile + import smoke + Docker build
├── ISSUE_TEMPLATE/ # bug / feature templates
└── PULL_REQUEST_TEMPLATE.md
| Table | Purpose |
|---|---|
| channels | Buffer channel cache: id, name, service, enabled |
| binance_queue | Pending posts: text, image_urls (JSON, imgbb), image_file_ids (JSON, Telegram), video_file_id / video_cover_file_id / video_duration, content_type, title, publish_at, status (pending/published/dead), next_attempt_at, last_error, attempt_count |
| published_hashes | MD5 of every successfully scheduled post body (dedup guard) |
| post_history | Journal: kind (buffer/binance), service, status, text_preview, ext_id, ext_url, error (rotates by HISTORY_LIMIT) |
| kv | Key-value store for scheduler state (binance_paused etc.) |
Migrations run incrementally on startup via PRAGMA user_version — upgrading from v1.x preserves your data.
See .env.example for the full annotated list. Required:
TELEGRAM_BOT_TOKEN=123456789:AA...
ALLOWED_USER_ID=123456789
BUFFER_ACCESS_TOKEN=1/abc...Optional:
IMGBB_API_KEY=... # recommended — primary image host for Buffer
BINANCE_SQUARE_API_KEY=... # enables Binance Square publishing
BINANCE_USE_IMAGES=1 # 1 = upload media to Binance v2, 0 = text-only Binance posts
BINANCE_IMAGE_FALLBACK_TEXT=0 # 1 = publish text-only when a media upload fails (media is lost)
BINANCE_MAX_ATTEMPTS=6 # attempts before a post goes to dead-letter
BINANCE_BACKOFF_BASE_SEC=300 # retry backoff: base 5 min
BINANCE_BACKOFF_MAX_SEC=21600 # retry backoff: cap 6 h
BINANCE_PUBLISHED_TTL_DAYS=30 # clean published posts from the queue table after N days (0 = keep)
SCHEDULE_MIN_HOURS=1 # default 1 (one hour)
SCHEDULE_MAX_HOURS=240 # default 240 (ten days)
HISTORY_LIMIT=500 # post_history rotation size
ECOSYSTEM_LINKS_ENABLED=1 # 0 = hide the "🚀 More tools" menu section
SUNSET_NOTICE= # optional banner text shown in /start
DB_PATH=/app/data/bot.db # override only for local devAnything Buffer supports (currently 9+ networks) just works. No code changes needed.
Don't want to self-host? The same team runs ready-to-use hosted bots for channel owners and content makers:
| Bot | What it does |
|---|---|
| @SuperappAIbot | Channel management suite: cross-posting, AI composer, competitor analytics («Radar») |
| @BridgePostBot | Auto-bridge posts from Telegram to external platforms with AI rewriting |
| @ZavodClawbot | AI content factory — generates niche posts on schedule |
| @TonChatAIbot | AI assistant for texts, ideas and reviews |
| @SaveAsVideoFreebot | Download videos from social networks for reposting |
| @StarsCashFlowbot | Monetize your audience with Telegram Stars |
Open-source neighbours in the SMOService org:
PRs welcome — see CONTRIBUTING.md. Bug reports via the issue templates. Security disclosures: SECURITY.md.
MIT © 2026 SMOService
| Back | FazBrowse Home | New Git URL |