Junhui Ji commited on
Commit
1ac33d0
·
1 Parent(s): 4d812cb

delete client ip

Browse files
Files changed (3) hide show
  1. main.py +120 -34
  2. requirements.txt +3 -1
  3. static/script.js +51 -1
main.py CHANGED
@@ -20,8 +20,18 @@ from starlette.middleware.base import BaseHTTPMiddleware
20
  import uvicorn
21
  from collections import defaultdict
22
  from PIL import Image
 
 
 
 
 
23
 
24
 
 
 
 
 
 
25
  app = FastAPI()
26
 
27
  # 设置最大连接数
@@ -84,6 +94,7 @@ class OptimizationRequest(BaseModel):
84
  suggestions: List[str]
85
  request_model_id: str = 'gpt-image-1'
86
  openai_key: str = ''
 
87
 
88
  class CaseStudyRequest(BaseModel):
89
  user_input: str
@@ -202,41 +213,114 @@ async def analyze_feedback(request: AnalysisRequest):
202
  logging.error(f'Error: {e}, traceback: {traceback.format_exc()}')
203
  raise HTTPException(status_code=500, detail=f'Error: {e}, traceback: {traceback.format_exc()}')
204
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
  @app.post("/api/optimize-design")
206
- async def optimize_design(request: OptimizationRequest, client_ip: str = None):
207
  try:
208
- # 查看客户是否提供了openai_key,获取客户端IP(如果未提供,使用默认值)
209
- if not request.openai_key and client_ip not in white_list:
210
- print(f'user_ip {client_ip} not in whitelist')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
211
  raise HTTPException(
212
  status_code=503,
213
- detail="当前用户无生图权限,请点击'想使用自己的OpenAI API Key?'输入您的OpenAI API Key或联系@wangyue161添加白名单后重试。"
214
  )
215
-
216
- # user_rate_limit = white_list[client_ip]
217
- #
218
- # current_time = time.time()
219
- #
220
- # # 检查是否需要重置计数器(超过24小时)
221
- # if current_time - optimize_design_timestamps[client_ip] > 3600*24:
222
- # optimize_design_requests[client_ip] = 0
223
- # optimize_design_timestamps[client_ip] = current_time
224
- #
225
- # # 如果是首次请求,记录时间戳
226
- # if optimize_design_requests[client_ip] == 0:
227
- # optimize_design_timestamps[client_ip] = current_time
228
- #
229
- # # 检查是否超过限制
230
- # print(f'user_ip {client_ip}, total requests in routine: {optimize_design_requests[client_ip]}, rate limit: {user_rate_limit}')
231
- # if optimize_design_requests[client_ip] >= user_rate_limit:
232
- # raise HTTPException(
233
- # status_code=503,
234
- # detail="用户当日改图接口访问已达上限,请24小时后重试"
235
- # )
236
- #
237
- # # 增加请求计数
238
- # optimize_design_requests[client_ip] += 1
239
-
240
  # 提取设计类型
241
  design_type = f"设计类型:{request.text.split()[0]}\n" if len(request.text.split()) > 1 else ""
242
 
@@ -254,16 +338,18 @@ async def optimize_design(request: OptimizationRequest, client_ip: str = None):
254
  openai_key=request.openai_key
255
  )
256
 
 
 
 
 
 
 
257
  return JSONResponse(response)
258
  except HTTPException as he:
259
  raise he
260
  except Exception as e:
261
  logging.error(f'Error: {e}, traceback: {traceback.format_exc()}')
262
  raise HTTPException(status_code=500, detail=f'Error: {e}, traceback: {traceback.format_exc()}')
263
- finally:
264
- # 如果发生异常,减少请求计数
265
- if 'he' in locals() and isinstance(he, HTTPException):
266
- optimize_design_requests[client_ip] -= 1
267
 
268
  @app.post("/api/optimize-text")
269
  async def optimize_text(request: TextOptimizationRequest):
 
20
  import uvicorn
21
  from collections import defaultdict
22
  from PIL import Image
23
+ from Crypto.PublicKey import RSA
24
+ from Crypto.Cipher import PKCS1_OAEP
25
+ from datetime import datetime
26
+ from pymongo.mongo_client import MongoClient
27
+ from pymongo.server_api import ServerApi
28
 
29
 
30
+ # mongodb uri
31
+ URI = os.getenv("URI")
32
+ # Create a new client and connect to the server
33
+ client = MongoClient(URI, server_api=ServerApi('1'))
34
+
35
  app = FastAPI()
36
 
37
  # 设置最大连接数
 
94
  suggestions: List[str]
95
  request_model_id: str = 'gpt-image-1'
96
  openai_key: str = ''
97
+ user_key: str = ''
98
 
99
  class CaseStudyRequest(BaseModel):
100
  user_input: str
 
213
  logging.error(f'Error: {e}, traceback: {traceback.format_exc()}')
214
  raise HTTPException(status_code=500, detail=f'Error: {e}, traceback: {traceback.format_exc()}')
215
 
216
+ def decrypt_user_key(encrypted_key: str) -> str:
217
+ try:
218
+ # 使用与前端相同的私钥
219
+ private_key = 'wangyuejunhui'
220
+
221
+ # 创建RSA解密对象
222
+ cipher = PKCS1_OAEP.new(RSA.import_key(private_key))
223
+
224
+ # 解码base64并解密
225
+ encrypted_data = base64.b64decode(encrypted_key)
226
+ decrypted_data = cipher.decrypt(encrypted_data)
227
+
228
+ # 返回解密后的字符串
229
+ return decrypted_data.decode('utf-8')
230
+ except Exception as e:
231
+ logging.error(f'Error decrypting user key: {e}')
232
+ return None
233
+
234
+ def search_user_key(user_key: str) -> dict:
235
+ try:
236
+ # Create a new client and connect to the server
237
+ client = MongoClient(URI, server_api=ServerApi('1'))
238
+
239
+ # Get the user_info database and user_keys collection
240
+ user_info_db = client.user_info
241
+ user_keys_collection = user_info_db['user_keys']
242
+
243
+ # Search for the user key
244
+ search_res = user_keys_collection.aggregate([
245
+ {
246
+ '$search': {
247
+ 'index': "user_key",
248
+ 'text': {
249
+ 'query': user_key,
250
+ 'path': {
251
+ 'wildcard': "*"
252
+ }
253
+ }
254
+ }
255
+ },
256
+ {
257
+ '$limit': 3
258
+ },
259
+ {
260
+ '$project': {
261
+ '_id': 0,
262
+ 'user_key': 1,
263
+ 'user_name': 1,
264
+ 'credit': 1,
265
+ 'expiration': 1
266
+ }
267
+ }
268
+ ])
269
+
270
+ # Get the first result
271
+ result = next(search_res, None)
272
+
273
+ if result:
274
+ return result
275
+ else:
276
+ return None
277
+
278
+ except Exception as e:
279
+ logging.error(f'Error searching user key: {e}')
280
+ return None
281
+
282
  @app.post("/api/optimize-design")
283
+ async def optimize_design(request: OptimizationRequest):
284
  try:
285
+ # 检查用户密钥
286
+ user_key = None
287
+ if request.user_key:
288
+ user_key = decrypt_user_key(request.user_key)
289
+ if not user_key:
290
+ raise HTTPException(
291
+ status_code=400,
292
+ detail="无效的用户密钥"
293
+ )
294
+ user_info = eval(user_key)
295
+
296
+ credit_data = {
297
+ "user_key": request.user_key,
298
+ "user_name": user_info['user_id'],
299
+ "credit": user_info['credit'],
300
+ "expiration": datetime.fromisoformat(user_info['expiration'])
301
+ }
302
+
303
+ query_res = search_user_key(request.user_key)
304
+ user_info_db = client.user_info
305
+ user_keys_collection = user_info_db['user_keys']
306
+ if not query_res:
307
+ user_keys_collection.insert_many([credit_data])
308
+ else:
309
+ credit_data = query_res
310
+
311
+ if credit_data['credit'] < 1:
312
+ raise HTTPException(
313
+ status_code=503,
314
+ detail="当前user-key额度已用尽。"
315
+ )
316
+
317
+ # 查看客户是否提供了openai_key
318
+ if not request.openai_key and not user_key:
319
  raise HTTPException(
320
  status_code=503,
321
+ detail="当前用户无生图权限,请点击'想使用自己的OpenAI API Key?'输入您的OpenAI API Key或联系@wangyue161并添加白名单user-key后重试。"
322
  )
323
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
324
  # 提取设计类型
325
  design_type = f"设计类型:{request.text.split()[0]}\n" if len(request.text.split()) > 1 else ""
326
 
 
338
  openai_key=request.openai_key
339
  )
340
 
341
+ # Update credit count by decrementing it by 1
342
+ user_keys_collection.update_one(
343
+ {"user_key": request.user_key},
344
+ {"$inc": {"credit": -1}}
345
+ )
346
+
347
  return JSONResponse(response)
348
  except HTTPException as he:
349
  raise he
350
  except Exception as e:
351
  logging.error(f'Error: {e}, traceback: {traceback.format_exc()}')
352
  raise HTTPException(status_code=500, detail=f'Error: {e}, traceback: {traceback.format_exc()}')
 
 
 
 
353
 
354
  @app.post("/api/optimize-text")
355
  async def optimize_text(request: TextOptimizationRequest):
requirements.txt CHANGED
@@ -7,4 +7,6 @@ python-dotenv==1.0.0
7
  pydantic==2.5.2
8
  requests==2.31.0
9
  openai
10
- pillow
 
 
 
7
  pydantic==2.5.2
8
  requests==2.31.0
9
  openai
10
+ pillow
11
+ Crypto
12
+ pymongo
static/script.js CHANGED
@@ -714,6 +714,7 @@ document.addEventListener('DOMContentLoaded', function() {
714
  suggestions: suggestions,
715
  request_model_id: 'gpt-image-1',
716
  openai_key: sessionStorage.getItem('userOpenaiKey') || '',
 
717
  })
718
  });
719
 
@@ -785,7 +786,8 @@ document.addEventListener('DOMContentLoaded', function() {
785
  image_data: uploadedImage,
786
  suggestions: suggestions,
787
  request_model_id: 'dall-e-2',
788
- openai_key: sessionStorage.getItem('userOpenaiKey') || ''
 
789
  })
790
  });
791
  if (response.status === 503) {
@@ -1002,4 +1004,52 @@ document.addEventListener('DOMContentLoaded', function() {
1002
  }
1003
  });
1004
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1005
  });
 
714
  suggestions: suggestions,
715
  request_model_id: 'gpt-image-1',
716
  openai_key: sessionStorage.getItem('userOpenaiKey') || '',
717
+ user_key: sessionStorage.getItem('userKey') || ''
718
  })
719
  });
720
 
 
786
  image_data: uploadedImage,
787
  suggestions: suggestions,
788
  request_model_id: 'dall-e-2',
789
+ openai_key: sessionStorage.getItem('userOpenaiKey') || '',
790
+ user_key: sessionStorage.getItem('userKey') || ''
791
  })
792
  });
793
  if (response.status === 503) {
 
1004
  }
1005
  });
1006
  }
1007
+
1008
+ // User Key Dialog functionality
1009
+ const userKeyLink = document.getElementById('userKeyLink');
1010
+ const userKeyDialog = document.getElementById('userKeyDialog');
1011
+ const userKeyInput = document.getElementById('userKeyInput');
1012
+ const saveUserKey = document.getElementById('saveUserKey');
1013
+ const cancelUserKey = document.getElementById('cancelUserKey');
1014
+
1015
+ if (userKeyLink && userKeyDialog) {
1016
+ // Show dialog when clicking the link
1017
+ userKeyLink.addEventListener('click', function(e) {
1018
+ e.preventDefault();
1019
+ userKeyDialog.style.display = 'flex';
1020
+ // Load existing key if available
1021
+ const existingKey = sessionStorage.getItem('userKey');
1022
+ if (existingKey) {
1023
+ userKeyInput.value = existingKey;
1024
+ }
1025
+ });
1026
+
1027
+ // Save User Key
1028
+ saveUserKey.addEventListener('click', function() {
1029
+ const key = userKeyInput.value.trim();
1030
+ if (key) {
1031
+ sessionStorage.setItem('userKey', key);
1032
+ userKeyDialog.style.display = 'none';
1033
+ // Show success message
1034
+ const toast = document.getElementById('toast');
1035
+ toast.textContent = '用户密钥已保存';
1036
+ toast.style.display = 'block';
1037
+ setTimeout(() => {
1038
+ toast.style.display = 'none';
1039
+ }, 2000);
1040
+ }
1041
+ });
1042
+
1043
+ // Cancel button
1044
+ cancelUserKey.addEventListener('click', function() {
1045
+ userKeyDialog.style.display = 'none';
1046
+ });
1047
+
1048
+ // Close dialog when clicking outside
1049
+ userKeyDialog.addEventListener('click', function(e) {
1050
+ if (e.target === userKeyDialog) {
1051
+ userKeyDialog.style.display = 'none';
1052
+ }
1053
+ });
1054
+ }
1055
  });