djs-builder 0.6.401 → 0.7.1

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,894 @@
1
+ <!DOCTYPE html>
2
+ <html lang="ar" dir="rtl">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>لوحة التحكم - DJS-Builder</title>
7
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Noto+Color+Emoji&display=swap" rel="stylesheet">
8
+ <link href="https://cdn.jsdelivr.net/npm/remixicon@3.5.0/fonts/remixicon.css" rel="stylesheet">
9
+ <style>
10
+ :root {
11
+ --bg-primary: #030305;
12
+ --bg-secondary: #0a0a0f;
13
+ --bg-card: #12121a;
14
+ --bg-card-hover: #1a1a25;
15
+ --accent: #5865F2;
16
+ --accent-light: #7289DA;
17
+ --accent-glow: rgba(88, 101, 242, 0.3);
18
+ --purple: #9b59b6;
19
+ --pink: #e91e63;
20
+ --success: #10b981;
21
+ --warning: #f59e0b;
22
+ --danger: #ef4444;
23
+ --text-primary: #ffffff;
24
+ --text-secondary: #94a3b8;
25
+ --text-muted: #64748b;
26
+ --border: rgba(255,255,255,0.06);
27
+ --radius: 16px;
28
+ --radius-sm: 10px;
29
+ }
30
+
31
+ * { margin: 0; padding: 0; box-sizing: border-box; }
32
+ body { font-family: 'Inter', sans-serif; background: var(--bg-primary); color: var(--text-primary); min-height: 100vh; overflow-x: hidden; }
33
+ a { color: inherit; text-decoration: none; }
34
+ ::-webkit-scrollbar { width: 6px; }
35
+ ::-webkit-scrollbar-track { background: transparent; }
36
+ ::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.1); border-radius: 6px; }
37
+ ::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.2); }
38
+
39
+ /* Background Effects */
40
+ .bg-effects { position: fixed; inset: 0; pointer-events: none; overflow: hidden; z-index: 0; }
41
+ .bg-gradient-1 { position: absolute; top: -30%; right: -20%; width: 60%; height: 60%; background: radial-gradient(circle, rgba(88,101,242,0.12) 0%, transparent 60%); filter: blur(80px); }
42
+ .bg-gradient-2 { position: absolute; bottom: -30%; left: -20%; width: 50%; height: 50%; background: radial-gradient(circle, rgba(155,89,182,0.08) 0%, transparent 60%); filter: blur(80px); }
43
+ .bg-grid { position: absolute; inset: 0; background-image: linear-gradient(rgba(255,255,255,0.015) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,0.015) 1px, transparent 1px); background-size: 50px 50px; }
44
+
45
+ /* Buttons */
46
+ .btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; padding: 12px 24px; border-radius: var(--radius-sm); font-weight: 600; font-size: 14px; cursor: pointer; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); border: none; }
47
+ .btn-primary { background: linear-gradient(135deg, var(--accent), var(--accent-light)); color: white; box-shadow: 0 4px 15px var(--accent-glow); }
48
+ .btn-primary:hover { transform: translateY(-2px); box-shadow: 0 8px 25px var(--accent-glow); }
49
+ .btn-secondary { background: rgba(255,255,255,0.03); color: var(--text-primary); border: 1px solid var(--border); }
50
+ .btn-secondary:hover { background: rgba(255,255,255,0.06); border-color: var(--accent); }
51
+ .btn-ghost { background: transparent; color: var(--text-secondary); padding: 10px 16px; }
52
+ .btn-ghost:hover { color: var(--text-primary); background: rgba(255,255,255,0.05); }
53
+ .btn-sm { padding: 8px 16px; font-size: 13px; }
54
+
55
+ /* Navigation */
56
+ .nav {
57
+ position: fixed;
58
+ top: 0;
59
+ left: 0;
60
+ right: 0;
61
+ z-index: 1000;
62
+ padding: 16px 40px;
63
+ display: flex;
64
+ align-items: center;
65
+ justify-content: space-between;
66
+ background: rgba(3,3,5,0.8);
67
+ backdrop-filter: blur(20px);
68
+ border-bottom: 1px solid var(--border);
69
+ }
70
+ .nav-brand { display: flex; align-items: center; gap: 12px; }
71
+ .nav-brand img { width: 40px; height: 40px; border-radius: var(--radius-sm); }
72
+ .nav-logo { width: 40px; height: 40px; border-radius: var(--radius-sm); background: linear-gradient(135deg, var(--accent), var(--purple)); display: flex; align-items: center; justify-content: center; font-size: 18px; }
73
+ .nav-brand h1 { font-size: 20px; font-weight: 700; }
74
+
75
+ .nav-tabs { display: flex; gap: 4px; background: rgba(255,255,255,0.03); padding: 4px; border-radius: 50px; border: 1px solid var(--border); }
76
+ .nav-tab { display: flex; align-items: center; gap: 8px; padding: 10px 20px; border-radius: 50px; color: var(--text-secondary); font-size: 14px; font-weight: 500; cursor: pointer; transition: all 0.3s; border: none; background: transparent; }
77
+ .nav-tab:hover { color: var(--text-primary); }
78
+ .nav-tab.active { background: var(--accent); color: white; }
79
+ .nav-tab i { font-size: 18px; }
80
+
81
+ .nav-user { display: flex; align-items: center; gap: 12px; }
82
+ .user-menu { display: flex; align-items: center; gap: 10px; padding: 6px 14px 6px 6px; background: rgba(255,255,255,0.03); border-radius: 50px; border: 1px solid var(--border); transition: all 0.3s; }
83
+ .user-menu:hover { border-color: var(--accent); }
84
+ .user-menu img { width: 32px; height: 32px; border-radius: 50%; }
85
+ .user-menu span { font-size: 14px; font-weight: 500; }
86
+
87
+ /* Main Content */
88
+ .main { max-width: 1400px; margin: 0 auto; padding: 100px 40px 60px; position: relative; z-index: 1; }
89
+
90
+ .page-header { margin-bottom: 40px; }
91
+ .page-header h2 { font-size: 36px; font-weight: 800; margin-bottom: 8px; background: linear-gradient(135deg, #fff, var(--text-secondary)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
92
+ .page-header p { color: var(--text-secondary); font-size: 16px; }
93
+
94
+ .tab-content { display: none; }
95
+ .tab-content.active { display: block; }
96
+
97
+ /* Server Cards */
98
+ .servers-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: 20px; }
99
+
100
+ .server-card {
101
+ background: linear-gradient(145deg, var(--bg-card), rgba(18,18,26,0.6));
102
+ border: 1px solid var(--border);
103
+ border-radius: var(--radius);
104
+ padding: 24px;
105
+ display: flex;
106
+ align-items: center;
107
+ gap: 18px;
108
+ transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
109
+ position: relative;
110
+ overflow: hidden;
111
+ }
112
+ .server-card::before {
113
+ content: '';
114
+ position: absolute;
115
+ top: 0;
116
+ left: 0;
117
+ right: 0;
118
+ height: 3px;
119
+ background: linear-gradient(90deg, var(--accent), var(--purple));
120
+ transform: scaleX(0);
121
+ transform-origin: left;
122
+ transition: transform 0.4s;
123
+ }
124
+ .server-card:hover {
125
+ border-color: rgba(88,101,242,0.3);
126
+ transform: translateY(-6px);
127
+ box-shadow: 0 20px 50px rgba(0,0,0,0.4);
128
+ }
129
+ .server-card:hover::before { transform: scaleX(1); }
130
+
131
+ .server-icon { width: 64px; height: 64px; border-radius: var(--radius-sm); flex-shrink: 0; }
132
+ .server-icon-placeholder {
133
+ width: 64px;
134
+ height: 64px;
135
+ border-radius: var(--radius-sm);
136
+ background: linear-gradient(135deg, var(--bg-card-hover), var(--bg-secondary));
137
+ display: flex;
138
+ align-items: center;
139
+ justify-content: center;
140
+ font-size: 26px;
141
+ font-weight: 700;
142
+ color: var(--accent);
143
+ flex-shrink: 0;
144
+ }
145
+ .server-info { flex: 1; min-width: 0; }
146
+ .server-name { font-size: 17px; font-weight: 600; margin-bottom: 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
147
+ .server-meta { display: flex; align-items: center; gap: 10px; font-size: 13px; color: var(--text-muted); }
148
+ .server-status { display: flex; align-items: center; gap: 6px; }
149
+ .server-status .dot { width: 8px; height: 8px; background: var(--success); border-radius: 50%; animation: pulse 2s infinite; }
150
+ @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }
151
+ .server-arrow { color: var(--text-muted); font-size: 24px; transition: all 0.3s; }
152
+ .server-card:hover .server-arrow { color: var(--accent); transform: translateX(-8px); }
153
+
154
+ .no-servers {
155
+ text-align: center;
156
+ padding: 80px 40px;
157
+ background: linear-gradient(145deg, var(--bg-card), rgba(18,18,26,0.6));
158
+ border: 1px solid var(--border);
159
+ border-radius: var(--radius);
160
+ }
161
+ .no-servers-icon {
162
+ width: 100px;
163
+ height: 100px;
164
+ border-radius: 50%;
165
+ background: rgba(88,101,242,0.1);
166
+ display: flex;
167
+ align-items: center;
168
+ justify-content: center;
169
+ margin: 0 auto 24px;
170
+ }
171
+ .no-servers-icon i { font-size: 44px; color: var(--accent); }
172
+ .no-servers h3 { font-size: 24px; font-weight: 700; margin-bottom: 12px; }
173
+ .no-servers p { color: var(--text-secondary); margin-bottom: 28px; font-size: 16px; }
174
+
175
+ /* Bot Management Section */
176
+ .section-card {
177
+ background: linear-gradient(145deg, var(--bg-card), rgba(18,18,26,0.6));
178
+ border: 1px solid var(--border);
179
+ border-radius: var(--radius);
180
+ margin-bottom: 24px;
181
+ overflow: hidden;
182
+ }
183
+ .section-header {
184
+ padding: 20px 28px;
185
+ border-bottom: 1px solid var(--border);
186
+ display: flex;
187
+ align-items: center;
188
+ justify-content: space-between;
189
+ background: rgba(0,0,0,0.2);
190
+ }
191
+ .section-header h3 {
192
+ font-size: 17px;
193
+ font-weight: 600;
194
+ display: flex;
195
+ align-items: center;
196
+ gap: 12px;
197
+ }
198
+ .section-header h3 i { color: var(--accent); font-size: 22px; }
199
+ .section-content { padding: 28px; }
200
+
201
+ .badge { display: inline-flex; align-items: center; gap: 6px; padding: 6px 14px; border-radius: 50px; font-size: 12px; font-weight: 600; }
202
+ .badge-success { background: rgba(16,185,129,0.15); color: var(--success); }
203
+ .badge-warning { background: rgba(245,158,11,0.15); color: var(--warning); }
204
+
205
+ /* Bot Profile */
206
+ .bot-profile {
207
+ display: flex;
208
+ align-items: flex-start;
209
+ gap: 28px;
210
+ margin-bottom: 28px;
211
+ padding-bottom: 28px;
212
+ border-bottom: 1px solid var(--border);
213
+ }
214
+ .bot-avatar-wrapper { position: relative; }
215
+ .bot-avatar {
216
+ width: 100px;
217
+ height: 100px;
218
+ border-radius: var(--radius);
219
+ border: 3px solid transparent;
220
+ background: linear-gradient(var(--bg-card), var(--bg-card)) padding-box,
221
+ linear-gradient(135deg, var(--accent), var(--purple)) border-box;
222
+ box-shadow: 0 8px 30px var(--accent-glow);
223
+ }
224
+ .bot-status-indicator {
225
+ position: absolute;
226
+ bottom: -8px;
227
+ right: -8px;
228
+ background: var(--success);
229
+ color: white;
230
+ padding: 5px 12px;
231
+ border-radius: 50px;
232
+ font-size: 11px;
233
+ font-weight: 600;
234
+ display: flex;
235
+ align-items: center;
236
+ gap: 5px;
237
+ box-shadow: 0 4px 15px rgba(16,185,129,0.3);
238
+ }
239
+ .bot-status-indicator .dot { width: 6px; height: 6px; background: white; border-radius: 50%; animation: pulse 1.5s infinite; }
240
+
241
+ .bot-info { flex: 1; }
242
+ .bot-name { font-size: 28px; font-weight: 700; margin-bottom: 6px; }
243
+ .bot-id { font-family: monospace; font-size: 13px; color: var(--text-muted); margin-bottom: 18px; padding: 6px 12px; background: rgba(255,255,255,0.03); border-radius: var(--radius-sm); display: inline-block; }
244
+
245
+ .bot-details {
246
+ display: grid;
247
+ grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
248
+ gap: 12px;
249
+ }
250
+ .bot-detail {
251
+ background: rgba(255,255,255,0.02);
252
+ border: 1px solid var(--border);
253
+ border-radius: var(--radius-sm);
254
+ padding: 14px 16px;
255
+ transition: all 0.3s;
256
+ }
257
+ .bot-detail:hover { border-color: var(--accent); transform: translateY(-2px); }
258
+ .bot-detail-label { font-size: 11px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 4px; }
259
+ .bot-detail-value { font-size: 18px; font-weight: 700; color: var(--accent); }
260
+
261
+ /* Bot Stats */
262
+ .stats-grid {
263
+ display: grid;
264
+ grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
265
+ gap: 16px;
266
+ }
267
+ .stat-card {
268
+ text-align: center;
269
+ padding: 24px 16px;
270
+ background: rgba(255,255,255,0.02);
271
+ border: 1px solid var(--border);
272
+ border-radius: var(--radius-sm);
273
+ transition: all 0.3s;
274
+ }
275
+ .stat-card:hover { background: rgba(255,255,255,0.04); border-color: var(--accent); transform: translateY(-4px); }
276
+ .stat-card i { font-size: 28px; margin-bottom: 12px; display: block; }
277
+ .stat-card:nth-child(1) i { color: var(--accent); }
278
+ .stat-card:nth-child(2) i { color: var(--purple); }
279
+ .stat-card:nth-child(3) i { color: var(--pink); }
280
+ .stat-card:nth-child(4) i { color: var(--success); }
281
+ .stat-card:nth-child(5) i { color: var(--warning); }
282
+ .stat-value { font-size: 32px; font-weight: 800; background: linear-gradient(135deg, #fff, var(--text-secondary)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
283
+ .stat-label { font-size: 12px; color: var(--text-muted); margin-top: 6px; }
284
+
285
+ /* Commands Grid */
286
+ .commands-grid {
287
+ display: grid;
288
+ grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
289
+ gap: 12px;
290
+ padding: 24px;
291
+ }
292
+ .command-item {
293
+ background: rgba(255,255,255,0.02);
294
+ border: 1px solid var(--border);
295
+ border-radius: var(--radius-sm);
296
+ padding: 14px 16px;
297
+ display: flex;
298
+ align-items: center;
299
+ gap: 12px;
300
+ transition: all 0.3s;
301
+ }
302
+ .command-item:hover { background: rgba(255,255,255,0.04); border-color: var(--accent); transform: translateX(4px); }
303
+ .command-icon {
304
+ width: 38px;
305
+ height: 38px;
306
+ border-radius: var(--radius-sm);
307
+ background: linear-gradient(135deg, var(--accent), var(--accent-light));
308
+ display: flex;
309
+ align-items: center;
310
+ justify-content: center;
311
+ }
312
+ .command-icon i { color: white; font-size: 16px; }
313
+ .command-icon.prefix { background: linear-gradient(135deg, var(--success), #059669); }
314
+ .command-name { font-weight: 600; font-size: 14px; }
315
+ .command-type { font-size: 11px; color: var(--text-muted); margin-top: 2px; }
316
+
317
+ /* Blacklist Section */
318
+ .bl-tabs { display: flex; gap: 8px; padding: 16px 24px; border-bottom: 1px solid var(--border); }
319
+ .bl-tab {
320
+ padding: 10px 18px;
321
+ border-radius: var(--radius-sm);
322
+ background: transparent;
323
+ border: 1px solid var(--border);
324
+ color: var(--text-secondary);
325
+ cursor: pointer;
326
+ font-size: 13px;
327
+ font-weight: 500;
328
+ transition: all 0.3s;
329
+ display: flex;
330
+ align-items: center;
331
+ gap: 8px;
332
+ }
333
+ .bl-tab i { font-size: 16px; }
334
+ .bl-tab.active { background: var(--accent); border-color: var(--accent); color: white; }
335
+ .bl-tab:hover:not(.active) { background: rgba(255,255,255,0.03); border-color: var(--text-muted); }
336
+
337
+ .bl-content { padding: 20px 24px; max-height: 340px; overflow-y: auto; }
338
+ .bl-item {
339
+ display: flex;
340
+ align-items: center;
341
+ justify-content: space-between;
342
+ padding: 14px 16px;
343
+ background: rgba(255,255,255,0.02);
344
+ border: 1px solid var(--border);
345
+ border-radius: var(--radius-sm);
346
+ margin-bottom: 10px;
347
+ transition: all 0.3s;
348
+ }
349
+ .bl-item:hover { background: rgba(255,255,255,0.04); border-color: rgba(88,101,242,0.3); }
350
+ .bl-item:last-child { margin-bottom: 0; }
351
+ .bl-info { display: flex; align-items: center; gap: 12px; }
352
+ .bl-icon {
353
+ width: 40px;
354
+ height: 40px;
355
+ border-radius: 50%;
356
+ background: rgba(255,255,255,0.03);
357
+ border: 1px solid var(--border);
358
+ display: flex;
359
+ align-items: center;
360
+ justify-content: center;
361
+ color: var(--text-muted);
362
+ }
363
+ .bl-icon img { width: 40px; height: 40px; border-radius: 50%; }
364
+ .bl-name { font-weight: 600; font-size: 14px; }
365
+ .bl-remove {
366
+ padding: 8px 14px;
367
+ background: transparent;
368
+ border: 1px solid var(--danger);
369
+ color: var(--danger);
370
+ border-radius: var(--radius-sm);
371
+ cursor: pointer;
372
+ font-size: 12px;
373
+ font-weight: 500;
374
+ transition: all 0.3s;
375
+ display: flex;
376
+ align-items: center;
377
+ gap: 6px;
378
+ }
379
+ .bl-remove:hover { background: var(--danger); color: white; }
380
+ .bl-empty { text-align: center; padding: 60px 20px; color: var(--text-muted); }
381
+ .bl-empty i { font-size: 48px; display: block; margin-bottom: 16px; opacity: 0.3; }
382
+
383
+ /* Modal */
384
+ .modal { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.8); backdrop-filter: blur(8px); align-items: center; justify-content: center; z-index: 2000; }
385
+ .modal.show { display: flex; }
386
+ .modal-content {
387
+ background: linear-gradient(145deg, var(--bg-card), rgba(18,18,26,0.95));
388
+ border: 1px solid var(--border);
389
+ border-radius: var(--radius);
390
+ width: 440px;
391
+ max-width: 90%;
392
+ box-shadow: 0 25px 60px rgba(0,0,0,0.5);
393
+ animation: modalIn 0.3s ease;
394
+ }
395
+ @keyframes modalIn { from { opacity: 0; transform: scale(0.95) translateY(20px); } to { opacity: 1; transform: scale(1) translateY(0); } }
396
+ .modal-header { padding: 24px; border-bottom: 1px solid var(--border); display: flex; align-items: center; justify-content: space-between; }
397
+ .modal-header h3 { font-size: 18px; font-weight: 600; }
398
+ .modal-close { background: none; border: none; color: var(--text-muted); cursor: pointer; font-size: 24px; transition: all 0.3s; }
399
+ .modal-close:hover { color: var(--text-primary); transform: rotate(90deg); }
400
+ .modal-body { padding: 24px; }
401
+ .form-group { margin-bottom: 20px; }
402
+ .form-group label { display: block; font-size: 13px; font-weight: 500; margin-bottom: 8px; color: var(--text-secondary); }
403
+ .form-group input, .form-group select {
404
+ width: 100%;
405
+ padding: 14px 16px;
406
+ background: rgba(255,255,255,0.03);
407
+ border: 1px solid var(--border);
408
+ border-radius: var(--radius-sm);
409
+ color: var(--text-primary);
410
+ font-size: 14px;
411
+ transition: all 0.3s;
412
+ }
413
+ .form-group input:focus, .form-group select:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-glow); }
414
+ .modal-footer { padding: 20px 24px; border-top: 1px solid var(--border); display: flex; justify-content: flex-end; gap: 10px; }
415
+
416
+ .type-btns { display: flex; gap: 10px; margin-bottom: 20px; }
417
+ .type-btn {
418
+ flex: 1;
419
+ display: flex;
420
+ flex-direction: column;
421
+ align-items: center;
422
+ gap: 8px;
423
+ padding: 18px 14px;
424
+ background: rgba(255,255,255,0.02);
425
+ border: 2px solid var(--border);
426
+ border-radius: var(--radius-sm);
427
+ cursor: pointer;
428
+ transition: all 0.3s;
429
+ color: var(--text-primary);
430
+ }
431
+ .type-btn:hover { border-color: var(--text-muted); }
432
+ .type-btn.active { background: rgba(88,101,242,0.15); border-color: var(--accent); }
433
+ .type-btn i { font-size: 24px; }
434
+ .type-btn.active i { color: var(--accent); }
435
+ .type-btn span { font-size: 12px; font-weight: 500; }
436
+
437
+ /* Toast */
438
+ .toast {
439
+ position: fixed;
440
+ bottom: 24px;
441
+ left: 24px;
442
+ background: var(--bg-card);
443
+ border: 1px solid var(--border);
444
+ border-radius: var(--radius-sm);
445
+ padding: 16px 24px;
446
+ display: flex;
447
+ align-items: center;
448
+ gap: 12px;
449
+ box-shadow: 0 10px 40px rgba(0,0,0,0.4);
450
+ transform: translateY(120px);
451
+ opacity: 0;
452
+ transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
453
+ z-index: 3000;
454
+ }
455
+ .toast.show { transform: translateY(0); opacity: 1; }
456
+ .toast.success { border-color: var(--success); }
457
+ .toast.success i { color: var(--success); }
458
+ .toast.error { border-color: var(--danger); }
459
+ .toast.error i { color: var(--danger); }
460
+
461
+ /* Animations */
462
+ @keyframes fadeIn { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } }
463
+ .animate-in { animation: fadeIn 0.5s ease forwards; }
464
+
465
+ /* Responsive */
466
+ @media (max-width: 992px) {
467
+ .nav-tabs { gap: 2px; }
468
+ .nav-tab span { display: none; }
469
+ .nav-tab { padding: 10px 14px; }
470
+ }
471
+ @media (max-width: 768px) {
472
+ .nav { padding: 14px 16px; }
473
+ .nav-tabs { display: flex; }
474
+ .nav-brand h1 { font-size: 16px; }
475
+ .user-menu span { display: none; }
476
+ .user-menu { padding: 6px; }
477
+ .main { padding: 90px 16px 40px; }
478
+ .page-header h2 { font-size: 28px; }
479
+ .servers-grid { grid-template-columns: 1fr; gap: 14px; }
480
+ .server-card { padding: 18px; }
481
+ .server-icon, .server-icon-placeholder { width: 52px; height: 52px; }
482
+ .bot-profile { flex-direction: column; align-items: center; text-align: center; }
483
+ .bot-avatar { width: 80px; height: 80px; }
484
+ .bot-name { font-size: 22px; }
485
+ .bot-details { grid-template-columns: repeat(3, 1fr); }
486
+ .stats-grid { grid-template-columns: repeat(2, 1fr); gap: 12px; }
487
+ .stat-card { padding: 18px 14px; }
488
+ .stat-value { font-size: 26px; }
489
+ .commands-grid { grid-template-columns: 1fr; padding: 16px; }
490
+ .section-header { padding: 16px 20px; }
491
+ .section-header h3 { font-size: 15px; }
492
+ .bl-tabs { padding: 12px 16px; flex-wrap: wrap; }
493
+ .bl-tab { padding: 8px 14px; font-size: 12px; }
494
+ .bl-content { padding: 16px; }
495
+ .bl-item { padding: 12px; flex-direction: column; gap: 12px; align-items: flex-start; }
496
+ .type-btns { flex-direction: column; }
497
+ .modal-content { width: 95%; margin: 16px; }
498
+ }
499
+ @media (max-width: 480px) {
500
+ .page-header h2 { font-size: 24px; }
501
+ .bot-details { grid-template-columns: 1fr 1fr; }
502
+ .stats-grid { grid-template-columns: 1fr 1fr; }
503
+ .stat-card i { font-size: 22px; }
504
+ .stat-value { font-size: 22px; }
505
+ }
506
+ </style>
507
+ </head>
508
+ <body>
509
+ <!-- Background Effects -->
510
+ <div class="bg-effects">
511
+ <div class="bg-gradient-1"></div>
512
+ <div class="bg-gradient-2"></div>
513
+ <div class="bg-grid"></div>
514
+ </div>
515
+
516
+ <!-- Navigation -->
517
+ <nav class="nav">
518
+ <a href="/" class="nav-brand">
519
+ <% if (botStats.botAvatar) { %><img src="<%= botStats.botAvatar %>" alt="Bot"><% } else { %><div class="nav-logo"><i class="ri-robot-fill"></i></div><% } %>
520
+ <h1>DJS-Builder</h1>
521
+ </a>
522
+
523
+ <div class="nav-tabs">
524
+ <button class="nav-tab active" data-tab="servers"><i class="ri-server-line"></i><span>السيرفرات</span></button>
525
+ <button class="nav-tab" data-tab="bot"><i class="ri-robot-line"></i><span>إدارة البوت</span></button>
526
+ </div>
527
+
528
+ <div class="nav-user">
529
+ <a href="/logout" class="btn btn-ghost btn-sm"><i class="ri-logout-box-r-line"></i></a>
530
+ <div class="user-menu">
531
+ <img src="https://cdn.discordapp.com/avatars/<%= user.id %>/<%= user.avatar %>.png?size=64" alt="<%= user.username %>">
532
+ <span><%= user.username %></span>
533
+ </div>
534
+ </div>
535
+ </nav>
536
+
537
+ <!-- Main Content -->
538
+ <main class="main">
539
+ <!-- Servers Tab -->
540
+ <div id="servers" class="tab-content active">
541
+ <div class="page-header animate-in">
542
+ <h2><i class="ri-hand-heart-line" style="margin-left: 10px; color: var(--accent);"></i> مرحباً، <%= user.username %>!</h2>
543
+ <p>اختر سيرفر من القائمة لبدء الإدارة</p>
544
+ </div>
545
+
546
+ <% if (guilds.length > 0) { %>
547
+ <div class="servers-grid">
548
+ <% guilds.forEach((guild, index) => { %>
549
+ <a href="/dashboard/<%= guild.id %>" class="server-card animate-in" style="animation-delay: <%= index * 0.05 %>s">
550
+ <% if (guild.icon) { %>
551
+ <img src="https://cdn.discordapp.com/icons/<%= guild.id %>/<%= guild.icon %>.png?size=128" alt="<%= guild.name %>" class="server-icon">
552
+ <% } else { %>
553
+ <div class="server-icon-placeholder"><%= guild.name.charAt(0).toUpperCase() %></div>
554
+ <% } %>
555
+ <div class="server-info">
556
+ <div class="server-name"><%= guild.name %></div>
557
+ <div class="server-meta">
558
+ <div class="server-status"><span class="dot"></span> متصل</div>
559
+ </div>
560
+ </div>
561
+ <i class="ri-arrow-left-s-line server-arrow"></i>
562
+ </a>
563
+ <% }); %>
564
+ </div>
565
+ <% } else { %>
566
+ <div class="no-servers animate-in">
567
+ <div class="no-servers-icon"><i class="ri-server-line"></i></div>
568
+ <h3>لا توجد سيرفرات</h3>
569
+ <p>لا يوجد لديك سيرفرات مشتركة مع البوت حالياً</p>
570
+ <a href="https://discord.com/api/oauth2/authorize?client_id=<%= botStats.botId %>&permissions=8&scope=bot%20applications.commands" target="_blank" class="btn btn-primary">
571
+ <i class="ri-add-line"></i> أضف البوت لسيرفرك
572
+ </a>
573
+ </div>
574
+ <% } %>
575
+ </div>
576
+
577
+ <!-- Bot Management Tab -->
578
+ <div id="bot" class="tab-content">
579
+ <div class="page-header animate-in">
580
+ <h2>إدارة البوت</h2>
581
+ <p>معلومات وإحصائيات البوت والأوامر المتاحة</p>
582
+ </div>
583
+
584
+ <!-- Bot Info Section -->
585
+ <div class="section-card animate-in" style="animation-delay: 0.1s">
586
+ <div class="section-header">
587
+ <h3><i class="ri-robot-line"></i> معلومات البوت</h3>
588
+ <span class="badge badge-success"><i class="ri-wifi-line"></i> متصل</span>
589
+ </div>
590
+ <div class="section-content">
591
+ <div class="bot-profile">
592
+ <div class="bot-avatar-wrapper">
593
+ <img src="<%= botStats.botAvatar || 'https://cdn.discordapp.com/embed/avatars/0.png' %>" alt="Bot" class="bot-avatar">
594
+ <div class="bot-status-indicator"><span class="dot"></span> Online</div>
595
+ </div>
596
+ <div class="bot-info">
597
+ <div class="bot-name"><%= botStats.botName %></div>
598
+ <div class="bot-id">ID: <%= botStats.botId %></div>
599
+ <div class="bot-details">
600
+ <div class="bot-detail">
601
+ <div class="bot-detail-label">البادئة</div>
602
+ <div class="bot-detail-value"><%= botStats.prefix || '-' %></div>
603
+ </div>
604
+ <div class="bot-detail">
605
+ <div class="bot-detail-label">Ping</div>
606
+ <div class="bot-detail-value"><%= botStats.ping %>ms</div>
607
+ </div>
608
+ <div class="bot-detail">
609
+ <div class="bot-detail-label">التشغيل</div>
610
+ <div class="bot-detail-value" id="uptime">-</div>
611
+ </div>
612
+ </div>
613
+ </div>
614
+ </div>
615
+
616
+ <div class="stats-grid">
617
+ <div class="stat-card">
618
+ <i class="ri-server-line"></i>
619
+ <div class="stat-value"><%= botStats.guilds %></div>
620
+ <div class="stat-label">سيرفر</div>
621
+ </div>
622
+ <div class="stat-card">
623
+ <i class="ri-group-line"></i>
624
+ <div class="stat-value"><%= botStats.users.toLocaleString() %></div>
625
+ <div class="stat-label">مستخدم</div>
626
+ </div>
627
+ <div class="stat-card">
628
+ <i class="ri-terminal-box-line"></i>
629
+ <div class="stat-value"><%= botStats.slashCommands %></div>
630
+ <div class="stat-label">سلاش</div>
631
+ </div>
632
+ <div class="stat-card">
633
+ <i class="ri-text"></i>
634
+ <div class="stat-value"><%= botStats.prefixCommands %></div>
635
+ <div class="stat-label">بريفكس</div>
636
+ </div>
637
+ <div class="stat-card">
638
+ <i class="ri-calendar-event-line"></i>
639
+ <div class="stat-value"><%= botStats.events %></div>
640
+ <div class="stat-label">حدث</div>
641
+ </div>
642
+ </div>
643
+ </div>
644
+ </div>
645
+
646
+ <!-- Commands Section -->
647
+ <div class="section-card animate-in" style="animation-delay: 0.15s">
648
+ <div class="section-header">
649
+ <h3><i class="ri-terminal-line"></i> أوامر البوت</h3>
650
+ <span class="badge badge-warning"><%= botStats.slashCommands + botStats.prefixCommands %> أمر</span>
651
+ </div>
652
+ <div class="commands-grid">
653
+ <% if (client.slashCommands) { client.slashCommands.forEach(cmd => { if (cmd && cmd.name) { %>
654
+ <div class="command-item">
655
+ <div class="command-icon"><i class="ri-slash-commands-2"></i></div>
656
+ <div>
657
+ <div class="command-name">/<%= cmd.name %></div>
658
+ <div class="command-type">Slash Command</div>
659
+ </div>
660
+ </div>
661
+ <% } }); } %>
662
+ <% const seenPrefix = new Set(); if (client.prefixCommands) { client.prefixCommands.forEach(cmd => { if (cmd && cmd.name && !seenPrefix.has(cmd.name)) { seenPrefix.add(cmd.name); %>
663
+ <div class="command-item">
664
+ <div class="command-icon prefix"><i class="ri-text"></i></div>
665
+ <div>
666
+ <div class="command-name"><%= botStats.prefix || '-' %><%= cmd.name %></div>
667
+ <div class="command-type">Prefix Command</div>
668
+ </div>
669
+ </div>
670
+ <% } }); } %>
671
+ </div>
672
+ </div>
673
+
674
+ <!-- Blacklist Section -->
675
+ <div class="section-card animate-in" style="animation-delay: 0.2s">
676
+ <div class="section-header">
677
+ <h3><i class="ri-shield-cross-line"></i> القائمة السوداء العامة</h3>
678
+ <button class="btn btn-sm btn-primary" onclick="openBlacklistModal()"><i class="ri-add-line"></i> إضافة</button>
679
+ </div>
680
+ <div class="bl-tabs">
681
+ <button class="bl-tab active" data-bl="users"><i class="ri-user-line"></i> المستخدمون</button>
682
+ <button class="bl-tab" data-bl="roles"><i class="ri-shield-user-line"></i> الأدوار</button>
683
+ <button class="bl-tab" data-bl="channels"><i class="ri-hashtag"></i> القنوات</button>
684
+ </div>
685
+ <div class="bl-content" id="blacklistContent">
686
+ <div class="bl-empty"><i class="ri-shield-line"></i>لا توجد عناصر في القائمة</div>
687
+ </div>
688
+ </div>
689
+ </div>
690
+ </main>
691
+
692
+ <!-- Blacklist Modal -->
693
+ <div class="modal" id="blacklistModal">
694
+ <div class="modal-content">
695
+ <div class="modal-header">
696
+ <h3>إضافة للقائمة السوداء العامة</h3>
697
+ <button class="modal-close" onclick="closeBlacklistModal()">&times;</button>
698
+ </div>
699
+ <div class="modal-body">
700
+ <label style="font-size: 13px; font-weight: 500; margin-bottom: 12px; display: block;">اختر النوع</label>
701
+ <div class="type-btns">
702
+ <button type="button" class="type-btn active" data-type="user" onclick="selectBlType('user')">
703
+ <i class="ri-user-line"></i>
704
+ <span>مستخدم</span>
705
+ </button>
706
+ <button type="button" class="type-btn" data-type="role" onclick="selectBlType('role')">
707
+ <i class="ri-shield-user-line"></i>
708
+ <span>رتبة</span>
709
+ </button>
710
+ <button type="button" class="type-btn" data-type="channel" onclick="selectBlType('channel')">
711
+ <i class="ri-hashtag"></i>
712
+ <span>قناة</span>
713
+ </button>
714
+ </div>
715
+ <div class="form-group">
716
+ <label id="blTypeLabel">معرف المستخدم</label>
717
+ <input type="text" id="blId" placeholder="أدخل المعرف...">
718
+ </div>
719
+ <input type="hidden" id="blType" value="user">
720
+ </div>
721
+ <div class="modal-footer">
722
+ <button class="btn btn-secondary" onclick="closeBlacklistModal()">إلغاء</button>
723
+ <button class="btn btn-primary" onclick="addToGlobalBlacklist()"><i class="ri-add-line"></i> إضافة</button>
724
+ </div>
725
+ </div>
726
+ </div>
727
+
728
+ <div class="toast" id="toast"><i class="ri-checkbox-circle-fill"></i><span id="toastText"></span></div>
729
+
730
+ <script>
731
+ // Tab switching
732
+ document.querySelectorAll('.nav-tab').forEach(tab => {
733
+ tab.addEventListener('click', () => {
734
+ document.querySelectorAll('.nav-tab').forEach(t => t.classList.remove('active'));
735
+ document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
736
+ tab.classList.add('active');
737
+ document.getElementById(tab.dataset.tab).classList.add('active');
738
+ });
739
+ });
740
+
741
+ // Blacklist tabs
742
+ document.querySelectorAll('.bl-tab').forEach(tab => {
743
+ tab.addEventListener('click', () => {
744
+ document.querySelectorAll('.bl-tab').forEach(t => t.classList.remove('active'));
745
+ tab.classList.add('active');
746
+ loadBlacklist(tab.dataset.bl);
747
+ });
748
+ });
749
+
750
+ // Uptime
751
+ const startTime = <%= botStats.startedAt || Date.now() %>;
752
+ function updateUptime() {
753
+ const diff = Date.now() - startTime;
754
+ const hours = Math.floor(diff / (1000 * 60 * 60));
755
+ const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
756
+ document.getElementById('uptime').textContent = hours + 'h ' + minutes + 'm';
757
+ }
758
+ updateUptime();
759
+ setInterval(updateUptime, 60000);
760
+
761
+ // Toast
762
+ function showToast(message, type = 'success') {
763
+ const toast = document.getElementById('toast');
764
+ document.getElementById('toastText').textContent = message;
765
+ toast.className = 'toast show ' + type;
766
+ setTimeout(() => toast.classList.remove('show'), 3000);
767
+ }
768
+
769
+ // Modal functions
770
+ function selectBlType(type) {
771
+ document.querySelectorAll('.type-btn').forEach(btn => {
772
+ btn.classList.toggle('active', btn.dataset.type === type);
773
+ });
774
+ document.getElementById('blType').value = type;
775
+ const labels = { user: 'معرف المستخدم', role: 'معرف الرتبة', channel: 'معرف القناة' };
776
+ document.getElementById('blTypeLabel').textContent = labels[type];
777
+ }
778
+
779
+ function openBlacklistModal() {
780
+ selectBlType('user');
781
+ document.getElementById('blacklistModal').classList.add('show');
782
+ }
783
+
784
+ function closeBlacklistModal() {
785
+ document.getElementById('blacklistModal').classList.remove('show');
786
+ document.getElementById('blId').value = '';
787
+ }
788
+
789
+ // Load blacklist
790
+ async function loadBlacklist(type) {
791
+ try {
792
+ const res = await fetch('/api/blacklist/' + type);
793
+ const data = await res.json();
794
+ const content = document.getElementById('blacklistContent');
795
+
796
+ if (data.items && data.items.length > 0) {
797
+ content.innerHTML = data.items.map(item => {
798
+ let iconHtml = '';
799
+ if (type === 'users') {
800
+ iconHtml = '<i class="ri-user-fill" style="font-size: 18px;"></i>';
801
+ } else if (type === 'roles') {
802
+ iconHtml = '<i class="ri-shield-user-fill" style="font-size: 18px;"></i>';
803
+ } else {
804
+ iconHtml = '<span style="font-size: 20px; font-weight: 700; color: var(--text-muted);">#</span>';
805
+ }
806
+ return `
807
+ <div class="bl-item" data-id="${item.id}" data-type="${type}">
808
+ <div class="bl-info">
809
+ <div class="bl-icon">${iconHtml}</div>
810
+ <div>
811
+ <div class="bl-name" id="bl-name-${item.id}">${item.id}</div>
812
+ <div style="font-size: 11px; color: var(--text-muted);">${type === 'users' ? 'مستخدم' : type === 'roles' ? 'رتبة' : 'قناة'}</div>
813
+ </div>
814
+ </div>
815
+ <button class="bl-remove" onclick="removeFromGlobalBlacklist('${type.slice(0,-1)}', '${item.id}')">
816
+ <i class="ri-delete-bin-line"></i> إزالة
817
+ </button>
818
+ </div>
819
+ `}).join('');
820
+
821
+ if (type === 'users') {
822
+ data.items.forEach(item => loadUserInfo(item.id));
823
+ }
824
+ } else {
825
+ content.innerHTML = '<div class="bl-empty"><i class="ri-shield-line"></i>لا توجد عناصر في القائمة</div>';
826
+ }
827
+ } catch (e) { console.error(e); }
828
+ }
829
+
830
+ async function loadUserInfo(userId) {
831
+ try {
832
+ const res = await fetch(`/api/user/${userId}`);
833
+ if (res.ok) {
834
+ const user = await res.json();
835
+ if (user && !user.error) {
836
+ const nameEl = document.getElementById(`bl-name-${userId}`);
837
+ const iconEl = document.querySelector(`.bl-item[data-id="${userId}"] .bl-icon`);
838
+ if (nameEl) nameEl.textContent = user.global_name || user.username || userId;
839
+ if (iconEl && user.avatar) {
840
+ iconEl.innerHTML = `<img src="https://cdn.discordapp.com/avatars/${userId}/${user.avatar}.png?size=64" alt="">`;
841
+ }
842
+ }
843
+ }
844
+ } catch (e) { console.error('Error loading user:', e); }
845
+ }
846
+
847
+ async function addToGlobalBlacklist() {
848
+ const type = document.getElementById('blType').value;
849
+ const id = document.getElementById('blId').value.trim();
850
+ if (!id) return showToast('أدخل المعرف', 'error');
851
+
852
+ try {
853
+ const res = await fetch('/api/blacklist', {
854
+ method: 'POST',
855
+ headers: { 'Content-Type': 'application/json' },
856
+ body: JSON.stringify({ type, id })
857
+ });
858
+ const data = await res.json();
859
+
860
+ if (data.success) {
861
+ showToast('تمت الإضافة بنجاح');
862
+ closeBlacklistModal();
863
+ loadBlacklist(type + 's');
864
+ } else {
865
+ showToast(data.error || 'حدث خطأ', 'error');
866
+ }
867
+ } catch (e) { showToast('حدث خطأ', 'error'); }
868
+ }
869
+
870
+ async function removeFromGlobalBlacklist(type, id) {
871
+ if (!confirm('هل أنت متأكد من الإزالة؟')) return;
872
+
873
+ try {
874
+ const res = await fetch('/api/blacklist', {
875
+ method: 'DELETE',
876
+ headers: { 'Content-Type': 'application/json' },
877
+ body: JSON.stringify({ type, id })
878
+ });
879
+ const data = await res.json();
880
+
881
+ if (data.success) {
882
+ showToast('تمت الإزالة بنجاح');
883
+ document.querySelector(`.bl-item[data-id="${id}"]`).remove();
884
+ } else {
885
+ showToast(data.error || 'خطأ', 'error');
886
+ }
887
+ } catch (e) { showToast('خطأ', 'error'); }
888
+ }
889
+
890
+ // Load blacklist on init
891
+ loadBlacklist('users');
892
+ </script>
893
+ </body>
894
+ </html>