Files
stealergram/core/tdl_downloader.md
anti 741e6bb0d3 Rename to stealergram, add pyproject.toml, purge em-dashes
- Rename project to stealergram throughout
- Add pyproject.toml (replaces requirements.txt split, folds pytest.ini)
- Replace all em-dashes with hyphens across all source files

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 10:06:30 -04:00

2.2 KiB

core/tdl_downloader.py

Fast file downloads via tdl (Go MTProto). Falls back gracefully if tdl is not installed.

Public API

from core.tdl_downloader import (
    is_tdl_available,
    download_single_with_tdl,
    download_batch_with_tdl,
    BatchEntry,
)

is_tdl_available() -> bool

Returns True if tdl binary is on PATH.

download_single_with_tdl(msg, dest: Path) -> bool

async. Downloads one message's document. Returns True on success.
Used by the live handler and bot_downloader.

download_batch_with_tdl(entries: list[BatchEntry]) -> dict[int, bool]

async. Downloads up to TDL_AMOUNT messages in a single tdl dl invocation.
Returns {doc_id: True|False} - False means Telethon fallback needed.


BatchEntry dataclass

@dataclass
class BatchEntry:
    msg:         object       # Telethon Message
    filename:    str
    dest:        Path         # final destination path in TEMP_DIR
    doc_id:      int          # msg.media.document.id
    source_name: str
    password:    str | None

TUI output pipeline

In TUI mode (bus.tui_active == True), _run_tdl pipes stdout+stderr and relays lines as EvTdlOutput events in real time.
Reads raw 256-byte chunks (not line-by-line) and splits on \r and \n, because tdl uses \r to overwrite its progress bar in place.

In CLI mode: subprocess inherits the terminal, progress bars render natively.


Staging directory isolation

Each batch/single download gets a unique data/tmp/_tdl_{monotonic_ns}/ staging dir.
After tdl exits, files are matched by name (with fuzzy stem fallback for filenamify() mangling) and moved to final dest. Staging dir is removed regardless of outcome.

--template '{{ filenamify .FileName }}' - tdl uses the original Telegram filename, not its default DialogID_MessageID_filename format.


Config knobs (config.py)

Setting Default Description
TDL_NAMESPACE "default" -n flag; None omits it
TDL_THREADS 8 -t chunk workers per file
TDL_PERFILE 4 -l concurrent files per invocation
TDL_AMOUNT 4 Max messages per batch
TDL_TAKEOUT False --takeout session flag