selfitcamera commited on
Commit
6855df4
·
1 Parent(s): a5cbffc
__lib__/app.py CHANGED
@@ -59,6 +59,8 @@ PRINT_STATS_INTERVAL = 10 # Print stats every N requests
59
 
60
  # Async IP query tracking
61
  IP_Query_Results = {} # Track async query results
 
 
62
 
63
  # Restricted countries list (these countries have lower usage limits)
64
  RESTRICTED_COUNTRIES = ["印度", "巴基斯坦", "俄罗斯", "中国", "伊朗"]
@@ -525,8 +527,22 @@ def edit_image_interface(input_image, prompt, lang, request: gr.Request, progres
525
  if len(prompt.strip()) <= 3:
526
  return None, t("error_prompt_too_short", lang), gr.update(visible=False)
527
  except Exception as e:
528
- print(f"⚠️ Request preprocessing error: {e}")
529
- return None, t("error_request_processing", lang), gr.update(visible=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
530
 
531
  # Get user current phase
532
  current_phase = get_ip_phase(client_ip)
@@ -657,6 +673,9 @@ def edit_image_interface(input_image, prompt, lang, request: gr.Request, progres
657
  # First high_priority_n tasks for each IP get priority=1
658
  task_priority = 1 if current_count < high_priority_n else 0
659
 
 
 
 
660
  # Record generation attempt (before actual generation to ensure correct count)
661
  record_generation_attempt(client_ip, current_phase)
662
  updated_count = get_ip_generation_count(client_ip)
@@ -801,71 +820,9 @@ def edit_image_interface(input_image, prompt, lang, request: gr.Request, progres
801
  align-items: center;
802
  justify-content: center;
803
  padding: 12px 24px;
804
- background: linear-gradient(135deg, #ff6b6b 0%, #feca57 100%);
805
- color: white;
806
- border-radius: 10px;
807
- font-weight: 600;
808
- font-size: 14px;
809
- text-align: center;
810
- max-width: 400px;
811
- box-shadow: 0 3px 12px rgba(255, 107, 107, 0.3);
812
- border: none;
813
- '>👉 Click the ❤️ Like button to unlock more free trial attempts!</div>
814
- </div>
815
- """
816
- else:
817
- # For non-restricted countries, show action buttons
818
- # Start with HF Space promo block so CTA is prominent above other actions
819
- action_buttons_html = """
820
- <div style='margin: 16px auto 0; max-width: 700px; background: linear-gradient(120deg, #f0f4ff 0%, #e5edff 50%, #f7fbff 100%); border: 1px solid #cbd5ff; border-radius: 14px; padding: 16px 18px; box-shadow: 0 12px 28px rgba(88, 101, 242, 0.18); text-align: center;'>
821
- <div style='font-size: 16px; font-weight: 900; color: #1f2a44; display: flex; align-items: center; justify-content: center; gap: 8px;'>
822
- 🚀 Omni Image Editor 2.0 is live!
823
- </div>
824
- <a href='https://huggingface.co/spaces/selfit-camera/Omni-Image-Editor' target='_blank' style='display: inline-flex; align-items: center; justify-content: center; margin-top: 8px; padding: 10px 18px; background: #5865f2; color: white; border-radius: 10px; font-weight: 800; text-decoration: none; box-shadow: 0 6px 18px rgba(88, 101, 242, 0.35);'>
825
- Try the Hugging Face Space demo (free)
826
- </a>
827
- <div style='font-size: 13px; color: #4a5568; margin-top: 6px; font-weight: 700;'>This is a free HF Space demo for Omni Image Editor 2.0.</div>
828
- </div>
829
- """
830
-
831
- if task_uuid and lang not in ["zh", "hi", "ru"]:
832
- # Create i2v URL with input and output images and prompt
833
- from urllib.parse import quote
834
- encoded_prompt = quote(prompt.strip())
835
- i2v_url = f"https://omnicreator.net/image-to-video?input_image={input_image_url}&end_image={result_url}&prompt={encoded_prompt}"
836
- action_buttons_html += f"""
837
- <div style='display: flex; justify-content: center; gap: 12px; margin: 10px 0 5px 0; padding: 0px;'>
838
- <a href='{i2v_url}' target='_blank' style='
839
- display: inline-flex;
840
- align-items: center;
841
- justify-content: center;
842
- padding: 16px 32px;
843
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
844
  color: white;
845
  text-decoration: none;
846
- border-radius: 12px;
847
- font-weight: 700;
848
- font-size: 16px;
849
- text-align: center;
850
- min-width: 160px;
851
- box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
852
- transition: all 0.3s ease;
853
- border: none;
854
- '>&#127909; Convert to Video</a>
855
- </div>
856
- """
857
-
858
- # Add popup script if needed (using different approach)
859
- if show_like_tip or lang in ["zh", "hi", "ru"]:
860
- action_buttons_html += """
861
- <div style='display: flex; justify-content: center; margin: 15px 0 5px 0; padding: 0px;'>
862
- <div style='
863
- display: inline-flex;
864
- align-items: center;
865
- justify-content: center;
866
- padding: 12px 24px;
867
- background: linear-gradient(135deg, #ff6b6b 0%, #feca57 100%);
868
- color: white;
869
  border-radius: 10px;
870
  font-weight: 600;
871
  font-size: 14px;
@@ -885,6 +842,9 @@ def edit_image_interface(input_image, prompt, lang, request: gr.Request, progres
885
  except Exception as e:
886
  print(f"❌ Processing exception - IP: {client_ip}, error: {str(e)}")
887
  return None, t("error_processing_exception", lang).format(error=str(e)), gr.update(visible=False)
 
 
 
888
 
889
  # Create Gradio interface
890
  def create_app():
 
59
 
60
  # Async IP query tracking
61
  IP_Query_Results = {} # Track async query results
62
+ # Active task tracking (within recent time window)
63
+ Active_Tasks = {} # {client_ip: {"start": timestamp}}
64
 
65
  # Restricted countries list (these countries have lower usage limits)
66
  RESTRICTED_COUNTRIES = ["印度", "巴基斯坦", "俄罗斯", "中国", "伊朗"]
 
527
  if len(prompt.strip()) <= 3:
528
  return None, t("error_prompt_too_short", lang), gr.update(visible=False)
529
  except Exception as e:
530
+ print(f"⚠️ Unexpected error: {e}", flush=True)
531
+ return None, t("error_processing_failed", lang), gr.update(visible=False)
532
+
533
+ # Concurrency guard: block if there is an active task within last 3 minutes
534
+ try:
535
+ now_ts = time.time()
536
+ active_info = Active_Tasks.get(client_ip)
537
+ if active_info:
538
+ start_ts = active_info.get("start", 0)
539
+ if now_ts - start_ts <= 180:
540
+ return None, "You already have a task in progress. Please wait for it to finish before submitting a new one.", gr.update(visible=False, value=None)
541
+ else:
542
+ # Cleanup stale record
543
+ Active_Tasks.pop(client_ip, None)
544
+ except Exception as e:
545
+ print(f"⚠️ Concurrency guard check failed: {e}")
546
 
547
  # Get user current phase
548
  current_phase = get_ip_phase(client_ip)
 
673
  # First high_priority_n tasks for each IP get priority=1
674
  task_priority = 1 if current_count < high_priority_n else 0
675
 
676
+ # Record active task start (for concurrency guard)
677
+ Active_Tasks[client_ip] = {"start": time.time()}
678
+
679
  # Record generation attempt (before actual generation to ensure correct count)
680
  record_generation_attempt(client_ip, current_phase)
681
  updated_count = get_ip_generation_count(client_ip)
 
820
  align-items: center;
821
  justify-content: center;
822
  padding: 12px 24px;
823
+ background: linear-gradient(135deg, #7c3aed 0%, #6366f1 100%);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
824
  color: white;
825
  text-decoration: none;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
826
  border-radius: 10px;
827
  font-weight: 600;
828
  font-size: 14px;
 
842
  except Exception as e:
843
  print(f"❌ Processing exception - IP: {client_ip}, error: {str(e)}")
844
  return None, t("error_processing_exception", lang).format(error=str(e)), gr.update(visible=False)
845
+ finally:
846
+ # Task finished (success or failure) — clear active marker to allow next submission immediately
847
+ Active_Tasks.pop(client_ip, None)
848
 
849
  # Create Gradio interface
850
  def create_app():
__lib__/i18n/ar.pyc CHANGED
Binary files a/__lib__/i18n/ar.pyc and b/__lib__/i18n/ar.pyc differ
 
__lib__/i18n/da.pyc CHANGED
Binary files a/__lib__/i18n/da.pyc and b/__lib__/i18n/da.pyc differ
 
__lib__/i18n/de.pyc CHANGED
Binary files a/__lib__/i18n/de.pyc and b/__lib__/i18n/de.pyc differ
 
__lib__/i18n/en.pyc CHANGED
Binary files a/__lib__/i18n/en.pyc and b/__lib__/i18n/en.pyc differ
 
__lib__/i18n/es.pyc CHANGED
Binary files a/__lib__/i18n/es.pyc and b/__lib__/i18n/es.pyc differ
 
__lib__/i18n/fi.pyc CHANGED
Binary files a/__lib__/i18n/fi.pyc and b/__lib__/i18n/fi.pyc differ
 
__lib__/i18n/fr.pyc CHANGED
Binary files a/__lib__/i18n/fr.pyc and b/__lib__/i18n/fr.pyc differ
 
__lib__/i18n/he.pyc CHANGED
Binary files a/__lib__/i18n/he.pyc and b/__lib__/i18n/he.pyc differ
 
__lib__/i18n/hi.pyc CHANGED
Binary files a/__lib__/i18n/hi.pyc and b/__lib__/i18n/hi.pyc differ
 
__lib__/i18n/id.pyc CHANGED
Binary files a/__lib__/i18n/id.pyc and b/__lib__/i18n/id.pyc differ
 
__lib__/i18n/it.pyc CHANGED
Binary files a/__lib__/i18n/it.pyc and b/__lib__/i18n/it.pyc differ
 
__lib__/i18n/ja.pyc CHANGED
Binary files a/__lib__/i18n/ja.pyc and b/__lib__/i18n/ja.pyc differ
 
__lib__/i18n/nl.pyc CHANGED
Binary files a/__lib__/i18n/nl.pyc and b/__lib__/i18n/nl.pyc differ
 
__lib__/i18n/no.pyc CHANGED
Binary files a/__lib__/i18n/no.pyc and b/__lib__/i18n/no.pyc differ
 
__lib__/i18n/pt.pyc CHANGED
Binary files a/__lib__/i18n/pt.pyc and b/__lib__/i18n/pt.pyc differ
 
__lib__/i18n/ru.pyc CHANGED
Binary files a/__lib__/i18n/ru.pyc and b/__lib__/i18n/ru.pyc differ
 
__lib__/i18n/sv.pyc CHANGED
Binary files a/__lib__/i18n/sv.pyc and b/__lib__/i18n/sv.pyc differ
 
__lib__/i18n/tr.pyc CHANGED
Binary files a/__lib__/i18n/tr.pyc and b/__lib__/i18n/tr.pyc differ
 
__lib__/i18n/uk.pyc CHANGED
Binary files a/__lib__/i18n/uk.pyc and b/__lib__/i18n/uk.pyc differ
 
__lib__/i18n/vi.pyc CHANGED
Binary files a/__lib__/i18n/vi.pyc and b/__lib__/i18n/vi.pyc differ
 
__lib__/i18n/zh.pyc CHANGED
Binary files a/__lib__/i18n/zh.pyc and b/__lib__/i18n/zh.pyc differ
 
__lib__/util.pyc CHANGED
Binary files a/__lib__/util.pyc and b/__lib__/util.pyc differ