Skip to content

azusachino/daphne

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

60 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🌸 Daphne (ダフニー Β· 沈丁花)

A fast, stateless Telegram bot that turns raw media links into native, Telegram-friendly media.

Twitter/X Β· Pixiv Β· Bluesky Β· TikTok Β· Instagram Β· Bilibili Β· YouTube β€” pasted as a link, delivered as playable media.

Python Version License: MIT Lint & format: ruff Package manager: uv Tests


Table of Contents

Why Daphne

Most link-downloader bots pipe every URL through a single blind yt-dlp call. Daphne instead uses purpose-built, login-wall-bypassing handlers per platform for clean native rendering, and falls back to a multi-engine downloader (yt-dlp β†’ you-get β†’ lux) only where it helps. It keeps zero persistent state by default β€” no database, secrets in the environment, everything else in a single config.toml. An optional Valkey connection can back live RBAC edits (see RBAC.md); everything else stays stateless.

Features

  • 🎯 Per-platform extractors β€” bespoke handlers render photos, GIFs, videos, and carousels natively instead of dumping a link.
  • 🎬 Multi-engine video downloads β€” yt-dlp β†’ you-get β†’ lux fallback with automatic dimension/duration probing and truncation detection (a partial download is retried on the next engine rather than accepted).
  • 🎧 Audio extraction β€” /audio <link> pulls the audio track and encodes it to MP3 with performer/title metadata.
  • πŸ–ΌοΈ Image galleries β€” /gallery <link> fetches full galleries via gallery-dl and posts them as chunked media groups.
  • ⚑ Inline mode β€” @daphne <link> converts Twitter/X, Instagram, and YouTube/Bilibili links from any chat (user-allowlisted).
  • πŸ” Role-based access control β€” multi-tenant RBAC by user and chat ID, configured in config.toml or, optionally, live-edited via Valkey and the admin-only /grant, /revoke, /roles commands. See RBAC.md.
  • 🚦 Concurrency guard β€” per-user and global download semaphores so one large transfer never starves the others; users see a Queued… notice.
  • πŸ‘€ Live feedback β€” message reactions (πŸ‘€ working β†’ πŸ‘ done / 😒 failed) plus upload_video/upload_photo/upload_audio chat actions.
  • 🎨 Rich HTML captions β€” title, uploader, duration, source link, platform tag, and requester attribution.
  • πŸ›Ÿ Safety-first β€” the original message is deleted only after a successful conversion and upload, so links are never lost on error.

Supported Platforms

Platform Method Media Inline
Twitter / X FxTwitter API Photos, GIFs, videos βœ…
Instagram parth-dl (GraphQL) Images, carousels, reels βœ…
YouTube Β· Bilibili Β· b23 yt-dlp / you-get / lux Video downloads βœ…
Pixiv Artwork/gallery resolver Photo / media groups β€”
Bluesky XRPC identity + HLS parsing Image carousels, videos β€”
TikTok / Douyin TikWM API (+ yt-dlp fallback) Direct video β€”
Image galleries gallery-dl (/gallery) Batched photo groups β€”

Pixiv is intentionally excluded from inline: its CDN rejects hotlinking (requires a Referer header), and inline results hand Telegram a bare URL to fetch β€” so it works in-chat only.

Commands & Modes

Command Description
Paste a link Auto-detect the platform and convert it in the chat
/start Welcome message; answers even before RBAC has whitelisted you
/audio <link> Extract the audio track as MP3
/gallery <link> Download an image gallery and send it as media group(s)
/help Show usage
@daphne <link> Inline mode β€” convert from any chat (requires inline_convert)

Admins get three additional commands (/grant, /revoke, /roles) β€” deliberately left out of Telegram's / picker for everyone else. See RBAC.md.

Quick Start

Daphne uses uv for dependencies and runs cleanly in containers (Podman / Docker) with an optional local Telegram Bot API sidecar for 2 GB uploads.

# 1. Generate local config + env templates (untracked)
make init-local

# 2. Fill in your bot credentials and allowed user/chat IDs
#    .daphne.local.env  and  .daphne.config.local.toml

# 3. Spin up the stack (bot + local Bot API sidecar)
make up

# 4. Tear it down
make down

For inline mode, enable it once with @BotFather β†’ /setinline.

Secrets (environment)

Variable Purpose
DAPHNE_BOT_TOKEN Bot token from @BotFather
TELEGRAM_API_ID / TELEGRAM_API_HASH Credentials for the local Bot API sidecar

Configuration

Non-secret runtime settings live in config.toml:

[app]
# telegram_api_url = "http://localhost:8081"
video_upload_limit_mb = 256

# Heavy-download concurrency guard (yt-dlp / gallery-dl):
# max_concurrent_downloads = 3        # across the whole bot
# max_user_concurrent_downloads = 1   # per user

[rbac]
public_commands = ["help"]

[rbac.roles.admin]
permissions = ["*"]

# Example non-admin roles, graduated from minimal to full. Available
# permissions: convert_link, fetch_metadata, preview_video, download_video,
# extract_audio, download_gallery, inline_convert.
# [rbac.roles.default]
# permissions = ["convert_link"]
# [rbac.roles.power_user]
# permissions = ["convert_link", "preview_video", "fetch_metadata", "extract_audio", "download_video"]

[rbac.users]
# 111111111 = "admin"  # Replace with your Telegram user ID

[rbac.chats]
# -1001111111111 = "power_user"  # Replace with your chat ID

If a detected video exceeds video_upload_limit_mb, Daphne replies with a decorated HTML info card (with a direct-download button) instead of uploading the file.

Access Control (RBAC)

Daphne resolves access in order: admin bypass β†’ public commands β†’ chat-level role β†’ user-level role. Full authorization flows and fallback mechanics are documented in RBAC.md.

Important

Inline mode is user-level only. Telegram provides no chat_id for inline queries, so the chat tier of RBAC can never apply. Grant inline_convert via [rbac.users] (or admin), not [rbac.chats]. This is intentional β€” inline runs from anywhere in Telegram, outside any group boundary.

Development

make fmt      # Format code (ruff)
make lint     # Lint check (ruff)
make test     # Run unit tests
make ready    # fmt + lint + test + container smoke build
  • Nix-first tooling from the devShell; uv for the Python runtime.
  • Every subprocess call to an external downloader (yt-dlp, you-get, lux, gallery-dl, ffprobe) carries an explicit timeout to protect the executor pool.

Architecture

  • Python 3.12+, python-telegram-bot, polling-based.
  • Stateless: no database; secrets in env, everything else in config.toml.
  • Deployed as a systemd user service or a Podman/Docker stack with a local Bot API sidecar (TZ Asia/Tokyo, no token-bearing HTTP logs).

License

Released under the MIT License.

About

A fast, stateless Telegram bot that turns raw media links into native, Telegram-friendly media.

Topics

Resources

License

Contributing

Stars

2 stars

Watchers

1 watching

Forks

Packages

 
 
 

Contributors

Languages