Skip to content

CrashSystemZ/spiw-bot

Repository files navigation

spiw-bot

Send social-media videos inline in any Telegram chat. No files on disk, no ffmpeg, no yt-dlp — just forward the link.

Node 22 TypeScript 6 SQLite Docker MIT


What it does

Type a social-media URL into Telegram's inline mode in any chat → the bot replies with a playable inline card. Tap it — media is fetched through a pool of cobalt servers and the message becomes the actual video, photo carousel, or audio.

All media stays in RAM. Nothing is written to disk on the bot host.

Supported platforms

TikTok Instagram X / Twitter Threads

Videos, photo carousels, GIFs, and audio tracks are all supported. Carousel items have ⬅️ ➡️ navigation, a 🎵 toggle when there's a separate audio track, and a 🔄 retry if delivery fails.

Not supported (and why)

YouTube (blocked)

YouTube is explicitly blocked. Cobalt needs logged-in YouTube cookies or a residential proxy to bypass bot-check, and we don't ship either. Posting a youtube.com or youtu.be link returns Link not supported 😩 instead of silently failing.

Everything else that isn't in the list above (Reddit, Facebook, random sites, etc.) gets the same rejection at parse time — no wasted cobalt calls.

How it works

 Telegram user
     │ inline query: https://tiktok.com/…
     ▼
 spiw-bot ──► metadata resolver (tiktok / instagram / x / threads)
     │
     │ on tap
     ▼
 Cobalt pool ──► self-hosted cobalt   (fast, private)
     │          ↳ if rate-limited, fall through to
     │             community instances from cobalt.directory
     ▼
 RAM buffers ──► Telegram edit-message
  1. Inline query hits our resolver whitelist; unsupported URLs are rejected immediately.
  2. Tap starts the real work: cobalt resolves the URL to a media tunnel, we stream the bytes into RAM (hard cap, default 2 GB), probe them with mediainfo.js, and edit the inline message to the actual media.
  3. Cobalt pool with fallback — our primary instance is self-hosted. When TikTok/Instagram rate-limit our data-center IP, the bot auto-falls through to community cobalt instances discovered via cobalt.directory. Endpoints that return auth.jwt.missing or HTTP 403 are auto-banned until the next hourly refresh.

Why MTProto ⚡

MTProto

Unlike 99% of Telegram bots this one does not use the HTTPS Bot API. It talks native MTProto through mtcute — the same protocol the official Telegram apps use. That matters:

  • Big files. Bot API caps uploads at 50 MB. MTProto lets us push up to 2 GB per file (4 GB for Premium). No "file too large" when forwarding a 100 MB TikTok.
  • Faster inline. Updates flow over a persistent MTProto connection, not long-polled HTTPS — inline cards appear and edit with minimum round-trip latency.
  • Direct data-center upload. Media goes straight to Telegram's file DCs, bypassing the Bot API proxy layer entirely. Less copying, less bandwidth, less lag.
  • Full Telegram capability. Features the Bot API exposes slowly or not at all (stable inline edits, large-file chunking, rich message operations) are available natively.

In short: it's not a toy wrapper — it's a real Telegram client that happens to answer as a bot.

Quick start

# 1. clone + install
git clone https://github.com/CrashSystemZ/spiw-bot
cd spiw-bot
npm install

# 2. configure
cp .env.example .env
# fill in BOT_TOKEN, TG_API_ID, TG_API_HASH

# 3. run
docker compose up -d

For local dev without Docker:

npm run dev   # tsx watch, hot-reload

Configuration

The bot reads env via Zod; unset optional vars get sane defaults.

Variable Required Default What it does
BOT_TOKEN Telegram bot token
TG_API_ID / TG_API_HASH MTProto app credentials
COBALT_BASE_URL Primary cobalt instance URL
COBALT_DISCOVERY_ENABLED true Enable community fallback pool
COBALT_DISCOVERY_SERVICES tiktok,instagram Which service categories to pick from cobalt.directory
COBALT_DISCOVERY_MAX 5 Max dynamic endpoints to keep
MEDIA_BUFFER_BUDGET_BYTES 2 GB LRU session cache size
MAX_CONCURRENT_JOBS 32 Parallel session builds

All user-facing strings live in resources/messages.json — edit them without rebuilding.

Architecture

src/
├── telegram/       mtcute dispatcher, handlers, UI builders
├── use-cases/      request-flow, session-flow, details-flow
├── core/           runtime, cobalt client & pool, errors, logger
│   ├── metadata/   platform resolvers (whitelist lives here)
│   └── db/         drizzle schema + SQLite client
└── adapters/       metadata gateway, media session builder, repos

Layered, dependency-injected, testable. SpiwRuntime is the DI root; nothing reads globals except the validated env object.

Tech stack

Node TypeScript mtcute Drizzle better-sqlite3 Zod Docker cobalt

Honest limits

  • Platforms can break overnight. TikTok and Instagram actively fight scrapers. If the whole cobalt ecosystem is down, so are we.
  • Community cobalt endpoints are unreliable. They can go offline, enable Turnstile, or hit rate limits. The bot auto-bans failing ones until the next refresh, but can't make them work.
  • Files > 2 GB won't be sent. Hard cap to protect RAM. Telegram itself also has upload limits (50 MB via Bot API; we use user-client, so higher, but not infinite).

License

MIT

About

SPIW-bot is a Telegram inline bot for resolving and delivering social media content as cached Telegram media

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors