Opera8 commited on
Commit
8d7ac9a
·
verified ·
1 Parent(s): 47c472c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +264 -7
app.py CHANGED
@@ -353,8 +353,13 @@ def infer(
353
 
354
  except Exception as e:
355
  error_str = str(e)
 
 
 
356
  if "quota" in error_str.lower() or "exceeded" in error_str.lower():
 
357
  raise e
 
358
  return None, seed, get_error_html(f"خطا در پردازش: {error_str}"), gr.update(visible=True), gr.update(visible=False)
359
 
360
  @spaces.GPU(duration=30)
@@ -390,7 +395,7 @@ js_upgrade_func = """
390
  }
391
  """
392
 
393
- # --- جاوااسکریپت سراسری ---
394
  js_global_content = """
395
  <script>
396
  document.addEventListener('DOMContentLoaded', () => {
@@ -437,7 +442,6 @@ document.addEventListener('DOMContentLoaded', () => {
437
  const fpInput = document.querySelector('#fingerprint_storage textarea');
438
  const stInput = document.querySelector('#status_storage textarea');
439
 
440
- // Only dispatch if value changes or if it's empty
441
  if(fpInput && fingerprint && fpInput.value !== fingerprint) {
442
  fpInput.value = fingerprint;
443
  fpInput.dispatchEvent(new Event('input', { bubbles: true }));
@@ -500,7 +504,118 @@ document.addEventListener('DOMContentLoaded', () => {
500
 
501
  initUserIdentity();
502
 
503
- // 2. Force Light Mode
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
504
  const forceLight = () => {
505
  const body = document.querySelector('body');
506
  if (body) {
@@ -516,7 +631,7 @@ document.addEventListener('DOMContentLoaded', () => {
516
  </script>
517
  """
518
 
519
- # --- CSS Updated ---
520
  css_code = """
521
  <style>
522
  @import url('https://fonts.googleapis.com/css2?family=Vazirmatn:wght@300;400;500;700&display=swap');
@@ -535,6 +650,149 @@ css_code = """
535
  font-family: 'Vazirmatn', sans-serif !important;
536
  }
537
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
538
  /* Hidden inputs logic */
539
  #fingerprint_storage, #status_storage {
540
  display: none !important;
@@ -557,7 +815,6 @@ css_code = """
557
  transition: all 0.3s ease;
558
  }
559
 
560
- /* Main App CSS */
561
  body { margin: 0; padding: 10px; }
562
 
563
  #col-container {
@@ -710,6 +967,8 @@ textarea:focus, input[type="text"]:focus {
710
 
711
  footer { display: none !important; }
712
  .flagging { display: none !important; }
 
 
713
  .toast-body { direction: rtl !important; text-align: right !important; background: transparent !important; box-shadow: none !important; border: none !important; padding: 0 !important; max-width: 100% !important; width: auto !important; }
714
  .toast-wrap { background: transparent !important; border: none !important; box-shadow: none !important; }
715
 
@@ -731,7 +990,6 @@ with gr.Blocks() as demo:
731
  gr.HTML(combined_html)
732
 
733
  # اینپوت‌های مخفی برای انتقال دیتای کاربر از JS به Python
734
- # visible=True است تا در DOM باشد ولی با CSS مخفی شده است
735
  fingerprint_box = gr.Textbox(elem_id="fingerprint_storage", visible=True)
736
  status_box_input = gr.Textbox(elem_id="status_storage", visible=True)
737
 
@@ -835,7 +1093,6 @@ with gr.Blocks() as demo:
835
  )
836
 
837
  # --- سیستم هوشمند: بررسی اعتبار در لحظه لود شدن ---
838
- # به محض اینکه JS اثرانگشت را در باکس مخفی می‌ریزد، این تابع اجرا شده و دکمه‌ها را تنظیم می‌کند
839
  fingerprint_box.change(
840
  fn=check_initial_quota,
841
  inputs=[fingerprint_box, status_box_input],
 
353
 
354
  except Exception as e:
355
  error_str = str(e)
356
+ # -------------------------------------------------------------
357
+ # مدیریت خطای GPU QUOTA برای نمایش Modal سفارشی (بخش درخواستی)
358
+ # -------------------------------------------------------------
359
  if "quota" in error_str.lower() or "exceeded" in error_str.lower():
360
+ # خطا را به بالا پرتاب می‌کنیم تا اسکنر جاوااسکریپت آن را بگیرد
361
  raise e
362
+
363
  return None, seed, get_error_html(f"خطا در پردازش: {error_str}"), gr.update(visible=True), gr.update(visible=False)
364
 
365
  @spaces.GPU(duration=30)
 
395
  }
396
  """
397
 
398
+ # --- جاوااسکریپت سراسری (ترکیب شده: اعتبار سنجی + هندلینگ خطای GPU) ---
399
  js_global_content = """
400
  <script>
401
  document.addEventListener('DOMContentLoaded', () => {
 
442
  const fpInput = document.querySelector('#fingerprint_storage textarea');
443
  const stInput = document.querySelector('#status_storage textarea');
444
 
 
445
  if(fpInput && fingerprint && fpInput.value !== fingerprint) {
446
  fpInput.value = fingerprint;
447
  fpInput.dispatchEvent(new Event('input', { bubbles: true }));
 
504
 
505
  initUserIdentity();
506
 
507
+ // ---------------------------------------------
508
+ // 2. GPU QUOTA HANDLER (Modal & Scanner)
509
+ // ---------------------------------------------
510
+
511
+ // RETRY FUNCTION
512
+ window.retryGeneration = function() {
513
+ const modal = document.getElementById('custom-quota-modal');
514
+ if (modal) modal.remove();
515
+
516
+ const runBtn = document.getElementById('run-btn');
517
+ if(runBtn) runBtn.click();
518
+ };
519
+
520
+ // Close function
521
+ window.closeErrorModal = function() {
522
+ const modal = document.getElementById('custom-quota-modal');
523
+ if (modal) modal.remove();
524
+ };
525
+
526
+ // SHOW MODAL FUNCTION
527
+ const showQuotaModal = () => {
528
+ if (document.getElementById('custom-quota-modal')) return;
529
+
530
+ const modalHtml = `
531
+ <div id="custom-quota-modal" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.6); backdrop-filter: blur(5px); z-index: 99999; display: flex; align-items: center; justify-content: center; font-family: 'Vazirmatn', sans-serif;">
532
+ <div class="ip-reset-guide-container">
533
+ <div class="guide-header">
534
+ <svg class="guide-header-icon" viewbox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
535
+ <defs><lineargradient id="grad1" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" style="stop-color: #667eea; stop-opacity: 1;"></stop><stop offset="100%" style="stop-color: #764ba2; stop-opacity: 1;"></stop></lineargradient></defs>
536
+ <circle cx="50" cy="50" r="45" fill="url(#grad1)" opacity="0.1"></circle>
537
+ <circle cx="50" cy="50" r="35" fill="none" stroke="url(#grad1)" stroke-width="2" opacity="0.3"></circle>
538
+ <path d="M35 50 L45 60 L65 40" stroke="url(#grad1)" stroke-width="4" fill="none" stroke-linecap="round" stroke-linejoin="round"></path>
539
+ <circle cx="65" cy="35" r="8" fill="#fee140"></circle>
540
+ <path d="M62 35 L68 35 M65 32 L65 38" stroke="white" stroke-width="2" stroke-linecap="round"></path>
541
+ </svg>
542
+ <div>
543
+ <h2>یک قدم تا ساخت تصاویر جدید</h2>
544
+ <p>نیازمند تغییر نقطه دستیابی</p>
545
+ </div>
546
+ </div>
547
+
548
+ <div class="guide-content">
549
+ <div class="info-card">
550
+ <div class="info-card-header">
551
+ <svg class="info-card-icon" viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z" fill="#667eea" opacity="0.2"></path><path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z" stroke="#667eea" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>
552
+ <span class="info-card-title">راه حل سریع</span>
553
+ </div>
554
+ <p>طبق ویدیو آموزشی پایین بین نقطه دستیابی جابجا شوید تلاش مجدد بزنید تا تصاویر مجدداً تولید بشه.</p>
555
+ </div>
556
+
557
+ <div class="summary-section">
558
+ <div class="summary-header">
559
+ <svg class="summary-icon" viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10" fill="#56ab2f" opacity="0.2"></circle><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2z" stroke="#56ab2f" stroke-width="2"></path><path d="M9 12l2 2 4-4" stroke="#56ab2f" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>
560
+ <span class="summary-title">خلاصه راهنما</span>
561
+ </div>
562
+ <div class="summary-text">هربار که این صفحه را مشاهده کردید: از اینترنت سیم‌کارت استفاده کنید، VPN را خاموش کرده و طبق ویدیو آموزشی پایین نقطه دستیابی رو تغییر دهید. «تلاش مجدد» کلیک کنید. با این روش ساده می‌توانید به صورت نامحدود تصویر بسازید! ☘️</div>
563
+ </div>
564
+
565
+ <div class="video-button-container">
566
+ <button onclick="parent.postMessage({ type: 'NAVIGATE_TO_URL', url: '#/nav/online/news/getSingle/1149635/eyJpdiI6IjhHVGhPQWJwb3E0cjRXbnFWTW5BaUE9PSIsInZhbHVlIjoiS1V0dTdvT21wbXAwSXZaK1RCTG1pVXZqdlFJa1hXV1RKa2FLem9zU3pXMjd5MmlVOGc2YWY0NVdNR3h3Smp1aSIsIm1hYyI6IjY1NTA5ZDYzMjAzMTJhMGQyMWQ4NjA4ZDgyNGZjZDVlY2MyNjdiMjA2NWYzOWRjY2M4ZmVjYWRlMWNlMWQ3ODEiLCJ0YWciOiIifQ==/21135210' }, '*')" class="elegant-video-button">
567
+ <svg class="elegant-video-button-icon" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M8 5v14l11-7z"></path></svg>
568
+ <span>دیدن ویدیو آموزشی استفاده نامحدود</span>
569
+ </button>
570
+ </div>
571
+ </div>
572
+
573
+ <div class="guide-actions">
574
+ <button class="action-button back-button" onclick="window.closeErrorModal()">
575
+ <svg class="action-button-icon" viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M19 12H5M12 19l-7-7 7-7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>
576
+ <span>بازگشت</span>
577
+ </button>
578
+ <button class="action-button retry-button" onclick="window.retryGeneration()">
579
+ <svg class="action-button-icon" viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M23 4v6h-6M1 20v-6h6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path><path d="M20.49 9A9 9 0 0 0 5.64 5.64L1 10m22 4l-4.64 4.36A9 9 0 0 1 3.51 15" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>
580
+ <span>تلاش مجدد</span>
581
+ </button>
582
+ </div>
583
+ </div>
584
+ </div>
585
+ `;
586
+
587
+ document.body.insertAdjacentHTML('beforeend', modalHtml);
588
+
589
+ // Auto close after 10 seconds
590
+ setTimeout(() => {
591
+ window.closeErrorModal();
592
+ }, 10000);
593
+ };
594
+
595
+ // ERROR SCANNER
596
+ setInterval(() => {
597
+ const potentialErrors = document.querySelectorAll('.toast-body, .error, .toast-wrap, .eta-bar, div[class*="error"]');
598
+
599
+ potentialErrors.forEach(el => {
600
+ const text = el.innerText || "";
601
+ if (text.toLowerCase().includes('quota') || text.toLowerCase().includes('exceeded')) {
602
+
603
+ showQuotaModal();
604
+
605
+ // Immediately hide the Gradio error
606
+ el.style.display = 'none';
607
+ el.style.opacity = '0';
608
+ el.innerText = '';
609
+
610
+ const parentWrap = el.closest('.toast-wrap');
611
+ if(parentWrap) parentWrap.style.display = 'none';
612
+ }
613
+ });
614
+ }, 100);
615
+
616
+ // ---------------------------------------------
617
+ // 3. Force Light Mode
618
+ // ---------------------------------------------
619
  const forceLight = () => {
620
  const body = document.querySelector('body');
621
  if (body) {
 
631
  </script>
632
  """
633
 
634
+ # --- CSS Updated (ترکیب استایل‌های مودال، بج و گرادیو) ---
635
  css_code = """
636
  <style>
637
  @import url('https://fonts.googleapis.com/css2?family=Vazirmatn:wght@300;400;500;700&display=swap');
 
650
  font-family: 'Vazirmatn', sans-serif !important;
651
  }
652
 
653
+ /* --- IP Reset Guide CSS (مودال سفارشی) --- */
654
+ :root {
655
+ --guide-bg: rgba(255, 255, 255, 0.98);
656
+ --guide-border: rgba(102, 126, 234, 0.2);
657
+ --guide-text-title: #2d3748;
658
+ --guide-text-body: #4a5568;
659
+ --guide-accent: #667eea;
660
+ --primary-gradient-guide: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
661
+ --success-gradient-guide: linear-gradient(135deg, #56ab2f 0%, #a8e063 100%);
662
+ --radius-md-guide: 12px;
663
+ --radius-lg-guide: 16px;
664
+ --shadow-sm: 0 1px 2px 0 rgba(26, 32, 44, 0.03);
665
+ --shadow-md: 0 4px 6px -1px rgba(26, 32, 44, 0.05), 0 2px 4px -2px rgba(26, 32, 44, 0.04);
666
+ --shadow-xl: 0 20px 25px -5px rgba(26, 32, 44, 0.07), 0 8px 10px -6px rgba(26, 32, 44, 0.05);
667
+ }
668
+
669
+ @keyframes float {
670
+ 0%, 100% { transform: translateY(0px); }
671
+ 50% { transform: translateY(-10px); }
672
+ }
673
+ @keyframes slideInUp {
674
+ from { opacity: 0; transform: translateY(30px); }
675
+ to { opacity: 1; transform: translateY(0); }
676
+ }
677
+
678
+ .ip-reset-guide-container {
679
+ text-align: right;
680
+ direction: rtl;
681
+ background: var(--guide-bg);
682
+ backdrop-filter: blur(10px);
683
+ padding: 20px;
684
+ border-radius: var(--radius-lg-guide);
685
+ box-shadow: var(--shadow-xl);
686
+ border: 1px solid var(--guide-border);
687
+ animation: slideInUp 0.6s cubic-bezier(0.4, 0, 0.2, 1) both;
688
+ width: 90%;
689
+ max-width: 420px;
690
+ max-height: 90vh;
691
+ overflow-y: auto;
692
+ position: relative;
693
+ box-sizing: border-box;
694
+ font-family: 'Vazirmatn', sans-serif !important;
695
+ }
696
+ .ip-reset-guide-container::before {
697
+ content: ''; position: absolute; top: 0; left: 0; right: 0; height: 4px; background: var(--primary-gradient-guide);
698
+ }
699
+ .guide-header { display: flex; align-items: center; margin-bottom: 15px; }
700
+ .guide-header-icon { width: 45px; height: 45px; margin-left: 15px; animation: float 3s ease-in-out infinite; flex-shrink: 0; }
701
+ .guide-header h2 { font-size: 1.2rem; color: var(--guide-text-title); font-weight: 700; margin: 0; }
702
+ .guide-header p { color: var(--guide-text-body); font-size: 0.8rem; margin-top: 3px; margin-bottom: 0; }
703
+
704
+ .guide-content { font-size: 0.9rem; color: var(--guide-text-body); line-height: 1.6; }
705
+
706
+ .info-card { background: linear-gradient(135deg, #667eea15 0%, #764ba215 100%); border: 1px solid rgba(102, 126, 234, 0.2); border-radius: var(--radius-md-guide); padding: 12px; margin: 12px 0; position: relative; overflow: hidden; }
707
+ .info-card p { font-size: 0.85rem; line-height: 1.6; margin: 0; }
708
+ .info-card::before { content: ''; position: absolute; top: 0; right: 0; width: 3px; height: 100%; background: var(--primary-gradient-guide); }
709
+ .info-card-header { display: flex; align-items: center; margin-bottom: 8px; }
710
+ .info-card-icon { width: 18px; height: 18px; margin-left: 8px; }
711
+ .info-card-title { font-weight: 600; color: var(--guide-text-title); font-size: 0.95rem; }
712
+
713
+ .summary-section { margin-top: 12px; padding: 12px; border-radius: var(--radius-md-guide); background: linear-gradient(135deg, #56ab2f15 0%, #a8e06315 100%); border: 1px solid rgba(86, 171, 47, 0.2); position: relative; overflow: hidden; }
714
+ .summary-section::before { content: ''; position: absolute; top: 0; right: 0; width: 3px; height: 100%; background: var(--success-gradient-guide); }
715
+ .summary-header { display: flex; align-items: center; margin-bottom: 8px; }
716
+ .summary-icon { width: 18px; height: 18px; margin-left: 8px; }
717
+ .summary-title { font-weight: 600; color: #2f5a33; font-size: 0.95rem; }
718
+ .summary-text { color: #2f5a33; font-size: 0.85rem; line-height: 1.6; }
719
+
720
+ .video-button-container { text-align: center; margin: 20px 0 15px 0; width: 100%; }
721
+ .elegant-video-button {
722
+ display: inline-flex !important;
723
+ align-items: center;
724
+ justify-content: center;
725
+ padding: 10px 20px !important;
726
+ background-color: #fff !important;
727
+ color: var(--guide-accent) !important;
728
+ border: 1px solid #e2e8f0 !important;
729
+ text-decoration: none;
730
+ border-radius: 50px !important;
731
+ font-weight: 600 !important;
732
+ font-size: 0.9rem !important;
733
+ cursor: pointer !important;
734
+ font-family: inherit;
735
+ transition: all 0.3s ease !important;
736
+ box-shadow: 0 2px 10px rgba(0,0,0,0.05) !important;
737
+ width: auto !important;
738
+ }
739
+ .elegant-video-button:hover {
740
+ background: var(--primary-gradient-guide) !important;
741
+ color: white !important;
742
+ border-color: transparent !important;
743
+ transform: translateY(-2px);
744
+ box-shadow: 0 6px 16px rgba(102, 126, 234, 0.3) !important;
745
+ }
746
+ .elegant-video-button-icon { width: 18px; height: 18px; margin-left: 8px; fill: currentColor; }
747
+
748
+ .guide-actions {
749
+ display: flex !important;
750
+ gap: 12px !important;
751
+ margin-top: 20px;
752
+ padding-top: 20px;
753
+ border-top: 1px solid #e2e8f0;
754
+ width: 100% !important;
755
+ }
756
+ .action-button {
757
+ padding: 12px 15px !important;
758
+ border: none !important;
759
+ border-radius: 12px !important;
760
+ font-size: 0.95rem !important;
761
+ font-weight: 600 !important;
762
+ cursor: pointer !important;
763
+ flex: 1 !important;
764
+ transition: all 0.3s ease !important;
765
+ display: flex !important;
766
+ align-items: center;
767
+ justify-content: center;
768
+ font-family: inherit;
769
+ height: 48px !important;
770
+ }
771
+ .action-button-icon { width: 20px; height: 20px; margin-right: 0; margin-left: 8px; }
772
+
773
+ .back-button {
774
+ background: white !important;
775
+ color: var(--guide-text-body) !important;
776
+ border: 2px solid #e2e8f0 !important;
777
+ }
778
+ .back-button:hover {
779
+ background: #f7fafc !important;
780
+ border-color: var(--guide-accent) !important;
781
+ transform: translateY(-2px);
782
+ box-shadow: var(--shadow-md) !important;
783
+ }
784
+
785
+ .retry-button {
786
+ background: var(--primary-gradient-guide) !important;
787
+ color: white !important;
788
+ box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3) !important;
789
+ }
790
+ .retry-button:hover {
791
+ transform: translateY(-2px);
792
+ box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4) !important;
793
+ }
794
+
795
+ /* --- Main App CSS --- */
796
  /* Hidden inputs logic */
797
  #fingerprint_storage, #status_storage {
798
  display: none !important;
 
815
  transition: all 0.3s ease;
816
  }
817
 
 
818
  body { margin: 0; padding: 10px; }
819
 
820
  #col-container {
 
967
 
968
  footer { display: none !important; }
969
  .flagging { display: none !important; }
970
+
971
+ /* Force toast transparency for cleaner Custom Modal */
972
  .toast-body { direction: rtl !important; text-align: right !important; background: transparent !important; box-shadow: none !important; border: none !important; padding: 0 !important; max-width: 100% !important; width: auto !important; }
973
  .toast-wrap { background: transparent !important; border: none !important; box-shadow: none !important; }
974
 
 
990
  gr.HTML(combined_html)
991
 
992
  # اینپوت‌های مخفی برای انتقال دیتای کاربر از JS به Python
 
993
  fingerprint_box = gr.Textbox(elem_id="fingerprint_storage", visible=True)
994
  status_box_input = gr.Textbox(elem_id="status_storage", visible=True)
995
 
 
1093
  )
1094
 
1095
  # --- سیستم هوشمند: بررسی اعتبار در لحظه لود شدن ---
 
1096
  fingerprint_box.change(
1097
  fn=check_initial_quota,
1098
  inputs=[fingerprint_box, status_box_input],