Commit 7604fd8
feat(commands): add /util download (yt-dlp + ffmpeg 2-pass) and group utility commands
Adds /util download <url> [start] [end] that pulls media via yt-dlp, trims
with ffmpeg if a range is given, and 2-pass compresses to an 8MB budget
(mirroring compress_video.py from
https://github.com/1Git2Clone/dotfiles/blob/main/dot-config/programs/py_scripts/compress_video.py:
bitrate = target_size / duration, pass 1 analysis, pass 2 encode with
audio, ~0.94 muxing margin, 64 kbps sanity floor, skip-if-already-small).
Uploads the result as a Discord attachment — no S3/CDN.
Groups existing utility commands under /util parent (per #34):
- /util avatar (was /avatar)
- /util uptime (was /uptime)
- /util age (was /age)
Old standalone commands remain registered for backward compatibility.
Gated behind new util-download Cargo feature
(util-download = ["dep:ffmpeg-sidecar", "dep:tempfile", "dep:url"])
matching the existing ai-* / redis style.
Security and operational hardening:
- Input validation: validate_url() rejects non-http/https schemes,
userinfo, private/loopback/link-local IPs (SSRF defense), and
flag-like -- content in path/query. Domain allowlist restricts to
yt-dlp-supported social media platforms (YouTube, Facebook,
Instagram, TikTok, Twitter/X, Reddit, Vimeo).
- validate_timecode() rejects shell metacharacters, spaces, and only
allows pure digits (seconds) or HH:MM:SS / MM:SS format.
- Async subprocesses: tokio::process::Command + .await so the tokio
worker thread isn't blocked during ffmpeg encodes.
- Per-subprocess timeouts (yt-dlp: 3m, ffprobe: 30s, trim: 1m, each
encode pass: 4m) fitting within Discord's 15-min interaction token
lifetime. Child processes are killed on timeout.
- --no-playlist guard on yt-dlp to reject playlist URLs upfront.
- User-facing error messages via ctx.say() instead of silent ? propagation.
- Cross-platform: /dev/null replaced with a temp file inside temp_dir.
- ffmpeg2pass log paths via -passlogfile pointing inside temp_dir.
5-minute max source duration guard.
Co-authored-by: DeepSeek V4 Pro <service@deepseek.com>1 parent ed49200 commit 7604fd8
12 files changed
Lines changed: 838 additions & 0 deletions
File tree
- docs
- src
- commands
- util
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
| 12 | + | |
| 13 | + | |
12 | 14 | | |
13 | 15 | | |
14 | 16 | | |
| |||
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
49 | 49 | | |
50 | 50 | | |
51 | 51 | | |
| 52 | + | |
| 53 | + | |
52 | 54 | | |
53 | 55 | | |
54 | 56 | | |
| |||
73 | 75 | | |
74 | 76 | | |
75 | 77 | | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
63 | 63 | | |
64 | 64 | | |
65 | 65 | | |
| 66 | + | |
66 | 67 | | |
67 | 68 | | |
68 | 69 | | |
| |||
83 | 84 | | |
84 | 85 | | |
85 | 86 | | |
| 87 | + | |
86 | 88 | | |
87 | 89 | | |
88 | 90 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
45 | 45 | | |
46 | 46 | | |
47 | 47 | | |
| 48 | + | |
| 49 | + | |
48 | 50 | | |
49 | 51 | | |
50 | 52 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
| 6 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
0 commit comments