lumenfetch 2.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,35 @@
1
+ name: Tests
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python-version: ["3.9", "3.10", "3.11", "3.12"]
15
+
16
+ steps:
17
+ - name: Checkout repo
18
+ uses: actions/checkout@v4
19
+
20
+ - name: Setup Python ${{ matrix.python-version }}
21
+ uses: actions/setup-python@v5
22
+ with:
23
+ python-version: ${{ matrix.python-version }}
24
+
25
+ - name: Install ffmpeg
26
+ run: sudo apt-get update && sudo apt-get install -y ffmpeg
27
+
28
+ - name: Install dependencies
29
+ run: pip install -r requirements-dev.txt
30
+
31
+ - name: Run tests
32
+ run: pytest tests/ -v
33
+
34
+ - name: Lint with ruff
35
+ run: ruff check .
@@ -0,0 +1,13 @@
1
+ __pycache__/
2
+ *.pyc
3
+ .venv/
4
+ venv/
5
+ .pytest_cache/
6
+ .ruff_cache/
7
+ downloads/*
8
+ !downloads/.gitkeep
9
+ config.json
10
+ *.log
11
+ dist/
12
+ build/
13
+ *.egg-info/
@@ -0,0 +1,67 @@
1
+ # Kontribusi ke Lumenfetch
2
+
3
+ Makasih udah mau bantu kembangin Lumenfetch. Panduan ini biar kontribusi kamu gampang diproses.
4
+
5
+ ## πŸ›  Setup Development
6
+
7
+ 1. Fork & clone repo ini
8
+ 2. Install dependency (termasuk tools testing & lint):
9
+ ```bash
10
+ pip install -r requirements-dev.txt
11
+ ```
12
+ 3. Pastikan `ffmpeg` sudah terinstall di sistem kamu (lihat bagian Requirements di README)
13
+
14
+ ## πŸ—‚ Struktur & Prinsip Modul
15
+
16
+ Lumenfetch sengaja dipisah per tanggung jawab, tolong dijaga konsistensinya kalau nambah/ubah kode:
17
+
18
+ | File | Tanggung jawab | Tidak boleh |
19
+ |------|-----------------|-------------|
20
+ | `core/constants.py` | Nilai shared (versi, format, batas) | Logic bisnis |
21
+ | `core/errors.py` | Klasifikasi error + pesan ramah terpusat | Logic download/deteksi |
22
+ | `core/ffmpeg.py` | Deteksi ffmpeg sistem dulu, bundled fallback | Download/deteksi |
23
+ | `core/log.py` | Logging file terpusat | Tampilan rich/menu |
24
+ | `core/detector.py` | Deteksi info video YouTube via yt-dlp | Mendownload apa pun |
25
+ | `core/downloader.py` | Proses download, progress hook, retry | Menampilkan menu/prompt |
26
+ | `core/options.py` | Semua interaksi & tampilan menu (rich) | Logic download |
27
+ | `core/utils.py` | Helper murni: sanitasi, format, config.json | Bergantung ke CLI atau jaringan |
28
+ | `main.py` | Menyatukan semua modul lewat satu loop | Logic bisnis baru |
29
+
30
+ Kalau nambah fitur, coba taruh di modul yang paling sesuai dulu sebelum bikin file baru.
31
+
32
+ ## βœ… Sebelum Bikin Pull Request
33
+
34
+ Jalankan ini dulu di root project:
35
+
36
+ ```bash
37
+ pytest tests/ -v
38
+ ruff check .
39
+ ```
40
+
41
+ Pastikan semua test lulus dan tidak ada warning lint baru. GitHub Actions juga bakal jalanin ini otomatis di setiap PR.
42
+
43
+ ## πŸ“ Commit Message
44
+
45
+ Pakai prefix singkat biar history gampang dibaca:
46
+
47
+ - `feat:` β€” fitur baru
48
+ - `fix:` β€” perbaikan bug
49
+ - `docs:` β€” perubahan dokumentasi (README, CONTRIBUTING, dll)
50
+ - `refactor:` β€” perubahan struktur kode tanpa mengubah perilaku
51
+ - `test:` β€” nambah/ubah test
52
+
53
+ Contoh: `fix: handle carousel gambar dengan 1 gambar saja`
54
+
55
+ ## πŸ› Lapor Bug / Request Fitur
56
+
57
+ Buka [Issues](../../issues) baru, sertakan:
58
+ - Platform/link yang bermasalah (kalau ada, hapus info pribadi)
59
+ - Pesan error yang muncul di terminal
60
+ - Langkah buat reproduce masalahnya
61
+
62
+ ## 🀝 Pull Request
63
+
64
+ 1. Buat branch baru dari `main`, kasih nama yang jelas (misal `fix/carousel-single-image`)
65
+ 2. Pastikan `pytest` dan `ruff check .` lulus
66
+ 3. Jelasin di deskripsi PR apa yang diubah dan kenapa
67
+ 4. Tunggu review β€” mungkin ada request perubahan kecil sebelum di-merge
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nicolas Dwi Dharma
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,387 @@
1
+ Metadata-Version: 2.5
2
+ Name: lumenfetch
3
+ Version: 2.0.0
4
+ Summary: YouTube downloader buat terminal - MP4 & MP3.
5
+ Project-URL: Homepage, https://github.com/nekonaru/lumenfetch
6
+ Author: Nicolas Dwi Dharma
7
+ License: MIT
8
+ License-File: LICENSE
9
+ Keywords: cli,downloader,mp3,mp4,youtube,yt-dlp
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: End Users/Desktop
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Multimedia :: Video
21
+ Classifier: Topic :: Utilities
22
+ Requires-Python: >=3.9
23
+ Requires-Dist: curl-cffi
24
+ Requires-Dist: pyperclip
25
+ Requires-Dist: rich
26
+ Requires-Dist: static-ffmpeg
27
+ Requires-Dist: yt-dlp
28
+ Provides-Extra: dev
29
+ Requires-Dist: pyinstaller; extra == 'dev'
30
+ Requires-Dist: pytest; extra == 'dev'
31
+ Requires-Dist: ruff; extra == 'dev'
32
+ Description-Content-Type: text/markdown
33
+
34
+ <div align="center">
35
+
36
+ ### πŸ“₯ Lumenfetch
37
+ **YouTube downloader buat terminal - MP4 & MP3. Paste link, pilih quality, beres.**
38
+
39
+ <br>
40
+
41
+ ![Python](https://img.shields.io/badge/Python-3.9%2B-3776AB?style=flat-square&logo=python&logoColor=white)
42
+ ![License](https://img.shields.io/badge/License-MIT-green?style=flat-square)
43
+ ![Platform](https://img.shields.io/badge/Platform-Windows%20%7C%20macOS%20%7C%20Linux-lightgrey?style=flat-square)
44
+ ![Status](https://img.shields.io/badge/Status-Active-brightgreen?style=flat-square)
45
+ ![Tests](https://github.com/nekonaru/lumenfetch/actions/workflows/tests.yml/badge.svg)
46
+
47
+ </div>
48
+
49
+ ## ✨ Tentang Project
50
+
51
+ **Lumenfetch** adalah CLI Python buat download video YouTube jadi **MP4** atau ekstrak audionya jadi **MP3** - cukup paste link, dia otomatis deteksi judul, durasi, dan estimasi ukuran, lalu kasih kamu opsi quality yang relevan. Didukung [yt-dlp](https://github.com/yt-dlp/yt-dlp) di belakang layar, plus `curl_cffi` buat lolos bot-check YouTube.
52
+
53
+ > _"Satu command, langsung MP4/MP3."_
54
+
55
+ ## 🎯 Fitur
56
+
57
+ | Fitur | Keterangan |
58
+ |-------|------------|
59
+ | πŸ” **Auto-detect** | Judul, durasi, dan estimasi ukuran terdeteksi otomatis |
60
+ | πŸŽ› **Opsi dinamis** | Menu quality menyesuaikan (video / audio saja) |
61
+ | 🎞 **Video MP4** | Pilihan quality Best/1080p/720p/480p/360p/Worst, thumbnail otomatis ter-embed |
62
+ | 🎡 **Audio MP3** | Pilihan bitrate Best/320kbps/192kbps/128kbps |
63
+ | πŸ“œ **Playlist** | Default video pertama saja; `--playlist all` untuk semua sekaligus |
64
+ | πŸ’¬ **Subtitle & metadata** | Download subtitle (SRT) + embed ke MP4, opsional via flag/CLI |
65
+ | πŸ“‹ **Auto-paste clipboard** | Kalau ada link valid di clipboard, langsung ditawarkan tanpa perlu paste manual - tidak akan nanya ulang isi clipboard yang sama berkali-kali |
66
+ | πŸ“Š **Progress bar real-time** | Kecepatan, ukuran, dan estimasi waktu tersisa lewat `rich` |
67
+ | πŸ“ **Estimasi ukuran & waktu** | Muncul di menu pilih quality (video/audio), dihitung dari data yt-dlp + kecepatan rata-rata download kamu sebelumnya |
68
+ | πŸ”„ **Auto-retry** | Error koneksi dicoba ulang otomatis (default 3x), error fatal (private/invalid) langsung dilaporkan |
69
+ | πŸ—‚ **Riwayat download** | 20 entri terakhir tersimpan, bisa dilihat kapan saja lewat command `history` |
70
+ | βš™οΈ **Pengaturan persisten** | Folder download (default: folder Downloads OS, ganti kapan saja), max retry, auto-paste, dan naming template diingat lewat `config.json` |
71
+ | πŸͺ **Cookies browser/file** | Opsional, buat video age-restricted/private - dari Chrome/Firefox/Edge/dll atau file `cookies.txt` |
72
+ | 🧼 **Nama file aman** | Karakter ilegal disanitasi, duplikat otomatis dikasih suffix `(1)`, `(2)`, dst |
73
+ | πŸ”” **Auto-check update yt-dlp** | Tiap dibuka, dicek ke PyPI apakah ada versi yt-dlp lebih baru - gagal cek (mis. offline) diam-diam diabaikan |
74
+
75
+ ## πŸ“¦ Requirements
76
+
77
+ - **Python** 3.9 atau lebih baru
78
+ - **Koneksi internet**
79
+
80
+ > ffmpeg **tidak perlu diinstall manual** - Lumenfetch otomatis mengunduh dan memakai versi bundled-nya sendiri (lewat `static-ffmpeg`) begitu pertama kali dijalankan, persis seperti cara kerja `ffmpeg-static` di project Node.js.
81
+
82
+ ### Belum pernah pakai terminal? Ikuti ini dulu
83
+
84
+ <details>
85
+ <summary><b>πŸͺŸ Cara buka terminal di Windows</b></summary>
86
+
87
+ 1. Tekan tombol **Windows**, ketik `PowerShell`, lalu tekan **Enter**
88
+ 2. Jendela hitam/biru akan terbuka. Itu tempat kamu mengetik perintah
89
+ 3. Semua perintah `python ...` atau `pip ...` di panduan ini diketik di jendela itu, lalu tekan **Enter**
90
+
91
+ </details>
92
+
93
+ <details>
94
+ <summary><b>🍎 Cara buka terminal di macOS</b></summary>
95
+
96
+ 1. Tekan **Cmd + Spasi**, ketik `Terminal`, lalu tekan **Enter**
97
+ 2. Ketik perintah-perintah di panduan ini di situ, lalu tekan **Enter**
98
+
99
+ </details>
100
+
101
+ <details>
102
+ <summary><b>🐧 Cara buka terminal di Linux</b></summary>
103
+
104
+ Tekan **Ctrl + Alt + T**, atau cari aplikasi "Terminal" di menu aplikasi.
105
+
106
+ </details>
107
+
108
+ ### Belum punya Python?
109
+
110
+ 1. Buka [python.org/downloads](https://www.python.org/downloads/) dan unduh versi terbaru
111
+ 2. **Khusus Windows**: saat instalasi, centang dulu kotak **"Add Python to PATH"** di layar pertama sebelum klik Install
112
+ 3. Setelah selesai install, cek dengan:
113
+
114
+ ```bash
115
+ python --version
116
+ # atau
117
+ python3 --version
118
+ ```
119
+
120
+ ## πŸš€ Instalasi
121
+
122
+ **1. Ambil kode project ini**
123
+
124
+ <details>
125
+ <summary><b>Punya Git terinstall</b></summary>
126
+
127
+ ```bash
128
+ git clone https://github.com/nekonaru/lumenfetch.git
129
+ cd lumenfetch
130
+ ```
131
+
132
+ </details>
133
+
134
+ <details>
135
+ <summary><b>Tidak punya Git</b></summary>
136
+
137
+ 1. Buka halaman repository di GitHub
138
+ 2. Klik tombol hijau **`Code`** β†’ pilih **`Download ZIP`**
139
+ 3. Ekstrak file ZIP yang terunduh ke folder pilihanmu
140
+ 4. Di terminal, masuk ke folder hasil ekstrak
141
+
142
+ </details>
143
+
144
+ **2. Install dependency**
145
+ ```bash
146
+ pip install -r requirements.txt
147
+ ```
148
+
149
+ > Kalau muncul error `externally-managed-environment` (biasanya di Linux):
150
+ > ```bash
151
+ > pip install -r requirements.txt --break-system-packages
152
+ > ```
153
+
154
+ **3. (Opsional) Install sebagai command `lumenfetch`**
155
+ ```bash
156
+ pip install -e .
157
+ lumenfetch --version
158
+ ```
159
+
160
+ ## πŸ–₯️ Cara Pakai
161
+
162
+ **Jalankan:**
163
+ ```bash
164
+ python main.py
165
+ # atau non-interaktif:
166
+ python main.py "https://youtube.com/watch?v=..." -t video -f mp4 -q 720p -y
167
+ python main.py --batch daftar.txt --jobs 2
168
+ python main.py --history
169
+ python main.py --help
170
+ ```
171
+
172
+ **Flag CLI:**
173
+ ```
174
+ -t/--type {video,audio} -f/--format {mp4,mp3} -q/--quality
175
+ -o/--output --cookies --cookies-file --max-retry --playlist {single,all}
176
+ --subs --sub-langs en,id --embed-subs --embed-metadata
177
+ --batch file.txt --jobs 1-4 --no-clipboard -y/--yes -v/--verbose
178
+ --history --version
179
+ ```
180
+
181
+ **Masukkan URL saat diminta:**
182
+ ```
183
+ Masukkan URL (q: keluar, history, settings, help): https://youtube.com/watch?v=...
184
+ ```
185
+
186
+ Kalau ada link valid di clipboard, Lumenfetch akan menawarkannya duluan - tinggal jawab `y` kalau mau pakai itu.
187
+
188
+ **Link YouTube otomatis terdeteksi, lalu menu menyesuaikan:**
189
+
190
+ - **Video** β†’ pilih output Video (MP4) / Audio (MP3) β†’ pilih quality
191
+ - **Stream audio** β†’ langsung pilih bitrate MP3
192
+ - **Playlist** β†’ default video pertama; `--playlist all` untuk semua
193
+
194
+ **Konfirmasi nama file, lalu proses download berjalan** dengan progress bar real-time (kecepatan, ukuran, ETA). Tekan `Ctrl+C` kapan saja untuk membatalkan dengan aman.
195
+
196
+ ## ⌨️ Command
197
+
198
+ Diketik langsung di prompt utama, menggantikan URL:
199
+
200
+ | Command | Fungsi |
201
+ |---------|--------|
202
+ | `history` | Lihat 20 riwayat download terakhir (tanggal, judul, format, ukuran, status) |
203
+ | `settings` | Ganti folder default, max retry, auto-paste clipboard, naming template, atau cookies |
204
+ | `help` | Tampilkan panduan singkat di dalam aplikasi |
205
+ | `q` / `quit` | Keluar dari aplikasi |
206
+ | `Ctrl+C` | Batalkan download yang sedang berjalan |
207
+
208
+ ## πŸͺ Cookies (Opsional)
209
+
210
+ Video age-restricted atau private butuh login. Kalau ketemu error semacam itu, aktifkan salah satu:
211
+
212
+ **A. Cookies dari browser:**
213
+ 1. Buka Lumenfetch, ketik `settings`
214
+ 2. Pilih `[5] Pakai cookies dari browser/file`
215
+ 3. Pilih browser di mana kamu sudah login YouTube (Chrome/Firefox/Edge/Brave/Opera/Vivaldi/Safari)
216
+
217
+ Setelah aktif, Lumenfetch akan meminjam cookies dari browser itu setiap kali mendeteksi atau mendownload konten, seolah request-nya datang dari sesi browser kamu yang sudah login. Cukup pilih `[1] Nonaktifkan` di menu yang sama kalau mau matikan lagi.
218
+
219
+ > **Penting:** browser yang dipilih harus **benar-benar tertutup total** saat download (file cookies dikunci selama browser terbuka - errornya `Could not copy ... cookie database`). Cek Task Manager dan matikan semua proses browser tersebut (Edge/Chrome sering masih jalan di background).
220
+
221
+ > **Alternatif paling reliable (disarankan kalau error cookies terus muncul):** pakai **file cookies** yang works walau browser terbuka:
222
+ > 1. Install extension **"Get cookies.txt LOCALLY"** (Chrome/Edge/Firefox) di browser
223
+ > 2. Buka youtube.com (pastikan sudah login), klik extension β†’ **Export** β†’ simpan mis. `D:\cookies.txt`
224
+ > 3. Di Lumenfetch: `settings` β†’ `[5]` β†’ `[1] Nonaktifkan` β†’ isi path file cookies tadi
225
+ > 4. Atau via CLI: `python main.py <URL> --cookies-file D:\cookies.txt`
226
+
227
+ ## πŸ“ Estimasi Ukuran & Waktu Download
228
+
229
+ Pas milih quality buat video atau audio, Lumenfetch nampilin perkiraan ukuran file dan waktu download di sebelah tiap opsi:
230
+
231
+ ```
232
+ Pilih Quality:
233
+ [1] Best (default) (~147.8 MB, ~31 detik)
234
+ [2] 1080p (~147.8 MB, ~31 detik)
235
+ [3] 720p (~81.1 MB, ~17 detik)
236
+ [4] 480p (~42.9 MB, ~9 detik)
237
+ ```
238
+
239
+ Cara kerjanya:
240
+
241
+ - **Ukuran** dihitung dari data yang yt-dlp udah dapat pas proses "Mendeteksi konten..." (gak ada request tambahan ke platform, jadi gak bikin lambat)
242
+ - **Waktu** dihitung dari kecepatan rata-rata beberapa download terakhir kamu yang sukses (bukan angka tebakan generik) - makin sering pakai Lumenfetch, makin akurat estimasinya
243
+ - Kalau datanya gak cukup buat ngasih estimasi yang jujur (mis. platform gak expose ukuran file sama sekali, quality tier yang diminta gak tersedia buat konten itu, atau ini baru pertama kali pakai aplikasi jadi belum ada riwayat kecepatan) - estimasinya gak ditampilin sama sekali, daripada nampilin angka ngasal
244
+
245
+ ## πŸ”” Auto-check Update yt-dlp
246
+
247
+ YouTube sering ubah sistemnya - jadi `yt-dlp` juga perlu sering di-update biar tetap kompatibel. Ini bukan "sekali fix, selesai selamanya", tapi proses berkelanjutan (mirip antivirus yang perlu update rutin).
248
+
249
+ Buat bantu itu, tiap kali Lumenfetch dibuka, otomatis dicek ke PyPI apakah ada versi `yt-dlp` yang lebih baru dari yang terinstall. Kalau ada, muncul notice kayak gini:
250
+
251
+ ```
252
+ πŸ”” Update yt-dlp tersedia
253
+ yt-dlp kamu versi 2026.1.1, versi terbaru 2026.8.19 sudah tersedia.
254
+ pip install --upgrade yt-dlp
255
+ ```
256
+
257
+ Tinggal jalankan command yang ditampilkan. Kalau lagi offline atau PyPI nggak bisa diakses, pengecekan ini gagal diam-diam dan **tidak** menghalangi kamu pakai aplikasinya.
258
+
259
+ ## πŸ—‚ Naming & Konfigurasi
260
+
261
+ Nama file mengikuti template di `config.json` (default: `%(platform)s_%(title)s_%(year)s`), contoh hasil:
262
+
263
+ ```
264
+ YouTube_Lofi-Hip-Hop-Radio_2026.mp4
265
+ YouTube_Lofi-Hip-Hop-Radio_2026.mp3
266
+ ```
267
+
268
+ Preferensi kamu (folder simpan, max retry, auto-paste, naming template, cookies browser, dan riwayat) otomatis tersimpan di config user
269
+ (`%APPDATA%/lumenfetch/config.json` di Windows, `~/.config/lumenfetch/config.json` di Linux, `~/Library/Application Support/lumenfetch/` di macOS)
270
+ - dibuat otomatis dengan nilai default saat pertama kali dijalankan. Config lama di `config.json` project root dimigrasi otomatis sekali.
271
+ Log detail tersimpan di `lumenfetch.log` sefolder config (pakai `-v/--verbose` untuk level debug).
272
+
273
+ **Folder download default** otomatis mengikuti folder **Downloads** asli sistem operasi kamu (`~/Downloads` di macOS/Linux, `C:\Users\<nama-kamu>\Downloads` di Windows) - persis seperti kebiasaan browser lain (Chrome, Firefox, Edge, dll), bukan folder relatif di dalam project. Mau ganti ke folder lain? Tinggal:
274
+
275
+ 1. Ketik `settings` di prompt utama
276
+ 2. Pilih `[1] Ganti folder download default`
277
+ 3. Ketik path folder yang diinginkan (boleh pakai `~` buat home folder, mis. `~/Documents/Video`, atau path absolut penuh)
278
+
279
+ > **Catatan:** config tersimpan di folder data user (lihat atas), bukan relatif ke folder project - jadi aman dijalankan dari mana saja.
280
+
281
+ ## ⚠️ Troubleshooting
282
+
283
+ | Masalah | Solusi |
284
+ |---------|--------|
285
+ | `ModuleNotFoundError: No module named 'yt_dlp'` / `'rich'` / `'curl_cffi'` / `'pyperclip'` / `'static_ffmpeg'` | Jalankan ulang `pip install -r requirements.txt` |
286
+ | `HTTP Error 403: Forbidden` | Update yt-dlp ke versi terbaru: `pip install --upgrade yt-dlp` |
287
+ | `Sign in to confirm you're not a bot` | Aktifkan fitur **Cookies** di atas (browser atau file) |
288
+ | `❌ Konten ini private / tidak bisa diakses` | Video private/age-restricted - aktifkan **Cookies** di atas |
289
+ | `❌ Format tidak tersedia untuk konten ini` | Coba quality lain |
290
+ | `❌ Koneksi internet bermasalah` terus muncul | Cek koneksi, atau naikkan `max_retry` lewat command `settings` |
291
+ | Video berhasil download tapi tidak ada suara | Jarang terjadi karena ffmpeg sudah bundled otomatis, tapi kalau muncul, jalankan ulang aplikasinya (ffmpeg diunduh ulang otomatis kalau file sebelumnya rusak) |
292
+ | Ganti naming template di `settings` ditolak | Template cuma boleh pakai `%(platform)s`, `%(title)s`, `%(year)s` - ditolak otomatis kalau ada placeholder salah ketik, biar tidak bikin nama file error saat download |
293
+ | `⚠️ URL ini playlist berisi N video` | Default cuma video pertama. Gunakan `--playlist all` untuk download semua sebagai file ber-index |
294
+ | Batch download | Buat file teks (satu URL per baris, `#` = komentar), lalu `python main.py --batch daftar.txt --jobs 2` |
295
+ | Resume download | Didukung via `continuedl` yt-dlp + retry backoff eksponensial (2s, 4s, 8s... max 30s). File parsial `.part` dilanjutkan, bukan diulang dari 0 |
296
+ | `ffmpeg tidak ditemukan` | Install ffmpeg sistem dulu (lebih ringan), fallback bundled otomatis. Cek dengan `ffmpeg -version` |
297
+
298
+ ## πŸ—‚οΈ Struktur Project
299
+
300
+ ```
301
+ lumenfetch/
302
+ β”œβ”€β”€ main.py # Entry point, CLI args, batch, loop utama
303
+ β”œβ”€β”€ core/
304
+ β”‚ β”œβ”€β”€ constants.py # Single source of truth (versi, format, batas)
305
+ β”‚ β”œβ”€β”€ errors.py # Taxonomy error terpusat (klasifikasi + pesan ramah)
306
+ β”‚ β”œβ”€β”€ ffmpeg.py # Deteksi ffmpeg sistem dulu, bundled fallback
307
+ β”‚ β”œβ”€β”€ log.py # Logging file terpusat
308
+ β”‚ β”œβ”€β”€ downloader.py # Download MP4 / ekstrak MP3 + resume + retry backoff
309
+ β”‚ β”œβ”€β”€ detector.py # Deteksi info video YouTube
310
+ β”‚ β”œβ”€β”€ options.py # Menu & prompt interaktif (rich)
311
+ β”‚ β”œβ”€β”€ update_checker.py # Auto-check versi terbaru yt-dlp di PyPI
312
+ β”‚ └── utils.py # Sanitasi nama file, format size, config user
313
+ β”œβ”€β”€ tests/
314
+ β”‚ β”œβ”€β”€ conftest.py # Fixture global (no-sleep) + SAMPLE_VIDEO_FORMATS
315
+ β”‚ β”œβ”€β”€ test_utils.py
316
+ β”‚ β”œβ”€β”€ test_detector.py
317
+ β”‚ β”œβ”€β”€ test_downloader.py
318
+ β”‚ β”œβ”€β”€ test_options.py
319
+ β”‚ β”œβ”€β”€ test_main.py
320
+ β”‚ └── test_features.py # Fitur (CLI, backoff, batch, ffmpeg, cookies, log)
321
+ β”œβ”€β”€ .github/
322
+ β”‚ └── workflows/
323
+ β”‚ └── tests.yml # CI: test & lint otomatis
324
+ β”œβ”€β”€ downloads/ # Folder placeholder (bukan lokasi download aktual - lihat "Naming & Konfigurasi")
325
+ β”œβ”€β”€ requirements.txt
326
+ β”œβ”€β”€ requirements-dev.txt # Dependency tambahan untuk development (pytest, ruff)
327
+ β”œβ”€β”€ pyproject.toml # Metadata project + entry point + konfigurasi ruff
328
+ β”œβ”€β”€ CONTRIBUTING.md
329
+ β”œβ”€β”€ LICENSE
330
+ └── README.md
331
+ ```
332
+
333
+ **Prinsip pemisahan modul:**
334
+ - `constants.py` - nilai shared (versi, format, batas) biar tidak drift antar modul
335
+ - `errors.py` - klasifikasi error terpusat, dipakai detector & downloader bersama
336
+ - `detector.py` - murni deteksi info video YouTube, tidak mendownload apa pun
337
+ - `downloader.py` - murni proses download MP4/MP3 & progress, tidak menampilkan menu
338
+ - `options.py` - semua interaksi & tampilan menu, tidak ada logic download
339
+ - `utils.py` - helper murni (sanitasi, format, baca/tulis config), tidak tahu soal CLI atau jaringan
340
+ - `main.py` - menyatukan semuanya lewat CLI + loop utama
341
+
342
+ ## πŸ—ΊοΈ Roadmap
343
+
344
+ - [x] **Phase 1 - Core**: struktur project, integrasi yt-dlp dasar, progress bar, config user
345
+ - [x] **Phase 2 - Smart Detection**: auto-detect video YouTube, auto-paste clipboard, preview nama file
346
+ - [x] **Phase 3 - Reliability**: resume, retry backoff eksponensial, playlist, cancel graceful
347
+ - [x] **Phase 4 - Polish**: menu history, settings, help, naming template, subtitle & metadata
348
+ - [x] **Phase 5 - Fokus YouTube**: scope MP4/MP3 saja (v2.0.0) - hapus jalur multi-platform & dep berat
349
+
350
+ ## πŸ§ͺ Testing
351
+
352
+ Ada unit test per modul (sanitasi nama file, naming template, resolve duplikat, format ukuran/durasi, config, validasi URL YouTube, opts yt-dlp, CLI, dll).
353
+
354
+ ```bash
355
+ pip install -r requirements-dev.txt
356
+ pytest tests/ -v
357
+ ruff check .
358
+ ```
359
+
360
+ CI (`.github/workflows/tests.yml`) otomatis menjalankan ini di setiap push & pull request ke `main`, di Python 3.9-3.12.
361
+
362
+ ## 🀝 Kontribusi
363
+
364
+ Mau bantu kembangin Lumenfetch? Baca [`CONTRIBUTING.md`](CONTRIBUTING.md) untuk struktur project dan alur kontribusi.
365
+
366
+ ## πŸ‘€ Author
367
+
368
+ <div align="center">
369
+
370
+ | [![Nicolas Dwi Dharma](https://github.com/github.png?size=100)](https://github.com/nekonaru) |
371
+ |:---:|
372
+ | **Nicolas Dwi Dharma** |
373
+ | [github.com/nekonaru](https://github.com/nekonaru) |
374
+
375
+ </div>
376
+
377
+ ## πŸ“„ License
378
+
379
+ Distributed under the **MIT License**. See [`LICENSE`](LICENSE) for more information.
380
+
381
+ <div align="center">
382
+
383
+ Made with πŸ“₯ by **Nicolas Dwi Dharma**
384
+
385
+ *Star ⭐ repo ini kalau project ini membantumu!*
386
+
387
+ </div>