Spaces:
Running
Running
selfitcamera
commited on
Commit
·
12555d4
1
Parent(s):
085778c
init
Browse files
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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
return 'free'
|
| 55 |
-
elif count < SLOW_TRY_N: #
|
| 56 |
-
return 'rate_limit_1' # NSFW blur +
|
| 57 |
-
elif count < SLOW2_TRY_N:
|
| 58 |
-
return 'rate_limit_2' # NSFW blur +
|
| 59 |
-
elif count <
|
| 60 |
-
return 'rate_limit_3' # NSFW blur +
|
| 61 |
-
else: #
|
| 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},
|
| 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},
|
| 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":
|
| 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 |
-
#
|
| 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 |
-
#
|
| 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(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
|