selfitcamera commited on
Commit
12555d4
·
1 Parent(s): 085778c
Files changed (2) hide show
  1. app.py +226 -12
  2. util.py +30 -11
app.py CHANGED
@@ -19,10 +19,91 @@ PHASE_2_WINDOW = 10 # 30-40 tries: 6 minutes
19
  PHASE_3_WINDOW = 15 # 40-60 tries: 10 minutes
20
  MAX_IMAGES_PER_WINDOW = 2 # Max images per time window
21
 
 
 
 
 
22
  IP_Dict = {}
23
  # IP generation statistics and time window tracking
24
  IP_Generation_Count = {} # Record total generation count for each IP
25
  IP_Rate_Limit_Track = {} # Record generation count and timestamp in current time window for each IP
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
  def get_ip_generation_count(client_ip):
28
  """
@@ -49,16 +130,25 @@ def get_ip_phase(client_ip):
49
  str: 'free', 'rate_limit_1', 'rate_limit_2', 'rate_limit_3', 'blocked'
50
  """
51
  count = get_ip_generation_count(client_ip)
 
52
 
53
- if count < FREE_TRY_N: # 0-19 tries
 
 
 
 
 
 
 
 
54
  return 'free'
55
- elif count < SLOW_TRY_N: # 20-29 tries
56
- return 'rate_limit_1' # NSFW blur + 3 minutes 2 images
57
- elif count < SLOW2_TRY_N: # 30-39 tries
58
- return 'rate_limit_2' # NSFW blur + 6 minutes 2 images
59
- elif count < RATE_LIMIT_60: # 40-59 tries
60
- return 'rate_limit_3' # NSFW blur + 10 minutes 2 images
61
- else: # 60+ tries
62
  return 'blocked' # Generation blocked
63
 
64
  def check_rate_limit_for_phase(client_ip, phase):
@@ -113,6 +203,31 @@ def check_rate_limit_for_phase(client_ip, phase):
113
 
114
  return False, 0, track_data['count']
115
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  def record_generation_attempt(client_ip, phase):
117
  """
118
  Record generation attempt
@@ -211,11 +326,38 @@ def edit_image_interface(input_image1, input_image2, input_image3, prompt, aspec
211
  print(f"⚠️ Request preprocessing error: {e}")
212
  return None, "❌ Request processing error", gr.update(visible=False)
213
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
214
  # Get user current phase
215
  current_phase = get_ip_phase(client_ip)
216
  current_count = get_ip_generation_count(client_ip)
 
 
217
 
218
- print(f"📊 User phase info - IP: {client_ip}, current phase: {current_phase}, generation count: {current_count}")
219
 
220
  # Check if completely blocked
221
  if current_phase == 'blocked':
@@ -321,10 +463,16 @@ def edit_image_interface(input_image1, input_image2, input_image3, prompt, aspec
321
  record_generation_attempt(client_ip, current_phase)
322
  updated_count = get_ip_generation_count(client_ip)
323
 
 
 
 
324
  print(f"✅ Multi-image processing started - IP: {client_ip}, phase: {current_phase}, total count: {updated_count}, images: {len(valid_images)}, size: {width}x{height}, prompt: {prompt.strip()}", flush=True)
325
 
 
 
 
326
  # Call multi-image editing processing function
327
- result_url, message, task_uuid = process_multi_image_edit(valid_images, prompt.strip(), width, height, progress_callback)
328
 
329
  if result_url:
330
  print(f"✅ Processing completed successfully - IP: {client_ip}, result_url: {result_url}, task_uuid: {task_uuid}", flush=True)
@@ -453,6 +601,9 @@ def edit_image_interface(input_image1, input_image2, input_image3, prompt, aspec
453
  except Exception as e:
454
  print(f"❌ Processing exception - IP: {client_ip}, error: {str(e)}")
455
  return None, f"❌ Error occurred during processing: {str(e)}", gr.update(visible=False)
 
 
 
456
 
457
  def local_edit_interface(image_dict, prompt, request: gr.Request, progress=gr.Progress()):
458
  """
@@ -491,11 +642,38 @@ def local_edit_interface(image_dict, prompt, request: gr.Request, progress=gr.Pr
491
  print(f"⚠️ Local edit request preprocessing error: {e}")
492
  return None, "❌ Request processing error", gr.update(visible=False)
493
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
494
  # Get user current phase
495
  current_phase = get_ip_phase(client_ip)
496
  current_count = get_ip_generation_count(client_ip)
 
 
497
 
498
- print(f"📊 Local edit user phase info - IP: {client_ip}, current phase: {current_phase}, generation count: {current_count}")
499
 
500
  # Check if completely blocked
501
  if current_phase == 'blocked':
@@ -588,10 +766,16 @@ def local_edit_interface(image_dict, prompt, request: gr.Request, progress=gr.Pr
588
  record_generation_attempt(client_ip, current_phase)
589
  updated_count = get_ip_generation_count(client_ip)
590
 
 
 
 
591
  print(f"✅ Local editing started - IP: {client_ip}, phase: {current_phase}, total count: {updated_count}, prompt: {prompt.strip()}", flush=True)
592
 
 
 
 
593
  # Call local image editing processing function
594
- result_url, message, task_uuid = process_local_image_edit(base_image, layers, prompt.strip(), progress_callback)
595
 
596
  if result_url:
597
  print(f"✅ Local editing completed successfully - IP: {client_ip}, result_url: {result_url}, task_uuid: {task_uuid}", flush=True)
@@ -720,6 +904,9 @@ def local_edit_interface(image_dict, prompt, request: gr.Request, progress=gr.Pr
720
  except Exception as e:
721
  print(f"❌ Local editing exception - IP: {client_ip}, error: {str(e)}")
722
  return None, f"❌ Error occurred during processing: {str(e)}", gr.update(visible=False)
 
 
 
723
 
724
  # Create Gradio interface
725
  def create_app():
@@ -1380,6 +1567,33 @@ def create_app():
1380
  </p>
1381
  </div>
1382
  """, padding=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1383
 
1384
  return app
1385
 
 
19
  PHASE_3_WINDOW = 15 # 40-60 tries: 10 minutes
20
  MAX_IMAGES_PER_WINDOW = 2 # Max images per time window
21
 
22
+ # Restricted countries configuration
23
+ RESTRICTED_COUNTRIES = ["印度", "巴基斯坦", "俄罗斯", "中国"]
24
+ RESTRICTED_COUNTRY_LIMIT = 1 # Max usage for restricted countries
25
+
26
  IP_Dict = {}
27
  # IP generation statistics and time window tracking
28
  IP_Generation_Count = {} # Record total generation count for each IP
29
  IP_Rate_Limit_Track = {} # Record generation count and timestamp in current time window for each IP
30
+ IP_Active_Tasks = {} # Track active tasks for each IP (to prevent concurrent submissions)
31
+ IP_Country_Cache = {} # Cache IP country information to avoid repeated queries
32
+
33
+ def query_ip_country(client_ip):
34
+ """
35
+ Query IP address geo information with robust error handling
36
+
37
+ Returns:
38
+ dict: {"country": str, "region": str, "city": str}
39
+ """
40
+ # Check cache first
41
+ if client_ip in IP_Country_Cache:
42
+ print(f"Using cached IP data for {client_ip}")
43
+ return IP_Country_Cache[client_ip]
44
+
45
+ # Validate IP address
46
+ if not client_ip or client_ip in ["127.0.0.1", "localhost", "::1"]:
47
+ print(f"Invalid or local IP address: {client_ip}, using default")
48
+ default_geo = {"country": "Unknown", "region": "Unknown", "city": "Unknown"}
49
+ IP_Country_Cache[client_ip] = default_geo
50
+ return default_geo
51
+
52
+ # Query API with robust error handling
53
+ print(f"Querying IP geolocation for {client_ip}...")
54
+
55
+ try:
56
+ import requests
57
+ from requests.exceptions import Timeout, ConnectionError, RequestException
58
+
59
+ api_url = f"https://api.vore.top/api/IPdata?ip={client_ip}"
60
+
61
+ # Make request with 3 second timeout
62
+ response = requests.get(api_url, timeout=3)
63
+
64
+ if response.status_code == 200:
65
+ data = response.json()
66
+ if data.get("code") == 200 and "ipdata" in data:
67
+ ipdata = data["ipdata"]
68
+ geo_info = {
69
+ "country": ipdata.get("info1", "Unknown"),
70
+ "region": ipdata.get("info2", "Unknown"),
71
+ "city": ipdata.get("info3", "Unknown")
72
+ }
73
+ IP_Country_Cache[client_ip] = geo_info
74
+ print(f"Successfully detected location for {client_ip}: {geo_info['country']}")
75
+ return geo_info
76
+
77
+ except Exception as e:
78
+ print(f"Error querying IP {client_ip}: {e}, using default")
79
+
80
+ # All failures lead here
81
+ default_geo = {"country": "Unknown", "region": "Unknown", "city": "Unknown"}
82
+ IP_Country_Cache[client_ip] = default_geo
83
+ return default_geo
84
+
85
+ def is_restricted_country_ip(client_ip):
86
+ """
87
+ Check if IP is from a restricted country
88
+
89
+ Returns:
90
+ bool: True if from restricted country
91
+ """
92
+ geo_info = query_ip_country(client_ip)
93
+ country = geo_info["country"]
94
+ return country in RESTRICTED_COUNTRIES
95
+
96
+ def get_ip_max_limit(client_ip):
97
+ """
98
+ Get max usage limit for IP based on country
99
+
100
+ Returns:
101
+ int: Max usage limit
102
+ """
103
+ if is_restricted_country_ip(client_ip):
104
+ return RESTRICTED_COUNTRY_LIMIT
105
+ else:
106
+ return RATE_LIMIT_60
107
 
108
  def get_ip_generation_count(client_ip):
109
  """
 
130
  str: 'free', 'rate_limit_1', 'rate_limit_2', 'rate_limit_3', 'blocked'
131
  """
132
  count = get_ip_generation_count(client_ip)
133
+ max_limit = get_ip_max_limit(client_ip)
134
 
135
+ # For restricted countries, check if they've reached their limit (1 task)
136
+ if is_restricted_country_ip(client_ip):
137
+ if count >= max_limit:
138
+ return 'blocked'
139
+ else:
140
+ return 'free' # Only 1 free task for restricted countries
141
+
142
+ # For normal countries, use standard limits
143
+ if count < FREE_TRY_N: # 0-2 tries
144
  return 'free'
145
+ elif count < SLOW_TRY_N: # 3-4 tries
146
+ return 'rate_limit_1' # NSFW blur + 5 minutes 2 images
147
+ elif count < SLOW2_TRY_N: # 5-7 tries
148
+ return 'rate_limit_2' # NSFW blur + 10 minutes 2 images
149
+ elif count < max_limit: # 8-9 tries
150
+ return 'rate_limit_3' # NSFW blur + 15 minutes 2 images
151
+ else: # 10+ tries
152
  return 'blocked' # Generation blocked
153
 
154
  def check_rate_limit_for_phase(client_ip, phase):
 
203
 
204
  return False, 0, track_data['count']
205
 
206
+ def has_active_task(client_ip):
207
+ """
208
+ Check if IP has an active task in progress
209
+
210
+ Returns:
211
+ bool: True if IP has an active task
212
+ """
213
+ return client_ip in IP_Active_Tasks and IP_Active_Tasks[client_ip]
214
+
215
+ def set_active_task(client_ip, active=True):
216
+ """
217
+ Set or clear active task status for IP
218
+
219
+ Args:
220
+ client_ip (str): Client IP address
221
+ active (bool): True to mark as active, False to clear
222
+ """
223
+ if active:
224
+ IP_Active_Tasks[client_ip] = True
225
+ print(f"🔒 Task locked for IP: {client_ip}")
226
+ else:
227
+ if client_ip in IP_Active_Tasks:
228
+ del IP_Active_Tasks[client_ip]
229
+ print(f"🔓 Task unlocked for IP: {client_ip}")
230
+
231
  def record_generation_attempt(client_ip, phase):
232
  """
233
  Record generation attempt
 
326
  print(f"⚠️ Request preprocessing error: {e}")
327
  return None, "❌ Request processing error", gr.update(visible=False)
328
 
329
+ # Check if user has an active task in progress
330
+ if has_active_task(client_ip):
331
+ concurrent_button_html = f"""
332
+ <div style='display: flex; justify-content: center; gap: 15px; margin: 10px 0 5px 0; padding: 0px;'>
333
+ <a href='https://omnicreator.net/multi-image-edit#generator' target='_blank' style='
334
+ display: inline-flex;
335
+ align-items: center;
336
+ justify-content: center;
337
+ padding: 16px 32px;
338
+ background: linear-gradient(135deg, #f39c12 0%, #e67e22 100%);
339
+ color: white;
340
+ text-decoration: none;
341
+ border-radius: 12px;
342
+ font-weight: 600;
343
+ font-size: 16px;
344
+ text-align: center;
345
+ min-width: 200px;
346
+ box-shadow: 0 4px 15px rgba(243, 156, 18, 0.4);
347
+ transition: all 0.3s ease;
348
+ border: none;
349
+ '>⏰ Process Multiple Tasks Simultaneously</a>
350
+ </div>
351
+ """
352
+ return None, "❌ You have a task in progress. Please wait for it to complete before submitting a new task. Or visit https://omnicreator.net/multi-image-edit#generator to process multiple tasks simultaneously.", gr.update(value=concurrent_button_html, visible=True)
353
+
354
  # Get user current phase
355
  current_phase = get_ip_phase(client_ip)
356
  current_count = get_ip_generation_count(client_ip)
357
+ geo_info = IP_Country_Cache.get(client_ip, {"country": "Unknown", "region": "Unknown", "city": "Unknown"})
358
+ is_restricted = is_restricted_country_ip(client_ip)
359
 
360
+ print(f"📊 User phase info - IP: {client_ip}, Location: {geo_info['country']}/{geo_info['region']}/{geo_info['city']}, Phase: {current_phase}, Count: {current_count}, Restricted: {is_restricted}, Active task: {has_active_task(client_ip)}")
361
 
362
  # Check if completely blocked
363
  if current_phase == 'blocked':
 
463
  record_generation_attempt(client_ip, current_phase)
464
  updated_count = get_ip_generation_count(client_ip)
465
 
466
+ # Mark this IP as having an active task
467
+ set_active_task(client_ip, active=True)
468
+
469
  print(f"✅ Multi-image processing started - IP: {client_ip}, phase: {current_phase}, total count: {updated_count}, images: {len(valid_images)}, size: {width}x{height}, prompt: {prompt.strip()}", flush=True)
470
 
471
+ # Determine priority (first few tasks for each IP get priority)
472
+ task_priority = 1 if current_count < 2 else 0
473
+
474
  # Call multi-image editing processing function
475
+ result_url, message, task_uuid = process_multi_image_edit(valid_images, prompt.strip(), width, height, progress_callback, priority=task_priority, client_ip=client_ip)
476
 
477
  if result_url:
478
  print(f"✅ Processing completed successfully - IP: {client_ip}, result_url: {result_url}, task_uuid: {task_uuid}", flush=True)
 
601
  except Exception as e:
602
  print(f"❌ Processing exception - IP: {client_ip}, error: {str(e)}")
603
  return None, f"❌ Error occurred during processing: {str(e)}", gr.update(visible=False)
604
+ finally:
605
+ # Always clear active task status when done (success or failure)
606
+ set_active_task(client_ip, active=False)
607
 
608
  def local_edit_interface(image_dict, prompt, request: gr.Request, progress=gr.Progress()):
609
  """
 
642
  print(f"⚠️ Local edit request preprocessing error: {e}")
643
  return None, "❌ Request processing error", gr.update(visible=False)
644
 
645
+ # Check if user has an active task in progress
646
+ if has_active_task(client_ip):
647
+ concurrent_button_html = f"""
648
+ <div style='display: flex; justify-content: center; gap: 15px; margin: 10px 0 5px 0; padding: 0px;'>
649
+ <a href='https://omnicreator.net/multi-image-edit#generator' target='_blank' style='
650
+ display: inline-flex;
651
+ align-items: center;
652
+ justify-content: center;
653
+ padding: 16px 32px;
654
+ background: linear-gradient(135deg, #f39c12 0%, #e67e22 100%);
655
+ color: white;
656
+ text-decoration: none;
657
+ border-radius: 12px;
658
+ font-weight: 600;
659
+ font-size: 16px;
660
+ text-align: center;
661
+ min-width: 200px;
662
+ box-shadow: 0 4px 15px rgba(243, 156, 18, 0.4);
663
+ transition: all 0.3s ease;
664
+ border: none;
665
+ '>⏰ Process Multiple Tasks Simultaneously</a>
666
+ </div>
667
+ """
668
+ return None, "❌ You have a task in progress. Please wait for it to complete before submitting a new task. Or visit https://omnicreator.net/multi-image-edit#generator to process multiple tasks simultaneously.", gr.update(value=concurrent_button_html, visible=True)
669
+
670
  # Get user current phase
671
  current_phase = get_ip_phase(client_ip)
672
  current_count = get_ip_generation_count(client_ip)
673
+ geo_info = IP_Country_Cache.get(client_ip, {"country": "Unknown", "region": "Unknown", "city": "Unknown"})
674
+ is_restricted = is_restricted_country_ip(client_ip)
675
 
676
+ print(f"📊 Local edit user phase info - IP: {client_ip}, Location: {geo_info['country']}/{geo_info['region']}/{geo_info['city']}, Phase: {current_phase}, Count: {current_count}, Restricted: {is_restricted}, Active task: {has_active_task(client_ip)}")
677
 
678
  # Check if completely blocked
679
  if current_phase == 'blocked':
 
766
  record_generation_attempt(client_ip, current_phase)
767
  updated_count = get_ip_generation_count(client_ip)
768
 
769
+ # Mark this IP as having an active task
770
+ set_active_task(client_ip, active=True)
771
+
772
  print(f"✅ Local editing started - IP: {client_ip}, phase: {current_phase}, total count: {updated_count}, prompt: {prompt.strip()}", flush=True)
773
 
774
+ # Determine priority (first few tasks for each IP get priority)
775
+ task_priority = 1 if current_count < 2 else 0
776
+
777
  # Call local image editing processing function
778
+ result_url, message, task_uuid = process_local_image_edit(base_image, layers, prompt.strip(), progress_callback, priority=task_priority, client_ip=client_ip)
779
 
780
  if result_url:
781
  print(f"✅ Local editing completed successfully - IP: {client_ip}, result_url: {result_url}, task_uuid: {task_uuid}", flush=True)
 
904
  except Exception as e:
905
  print(f"❌ Local editing exception - IP: {client_ip}, error: {str(e)}")
906
  return None, f"❌ Error occurred during processing: {str(e)}", gr.update(visible=False)
907
+ finally:
908
+ # Always clear active task status when done (success or failure)
909
+ set_active_task(client_ip, active=False)
910
 
911
  # Create Gradio interface
912
  def create_app():
 
1567
  </p>
1568
  </div>
1569
  """, padding=False)
1570
+
1571
+ # Load IP country information on page load
1572
+ def on_load(request: gr.Request):
1573
+ """
1574
+ Load page and query IP country information
1575
+ """
1576
+ try:
1577
+ # Extract client IP
1578
+ client_ip = request.client.host
1579
+ headers = dict(request.headers) if hasattr(request, 'headers') else {}
1580
+ x_forwarded_for = headers.get('x-forwarded-for') or headers.get('X-Forwarded-For')
1581
+ if x_forwarded_for:
1582
+ client_ip = x_forwarded_for.split(',')[0].strip()
1583
+
1584
+ print(f"Loading page for IP: {client_ip}")
1585
+
1586
+ # Query IP country information (cached for subsequent requests)
1587
+ query_ip_country(client_ip)
1588
+
1589
+ except Exception as e:
1590
+ print(f"Error in on_load: {e}")
1591
+
1592
+ app.load(
1593
+ on_load,
1594
+ inputs=None,
1595
+ outputs=None
1596
+ )
1597
 
1598
  return app
1599
 
util.py CHANGED
@@ -32,6 +32,8 @@ R2_ACCESS_KEY = OneKey[4]
32
  R2_SECRET_KEY = OneKey[5]
33
  R2_ENDPOINT = OneKey[6]
34
 
 
 
35
 
36
 
37
  samples = [
@@ -273,10 +275,14 @@ def upload_mask_image_r2(client_ip, time_id, mask_image):
273
 
274
 
275
 
276
- def submit_image_edit_task(user_image_url, prompt, task_type="80", mask_image_url="", user_image2_url="", user_image3_url="", width=0, height=0):
277
  """
278
  Submit image editing task with improved error handling using API v2
279
  Supports multi-image editing with user_image2, user_image3, width, height parameters
 
 
 
 
280
  """
281
  headers = {
282
  'Content-Type': 'application/json',
@@ -284,6 +290,7 @@ def submit_image_edit_task(user_image_url, prompt, task_type="80", mask_image_ur
284
  }
285
 
286
  data = {
 
287
  "user_image": user_image_url,
288
  "user_image2": user_image2_url,
289
  "user_image3": user_image3_url,
@@ -293,8 +300,9 @@ def submit_image_edit_task(user_image_url, prompt, task_type="80", mask_image_ur
293
  "height": height,
294
  "text": prompt,
295
  "user_uuid": APIKEY,
296
- "priority": 0,
297
- "secret_key": "219ngu"
 
298
  }
299
 
300
  retry_count = 0
@@ -407,7 +415,7 @@ def check_task_status(task_id):
407
  return 'error', None, f"Failed after {max_retries} retries"
408
 
409
 
410
- def process_multi_image_edit(img_inputs, prompt, width=0, height=0, progress_callback=None):
411
  """
412
  Complete process for multi-image editing
413
 
@@ -417,10 +425,11 @@ def process_multi_image_edit(img_inputs, prompt, width=0, height=0, progress_cal
417
  width: Output width (0 for auto)
418
  height: Output height (0 for auto)
419
  progress_callback: Progress callback function
 
 
420
  """
421
  try:
422
- # Generate client IP and timestamp
423
- client_ip = "127.0.0.1" # Default IP
424
  time_id = int(time.time())
425
 
426
  # Validate input images
@@ -476,7 +485,9 @@ def process_multi_image_edit(img_inputs, prompt, width=0, height=0, progress_cal
476
  user_image2_url=user_image2_url,
477
  user_image3_url=user_image3_url,
478
  width=width,
479
- height=height
 
 
480
  )
481
  if error:
482
  return None, error, None
@@ -540,7 +551,7 @@ def process_image_edit(img_input, prompt, progress_callback=None):
540
  return process_multi_image_edit([img_input], prompt, 0, 0, progress_callback)
541
 
542
 
543
- def process_local_image_edit(base_image, layers, prompt, progress_callback=None):
544
  """
545
  处理局部图片编辑的完整流程
546
 
@@ -549,10 +560,11 @@ def process_local_image_edit(base_image, layers, prompt, progress_callback=None)
549
  layers (list): ImageEditor的层数据
550
  prompt (str): 编辑指令
551
  progress_callback: 进度回调函数
 
 
552
  """
553
  try:
554
- # Generate client IP and timestamp
555
- client_ip = "127.0.0.1" # Default IP
556
  time_id = int(time.time())
557
 
558
  if progress_callback:
@@ -600,7 +612,14 @@ def process_local_image_edit(base_image, layers, prompt, progress_callback=None)
600
  progress_callback("submitting local edit task...")
601
 
602
  # 提交局部图片编辑任务 (task_type=81)
603
- task_id, error = submit_image_edit_task(uploaded_url, prompt, task_type="81", mask_image_url=mask_url)
 
 
 
 
 
 
 
604
  if error:
605
  return None, error, None
606
 
 
32
  R2_SECRET_KEY = OneKey[5]
33
  R2_ENDPOINT = OneKey[6]
34
 
35
+ # HuggingFace用户任务限制配置
36
+ HF_TASK_LIMIT = 20
37
 
38
 
39
  samples = [
 
275
 
276
 
277
 
278
+ def submit_image_edit_task(user_image_url, prompt, task_type="80", mask_image_url="", user_image2_url="", user_image3_url="", width=0, height=0, client_ip="", priority=0):
279
  """
280
  Submit image editing task with improved error handling using API v2
281
  Supports multi-image editing with user_image2, user_image3, width, height parameters
282
+
283
+ Args:
284
+ client_ip (str): Client IP address for task tracking
285
+ priority (int): Task priority, 1 for high priority, 0 for normal priority
286
  """
287
  headers = {
288
  'Content-Type': 'application/json',
 
290
  }
291
 
292
  data = {
293
+ "client_ip": client_ip,
294
  "user_image": user_image_url,
295
  "user_image2": user_image2_url,
296
  "user_image3": user_image3_url,
 
300
  "height": height,
301
  "text": prompt,
302
  "user_uuid": APIKEY,
303
+ "priority": priority,
304
+ "secret_key": "219ngu",
305
+ "hf_task_limit": HF_TASK_LIMIT # 传递HF用户任务限制配置
306
  }
307
 
308
  retry_count = 0
 
415
  return 'error', None, f"Failed after {max_retries} retries"
416
 
417
 
418
+ def process_multi_image_edit(img_inputs, prompt, width=0, height=0, progress_callback=None, priority=0, client_ip="127.0.0.1"):
419
  """
420
  Complete process for multi-image editing
421
 
 
425
  width: Output width (0 for auto)
426
  height: Output height (0 for auto)
427
  progress_callback: Progress callback function
428
+ priority (int): Task priority, 1 for high priority, 0 for normal priority
429
+ client_ip (str): Client IP address for task tracking
430
  """
431
  try:
432
+ # Use provided client IP or default
 
433
  time_id = int(time.time())
434
 
435
  # Validate input images
 
485
  user_image2_url=user_image2_url,
486
  user_image3_url=user_image3_url,
487
  width=width,
488
+ height=height,
489
+ client_ip=client_ip,
490
+ priority=priority
491
  )
492
  if error:
493
  return None, error, None
 
551
  return process_multi_image_edit([img_input], prompt, 0, 0, progress_callback)
552
 
553
 
554
+ def process_local_image_edit(base_image, layers, prompt, progress_callback=None, priority=0, client_ip="127.0.0.1"):
555
  """
556
  处理局部图片编辑的完整流程
557
 
 
560
  layers (list): ImageEditor的层数据
561
  prompt (str): 编辑指令
562
  progress_callback: 进度回调函数
563
+ priority (int): Task priority, 1 for high priority, 0 for normal priority
564
+ client_ip (str): Client IP address for task tracking
565
  """
566
  try:
567
+ # Use provided client IP or default
 
568
  time_id = int(time.time())
569
 
570
  if progress_callback:
 
612
  progress_callback("submitting local edit task...")
613
 
614
  # 提交局部图片编辑任务 (task_type=81)
615
+ task_id, error = submit_image_edit_task(
616
+ uploaded_url,
617
+ prompt,
618
+ task_type="81",
619
+ mask_image_url=mask_url,
620
+ client_ip=client_ip,
621
+ priority=priority
622
+ )
623
  if error:
624
  return None, error, None
625