barokastor commited on
Commit
27b03cf
·
verified ·
1 Parent(s): d9e477c

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +761 -19
index.html CHANGED
@@ -1,19 +1,761 @@
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="tr">
3
+
4
+ <head>
5
+ <meta charset="utf-8" />
6
+ <meta name="viewport" content="width=device-width,initial-scale=1" />
7
+ <title>Hugging Face Bağlantı Testi</title>
8
+ <meta name="description"
9
+ content="Hugging Face’e bağlanamıyorum hatası için basit bağlantı testi ve DNS/Geo/IP bilgileri. Türkçe arayüz, modern ve duyarlı tasarım." />
10
+ <style>
11
+ :root {
12
+ --bg: #0b0f14;
13
+ --bg2: #0e131a;
14
+ --text: #e6edf3;
15
+ --muted: #9aa5b1;
16
+ --border: #1c2530;
17
+ --card: #0f1620;
18
+ --ok: #10b981;
19
+ --warn: #f59e0b;
20
+ --bad: #ef4444;
21
+ --accent: #7c3aed;
22
+ --accent2: #22d3ee;
23
+ --shadow: 0 10px 30px rgba(0, 0, 0, .35);
24
+ --radius: 16px;
25
+ }
26
+
27
+ @media (prefers-color-scheme: light) {
28
+ :root {
29
+ --bg: #f8fafc;
30
+ --bg2: #f1f5f9;
31
+ --text: #0b1220;
32
+ --muted: #475569;
33
+ --border: #e2e8f0;
34
+ --card: #ffffff;
35
+ --shadow: 0 8px 24px rgba(0, 0, 0, .08);
36
+ }
37
+ }
38
+
39
+ * {
40
+ box-sizing: border-box
41
+ }
42
+
43
+ html,
44
+ body {
45
+ height: 100%
46
+ }
47
+
48
+ body {
49
+ margin: 0;
50
+ background: radial-gradient(1200px 600px at 10% -10%, rgba(124, 58, 237, .15), transparent 60%),
51
+ radial-gradient(1200px 600px at 110% 10%, rgba(34, 211, 238, .12), transparent 60%),
52
+ var(--bg);
53
+ color: var(--text);
54
+ font: 16px/1.5 ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Inter, Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji";
55
+ }
56
+
57
+ .wrap {
58
+ max-width: 1100px;
59
+ margin: 0 auto;
60
+ padding: 24px
61
+ }
62
+
63
+ header.hero {
64
+ display: flex;
65
+ gap: 16px;
66
+ align-items: center;
67
+ justify-content: space-between;
68
+ flex-wrap: wrap;
69
+ margin: 12px 0 20px;
70
+ }
71
+
72
+ .brand {
73
+ display: flex;
74
+ align-items: center;
75
+ gap: 14px;
76
+ }
77
+
78
+ .brand .logo {
79
+ width: 42px;
80
+ height: 42px;
81
+ border-radius: 12px;
82
+ background: conic-gradient(from 200deg at 50% 50%, var(--accent), var(--accent2));
83
+ box-shadow: var(--shadow);
84
+ position: relative;
85
+ isolation: isolate;
86
+ }
87
+
88
+ .brand .logo::after {
89
+ content: "";
90
+ position: absolute;
91
+ inset: 2px;
92
+ border-radius: 10px;
93
+ background: var(--card);
94
+ mix-blend-mode: screen;
95
+ opacity: .65;
96
+ }
97
+
98
+ .brand .title {
99
+ font-weight: 700;
100
+ font-size: 22px;
101
+ letter-spacing: .2px;
102
+ }
103
+
104
+ .brand .subtitle {
105
+ font-size: 13px;
106
+ color: var(--muted);
107
+ margin-top: 2px
108
+ }
109
+
110
+ .actions {
111
+ display: flex;
112
+ gap: 10px;
113
+ align-items: center;
114
+ flex-wrap: wrap;
115
+ }
116
+
117
+ button.btn {
118
+ appearance: none;
119
+ border: 1px solid var(--border);
120
+ background: linear-gradient(180deg, var(--bg2), var(--card));
121
+ color: var(--text);
122
+ padding: 10px 14px;
123
+ border-radius: 12px;
124
+ cursor: pointer;
125
+ font-weight: 600;
126
+ letter-spacing: .2px;
127
+ box-shadow: var(--shadow);
128
+ transition: .2s transform ease, .2s filter ease, .2s background ease;
129
+ }
130
+
131
+ button.btn:hover {
132
+ transform: translateY(-1px)
133
+ }
134
+
135
+ button.btn:active {
136
+ transform: translateY(0)
137
+ }
138
+
139
+ button.primary {
140
+ background: linear-gradient(180deg, rgba(124, 58, 237, .25), rgba(124, 58, 237, .1));
141
+ border-color: color-mix(in oklab, var(--accent) 50%, var(--border));
142
+ }
143
+
144
+ .hint {
145
+ font-size: 13px;
146
+ color: var(--muted)
147
+ }
148
+
149
+ .grid {
150
+ display: grid;
151
+ gap: 16px;
152
+ grid-template-columns: 1fr;
153
+ }
154
+
155
+ @media (min-width:860px) {
156
+ .grid {
157
+ grid-template-columns: 1.1fr .9fr
158
+ }
159
+ }
160
+
161
+ .card {
162
+ background: linear-gradient(180deg, rgba(255, 255, 255, .02), transparent 60%), var(--card);
163
+ border: 1px solid var(--border);
164
+ border-radius: var(--radius);
165
+ box-shadow: var(--shadow);
166
+ padding: 16px;
167
+ }
168
+
169
+ .card h3 {
170
+ margin: 6px 0 10px;
171
+ font-size: 18px
172
+ }
173
+
174
+ .status {
175
+ display: flex;
176
+ align-items: center;
177
+ gap: 12px;
178
+ padding: 12px;
179
+ border: 1px dashed var(--border);
180
+ border-radius: 12px;
181
+ background: linear-gradient(180deg, rgba(124, 58, 237, .05), transparent 70%);
182
+ }
183
+
184
+ .dot {
185
+ width: 14px;
186
+ height: 14px;
187
+ border-radius: 50%;
188
+ background: var(--bad);
189
+ box-shadow: 0 0 0 4px rgba(239, 68, 68, .12);
190
+ }
191
+
192
+ .dot.ok {
193
+ background: var(--ok);
194
+ box-shadow: 0 0 0 4px rgba(16, 185, 129, .12)
195
+ }
196
+
197
+ .dot.warn {
198
+ background: var(--warn);
199
+ box-shadow: 0 0 0 4px rgba(245, 158, 11, .12)
200
+ }
201
+
202
+ .row {
203
+ display: flex;
204
+ align-items: center;
205
+ justify-content: space-between;
206
+ gap: 10px;
207
+ flex-wrap: wrap
208
+ }
209
+
210
+ .progress {
211
+ width: 100%;
212
+ height: 10px;
213
+ border-radius: 999px;
214
+ background: rgba(148, 163, 184, .25);
215
+ overflow: hidden;
216
+ margin-top: 12px
217
+ }
218
+
219
+ .bar {
220
+ height: 100%;
221
+ width: 0%;
222
+ background: linear-gradient(90deg, var(--accent), var(--accent2));
223
+ transition: width .3s ease;
224
+ border-radius: inherit
225
+ }
226
+
227
+ .kv {
228
+ display: grid;
229
+ grid-template-columns: 140px 1fr;
230
+ gap: 10px;
231
+ font-size: 14px;
232
+ margin-top: 10px
233
+ }
234
+
235
+ .kv div {
236
+ color: var(--muted)
237
+ }
238
+
239
+ .kv strong {
240
+ color: var(--text);
241
+ font-weight: 600
242
+ }
243
+
244
+ .tests {
245
+ display: grid;
246
+ gap: 10px;
247
+ margin-top: 6px
248
+ }
249
+
250
+ .test {
251
+ display: flex;
252
+ align-items: center;
253
+ gap: 12px;
254
+ padding: 10px;
255
+ border: 1px solid var(--border);
256
+ border-radius: 12px;
257
+ background: linear-gradient(180deg, rgba(255, 255, 255, .02), transparent 60%)
258
+ }
259
+
260
+ .pill {
261
+ padding: 4px 8px;
262
+ border-radius: 999px;
263
+ font-size: 12px;
264
+ font-weight: 700;
265
+ letter-spacing: .3px;
266
+ border: 1px solid var(--border);
267
+ color: var(--muted)
268
+ }
269
+
270
+ .pill.ok {
271
+ color: #065f46;
272
+ background: rgba(16, 185, 129, .2);
273
+ border-color: rgba(16, 185, 129, .35)
274
+ }
275
+
276
+ .pill.bad {
277
+ color: #7f1d1d;
278
+ background: rgba(239, 68, 68, .18);
279
+ border-color: rgba(239, 68, 68, .35)
280
+ }
281
+
282
+ .pill.warn {
283
+ color: #78350f;
284
+ background: rgba(245, 158, 11, .18);
285
+ border-color: rgba(245, 158, 11, .35)
286
+ }
287
+
288
+ .test .name {
289
+ flex: 1 1 auto
290
+ }
291
+
292
+ .test .meta {
293
+ color: var(--muted);
294
+ font-size: 12px
295
+ }
296
+
297
+ .footer {
298
+ display: flex;
299
+ align-items: center;
300
+ justify-content: space-between;
301
+ gap: 10px;
302
+ margin-top: 18px;
303
+ flex-wrap: wrap;
304
+ color: var(--muted);
305
+ font-size: 13px
306
+ }
307
+
308
+ a.inline {
309
+ color: var(--accent);
310
+ text-decoration: none;
311
+ border-bottom: 1px dashed color-mix(in oklab, var(--accent) 60%, transparent)
312
+ }
313
+
314
+ a.inline:hover {
315
+ opacity: .85
316
+ }
317
+
318
+ .badge {
319
+ display: inline-flex;
320
+ align-items: center;
321
+ gap: 8px;
322
+ border: 1px solid var(--border);
323
+ padding: 8px 10px;
324
+ border-radius: 12px;
325
+ background: linear-gradient(180deg, rgba(124, 58, 237, .09), rgba(124, 58, 237, .03));
326
+ }
327
+
328
+ .tiny {
329
+ font-size: 12px;
330
+ color: var(--muted);
331
+ margin-top: 8px
332
+ }
333
+
334
+ .mono {
335
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace
336
+ }
337
+
338
+ .kbd {
339
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
340
+ font-size: 12px;
341
+ border: 1px solid var(--border);
342
+ padding: 2px 6px;
343
+ border-radius: 6px;
344
+ background: var(--bg2);
345
+ color: var(--muted)
346
+ }
347
+ </style>
348
+ </head>
349
+
350
+ <body>
351
+ <div class="wrap">
352
+ <header class="hero">
353
+ <div class="brand">
354
+ <div class="logo" aria-hidden="true"></div>
355
+ <div>
356
+ <div class="title">Hugging Face Bağlantı Testi</div>
357
+ <div class="subtitle">huggingface.co bağlanmayı reddetti hatası için hızlı teşhis ve durum paneli</div>
358
+ </div>
359
+ </div>
360
+ <div class="actions">
361
+ <button class="btn primary" id="runBtn">Yeniden dene</button>
362
+ <button class="btn" id="autoBtn">Otomatik aç/kapar</button>
363
+ </div>
364
+ </header>
365
+
366
+ <div class="grid">
367
+ <section class="card">
368
+ <div class="row">
369
+ <h3>Genel durum</h3>
370
+ <div class="hint" id="lastRun">Son test: —</div>
371
+ </div>
372
+ <div class="status" aria-live="polite" aria-atomic="true">
373
+ <div class="dot" id="statusDot" title="Durum"></div>
374
+ <div>
375
+ <div id="statusTitle" style="font-weight:700">Ölçüm bekleniyor…</div>
376
+ <div id="statusMsg" class="hint">Bağlantıyı doğrulamak için küçük bir istek gönderiyoruz.</div>
377
+ <div class="progress" title="İlerleme">
378
+ <div class="bar" id="progressBar"></div>
379
+ </div>
380
+ </div>
381
+ </div>
382
+
383
+ <div style="margin-top:14px">
384
+ <div class="row">
385
+ <h3 style="margin:0">Ağ bilgileri</h3>
386
+ <span class="badge">
387
+ <span style="width:8px;height:8px;border-radius:50%;background:var(--accent2);display:inline-block"></span>
388
+ Canlı
389
+ </span>
390
+ </div>
391
+ <div class="kv">
392
+ <div>İnternet</div>
393
+ <div id="netInfo">—</div>
394
+ <div>IP</div>
395
+ <div id="ipInfo">Tespit ediliyor…</div>
396
+ <div>DNS (1.1.1.1)</div>
397
+ <div id="dnsCloudflare" class="mono">—</div>
398
+ <div>DNS (8.8.8.8)</div>
399
+ <div id="dnsGoogle" class="mono">—</div>
400
+ </div>
401
+ <div class="tiny">IP bilgisi <a class="inline" href="https://api.ipify.org?format=json" target="_blank"
402
+ rel="noopener">api.ipify.org</a> üzerinden alınmaktadır.</div>
403
+ </div>
404
+
405
+ <div style="margin-top:16px">
406
+ <div class="row">
407
+ <h3 style="margin:0">Hızlı aç</h3>
408
+ <div class="hint">Aşağıdaki bağlantılar site açıldığında çalışacaktır</div>
409
+ </div>
410
+ <div class="row" style="margin-top:8px; gap:8px">
411
+ <a class="btn" target="_blank" rel="noopener" href="https://huggingface.co/">Hugging Face Ana Sayfa</a>
412
+ <a class="btn" target="_blank" rel="noopener" href="https://huggingface.co/models">Models</a>
413
+ <a class="btn" target="_blank" rel="noopener" href="https://huggingface.co/datasets">Datasets</a>
414
+ <a class="btn" target="_blank" rel="noopener" href="https://huggingface.co/spaces">Spaces</a>
415
+ </div>
416
+ </div>
417
+ </section>
418
+
419
+ <section class="card">
420
+ <div class="row">
421
+ <h3>Test detayları</h3>
422
+ <div class="hint">Hedefler ve sonuçlar</div>
423
+ </div>
424
+ <div class="tests" id="tests"></div>
425
+
426
+ <div style="margin-top:16px">
427
+ <h3 style="margin:0 0 8px">Öneriler</h3>
428
+ <ul class="hint" style="margin:0 0 0 18px">
429
+ <li>İnternet bağlantınızı ve Wi‑Fi/Ethernet’in durumunu kontrol edin.</li>
430
+ <li>Bir VPN kullanıyorsanız geçici olarak kapatın.</li>
431
+ <li>DNS sunucularınızı 1.1.1.1 veya 8.8.8.8 olarak ayarlayın.</li>
432
+ <li>Antivirüs/Güvenlik Duvarı uygulaması huggingface.co’yu engelliyor olabilir.</li>
433
+ <li>Tarayıcınızın DNS önbelleğini temizleyin: <span class="kbd">ipconfig /flushdns</span> (Windows) veya
434
+ <span class="kbd">sudo dscacheutil -flushcache</span> (macOS).
435
+ </li>
436
+ <li>Tarayıcı eklentileri (özellikle reklam engelleyicileri) baz istekleri engelleyebilir.</li>
437
+ </ul>
438
+ </div>
439
+ </section>
440
+ </div>
441
+
442
+ <div class="footer">
443
+ <div>
444
+ <strong>Durum özeti:</strong>
445
+ <span id="summaryText">—</span>
446
+ </div>
447
+ <div>
448
+ <span class="hint">Altyapı desteği:</span>
449
+ <a class="inline" href="https://huggingface.co/" target="_blank" rel="noopener">huggingface.co</a>
450
+ <span class="hint"> • </span>
451
+ <a class="inline" href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" rel="noopener">Built
452
+ with anycoder</a>
453
+ </div>
454
+ </div>
455
+ </div>
456
+
457
+ <script>
458
+ // Utility: time formatting in Turkish
459
+ const fmtTime = (d=new Date()) => d.toLocaleString('tr-TR', {hour:'2-digit', minute:'2-digit', second:'2-digit'});
460
+ const fmtDate = (d=new Date()) => d.toLocaleString('tr-TR', {day:'2-digit', month:'short', year:'numeric'});
461
+
462
+ const $ = (sel, parent=document) => parent.querySelector(sel);
463
+
464
+ // Build a tiny, modern spinner
465
+ const makeSpinner = (size=16) => {
466
+ const s = document.createElement('span');
467
+ s.style.cssText = `
468
+ width:${size}px;height:${size}px;border:2px solid rgba(255,255,255,.25);
469
+ border-top-color:var(--accent2); border-radius:50%; display:inline-block;
470
+ animation: spin 1s linear infinite;
471
+ `;
472
+ const style = document.createElement('style');
473
+ style.textContent = `@keyframes spin{to{transform:rotate(360deg)}}`;
474
+ document.head.append(style);
475
+ return s;
476
+ };
477
+
478
+ // Image test for a given URL, resolve/reject by load/error
479
+ function imageTest(url, timeout=7000){
480
+ return new Promise((resolve, reject)=>{
481
+ const img = new Image();
482
+ let done = false;
483
+ const tidy = ()=>{
484
+ if(done) return;
485
+ done = true;
486
+ clearTimeout(to);
487
+ img.onload = img.onerror = null;
488
+ };
489
+ const to = setTimeout(()=>{ tidy(); reject(new Error('timeout')); }, timeout);
490
+ img.onload = ()=>{ tidy(); resolve({url, status:'ok'}); };
491
+ img.onerror = ()=>{ tidy(); reject(new Error('load error')); };
492
+ img.referrerPolicy = 'no-referrer';
493
+ // cache-bust to avoid accidental cached "error"
494
+ img.src = url + (url.includes('?') ? '&' : '?') + 't=' + Date.now();
495
+ });
496
+ }
497
+
498
+ // Quick fetch to HF APIs to see if CORS / connectivity is there
499
+ async function quickFetchCheck(url){
500
+ try{
501
+ const r = await fetch(url, {mode:'cors', cache:'no-store'});
502
+ return {url, status: r.ok ? 'ok' : 'warn', http: r.status};
503
+ }catch(e){
504
+ return {url, status:'bad', error: String(e && e.message || e)};
505
+ }
506
+ }
507
+
508
+ // DNS resolution attempt via platform (not standard web, but modern browsers may support)
509
+ async function resolveHost(host){
510
+ try{
511
+ if('resolveDNS' in window && typeof window.resolveDNS === 'function'){
512
+ const addrs = await window.resolveDNS(host);
513
+ return Array.isArray(addrs) ? addrs : [String(addrs)];
514
+ }
515
+ }catch(_){}
516
+ try{
517
+ const res = await fetch(`https://dns.google/resolve?name=${encodeURIComponent(host)}&type=A`);
518
+ const js = await res.json();
519
+ const addrs = (js && js.Answer || []).filter(a=>a.type===1).map(a=>a.data);
520
+ return addrs.length ? addrs : null;
521
+ }catch(_){
522
+ return null;
523
+ }
524
+ }
525
+
526
+ // Build test list UI
527
+ const targets = [
528
+ {
529
+ id:'hf_home',
530
+ title:'Ana Sayfa (huggingface.co)',
531
+ url:'https://huggingface.co/',
532
+ note:'HTTP 200',
533
+ type:'fetch',
534
+ checker: ()=>quickFetchCheck('https://huggingface.co/')
535
+ },
536
+ {
537
+ id:'hf_avatar',
538
+ title:'Hesap Avatar Görseli (CDN)',
539
+ url:'https://huggingface.co/avalonia.ai/resolve/main/README.png',
540
+ note:'Küçük resim',
541
+ type:'image',
542
+ checker: ()=>imageTest('https://huggingface.co/avalonia.ai/resolve/main/README.png')
543
+ },
544
+ {
545
+ id:'hf_models',
546
+ title:'Models Listesi',
547
+ url:'https://huggingface.co/models',
548
+ note:'HTTP 200',
549
+ type:'fetch',
550
+ checker: ()=>quickFetchCheck('https://huggingface.co/models')
551
+ },
552
+ {
553
+ id:'hf_spaces',
554
+ title:'Spaces Listesi',
555
+ url:'https://huggingface.co/spaces',
556
+ note:'HTTP 200',
557
+ type:'fetch',
558
+ checker: ()=>quickFetchCheck('https://huggingface.co/spaces')
559
+ },
560
+ {
561
+ id:'hf_api_models',
562
+ title:'HF API: /api/models (JSON)',
563
+ url:'https://huggingface.co/api/models?sort=downloads&direction=-1&limit=1',
564
+ note:'JSON CORS',
565
+ type:'fetch',
566
+ checker: ()=>quickFetchCheck('https://huggingface.co/api/models?limit=1')
567
+ }
568
+ ];
569
+
570
+ const testContainer = $('#tests');
571
+
572
+ function renderTestList(){
573
+ testContainer.innerHTML = '';
574
+ for(const t of targets){
575
+ const row = document.createElement('div');
576
+ row.className = 'test';
577
+ row.id = 'test-' + t.id;
578
+ const badge = document.createElement('span');
579
+ badge.className = 'pill';
580
+ badge.textContent = t.type.toUpperCase();
581
+ badge.title = 'Test tipi';
582
+
583
+ const name = document.createElement('div');
584
+ name.className = 'name';
585
+ name.innerHTML = `<div style="font-weight:600">${t.title}</div><div class="meta">${t.note}</div>`;
586
+
587
+ const url = document.createElement('div');
588
+ url.className = 'meta mono';
589
+ url.style.maxWidth = '340px';
590
+ url.style.overflow = 'hidden';
591
+ url.style.textOverflow = 'ellipsis';
592
+ url.style.whiteSpace = 'nowrap';
593
+ url.textContent = t.url;
594
+
595
+ const status = document.createElement('span');
596
+ status.className = 'pill';
597
+ status.id = `status-${t.id}`;
598
+ status.textContent = 'bekleniyor…';
599
+
600
+ row.appendChild(badge);
601
+ row.appendChild(name);
602
+ row.appendChild(url);
603
+ row.appendChild(status);
604
+ testContainer.appendChild(row);
605
+ }
606
+ }
607
+
608
+ // Update a test row status
609
+ function setTestStatus(id, status, extra=''){
610
+ const el = document.getElementById('status-' + id);
611
+ if(!el) return;
612
+ el.className = 'pill ' + (status==='ok' ? 'ok' : status==='bad' ? 'bad' : status==='warn' ? 'warn' : '');
613
+ el.textContent = status==='ok' ? 'başarılı' : status==='bad' ? 'başarısız' : status==='warn' ? 'uyarı' : 'bekleniyor…';
614
+ if(extra){
615
+ el.title = extra;
616
+ }
617
+ }
618
+
619
+ // Aggregate status UI
620
+ const dot = $('#statusDot');
621
+ const progressBar = $('#progressBar');
622
+ const statusTitle = $('#statusTitle');
623
+ const statusMsg = $('#statusMsg');
624
+ const lastRun = $('#lastRun');
625
+ const summaryText = $('#summaryText');
626
+
627
+ function setGlobalStatus(kind, title, msg, progress=null){
628
+ dot.className = 'dot ' + (kind==='ok' ? 'ok' : kind==='warn' ? 'warn' : 'bad');
629
+ statusTitle.textContent = title;
630
+ statusMsg.textContent = msg;
631
+ if(progress!==null) progressBar.style.width = Math.max(2, Math.min(100, progress)) + '%';
632
+ }
633
+
634
+ // IP + DNS info
635
+ async function refreshNetInfo(){
636
+ const netInfo = $('#netInfo');
637
+ const ipInfo = $('#ipInfo');
638
+ netInfo.textContent = navigator.onLine ? 'Çevrimiçi' : 'Çevrimdışı';
639
+
640
+ // IP from ipify
641
+ try{
642
+ const res = await fetch('https://api.ipify.org?format=json', {cache:'no-store'});
643
+ const js = await res.json();
644
+ ipInfo.textContent = js.ip || '—';
645
+ }catch(_){
646
+ ipInfo.textContent = 'Alınamadı';
647
+ }
648
+
649
+ // DNS resolve attempt
650
+ const dnsCF = $('#dnsCloudflare');
651
+ const dnsGG = $('#dnsGoogle');
652
+ dnsCF.textContent = '…';
653
+ dnsGG.textContent = '…';
654
+ const [cf, gg] = await Promise.allSettled([
655
+ resolveHost('huggingface.co'),
656
+ resolveHost('huggingface.co')
657
+ ]);
658
+ const toList = (p)=> p.status==='fulfilled' && Array.isArray(p.value) && p.value.length ? p.value.join(', ') : 'Çözümlenemedi';
659
+ dnsCF.textContent = toList(cf);
660
+ dnsGG.textContent = toList(gg);
661
+ }
662
+
663
+ // Main runner
664
+ let autoTimer = null;
665
+ async function runTest(){
666
+ renderTestList();
667
+ const startedAt = new Date();
668
+ lastRun.textContent = `Son test: ${fmtDate(startedAt)} • ${fmtTime(startedAt)}`;
669
+ let okCount = 0, badCount = 0, warnCount = 0;
670
+ const total = targets.length;
671
+
672
+ // Reset UI
673
+ setGlobalStatus('warn', 'Test çalışıyor…', 'Lütfen bekleyin, birkaç küçük istek yapıyoruz.', 5);
674
+ summaryText.textContent = 'ölçüm devam ediyor…';
675
+
676
+ // Run checks with concurrency
677
+ try{
678
+ await refreshNetInfo();
679
+ }catch(_){}
680
+
681
+ const tasks = targets.map(async (t, i)=>{
682
+ try{
683
+ setTestStatus(t.id, 'warn', 'kontrol ediliyor…');
684
+ const spinner = makeSpinner(14);
685
+ const pill = document.getElementById('status-' + t.id);
686
+ const prev = pill.textContent;
687
+ pill.textContent = '';
688
+ pill.appendChild(spinner);
689
+ pill.title = 'Kontrol ediliyor…';
690
+
691
+ const res = await t.checker();
692
+
693
+ // Cleanup spinner
694
+ pill.removeChild(spinner);
695
+
696
+ if(res.status === 'ok'){
697
+ okCount++;
698
+ setTestStatus(t.id, 'ok', res.http ? `HTTP ${res.http}` : 'OK');
699
+ }else if(res.status === 'warn'){
700
+ warnCount++;
701
+ setTestStatus(t.id, 'warn', res.http ? `HTTP ${res.http}` : 'Uyarı');
702
+ }else{
703
+ badCount++;
704
+ setTestStatus(t.id, 'bad', res.error ? res.error : 'Başarısız');
705
+ }
706
+ }catch(e){
707
+ badCount++;
708
+ setTestStatus(t.id, 'bad', (e && e.message) || 'Başarısız');
709
+ }finally{
710
+ const pct = Math.round(((i+1)/total)*100);
711
+ progressBar.style.width = pct + '%';
712
+ }
713
+ });
714
+
715
+ await Promise.allSettled(tasks);
716
+
717
+ // Summarize
718
+ let kind = 'bad';
719
+ if(okCount === total) kind = 'ok';
720
+ else if(okCount >= Math.ceil(total/2)) kind = 'warn';
721
+
722
+ const title = kind==='ok' ? 'Bağlantı başarılı'
723
+ : kind==='warn' ? 'Kısmi sorun olabilir'
724
+ : 'Bağlantı başarısız';
725
+
726
+ const detail = `${okCount}/${total} kontrol başarılı`;
727
+ setGlobalStatus(kind, title, detail, 100);
728
+ summaryText.textContent = detail;
729
+
730
+ // If mostly OK, open HF in a new tab (only if user pressed "Yeniden dene" recently? Keep conservative: only on auto? We won’t auto-open silently; only update UI).
731
+ // Provide a hint:
732
+ statusMsg.title = 'Aşağıdaki "Hızlı aç" bağlantılarını kullanabilirsiniz.';
733
+ }
734
+
735
+ // Wire buttons
736
+ $('#runBtn').addEventListener('click', ()=>runTest());
737
+ $('#autoBtn').addEventListener('click', (e)=>{
738
+ if(autoTimer){
739
+ clearInterval(autoTimer);
740
+ autoTimer = null;
741
+ e.currentTarget.textContent = 'Otomatik aç/kapar';
742
+ e.currentTarget.classList.remove('primary');
743
+ }else{
744
+ e.currentTarget.textContent = 'Otomatik açık (Durdur)';
745
+ e.currentTarget.classList.add('primary');
746
+ runTest();
747
+ autoTimer = setInterval(runTest, 15000);
748
+ }
749
+ });
750
+
751
+ // Initial
752
+ renderTestList();
753
+ runTest();
754
+
755
+ // Keep net indicator fresh
756
+ window.addEventListener('online', ()=>refreshNetInfo());
757
+ window.addEventListener('offline', ()=>refreshNetInfo());
758
+ </script>
759
+ </body>
760
+
761
+ </html>