bibbler commited on
Commit
a34596e
·
verified ·
1 Parent(s): 3f71f86

improve and enhance this wiki page dramatically using professional best practices and ui/ux principles for best ultimate user experience.

Browse files
Files changed (2) hide show
  1. README.md +9 -5
  2. index.html +904 -19
README.md CHANGED
@@ -1,10 +1,14 @@
1
  ---
2
- title: Undefined
3
- emoji: 🏆
4
- colorFrom: indigo
5
- colorTo: yellow
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
1
  ---
2
+ title: undefined
3
+ colorFrom: purple
4
+ colorTo: red
5
+ emoji: 🐳
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite-v3
10
  ---
11
 
12
+ # Welcome to your new DeepSite project!
13
+ This project was created with [DeepSite](https://deepsite.hf.co).
14
+
index.html CHANGED
@@ -1,19 +1,904 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>yt-dlp Command Templates Wiki</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script>
9
+ tailwind.config = {
10
+ theme: {
11
+ extend: {
12
+ colors: {
13
+ primary: '#0f172a',
14
+ secondary: '#1e293b',
15
+ accent: '#10b981',
16
+ 'accent-dark': '#059669',
17
+ 'gray-custom': '#64748b',
18
+ }
19
+ }
20
+ }
21
+ }
22
+ </script>
23
+ <style>
24
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
25
+
26
+ * {
27
+ font-family: 'Inter', sans-serif;
28
+ }
29
+
30
+ .command-box pre {
31
+ white-space: pre-wrap;
32
+ word-break: break-word;
33
+ }
34
+
35
+ .sidebar-active {
36
+ transform: translateX(0);
37
+ }
38
+
39
+ @media (max-width: 768px) {
40
+ .floating-sidebar {
41
+ transform: translateX(-100%);
42
+ }
43
+ }
44
+
45
+ .scrollbar-thin::-webkit-scrollbar {
46
+ width: 6px;
47
+ }
48
+
49
+ .scrollbar-thin::-webkit-scrollbar-track {
50
+ background: #1e293b;
51
+ }
52
+
53
+ .scrollbar-thin::-webkit-scrollbar-thumb {
54
+ background: #10b981;
55
+ border-radius: 3px;
56
+ }
57
+
58
+ .scrollbar-thin::-webkit-scrollbar-thumb:hover {
59
+ background: #059669;
60
+ }
61
+ </style>
62
+ </head>
63
+ <body class="bg-gradient-to-br from-slate-900 via-slate-800 to-slate-900 text-slate-100 min-h-screen">
64
+
65
+ <!-- Mobile Menu Button -->
66
+ <button id="mobileMenuBtn" class="md:hidden fixed top-4 left-4 z-50 bg-accent hover:bg-accent-dark text-white p-3 rounded-lg shadow-lg transition-all">
67
+ <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
68
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/>
69
+ </svg>
70
+ </button>
71
+
72
+ <!-- Floating Sidebar -->
73
+ <aside id="sidebar" class="floating-sidebar fixed left-0 top-0 h-full w-64 bg-secondary border-r border-slate-700 shadow-2xl z-40 overflow-y-auto scrollbar-thin transition-transform duration-300 md:translate-x-0">
74
+ <div class="p-6">
75
+ <div class="mb-8">
76
+ <h2 class="text-xl font-bold text-white mb-1">yt-dlp Wiki</h2>
77
+ <p class="text-sm text-gray-custom">Command Templates</p>
78
+ </div>
79
+
80
+ <!-- Search Box -->
81
+ <div class="mb-6">
82
+ <div class="relative">
83
+ <input
84
+ type="text"
85
+ id="searchBox"
86
+ placeholder="Search commands..."
87
+ class="w-full bg-primary text-slate-100 placeholder-gray-custom border border-slate-700 rounded-lg px-4 py-2.5 pl-10 focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent transition-all text-sm"
88
+ >
89
+ <svg class="w-5 h-5 absolute left-3 top-3 text-gray-custom" fill="none" stroke="currentColor" viewBox="0 0 24 24">
90
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/>
91
+ </svg>
92
+ </div>
93
+ </div>
94
+
95
+ <!-- Navigation -->
96
+ <nav class="space-y-1">
97
+ <a href="#channels" class="nav-link flex items-center px-3 py-2.5 text-sm font-medium text-slate-300 hover:text-white hover:bg-primary rounded-lg transition-all group">
98
+ <svg class="w-5 h-5 mr-3 text-gray-custom group-hover:text-accent transition-colors" fill="none" stroke="currentColor" viewBox="0 0 24 24">
99
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z"/>
100
+ </svg>
101
+ Channels
102
+ </a>
103
+ <a href="#playlists" class="nav-link flex items-center px-3 py-2.5 text-sm font-medium text-slate-300 hover:text-white hover:bg-primary rounded-lg transition-all group">
104
+ <svg class="w-5 h-5 mr-3 text-gray-custom group-hover:text-accent transition-colors" fill="none" stroke="currentColor" viewBox="0 0 24 24">
105
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"/>
106
+ </svg>
107
+ Playlists
108
+ </a>
109
+ <a href="#videos" class="nav-link flex items-center px-3 py-2.5 text-sm font-medium text-slate-300 hover:text-white hover:bg-primary rounded-lg transition-all group">
110
+ <svg class="w-5 h-5 mr-3 text-gray-custom group-hover:text-accent transition-colors" fill="none" stroke="currentColor" viewBox="0 0 24 24">
111
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z"/>
112
+ </svg>
113
+ Videos
114
+ </a>
115
+ <a href="#shorts" class="nav-link flex items-center px-3 py-2.5 text-sm font-medium text-slate-300 hover:text-white hover:bg-primary rounded-lg transition-all group">
116
+ <svg class="w-5 h-5 mr-3 text-gray-custom group-hover:text-accent transition-colors" fill="none" stroke="currentColor" viewBox="0 0 24 24">
117
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 18h.01M8 21h8a2 2 0 002-2V5a2 2 0 00-2-2H8a2 2 0 00-2 2v14a2 2 0 002 2z"/>
118
+ </svg>
119
+ Shorts
120
+ </a>
121
+ <a href="#lives" class="nav-link flex items-center px-3 py-2.5 text-sm font-medium text-slate-300 hover:text-white hover:bg-primary rounded-lg transition-all group">
122
+ <svg class="w-5 h-5 mr-3 text-gray-custom group-hover:text-accent transition-colors" fill="none" stroke="currentColor" viewBox="0 0 24 24">
123
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5.636 18.364a9 9 0 010-12.728m12.728 0a9 9 0 010 12.728m-9.9-2.829a5 5 0 010-7.07m7.072 0a5 5 0 010 7.07M13 12a1 1 0 11-2 0 1 1 0 012 0z"/>
124
+ </svg>
125
+ Lives
126
+ </a>
127
+ <a href="#utility" class="nav-link flex items-center px-3 py-2.5 text-sm font-medium text-slate-300 hover:text-white hover:bg-primary rounded-lg transition-all group">
128
+ <svg class="w-5 h-5 mr-3 text-gray-custom group-hover:text-accent transition-colors" fill="none" stroke="currentColor" viewBox="0 0 24 24">
129
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/>
130
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
131
+ </svg>
132
+ Utility
133
+ </a>
134
+ </nav>
135
+
136
+ <!-- Stats -->
137
+ <div class="mt-8 p-4 bg-primary rounded-lg border border-slate-700">
138
+ <p class="text-xs text-gray-custom mb-2">Total Commands</p>
139
+ <p class="text-2xl font-bold text-accent">59</p>
140
+ </div>
141
+ </div>
142
+ </aside>
143
+
144
+ <!-- Main Content -->
145
+ <main class="md:ml-64 min-h-screen">
146
+ <!-- Header -->
147
+ <header class="bg-secondary border-b border-slate-700 sticky top-0 z-30 backdrop-blur-sm bg-opacity-95">
148
+ <div class="max-w-6xl mx-auto px-6 py-6">
149
+ <div class="flex items-center justify-between">
150
+ <div>
151
+ <h1 class="text-3xl font-bold text-white mb-2">yt-dlp Command Templates</h1>
152
+ <p class="text-gray-custom">Comprehensive collection of download commands with one-click copy</p>
153
+ </div>
154
+ <button id="toggleConfig" class="px-4 py-2 bg-accent hover:bg-accent-dark text-white rounded-lg transition-all flex items-center gap-2">
155
+ <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
156
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4"/>
157
+ </svg>
158
+ Configure
159
+ </button>
160
+ </div>
161
+ </div>
162
+ </header>
163
+
164
+ <!-- Configuration Panel -->
165
+ <div id="configPanel" class="hidden fixed inset-0 bg-black bg-opacity-50 z-50 overflow-y-auto">
166
+ <div class="min-h-screen px-4 py-8 flex items-start justify-center">
167
+ <div class="bg-secondary rounded-xl border border-slate-700 max-w-4xl w-full shadow-2xl">
168
+ <!-- Panel Header -->
169
+ <div class="flex items-center justify-between p-6 border-b border-slate-700">
170
+ <div>
171
+ <h2 class="text-2xl font-bold text-white">Command Configuration</h2>
172
+ <p class="text-gray-custom mt-1">Customize parameters that will be applied to all commands</p>
173
+ </div>
174
+ <button id="closeConfig" class="text-gray-custom hover:text-white transition-colors">
175
+ <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
176
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
177
+ </svg>
178
+ </button>
179
+ </div>
180
+
181
+ <!-- Panel Content -->
182
+ <div class="p-6 space-y-6">
183
+ <!-- Config File Path -->
184
+ <div>
185
+ <label class="block text-sm font-medium text-white mb-2">Config File Path</label>
186
+ <input type="text" id="configPath"
187
+ value="/Users/bibbler/Downloads/_VIDEOS_/_Admin_/config_local/yt-channel-thumbs-v2.conf"
188
+ class="w-full bg-primary text-slate-100 border border-slate-700 rounded-lg px-4 py-2.5 focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent transition-all">
189
+ </div>
190
+
191
+ <!-- URLs Section -->
192
+ <div class="grid md:grid-cols-2 gap-6">
193
+ <div>
194
+ <label class="block text-sm font-medium text-white mb-2">Channel URL/Handle</label>
195
+ <input type="text" id="channelUrl"
196
+ value="https://www.youtube.com/@ChannelName"
197
+ placeholder="@ChannelName or full URL"
198
+ class="w-full bg-primary text-slate-100 border border-slate-700 rounded-lg px-4 py-2.5 focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent transition-all">
199
+ </div>
200
+
201
+ <div>
202
+ <label class="block text-sm font-medium text-white mb-2">Playlist ID</label>
203
+ <input type="text" id="playlistId"
204
+ value="PLAYLIST_ID"
205
+ placeholder="Enter playlist ID"
206
+ class="w-full bg-primary text-slate-100 border border-slate-700 rounded-lg px-4 py-2.5 focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent transition-all">
207
+ </div>
208
+ </div>
209
+
210
+ <div class="grid md:grid-cols-3 gap-6">
211
+ <div>
212
+ <label class="block text-sm font-medium text-white mb-2">Video ID</label>
213
+ <input type="text" id="videoId"
214
+ value="VIDEO_ID"
215
+ placeholder="Enter video ID"
216
+ class="w-full bg-primary text-slate-100 border border-slate-700 rounded-lg px-4 py-2.5 focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent transition-all">
217
+ </div>
218
+
219
+ <div>
220
+ <label class="block text-sm font-medium text-white mb-2">Short ID</label>
221
+ <input type="text" id="shortId"
222
+ value="SHORT_ID"
223
+ placeholder="Enter short ID"
224
+ class="w-full bg-primary text-slate-100 border border-slate-700 rounded-lg px-4 py-2.5 focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent transition-all">
225
+ </div>
226
+
227
+ <div>
228
+ <label class="block text-sm font-medium text-white mb-2">Live ID</label>
229
+ <input type="text" id="liveId"
230
+ value="LIVE_ID"
231
+ placeholder="Enter live ID"
232
+ class="w-full bg-primary text-slate-100 border border-slate-700 rounded-lg px-4 py-2.5 focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent transition-all">
233
+ </div>
234
+ </div>
235
+
236
+ <!-- Date Filters -->
237
+ <div class="grid md:grid-cols-2 gap-6">
238
+ <div>
239
+ <label class="block text-sm font-medium text-white mb-2">Date After (YYYYMMDD)</label>
240
+ <input type="text" id="dateAfter"
241
+ value="20240101"
242
+ placeholder="e.g., 20240101"
243
+ class="w-full bg-primary text-slate-100 border border-slate-700 rounded-lg px-4 py-2.5 focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent transition-all">
244
+ </div>
245
+
246
+ <div>
247
+ <label class="block text-sm font-medium text-white mb-2">Date Before (YYYYMMDD)</label>
248
+ <input type="text" id="dateBefore"
249
+ value="20241231"
250
+ placeholder="e.g., 20241231"
251
+ class="w-full bg-primary text-slate-100 border border-slate-700 rounded-lg px-4 py-2.5 focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent transition-all">
252
+ </div>
253
+ </div>
254
+
255
+ <!-- Output Settings -->
256
+ <div class="grid md:grid-cols-2 gap-6">
257
+ <div>
258
+ <label class="block text-sm font-medium text-white mb-2">Playlist End (Max Videos)</label>
259
+ <input type="number" id="playlistEnd"
260
+ value="100"
261
+ min="1"
262
+ class="w-full bg-primary text-slate-100 border border-slate-700 rounded-lg px-4 py-2.5 focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent transition-all">
263
+ </div>
264
+
265
+ <div>
266
+ <label class="block text-sm font-medium text-white mb-2">Output Base Path</label>
267
+ <input type="text" id="outputPath"
268
+ value="~/Downloads/_VIDEOS_/Youtube"
269
+ class="w-full bg-primary text-slate-100 border border-slate-700 rounded-lg px-4 py-2.5 focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent transition-all">
270
+ </div>
271
+ </div>
272
+
273
+ <!-- Action Buttons -->
274
+ <div class="flex items-center justify-between pt-4 border-t border-slate-700">
275
+ <button id="resetConfig" class="px-4 py-2 text-gray-custom hover:text-white transition-colors">
276
+ Reset to Defaults
277
+ </button>
278
+ <div class="flex gap-3">
279
+ <button id="cancelConfig" class="px-6 py-2 bg-slate-700 hover:bg-slate-600 text-white rounded-lg transition-all">
280
+ Cancel
281
+ </button>
282
+ <button id="applyConfig" class="px-6 py-2 bg-accent hover:bg-accent-dark text-white rounded-lg transition-all">
283
+ Apply Changes
284
+ </button>
285
+ </div>
286
+ </div>
287
+ </div>
288
+ </div>
289
+ </div>
290
+ </div>
291
+
292
+ <!-- Content -->
293
+ <div class="max-w-6xl mx-auto px-6 py-8 space-y-8">
294
+
295
+ <!-- Channels Section -->
296
+ <section id="channels" class="scroll-mt-40">
297
+ <div class="sticky top-[104px] z-20 py-4 bg-gradient-to-r from-slate-800 to-slate-900 backdrop-blur-sm bg-opacity-95 -mx-6 px-6 border-b border-slate-700">
298
+ <div class="flex items-center justify-between">
299
+ <div class="flex items-center">
300
+ <div class="h-10 w-1 bg-accent rounded-full mr-4"></div>
301
+ <h2 class="text-2xl font-bold text-white">Channels</h2>
302
+ </div>
303
+ <button onclick="toggleTOC('channels')" class="flex items-center gap-2 text-gray-custom hover:text-white transition-colors text-sm">
304
+ <span>Quick Jump</span>
305
+ <svg id="channels-arrow" class="w-4 h-4 transform transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
306
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
307
+ </svg>
308
+ </button>
309
+ </div>
310
+
311
+ <!-- Section TOC Drawer -->
312
+ <div id="channels-toc" class="hidden mt-4 pt-4 border-t border-slate-700">
313
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
314
+ <!-- Metadata -->
315
+ <div>
316
+ <h4 class="text-xs font-semibold text-accent uppercase tracking-wider mb-2">Metadata & Info</h4>
317
+ <div class="space-y-1">
318
+ <a href="#channels-1" class="block text-sm text-gray-custom hover:text-white transition-colors">1. Thumbnails Only</a>
319
+ <a href="#channels-2" class="block text-sm text-gray-custom hover:text-white transition-colors">2. + Descriptions</a>
320
+ <a href="#channels-3" class="block text-sm text-gray-custom hover:text-white transition-colors">3. + Metadata JSON</a>
321
+ <a href="#channels-4" class="block text-sm text-gray-custom hover:text-white transition-colors">4. + Desc + JSON</a>
322
+ <a href="#channels-5" class="block text-sm text-gray-custom hover:text-white transition-colors">5. + Subtitles</a>
323
+ </div>
324
+ </div>
325
+
326
+ <!-- Audio -->
327
+ <div>
328
+ <h4 class="text-xs font-semibold text-orange-500 uppercase tracking-wider mb-2">Audio Downloads</h4>
329
+ <div class="space-y-1">
330
+ <a href="#channels-6" class="block text-sm text-gray-custom hover:text-white transition-colors">6. + Audio (Best)</a>
331
+ <a href="#channels-7" class="block text-sm text-gray-custom hover:text-white transition-colors">7. + Audio (MP3)</a>
332
+ <a href="#channels-8" class="block text-sm text-gray-custom hover:text-white transition-colors">8. + Audio (M4A)</a>
333
+ <a href="#channels-9" class="block text-sm text-gray-custom hover:text-white transition-colors">9. + Audio (WebM)</a>
334
+ <a href="#channels-10" class="block text-sm text-gray-custom hover:text-white transition-colors">10. + Audio (WAV)</a>
335
+ </div>
336
+ </div>
337
+
338
+ <!-- Video -->
339
+ <div>
340
+ <h4 class="text-xs font-semibold text-blue-400 uppercase tracking-wider mb-2">Video Downloads</h4>
341
+ <div class="space-y-1">
342
+ <a href="#channels-11" class="block text-sm text-gray-custom hover:text-white transition-colors">11. + Video (Best)</a>
343
+ <a href="#channels-12" class="block text-sm text-gray-custom hover:text-white transition-colors">12. + Video (1080p)</a>
344
+ <a href="#channels-13" class="block text-sm text-gray-custom hover:text-white transition-colors">13. + Video (720p)</a>
345
+ <a href="#channels-14" class="block text-sm text-gray-custom hover:text-white transition-colors">14. + Video (480p)</a>
346
+ </div>
347
+ </div>
348
+ </div>
349
+ </div>
350
+ </div>
351
+
352
+ <div class="space-y-6">
353
+ <!-- Command Group -->
354
+ <div id="channels-1" class="command-group bg-secondary border border-slate-700 rounded-xl overflow-hidden hover:border-accent transition-all scroll-mt-48">
355
+ <div class="p-5 border-b border-slate-700">
356
+ <h3 class="text-lg font-semibold text-white">1. Thumbnails Only (100 most recent)</h3>
357
+ </div>
358
+
359
+ <div class="p-5 space-y-4">
360
+ <!-- With Config -->
361
+ <div class="command-box bg-primary border border-slate-700 rounded-lg overflow-hidden hover:border-accent transition-all">
362
+ <div class="flex items-center justify-between p-3 bg-gradient-to-r from-accent/10 to-transparent border-b border-slate-700">
363
+ <span class="text-xs font-semibold text-accent uppercase tracking-wider">With Config File</span>
364
+ <button onclick="copyToClipboard(this)" class="copy-btn px-3 py-1.5 bg-accent hover:bg-accent-dark text-white text-xs font-medium rounded transition-all">
365
+ Copy
366
+ </button>
367
+ </div>
368
+ <pre class="p-4 text-sm text-slate-300 overflow-x-auto">yt-dlp --config-location /Users/bibbler/Downloads/_VIDEOS_/_Admin_/config_local/yt-channel-thumbs-v2.conf "https://www.youtube.com/@ChannelName"</pre>
369
+ </div>
370
+
371
+ <!-- Without Config -->
372
+ <div class="command-box bg-primary border border-slate-700 rounded-lg overflow-hidden hover:border-orange-500 transition-all">
373
+ <div class="flex items-center justify-between p-3 bg-gradient-to-r from-orange-500/10 to-transparent border-b border-slate-700">
374
+ <span class="text-xs font-semibold text-orange-500 uppercase tracking-wider">Without Config File</span>
375
+ <button onclick="copyToClipboard(this)" class="copy-btn px-3 py-1.5 bg-orange-500 hover:bg-orange-600 text-white text-xs font-medium rounded transition-all">
376
+ Copy
377
+ </button>
378
+ </div>
379
+ <pre class="p-4 text-sm text-slate-300 overflow-x-auto">yt-dlp --write-thumbnail --skip-download --playlist-end 100 --output "~/Downloads/_VIDEOS_/Youtube/Thumbs/%(uploader)s/%(playlist_title)s/%(upload_date)s - %(id)s - %(title)s.%(ext)s" "https://www.youtube.com/@ChannelName"</pre>
380
+ </div>
381
+ </div>
382
+ </div>
383
+
384
+ <!-- More command groups will be loaded via JavaScript -->
385
+ </div>
386
+ </section>
387
+
388
+ <!-- Loading indicator for additional sections -->
389
+ <div id="loading" class="text-center py-8">
390
+ <div class="inline-block animate-spin rounded-full h-8 w-8 border-4 border-accent border-t-transparent"></div>
391
+ <p class="mt-4 text-gray-custom">Loading remaining commands...</p>
392
+ </div>
393
+ </div>
394
+
395
+ <!-- Back to Top Button -->
396
+ <button id="backToTop" class="fixed bottom-6 right-6 bg-accent hover:bg-accent-dark text-white p-3 rounded-full shadow-lg transition-all opacity-0 pointer-events-none">
397
+ <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
398
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 10l7-7m0 0l7 7m-7-7v18"/>
399
+ </svg>
400
+ </button>
401
+ </main>
402
+
403
+ <script src="yt-dlp-commands-complete.js"></script>
404
+ <script>
405
+ // TOC Toggle function
406
+ function toggleTOC(sectionId) {
407
+ const toc = document.getElementById(`${sectionId}-toc`);
408
+ const arrow = document.getElementById(`${sectionId}-arrow`);
409
+
410
+ if (toc.classList.contains('hidden')) {
411
+ toc.classList.remove('hidden');
412
+ arrow.classList.add('rotate-180');
413
+ } else {
414
+ toc.classList.add('hidden');
415
+ arrow.classList.remove('rotate-180');
416
+ }
417
+ }
418
+
419
+ // Configuration state
420
+ let config = {
421
+ configPath: '/Users/bibbler/Downloads/_VIDEOS_/_Admin_/config_local/yt-channel-thumbs-v2.conf',
422
+ channelUrl: 'https://www.youtube.com/@ChannelName',
423
+ playlistId: 'PLAYLIST_ID',
424
+ videoId: 'VIDEO_ID',
425
+ shortId: 'SHORT_ID',
426
+ liveId: 'LIVE_ID',
427
+ dateAfter: '20240101',
428
+ dateBefore: '20241231',
429
+ playlistEnd: '100',
430
+ outputPath: '~/Downloads/_VIDEOS_/Youtube'
431
+ };
432
+
433
+ const defaults = {...config};
434
+
435
+ // Apply substitutions to command text
436
+ function applySubstitutions(text) {
437
+ return text
438
+ .replace(/\/Users\/bibbler\/Downloads\/_VIDEOS_\/_Admin_\/config_local\/yt-channel-thumbs-v2\.conf/g, config.configPath)
439
+ .replace(/https:\/\/www\.youtube\.com\/@ChannelName/g, config.channelUrl)
440
+ .replace(/"@ChannelName"/g, `"${config.channelUrl}"`)
441
+ .replace(/playlist\?list=PLAYLIST_ID/g, `playlist?list=${config.playlistId}`)
442
+ .replace(/watch\?v=VIDEO_ID/g, `watch?v=${config.videoId}`)
443
+ .replace(/shorts\/SHORT_ID/g, `shorts/${config.shortId}`)
444
+ .replace(/watch\?v=LIVE_ID/g, `watch?v=${config.liveId}`)
445
+ .replace(/--dateafter 20240101/g, `--dateafter ${config.dateAfter}`)
446
+ .replace(/--datebefore 20241231/g, `--datebefore ${config.dateBefore}`)
447
+ .replace(/--playlist-end 100/g, `--playlist-end ${config.playlistEnd}`)
448
+ .replace(/~\/Downloads\/_VIDEOS_\/Youtube/g, config.outputPath);
449
+ }
450
+
451
+ // Update all commands with current config
452
+ function updateAllCommands() {
453
+ document.querySelectorAll('.command-box pre').forEach(pre => {
454
+ const original = pre.getAttribute('data-original') || pre.textContent;
455
+ if (!pre.getAttribute('data-original')) {
456
+ pre.setAttribute('data-original', original);
457
+ }
458
+ pre.textContent = applySubstitutions(original);
459
+ });
460
+ }
461
+
462
+ // Copy to clipboard functionality
463
+ function copyToClipboard(button) {
464
+ const commandBox = button.closest('.command-box');
465
+ const pre = commandBox.querySelector('pre');
466
+ const text = pre.textContent;
467
+
468
+ navigator.clipboard.writeText(text).then(() => {
469
+ const originalText = button.textContent;
470
+ button.textContent = 'Copied!';
471
+ button.classList.add('bg-green-600');
472
+ setTimeout(() => {
473
+ button.textContent = originalText;
474
+ button.classList.remove('bg-green-600');
475
+ }, 2000);
476
+ }).catch(err => {
477
+ console.error('Failed to copy: ', err);
478
+ });
479
+ }
480
+
481
+ // Configuration panel controls
482
+ document.getElementById('toggleConfig').addEventListener('click', () => {
483
+ document.getElementById('configPanel').classList.remove('hidden');
484
+ });
485
+
486
+ document.getElementById('closeConfig').addEventListener('click', () => {
487
+ document.getElementById('configPanel').classList.add('hidden');
488
+ });
489
+
490
+ document.getElementById('cancelConfig').addEventListener('click', () => {
491
+ document.getElementById('configPanel').classList.add('hidden');
492
+ });
493
+
494
+ document.getElementById('applyConfig').addEventListener('click', () => {
495
+ // Get values from form
496
+ config.configPath = document.getElementById('configPath').value;
497
+ config.channelUrl = document.getElementById('channelUrl').value;
498
+ config.playlistId = document.getElementById('playlistId').value;
499
+ config.videoId = document.getElementById('videoId').value;
500
+ config.shortId = document.getElementById('shortId').value;
501
+ config.liveId = document.getElementById('liveId').value;
502
+ config.dateAfter = document.getElementById('dateAfter').value;
503
+ config.dateBefore = document.getElementById('dateBefore').value;
504
+ config.playlistEnd = document.getElementById('playlistEnd').value;
505
+ config.outputPath = document.getElementById('outputPath').value;
506
+
507
+ // Update all commands
508
+ updateAllCommands();
509
+
510
+ // Close panel
511
+ document.getElementById('configPanel').classList.add('hidden');
512
+
513
+ // Show success notification
514
+ const button = document.getElementById('toggleConfig');
515
+ const originalHTML = button.innerHTML;
516
+ button.innerHTML = '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/></svg> Applied!';
517
+ setTimeout(() => {
518
+ button.innerHTML = originalHTML;
519
+ }, 2000);
520
+ });
521
+
522
+ document.getElementById('resetConfig').addEventListener('click', () => {
523
+ // Reset form to defaults
524
+ document.getElementById('configPath').value = defaults.configPath;
525
+ document.getElementById('channelUrl').value = defaults.channelUrl;
526
+ document.getElementById('playlistId').value = defaults.playlistId;
527
+ document.getElementById('videoId').value = defaults.videoId;
528
+ document.getElementById('shortId').value = defaults.shortId;
529
+ document.getElementById('liveId').value = defaults.liveId;
530
+ document.getElementById('dateAfter').value = defaults.dateAfter;
531
+ document.getElementById('dateBefore').value = defaults.dateBefore;
532
+ document.getElementById('playlistEnd').value = defaults.playlistEnd;
533
+ document.getElementById('outputPath').value = defaults.outputPath;
534
+ });
535
+
536
+ // Close panel on outside click
537
+ document.getElementById('configPanel').addEventListener('click', (e) => {
538
+ if (e.target.id === 'configPanel') {
539
+ document.getElementById('configPanel').classList.add('hidden');
540
+ }
541
+ });
542
+
543
+ // Mobile menu toggle
544
+ const mobileMenuBtn = document.getElementById('mobileMenuBtn');
545
+ const sidebar = document.getElementById('sidebar');
546
+
547
+ mobileMenuBtn.addEventListener('click', () => {
548
+ sidebar.classList.toggle('sidebar-active');
549
+ });
550
+
551
+ // Close sidebar when clicking outside on mobile
552
+ document.addEventListener('click', (e) => {
553
+ if (window.innerWidth < 768) {
554
+ if (!sidebar.contains(e.target) && !mobileMenuBtn.contains(e.target)) {
555
+ sidebar.classList.remove('sidebar-active');
556
+ }
557
+ }
558
+ });
559
+
560
+ // Close sidebar when clicking nav link on mobile
561
+ document.querySelectorAll('.nav-link').forEach(link => {
562
+ link.addEventListener('click', () => {
563
+ if (window.innerWidth < 768) {
564
+ sidebar.classList.remove('sidebar-active');
565
+ }
566
+ });
567
+ });
568
+
569
+ // Search functionality
570
+ document.getElementById('searchBox').addEventListener('input', function(e) {
571
+ const searchTerm = e.target.value.toLowerCase();
572
+ const commandGroups = document.querySelectorAll('.command-group');
573
+
574
+ commandGroups.forEach(group => {
575
+ const text = group.textContent.toLowerCase();
576
+ if (text.includes(searchTerm) || searchTerm === '') {
577
+ group.style.display = 'block';
578
+ } else {
579
+ group.style.display = 'none';
580
+ }
581
+ });
582
+ });
583
+
584
+ // Back to top functionality
585
+ const backToTop = document.getElementById('backToTop');
586
+
587
+ window.addEventListener('scroll', () => {
588
+ if (window.pageYOffset > 300) {
589
+ backToTop.classList.remove('opacity-0', 'pointer-events-none');
590
+ backToTop.classList.add('opacity-100');
591
+ } else {
592
+ backToTop.classList.add('opacity-0', 'pointer-events-none');
593
+ backToTop.classList.remove('opacity-100');
594
+ }
595
+ });
596
+
597
+ backToTop.addEventListener('click', () => {
598
+ window.scrollTo({
599
+ top: 0,
600
+ behavior: 'smooth'
601
+ });
602
+ });
603
+
604
+ // Smooth scrolling for navigation links
605
+ document.querySelectorAll('a[href^="#"]').forEach(anchor => {
606
+ anchor.addEventListener('click', function (e) {
607
+ e.preventDefault();
608
+ const target = document.querySelector(this.getAttribute('href'));
609
+ if (target) {
610
+ target.scrollIntoView({
611
+ behavior: 'smooth',
612
+ block: 'start'
613
+ });
614
+ }
615
+ });
616
+ });
617
+
618
+ // Active navigation highlighting
619
+ function updateActiveNav() {
620
+ const sections = document.querySelectorAll('section[id]');
621
+ const navLinks = document.querySelectorAll('.nav-link');
622
+
623
+ let currentSection = '';
624
+
625
+ sections.forEach(section => {
626
+ const sectionTop = section.offsetTop;
627
+ const sectionHeight = section.clientHeight;
628
+
629
+ if (window.pageYOffset >= sectionTop - 200) {
630
+ currentSection = section.getAttribute('id');
631
+ }
632
+ });
633
+
634
+ navLinks.forEach(link => {
635
+ link.classList.remove('bg-primary', 'text-white', 'border-l-4', 'border-accent');
636
+ const href = link.getAttribute('href').substring(1);
637
+
638
+ if (href === currentSection) {
639
+ link.classList.add('bg-primary', 'text-white', 'border-l-4', 'border-accent');
640
+ }
641
+ });
642
+ }
643
+
644
+ // Update on scroll
645
+ window.addEventListener('scroll', updateActiveNav);
646
+
647
+ // Update on load
648
+ window.addEventListener('load', updateActiveNav);
649
+
650
+ // Generate command template
651
+ function generateCommandGroup(number, title, withConfigCmd, withoutConfigCmd, sectionId = '') {
652
+ const commandId = sectionId ? `${sectionId}-${number}` : '';
653
+ return `
654
+ <div id="${commandId}" class="command-group bg-secondary border border-slate-700 rounded-xl overflow-hidden hover:border-accent transition-all scroll-mt-48">
655
+ <div class="p-5 border-b border-slate-700">
656
+ <h3 class="text-lg font-semibold text-white">${number}. ${title}</h3>
657
+ </div>
658
+
659
+ <div class="p-5 space-y-4">
660
+ <div class="command-box bg-primary border border-slate-700 rounded-lg overflow-hidden hover:border-accent transition-all">
661
+ <div class="flex items-center justify-between p-3 bg-gradient-to-r from-accent/10 to-transparent border-b border-slate-700">
662
+ <span class="text-xs font-semibold text-accent uppercase tracking-wider">With Config File</span>
663
+ <button onclick="copyToClipboard(this)" class="copy-btn px-3 py-1.5 bg-accent hover:bg-accent-dark text-white text-xs font-medium rounded transition-all">
664
+ Copy
665
+ </button>
666
+ </div>
667
+ <pre class="p-4 text-sm text-slate-300 overflow-x-auto">${withConfigCmd}</pre>
668
+ </div>
669
+
670
+ <div class="command-box bg-primary border border-slate-700 rounded-lg overflow-hidden hover:border-orange-500 transition-all">
671
+ <div class="flex items-center justify-between p-3 bg-gradient-to-r from-orange-500/10 to-transparent border-b border-slate-700">
672
+ <span class="text-xs font-semibold text-orange-500 uppercase tracking-wider">Without Config File</span>
673
+ <button onclick="copyToClipboard(this)" class="copy-btn px-3 py-1.5 bg-orange-500 hover:bg-orange-600 text-white text-xs font-medium rounded transition-all">
674
+ Copy
675
+ </button>
676
+ </div>
677
+ <pre class="p-4 text-sm text-slate-300 overflow-x-auto">${withoutConfigCmd}</pre>
678
+ </div>
679
+ </div>
680
+ </div>
681
+ `;
682
+ }
683
+
684
+ // Command data
685
+ const commands = {
686
+ channels: [
687
+ {title: 'Thumbnails + Descriptions (100 most recent)',
688
+ withConfig: 'yt-dlp --config-location /Users/bibbler/Downloads/_VIDEOS_/_Admin_/config_local/yt-channel-thumbs-v2.conf --write-description "https://www.youtube.com/@ChannelName"',
689
+ withoutConfig: 'yt-dlp --write-thumbnail --write-description --skip-download --playlist-end 100 --output "~/Downloads/_VIDEOS_/Youtube/Thumbs/%(uploader)s/%(playlist_title)s/%(upload_date)s - %(id)s - %(title)s.%(ext)s" "https://www.youtube.com/@ChannelName"'},
690
+
691
+ {title: 'Thumbnails + Metadata JSON (100 most recent)',
692
+ withConfig: 'yt-dlp --config-location /Users/bibbler/Downloads/_VIDEOS_/_Admin_/config_local/yt-channel-thumbs-v2.conf --write-info-json "https://www.youtube.com/@ChannelName"',
693
+ withoutConfig: 'yt-dlp --write-thumbnail --write-info-json --skip-download --playlist-end 100 --output "~/Downloads/_VIDEOS_/Youtube/Thumbs/%(uploader)s/%(playlist_title)s/%(upload_date)s - %(id)s - %(title)s.%(ext)s" "https://www.youtube.com/@ChannelName"'},
694
+
695
+ {title: 'Thumbnails + Descriptions + Metadata JSON (100 most recent)',
696
+ withConfig: 'yt-dlp --config-location /Users/bibbler/Downloads/_VIDEOS_/_Admin_/config_local/yt-channel-thumbs-v2.conf --write-description --write-info-json "https://www.youtube.com/@ChannelName"',
697
+ withoutConfig: 'yt-dlp --write-thumbnail --write-description --write-info-json --skip-download --playlist-end 100 --output "~/Downloads/_VIDEOS_/Youtube/Thumbs/%(uploader)s/%(playlist_title)s/%(upload_date)s - %(id)s - %(title)s.%(ext)s" "https://www.youtube.com/@ChannelName"'},
698
+
699
+ {title: 'Thumbnails + Descriptions + Metadata JSON + Subtitles (100 most recent)',
700
+ withConfig: 'yt-dlp --config-location /Users/bibbler/Downloads/_VIDEOS_/_Admin_/config_local/yt-channel-thumbs-v2.conf --write-description --write-info-json --write-subs --write-auto-subs --sub-langs "en" "https://www.youtube.com/@ChannelName"',
701
+ withoutConfig: 'yt-dlp --write-thumbnail --write-description --write-info-json --write-subs --write-auto-subs --sub-langs "en" --skip-download --playlist-end 100 --output "~/Downloads/_VIDEOS_/Youtube/Thumbs/%(uploader)s/%(playlist_title)s/%(upload_date)s - %(id)s - %(title)s.%(ext)s" "https://www.youtube.com/@ChannelName"'},
702
+
703
+ {title: 'Thumbnails + Descriptions + Metadata JSON + Audio (Best) (100 most recent)',
704
+ withConfig: 'yt-dlp --config-location /Users/bibbler/Downloads/_VIDEOS_/_Admin_/config_local/yt-channel-thumbs-v2.conf --write-description --write-info-json --extract-audio --audio-format best --playlist-end 100 "https://www.youtube.com/@ChannelName"',
705
+ withoutConfig: 'yt-dlp --write-thumbnail --write-description --write-info-json --extract-audio --audio-format best --playlist-end 100 --output "~/Downloads/_VIDEOS_/Youtube/Audio/%(uploader)s/%(playlist_title)s/%(upload_date)s - %(id)s - %(title)s.%(ext)s" "https://www.youtube.com/@ChannelName"'},
706
+
707
+ {title: 'Thumbnails + Descriptions + Metadata JSON + Audio (MP3) (100 most recent)',
708
+ withConfig: 'yt-dlp --config-location /Users/bibbler/Downloads/_VIDEOS_/_Admin_/config_local/yt-channel-thumbs-v2.conf --write-description --write-info-json --extract-audio --audio-format mp3 --playlist-end 100 "https://www.youtube.com/@ChannelName"',
709
+ withoutConfig: 'yt-dlp --write-thumbnail --write-description --write-info-json --extract-audio --audio-format mp3 --playlist-end 100 --output "~/Downloads/_VIDEOS_/Youtube/Audio/%(uploader)s/%(playlist_title)s/%(upload_date)s - %(id)s - %(title)s.%(ext)s" "https://www.youtube.com/@ChannelName"'},
710
+
711
+ {title: 'Thumbnails + Descriptions + Metadata JSON + Audio (M4A) (100 most recent)',
712
+ withConfig: 'yt-dlp --config-location /Users/bibbler/Downloads/_VIDEOS_/_Admin_/config_local/yt-channel-thumbs-v2.conf --write-description --write-info-json --extract-audio --audio-format m4a --playlist-end 100 "https://www.youtube.com/@ChannelName"',
713
+ withoutConfig: 'yt-dlp --write-thumbnail --write-description --write-info-json --extract-audio --audio-format m4a --playlist-end 100 --output "~/Downloads/_VIDEOS_/Youtube/Audio/%(uploader)s/%(playlist_title)s/%(upload_date)s - %(id)s - %(title)s.%(ext)s" "https://www.youtube.com/@ChannelName"'},
714
+
715
+ {title: 'Thumbnails + Descriptions + Metadata JSON + Audio (WebM) (100 most recent)',
716
+ withConfig: 'yt-dlp --config-location /Users/bibbler/Downloads/_VIDEOS_/_Admin_/config_local/yt-channel-thumbs-v2.conf --write-description --write-info-json --extract-audio --audio-format webm --playlist-end 100 "https://www.youtube.com/@ChannelName"',
717
+ withoutConfig: 'yt-dlp --write-thumbnail --write-description --write-info-json --extract-audio --audio-format webm --playlist-end 100 --output "~/Downloads/_VIDEOS_/Youtube/Audio/%(uploader)s/%(playlist_title)s/%(upload_date)s - %(id)s - %(title)s.%(ext)s" "https://www.youtube.com/@ChannelName"'},
718
+
719
+ {title: 'Thumbnails + Descriptions + Metadata JSON + Audio (WAV) (100 most recent)',
720
+ withConfig: 'yt-dlp --config-location /Users/bibbler/Downloads/_VIDEOS_/_Admin_/config_local/yt-channel-thumbs-v2.conf --write-description --write-info-json --extract-audio --audio-format wav --playlist-end 100 "https://www.youtube.com/@ChannelName"',
721
+ withoutConfig: 'yt-dlp --write-thumbnail --write-description --write-info-json --extract-audio --audio-format wav --playlist-end 100 --output "~/Downloads/_VIDEOS_/Youtube/Audio/%(uploader)s/%(playlist_title)s/%(upload_date)s - %(id)s - %(title)s.%(ext)s" "https://www.youtube.com/@ChannelName"'},
722
+
723
+ {title: 'Thumbnails + Descriptions + Metadata JSON + Video (Best) (100 most recent)',
724
+ withConfig: 'yt-dlp --config-location /Users/bibbler/Downloads/_VIDEOS_/_Admin_/config_local/yt-channel-thumbs-v2.conf --write-description --write-info-json --format "best" --playlist-end 100 "https://www.youtube.com/@ChannelName"',
725
+ withoutConfig: 'yt-dlp --write-thumbnail --write-description --write-info-json --format "best" --playlist-end 100 --output "~/Downloads/_VIDEOS_/Youtube/Videos/%(uploader)s/%(playlist_title)s/%(upload_date)s - %(id)s - %(title)s.%(ext)s" "https://www.youtube.com/@ChannelName"'},
726
+
727
+ {title: 'Thumbnails + Descriptions + Metadata JSON + Video (1080p) (100 most recent)',
728
+ withConfig: 'yt-dlp --config-location /Users/bibbler/Downloads/_VIDEOS_/_Admin_/config_local/yt-channel-thumbs-v2.conf --write-description --write-info-json --format "best[height<=1080]" --playlist-end 100 "https://www.youtube.com/@ChannelName"',
729
+ withoutConfig: 'yt-dlp --write-thumbnail --write-description --write-info-json --format "best[height<=1080]" --playlist-end 100 --output "~/Downloads/_VIDEOS_/Youtube/Videos/%(uploader)s/%(playlist_title)s/%(upload_date)s - %(id)s - %(title)s.%(ext)s" "https://www.youtube.com/@ChannelName"'},
730
+
731
+ {title: 'Thumbnails + Descriptions + Metadata JSON + Video (720p) (100 most recent)',
732
+ withConfig: 'yt-dlp --config-location /Users/bibbler/Downloads/_VIDEOS_/_Admin_/config_local/yt-channel-thumbs-v2.conf --write-description --write-info-json --format "best[height<=720]" --playlist-end 100 "https://www.youtube.com/@ChannelName"',
733
+ withoutConfig: 'yt-dlp --write-thumbnail --write-description --write-info-json --format "best[height<=720]" --playlist-end 100 --output "~/Downloads/_VIDEOS_/Youtube/Videos/%(uploader)s/%(playlist_title)s/%(upload_date)s - %(id)s - %(title)s.%(ext)s" "https://www.youtube.com/@ChannelName"'},
734
+
735
+ {title: 'Thumbnails + Descriptions + Metadata JSON + Video (480p) (100 most recent)',
736
+ withConfig: 'yt-dlp --config-location /Users/bibbler/Downloads/_VIDEOS_/_Admin_/config_local/yt-channel-thumbs-v2.conf --write-description --write-info-json --format "best[height<=480]" --playlist-end 100 "https://www.youtube.com/@ChannelName"',
737
+ withoutConfig: 'yt-dlp --write-thumbnail --write-description --write-info-json --format "best[height<=480]" --playlist-end 100 --output "~/Downloads/_VIDEOS_/Youtube/Videos/%(uploader)s/%(playlist_title)s/%(upload_date)s - %(id)s - %(title)s.%(ext)s" "https://www.youtube.com/@ChannelName"'}
738
+ ]
739
+ };
740
+
741
+ // Categorize commands
742
+ function categorizeCommands(commands, sectionId) {
743
+ const metadata = [];
744
+ const audio = [];
745
+ const video = [];
746
+ const utility = [];
747
+ const dates = [];
748
+
749
+ commands.forEach((cmd, index) => {
750
+ const title = cmd.title.toLowerCase();
751
+ const num = index + 1;
752
+ const link = `<a href="#${sectionId}-${num}" class="block text-sm text-gray-custom hover:text-white transition-colors">${num}. ${cmd.title}</a>`;
753
+
754
+ if (title.includes('audio')) {
755
+ audio.push(link);
756
+ } else if (title.includes('video') || title.includes('1080p') || title.includes('720p') || title.includes('480p')) {
757
+ video.push(link);
758
+ } else if (title.includes('date') || title.includes('before') || title.includes('after')) {
759
+ dates.push(link);
760
+ } else if (title.includes('csv') || title.includes('list')) {
761
+ utility.push(link);
762
+ } else {
763
+ metadata.push(link);
764
+ }
765
+ });
766
+
767
+ return { metadata, audio, video, utility, dates };
768
+ }
769
+
770
+ // Generate section template
771
+ function generateSection(sectionId, title, commands) {
772
+ const categories = categorizeCommands(commands, sectionId);
773
+
774
+ let tocHtml = `
775
+ <div id="${sectionId}-toc" class="hidden mt-4 pt-4 border-t border-slate-700">
776
+ <div class="grid grid-cols-1 md:grid-cols-${categories.dates.length > 0 ? '4' : '3'} gap-4">
777
+ `;
778
+
779
+ // Metadata & Info
780
+ if (categories.metadata.length > 0) {
781
+ tocHtml += `
782
+ <div>
783
+ <h4 class="text-xs font-semibold text-accent uppercase tracking-wider mb-2">Metadata & Info</h4>
784
+ <div class="space-y-1">
785
+ ${categories.metadata.join('')}
786
+ </div>
787
+ </div>
788
+ `;
789
+ }
790
+
791
+ // Audio
792
+ if (categories.audio.length > 0) {
793
+ tocHtml += `
794
+ <div>
795
+ <h4 class="text-xs font-semibold text-orange-500 uppercase tracking-wider mb-2">Audio Downloads</h4>
796
+ <div class="space-y-1">
797
+ ${categories.audio.join('')}
798
+ </div>
799
+ </div>
800
+ `;
801
+ }
802
+
803
+ // Video
804
+ if (categories.video.length > 0) {
805
+ tocHtml += `
806
+ <div>
807
+ <h4 class="text-xs font-semibold text-blue-400 uppercase tracking-wider mb-2">Video Downloads</h4>
808
+ <div class="space-y-1">
809
+ ${categories.video.join('')}
810
+ </div>
811
+ </div>
812
+ `;
813
+ }
814
+
815
+ // Date Filters
816
+ if (categories.dates.length > 0) {
817
+ tocHtml += `
818
+ <div>
819
+ <h4 class="text-xs font-semibold text-purple-400 uppercase tracking-wider mb-2">Date Filters</h4>
820
+ <div class="space-y-1">
821
+ ${categories.dates.join('')}
822
+ </div>
823
+ </div>
824
+ `;
825
+ }
826
+
827
+ // Utility
828
+ if (categories.utility.length > 0) {
829
+ tocHtml += `
830
+ <div>
831
+ <h4 class="text-xs font-semibold text-yellow-400 uppercase tracking-wider mb-2">Utility</h4>
832
+ <div class="space-y-1">
833
+ ${categories.utility.join('')}
834
+ </div>
835
+ </div>
836
+ `;
837
+ }
838
+
839
+ tocHtml += `
840
+ </div>
841
+ </div>
842
+ `;
843
+
844
+ let html = `
845
+ <section id="${sectionId}" class="scroll-mt-40">
846
+ <div class="sticky top-[104px] z-20 py-4 bg-gradient-to-r from-slate-800 to-slate-900 backdrop-blur-sm bg-opacity-95 -mx-6 px-6 border-b border-slate-700">
847
+ <div class="flex items-center justify-between">
848
+ <div class="flex items-center">
849
+ <div class="h-10 w-1 bg-accent rounded-full mr-4"></div>
850
+ <h2 class="text-2xl font-bold text-white">${title}</h2>
851
+ </div>
852
+ <button onclick="toggleTOC('${sectionId}')" class="flex items-center gap-2 text-gray-custom hover:text-white transition-colors text-sm">
853
+ <span>Quick Jump</span>
854
+ <svg id="${sectionId}-arrow" class="w-4 h-4 transform transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
855
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
856
+ </svg>
857
+ </button>
858
+ </div>
859
+ ${tocHtml}
860
+ </div>
861
+
862
+ <div class="space-y-6">
863
+ `;
864
+
865
+ commands.forEach((cmd, index) => {
866
+ html += generateCommandGroup(index + 1, cmd.title, cmd.withConfig, cmd.withoutConfig, sectionId);
867
+ });
868
+
869
+ html += `
870
+ </div>
871
+ </section>
872
+ `;
873
+
874
+ return html;
875
+ }
876
+
877
+ // Load additional commands
878
+ document.addEventListener('DOMContentLoaded', () => {
879
+ setTimeout(() => {
880
+ const channelsSection = document.querySelector('#channels .space-y-6');
881
+ commands.channels.forEach((cmd, index) => {
882
+ channelsSection.insertAdjacentHTML('beforeend', generateCommandGroup(index + 2, cmd.title, cmd.withConfig, cmd.withoutConfig, 'channels'));
883
+ });
884
+
885
+ // Load other sections if available
886
+ if (typeof allCommands !== 'undefined') {
887
+ const contentArea = document.querySelector('main .max-w-6xl');
888
+ const loadingIndicator = document.getElementById('loading');
889
+
890
+ // Insert sections before the loading indicator
891
+ loadingIndicator.insertAdjacentHTML('beforebegin', generateSection('playlists', 'Playlists', allCommands.playlists));
892
+ loadingIndicator.insertAdjacentHTML('beforebegin', generateSection('videos', 'Videos', allCommands.videos));
893
+ loadingIndicator.insertAdjacentHTML('beforebegin', generateSection('shorts', 'Shorts', allCommands.shorts));
894
+ loadingIndicator.insertAdjacentHTML('beforebegin', generateSection('lives', 'Lives', allCommands.lives));
895
+ loadingIndicator.insertAdjacentHTML('beforebegin', generateSection('utility', 'Utility', allCommands.utility));
896
+ }
897
+
898
+ // Hide loading indicator
899
+ document.getElementById('loading').style.display = 'none';
900
+ }, 100);
901
+ });
902
+ </script>
903
+ </body>
904
+ </html>