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

71 lines
2.2 KiB
Markdown

# core/tdl_downloader.py
Fast file downloads via `tdl` (Go MTProto). Falls back gracefully if tdl is not installed.
## Public API
```python
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
```python
@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 |