selfit-camera commited on
Commit
46c5397
·
1 Parent(s): c94174a
Files changed (2) hide show
  1. app.py +101 -49
  2. util.py +7 -7
app.py CHANGED
@@ -4,7 +4,6 @@ import os
4
  import shutil
5
  import tempfile
6
  import time
7
- from collections import defaultdict, deque
8
  from util import process_image_edit, get_country_info_safe, get_location_info_safe, contains_chinese
9
  from nfsw import NSFWDetector
10
 
@@ -14,11 +13,38 @@ NSFW_LIMIT = 6 # 限制次数:6次
14
 
15
  IP_Dict = {}
16
  NSFW_Dict = {} # 记录每个IP的NSFW违规次数
17
- NSFW_Time_Dict = defaultdict(deque) # 记录每个IPNSFW检测时间戳
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
  def check_nsfw_rate_limit(client_ip):
20
  """
21
- 检查IP的NSFW检测频率限制
22
 
23
  Args:
24
  client_ip (str): 客户端IP地址
@@ -27,36 +53,81 @@ def check_nsfw_rate_limit(client_ip):
27
  tuple: (是否超过限制, 剩余等待时间)
28
  """
29
  current_time = time.time()
30
- time_window_start = current_time - (NSFW_TIME_WINDOW * 60) # 5分钟前的时间戳
 
 
 
 
 
 
 
31
 
32
- # 清理过期的时间戳
33
- while NSFW_Time_Dict[client_ip] and NSFW_Time_Dict[client_ip][0] < time_window_start:
34
- NSFW_Time_Dict[client_ip].popleft()
 
 
 
 
35
 
36
- # 检查是否超过限制
37
- if len(NSFW_Time_Dict[client_ip]) >= NSFW_LIMIT:
38
- # 计算需要等待的时间
39
- oldest_timestamp = NSFW_Time_Dict[client_ip][0]
40
- wait_time = oldest_timestamp + (NSFW_TIME_WINDOW * 60) - current_time
 
 
41
  return True, max(0, wait_time)
42
 
43
  return False, 0
44
 
45
  def record_nsfw_detection(client_ip):
46
  """
47
- 记录IP的NSFW检测时间
48
 
49
  Args:
50
  client_ip (str): 客户端IP地址
51
  """
52
- current_time = time.time()
53
- NSFW_Time_Dict[client_ip].append(current_time)
 
 
 
 
 
54
 
55
  # 记录到NSFW_Dict中(兼容现有逻辑)
56
  if client_ip not in NSFW_Dict:
57
  NSFW_Dict[client_ip] = 0
58
  NSFW_Dict[client_ip] += 1
59
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  # 初始化NSFW检测器(从Hugging Face���载)
61
  try:
62
  nsfw_detector = NSFWDetector() # 自动从Hugging Face下载falconsai_yolov9_nsfw_model_quantized.pt
@@ -105,7 +176,7 @@ def edit_image_interface(input_image, prompt, request: gr.Request, progress=gr.P
105
  # warning_msg = f"您的ip地址为{client_ip},地点为{prov}-{city},您的网络服务商为{isp_name},检测到您目前正在浏览,制作淫秽内容,已经上报给 {city_name}市公安局,已加急处理,请耐心等待警察上门调查"
106
  # return None, f"❌ {warning_msg}"
107
  # else:
108
- # return None, f"❌ Your ip {client_ip}your region has been blocked for too much nsfw content"
109
 
110
  if input_image is None:
111
  return None, "Please upload an image first"
@@ -130,40 +201,21 @@ def edit_image_interface(input_image, prompt, request: gr.Request, progress=gr.P
130
  is_rate_limited, wait_time = check_nsfw_rate_limit(client_ip)
131
 
132
  if is_rate_limited:
133
- # 超过频率限制,显示等待提示
134
  wait_minutes = int(wait_time / 60) + 1 # 向上取整到分钟
135
- print(f"⚠️ NSFW频率限制 - IP: {client_ip}({country_info}), 需要等待 {wait_minutes} 分钟")
136
- return None, f" 请等待 {wait_minutes} 分钟后继续生成"
137
-
138
- # 记录NSFW检测
139
- record_nsfw_detection(client_ip)
140
-
141
- # # 检查是否需要特殊处理(中文prompt或中国IP)
142
- # has_chinese = contains_chinese(prompt.strip())
143
- # is_china_ip = location_info.get("country", "").lower() == "中国"
144
- # if has_chinese or is_china_ip:
145
- # # 构建特殊警告信息
146
- # prov = location_info.get("prov", "未知省份")
147
- # city = location_info.get("city", "未知城市")
148
- # isp = location_info.get("isp", "Unknown")
149
-
150
- # # 处理城市名称
151
- # city_name = city.replace("市", "") if city != "未知城市" else "当地"
152
-
153
- # # 处理ISP名称,去掉"中国"前缀
154
- # isp_name = isp.replace("中国", "") if isp != "Unknown" else "未知"
155
-
156
- # warning_msg = f"您的ip地址为{client_ip},地点为{prov}-{city},您的网络服务商为{isp_name},检测到您目前正在浏览,制作淫秽内容,已经上报给 {city_name}市公安局,已加急处理,请耐心等待警察上门调查"
157
-
158
- # print(f"⚠️ 特殊NSFW警告 - IP: {client_ip}, 位置: {prov}-{city}, ISP: {isp_name}, 中文Prompt: {has_chinese}, 中国IP: {is_china_ip}")
159
- # print(warning_msg)
160
-
161
- # return None, f"❌ {warning_msg}"
162
- # else:
163
- # # 常规NSFW提示
164
- # print(f"❌ NSFW image detected - IP: {client_ip}({country_info}), violations: {NSFW_Dict[client_ip]}")
165
- # return None, f"❌ Your ip {client_ip},your region has been blocked for too much nsfw content"
166
-
167
 
168
  except Exception as e:
169
  print(f"⚠️ NSFW检测失败: {e}")
 
4
  import shutil
5
  import tempfile
6
  import time
 
7
  from util import process_image_edit, get_country_info_safe, get_location_info_safe, contains_chinese
8
  from nfsw import NSFWDetector
9
 
 
13
 
14
  IP_Dict = {}
15
  NSFW_Dict = {} # 记录每个IP的NSFW违规次数
16
+ NSFW_Time_Dict = {} # 记录每个IP在特定时间窗口的NSFW检测次数,键格式: "ip_timestamp"
17
+
18
+ def get_current_time_window():
19
+ """
20
+ 获取当前的整点时间窗口
21
+
22
+ Returns:
23
+ tuple: (窗口开始时间戳, 窗口结束时间戳)
24
+ """
25
+ current_time = time.time()
26
+ # 获取当前时间的分钟数
27
+ current_struct = time.localtime(current_time)
28
+ current_minute = current_struct.tm_min
29
+
30
+ # 计算当前5分钟时间窗口的开始分钟
31
+ window_start_minute = (current_minute // NSFW_TIME_WINDOW) * NSFW_TIME_WINDOW
32
+
33
+ # 构建窗口开始时间
34
+ window_start_struct = time.struct_time((
35
+ current_struct.tm_year, current_struct.tm_mon, current_struct.tm_mday,
36
+ current_struct.tm_hour, window_start_minute, 0,
37
+ current_struct.tm_wday, current_struct.tm_yday, current_struct.tm_isdst
38
+ ))
39
+
40
+ window_start_time = time.mktime(window_start_struct)
41
+ window_end_time = window_start_time + (NSFW_TIME_WINDOW * 60)
42
+
43
+ return window_start_time, window_end_time
44
 
45
  def check_nsfw_rate_limit(client_ip):
46
  """
47
+ 检查IP的NSFW检测频率限制(基于整点时间窗口)
48
 
49
  Args:
50
  client_ip (str): 客户端IP地址
 
53
  tuple: (是否超过限制, 剩余等待时间)
54
  """
55
  current_time = time.time()
56
+ window_start_time, window_end_time = get_current_time_window()
57
+
58
+ # 清理不在当前时间窗口的记录
59
+ current_window_key = f"{client_ip}_{int(window_start_time)}"
60
+
61
+ # 如果没有当前窗口的记录,创建新的
62
+ if current_window_key not in NSFW_Time_Dict:
63
+ NSFW_Time_Dict[current_window_key] = 0
64
 
65
+ # 清理旧的窗口记录(保持内存清洁)
66
+ keys_to_remove = []
67
+ for key in NSFW_Time_Dict:
68
+ if key.startswith(client_ip + "_"):
69
+ window_time = int(key.split("_")[1])
70
+ if window_time < window_start_time:
71
+ keys_to_remove.append(key)
72
 
73
+ for key in keys_to_remove:
74
+ del NSFW_Time_Dict[key]
75
+
76
+ # 检查当前窗口是否超过限制
77
+ if NSFW_Time_Dict[current_window_key] >= NSFW_LIMIT:
78
+ # 计算到下一个时间窗口的等待时间
79
+ wait_time = window_end_time - current_time
80
  return True, max(0, wait_time)
81
 
82
  return False, 0
83
 
84
  def record_nsfw_detection(client_ip):
85
  """
86
+ 记录IP的NSFW检测时间(基于整点时间窗口)
87
 
88
  Args:
89
  client_ip (str): 客户端IP地址
90
  """
91
+ window_start_time, _ = get_current_time_window()
92
+ current_window_key = f"{client_ip}_{int(window_start_time)}"
93
+
94
+ # 增加当前窗口的计数
95
+ if current_window_key not in NSFW_Time_Dict:
96
+ NSFW_Time_Dict[current_window_key] = 0
97
+ NSFW_Time_Dict[current_window_key] += 1
98
 
99
  # 记录到NSFW_Dict中(兼容现有逻辑)
100
  if client_ip not in NSFW_Dict:
101
  NSFW_Dict[client_ip] = 0
102
  NSFW_Dict[client_ip] += 1
103
 
104
+ def get_current_window_info(client_ip):
105
+ """
106
+ 获取当前窗口的统计信息(用于调试)
107
+
108
+ Args:
109
+ client_ip (str): 客户端IP地址
110
+
111
+ Returns:
112
+ dict: 当前窗口的统计信息
113
+ """
114
+ window_start_time, window_end_time = get_current_time_window()
115
+ current_window_key = f"{client_ip}_{int(window_start_time)}"
116
+
117
+ current_count = NSFW_Time_Dict.get(current_window_key, 0)
118
+
119
+ # 格式化时间显示
120
+ start_time_str = time.strftime("%H:%M:%S", time.localtime(window_start_time))
121
+ end_time_str = time.strftime("%H:%M:%S", time.localtime(window_end_time))
122
+
123
+ return {
124
+ "window_start": start_time_str,
125
+ "window_end": end_time_str,
126
+ "current_count": current_count,
127
+ "limit": NSFW_LIMIT,
128
+ "window_key": current_window_key
129
+ }
130
+
131
  # 初始化NSFW检测器(从Hugging Face���载)
132
  try:
133
  nsfw_detector = NSFWDetector() # 自动从Hugging Face下载falconsai_yolov9_nsfw_model_quantized.pt
 
176
  # warning_msg = f"您的ip地址为{client_ip},地点为{prov}-{city},您的网络服务商为{isp_name},检测到您目前正在浏览,制作淫秽内容,已经上报给 {city_name}市公安局,已加急处理,请耐心等待警察上门调查"
177
  # return None, f"❌ {warning_msg}"
178
  # else:
179
+ # return None, f"❌ Your ip {client_ip}, your region has been blocked for too much nsfw content"
180
 
181
  if input_image is None:
182
  return None, "Please upload an image first"
 
201
  is_rate_limited, wait_time = check_nsfw_rate_limit(client_ip)
202
 
203
  if is_rate_limited:
204
+ # 超过频率限制,显示等待提示并阻止继续
205
  wait_minutes = int(wait_time / 60) + 1 # 向上取整到分钟
206
+ window_info = get_current_window_info(client_ip)
207
+ print(f"⚠️ NSFW频率限制 - IP: {client_ip}({country_info})")
208
+ print(f" 时间窗口: {window_info['window_start']} - {window_info['window_end']}")
209
+ print(f" 当前计数: {window_info['current_count']}/{NSFW_LIMIT}, 需要等待 {wait_minutes} 分钟")
210
+ return None, f"❌ Please wait {wait_minutes} minutes before generating again"
211
+ else:
212
+ # 未超过频率限制,记录此次检测但允许继续处理
213
+ record_nsfw_detection(client_ip)
214
+ window_info = get_current_window_info(client_ip)
215
+ # print(f"🔍 NSFW检测记录 - IP: {client_ip}({country_info})")
216
+ # print(f" 时间窗口: {window_info['window_start']} - {window_info['window_end']}")
217
+ # print(f" 当前计数: {window_info['current_count']}/{NSFW_LIMIT}, 允许继续处理")
218
+ # 不return,允许继续处理图片编辑
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
219
 
220
  except Exception as e:
221
  print(f"⚠️ NSFW检测失败: {e}")
util.py CHANGED
@@ -265,11 +265,11 @@ def submit_image_edit_task(user_image_url, prompt):
265
  if result.get('code') == 0:
266
  return result['data']['task_id'], None
267
  else:
268
- return None, f"API 错误: {result.get('message', '未知错误')}"
269
  else:
270
- return None, f"HTTP 错误: {response.status_code}"
271
  except Exception as e:
272
- return None, f"请求异常: {str(e)}"
273
 
274
 
275
  def check_task_status(task_id):
@@ -298,11 +298,11 @@ def check_task_status(task_id):
298
  task_data = result['data']
299
  return task_data['status'], task_data.get('output1'), task_data
300
  else:
301
- return 'error', None, result.get('message', '未知错误')
302
  else:
303
- return 'error', None, f"HTTP 错误: {response.status_code}"
304
  except Exception as e:
305
- return 'error', None, f"请求异常: {str(e)}"
306
 
307
 
308
  def process_image_edit(img_input, prompt, progress_callback=None):
@@ -369,7 +369,7 @@ def process_image_edit(img_input, prompt, progress_callback=None):
369
  if output_url:
370
  return output_url, "image edit completed"
371
  else:
372
- return None, "任务完成但未返回结果图片"
373
  elif status == 'error' or status == 'failed':
374
  return None, f"task processing failed: {task_data}"
375
  elif status in ['queued', 'processing', 'running', 'created', 'working']:
 
265
  if result.get('code') == 0:
266
  return result['data']['task_id'], None
267
  else:
268
+ return None, f"API Error: {result.get('message', 'Unknown error')}"
269
  else:
270
+ return None, f"HTTP Error: {response.status_code}"
271
  except Exception as e:
272
+ return None, f"Request Exception: {str(e)}"
273
 
274
 
275
  def check_task_status(task_id):
 
298
  task_data = result['data']
299
  return task_data['status'], task_data.get('output1'), task_data
300
  else:
301
+ return 'error', None, result.get('message', 'Unknown error')
302
  else:
303
+ return 'error', None, f"HTTP Error: {response.status_code}"
304
  except Exception as e:
305
+ return 'error', None, f"Request Exception: {str(e)}"
306
 
307
 
308
  def process_image_edit(img_input, prompt, progress_callback=None):
 
369
  if output_url:
370
  return output_url, "image edit completed"
371
  else:
372
+ return None, "Task completed but no result image returned"
373
  elif status == 'error' or status == 'failed':
374
  return None, f"task processing failed: {task_data}"
375
  elif status in ['queued', 'processing', 'running', 'created', 'working']: