hzruo commited on
Commit
739b153
·
verified ·
1 Parent(s): 6679c63

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +335 -124
main.py CHANGED
@@ -1,9 +1,10 @@
1
  from fastapi import FastAPI, Request, Depends, HTTPException
2
  from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
3
- from fastapi.responses import StreamingResponse
4
  from fastapi.background import BackgroundTasks
 
5
  import requests
6
- from curl_cffi import requests as cffi_requests # 保留这个,用于获取cookies
7
  import uuid
8
  import json
9
  import time
@@ -13,66 +14,141 @@ import base64
13
  import tempfile
14
  import os
15
  import re
 
 
 
 
16
 
17
- app = FastAPI()
18
- security = HTTPBearer()
19
 
20
- # OpenAI API Key 配置,可以通过环境变量覆盖
21
- OPENAI_API_KEY = os.getenv("OPENAI_API_KEY", None) # 设置为 None 表示不校验,或设置具体值,如"sk-proj-1234567890"
 
 
 
 
22
 
23
  # 修改全局数据存储
24
  global_data = {
25
  "cookie": None,
26
  "cookies": None,
27
- "last_update": 0
 
28
  }
29
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  def get_cookie():
31
  try:
32
- # 使用 curl_cffi 发送请求
33
- response = cffi_requests.get(
34
- 'https://chat.akash.network/',
35
- impersonate="chrome110",
36
- timeout=30
37
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
 
39
- # 获取所有 cookies
40
- cookies = response.cookies.items()
41
- if cookies:
42
- cookie_str = '; '.join([f'{k}={v}' for k, v in cookies])
43
- global_data["cookie"] = cookie_str
44
- global_data["last_update"] = time.time()
45
- print(f"Got cookies: {cookie_str}")
46
- return cookie_str
47
 
48
  except Exception as e:
49
- print(f"Error fetching cookie: {e}")
50
- return None
 
 
 
 
 
 
 
 
51
 
52
  async def check_and_update_cookie(background_tasks: BackgroundTasks):
53
- # 如果cookie超过30分钟,在后台更新
54
- if time.time() - global_data["last_update"] > 1800:
 
 
55
  background_tasks.add_task(get_cookie)
56
-
57
- @app.on_event("startup")
58
- async def startup_event():
59
- get_cookie()
60
 
61
  async def get_api_key(credentials: HTTPAuthorizationCredentials = Depends(security)):
62
  token = credentials.credentials
 
63
 
64
  # 如果设置了 OPENAI_API_KEY,则需要验证
65
  if OPENAI_API_KEY is not None:
66
  # 去掉 Bearer 前缀后再比较
67
  clean_token = token.replace("Bearer ", "") if token.startswith("Bearer ") else token
 
68
  if clean_token != OPENAI_API_KEY:
 
69
  raise HTTPException(
70
  status_code=401,
71
  detail="Invalid API key"
72
  )
 
73
 
74
- # 返回去掉 "Bearer " 前缀的token
75
- return token.replace("Bearer ", "") if token.startswith("Bearer ") else token
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
 
77
  async def check_image_status(session: requests.Session, job_id: str, headers: dict) -> Optional[str]:
78
  """检查图片生成状态并获取生成的图片"""
@@ -120,19 +196,118 @@ async def check_image_status(session: requests.Session, job_id: str, headers: di
120
  print(f"Timeout waiting for job {job_id}")
121
  return None
122
 
123
- @app.get("/")
124
  async def health_check():
125
  """Health check endpoint"""
126
- return {"status": "ok"}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
 
128
  @app.post("/v1/chat/completions")
129
  async def chat_completions(
130
  request: Request,
131
- api_key: str = Depends(get_api_key)
 
 
132
  ):
133
  try:
134
  data = await request.json()
135
- print(f"Chat request data: {data}")
136
 
137
  chat_id = str(uuid.uuid4()).replace('-', '')[:16]
138
 
@@ -145,24 +320,23 @@ async def chat_completions(
145
  "topP": data.get('top_p', 0.95)
146
  }
147
 
 
148
  headers = {
149
  "Content-Type": "application/json",
150
- "Cookie": f"session_token={api_key}",
151
- "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
152
  "Accept": "*/*",
153
- "Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
154
  "Accept-Encoding": "gzip, deflate, br",
155
  "Origin": "https://chat.akash.network",
156
  "Referer": "https://chat.akash.network/",
157
  "Sec-Fetch-Dest": "empty",
158
  "Sec-Fetch-Mode": "cors",
159
  "Sec-Fetch-Site": "same-origin",
160
- "Connection": "keep-alive",
161
- "Priority": "u=1, i"
162
  }
163
 
164
- print(f"Sending request to Akash with headers: {headers}")
165
- print(f"Request data: {akash_data}")
166
 
167
  with requests.Session() as session:
168
  response = session.post(
@@ -172,6 +346,26 @@ async def chat_completions(
172
  stream=True
173
  )
174
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
  def generate():
176
  content_buffer = ""
177
  for line in response.iter_lines():
@@ -208,7 +402,7 @@ async def chat_completions(
208
  if result_messages:
209
  for message in result_messages:
210
  yield f"data: {json.dumps(message)}\n\n"
211
- continue
212
 
213
  content_buffer += msg_data
214
 
@@ -230,7 +424,7 @@ async def chat_completions(
230
  "id": f"chatcmpl-{chat_id}",
231
  "object": "chat.completion.chunk",
232
  "created": int(time.time()),
233
- "model": data.get('model'), # 使用请求中指定的模型
234
  "choices": [{
235
  "delta": {},
236
  "index": 0,
@@ -256,31 +450,48 @@ async def chat_completions(
256
  )
257
 
258
  except Exception as e:
 
 
 
259
  return {"error": str(e)}
260
 
261
  @app.get("/v1/models")
262
- async def list_models(api_key: str = Depends(get_api_key)):
 
 
 
263
  try:
264
  headers = {
265
- "Content-Type": "application/json",
266
- "Cookie": f"session_token={api_key}",
267
- "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
268
- "Accept": "*/*",
269
- "Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
270
- "Accept-Encoding": "gzip, deflate, br",
271
- "Origin": "https://chat.akash.network",
272
- "Referer": "https://chat.akash.network/",
273
- "Sec-Fetch-Dest": "empty",
274
- "Sec-Fetch-Mode": "cors",
275
- "Sec-Fetch-Site": "same-origin",
276
- "Connection": "keep-alive"
277
  }
278
 
 
 
 
 
 
 
279
  response = requests.get(
280
  'https://chat.akash.network/api/models',
281
  headers=headers
282
  )
283
 
 
 
 
 
 
 
 
284
  akash_response = response.json()
285
 
286
  # 添加错误处理和调试信息
@@ -333,73 +544,6 @@ async def list_models(api_key: str = Depends(get_api_key)):
333
  print(traceback.format_exc())
334
  return {"error": str(e)}
335
 
336
- async def upload_to_xinyew(image_base64: str, job_id: str) -> Optional[str]:
337
- """上传图片到新野图床并返回URL"""
338
- try:
339
- print(f"\n=== Starting image upload for job {job_id} ===")
340
- print(f"Base64 data length: {len(image_base64)}")
341
-
342
- # 解码base64图片数据
343
- try:
344
- image_data = base64.b64decode(image_base64.split(',')[1] if ',' in image_base64 else image_base64)
345
- print(f"Decoded image data length: {len(image_data)} bytes")
346
- except Exception as e:
347
- print(f"Error decoding base64: {e}")
348
- print(f"First 100 chars of base64: {image_base64[:100]}...")
349
- return None
350
-
351
- # 创建临时文件
352
- with tempfile.NamedTemporaryFile(suffix='.jpeg', delete=False) as temp_file:
353
- temp_file.write(image_data)
354
- temp_file_path = temp_file.name
355
-
356
- try:
357
- filename = f"{job_id}.jpeg"
358
- print(f"Using filename: {filename}")
359
-
360
- # 准备文件上传
361
- files = {
362
- 'file': (filename, open(temp_file_path, 'rb'), 'image/jpeg')
363
- }
364
-
365
- print("Sending request to xinyew.cn...")
366
- response = requests.post(
367
- 'https://api.xinyew.cn/api/jdtc',
368
- files=files,
369
- timeout=30
370
- )
371
-
372
- print(f"Upload response status: {response.status_code}")
373
- if response.status_code == 200:
374
- result = response.json()
375
- print(f"Upload response: {result}")
376
-
377
- if result.get('errno') == 0:
378
- url = result.get('data', {}).get('url')
379
- if url:
380
- print(f"Successfully got image URL: {url}")
381
- return url
382
- print("No URL in response data")
383
- else:
384
- print(f"Upload failed: {result.get('message')}")
385
- else:
386
- print(f"Upload failed with status {response.status_code}")
387
- print(f"Response content: {response.text}")
388
- return None
389
-
390
- finally:
391
- # 清理临时文件
392
- try:
393
- os.unlink(temp_file_path)
394
- except Exception as e:
395
- print(f"Error removing temp file: {e}")
396
-
397
- except Exception as e:
398
- print(f"Error in upload_to_xinyew: {e}")
399
- import traceback
400
- print(traceback.format_exc())
401
- return None
402
-
403
  async def process_image_generation(msg_data: str, session: requests.Session, headers: dict, chat_id: str) -> Optional[list]:
404
  """处理图片生成的逻辑,返回多个消息块"""
405
  match = re.search(r"jobId='([^']+)' prompt='([^']+)' negative='([^']*)'", msg_data)
@@ -472,6 +616,73 @@ async def process_image_generation(msg_data: str, session: requests.Session, hea
472
  return messages
473
  return None
474
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
475
  if __name__ == '__main__':
476
  import uvicorn
477
  uvicorn.run(app, host='0.0.0.0', port=9000)
 
1
  from fastapi import FastAPI, Request, Depends, HTTPException
2
  from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
3
+ from fastapi.responses import StreamingResponse, HTMLResponse
4
  from fastapi.background import BackgroundTasks
5
+ from contextlib import asynccontextmanager
6
  import requests
7
+ from curl_cffi import requests as cffi_requests
8
  import uuid
9
  import json
10
  import time
 
14
  import tempfile
15
  import os
16
  import re
17
+ import threading
18
+ from DrissionPage import ChromiumPage, ChromiumOptions
19
+ import logging
20
+ from dotenv import load_dotenv
21
 
22
+ # 加载环境变量
23
+ load_dotenv(override=True)
24
 
25
+ # 配置日志
26
+ logging.basicConfig(
27
+ level=logging.INFO, # 改为 INFO 级别
28
+ format='%(asctime)s - %(levelname)s - %(message)s'
29
+ )
30
+ logger = logging.getLogger(__name__)
31
 
32
  # 修改全局数据存储
33
  global_data = {
34
  "cookie": None,
35
  "cookies": None,
36
+ "last_update": 0,
37
+ "cookie_expires": 0 # 添加 cookie 过期时间
38
  }
39
 
40
+ @asynccontextmanager
41
+ async def lifespan(app: FastAPI):
42
+ # 启动时获取 cookie
43
+ threading.Thread(target=get_cookie).start()
44
+ yield
45
+ # 关闭时清理资源
46
+ global_data["cookie"] = None
47
+ global_data["cookies"] = None
48
+ global_data["last_update"] = 0
49
+
50
+ app = FastAPI(lifespan=lifespan)
51
+ security = HTTPBearer()
52
+
53
+ # OpenAI API Key 配置,可以通过环境变量覆盖
54
+ OPENAI_API_KEY = os.getenv("OPENAI_API_KEY", None)
55
+ logger.info(f"OPENAI_API_KEY is set: {OPENAI_API_KEY is not None}")
56
+ logger.info(f"OPENAI_API_KEY value: {OPENAI_API_KEY}")
57
+
58
  def get_cookie():
59
  try:
60
+ options = ChromiumOptions().headless()
61
+ page = ChromiumPage(addr_or_opts=options)
62
+ page.set.window.size(1920, 1080)
63
+ page.set.user_agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
64
+
65
+ page.get("https://chat.akash.network/")
66
+ time.sleep(10)
67
+
68
+ cookies = page.cookies()
69
+ if not cookies:
70
+ page.quit()
71
+ return None
72
+
73
+ cookie_dict = {cookie['name']: cookie['value'] for cookie in cookies}
74
+ if 'cf_clearance' not in cookie_dict:
75
+ page.quit()
76
+ return None
77
+
78
+ cookie_str = '; '.join([f"{cookie['name']}={cookie['value']}" for cookie in cookies])
79
+ global_data["cookie"] = cookie_str
80
+ global_data["last_update"] = time.time()
81
+
82
+ expires = min([cookie.get('expires', float('inf')) for cookie in cookies])
83
+ if expires != float('inf'):
84
+ global_data["cookie_expires"] = expires
85
+ else:
86
+ global_data["cookie_expires"] = time.time() + 3600
87
 
88
+ page.quit()
89
+ return cookie_str
 
 
 
 
 
 
90
 
91
  except Exception as e:
92
+ logger.error(f"Error fetching cookie: {e}")
93
+ return None
94
+
95
+ # 添加刷新 cookie 的函数
96
+ async def refresh_cookie():
97
+ logger.info("Refreshing cookie due to 401 error")
98
+ # 标记 cookie 为过期
99
+ global_data["cookie_expires"] = 0
100
+ # 获取新的 cookie
101
+ return get_cookie()
102
 
103
  async def check_and_update_cookie(background_tasks: BackgroundTasks):
104
+ # 如果 cookie 不存在或已过期,则更新
105
+ current_time = time.time()
106
+ if not global_data["cookie"] or current_time >= global_data["cookie_expires"]:
107
+ logger.info("Cookie expired or not available, refreshing...")
108
  background_tasks.add_task(get_cookie)
109
+ else:
110
+ logger.info("Using existing cookie")
 
 
111
 
112
  async def get_api_key(credentials: HTTPAuthorizationCredentials = Depends(security)):
113
  token = credentials.credentials
114
+ logger.info(f"Received token: {token}")
115
 
116
  # 如果设置了 OPENAI_API_KEY,则需要验证
117
  if OPENAI_API_KEY is not None:
118
  # 去掉 Bearer 前缀后再比较
119
  clean_token = token.replace("Bearer ", "") if token.startswith("Bearer ") else token
120
+ logger.info(f"Clean token: {clean_token}")
121
  if clean_token != OPENAI_API_KEY:
122
+ logger.error(f"Token mismatch. Expected: {OPENAI_API_KEY}, Got: {clean_token}")
123
  raise HTTPException(
124
  status_code=401,
125
  detail="Invalid API key"
126
  )
127
+ logger.info("API key validation passed")
128
 
129
+ return True
130
+
131
+ async def validate_cookie(background_tasks: BackgroundTasks):
132
+ # 检查并更新 cookie(如果需要)
133
+ await check_and_update_cookie(background_tasks)
134
+
135
+ # 等待 cookie 初始化完成
136
+ max_wait = 30 # 最大等待时间(秒)
137
+ start_time = time.time()
138
+ while not global_data["cookie"] and time.time() - start_time < max_wait:
139
+ await asyncio.sleep(1)
140
+ logger.info("Waiting for cookie initialization...")
141
+
142
+ # 检查是否有有效的 cookie
143
+ if not global_data["cookie"]:
144
+ logger.error("Cookie not available after waiting")
145
+ raise HTTPException(
146
+ status_code=503,
147
+ detail="Service temporarily unavailable - Cookie not available"
148
+ )
149
+
150
+ logger.info("Cookie validation passed")
151
+ return global_data["cookie"]
152
 
153
  async def check_image_status(session: requests.Session, job_id: str, headers: dict) -> Optional[str]:
154
  """检查图片生成状态并获取生成的图片"""
 
196
  print(f"Timeout waiting for job {job_id}")
197
  return None
198
 
199
+ @app.get("/", response_class=HTMLResponse)
200
  async def health_check():
201
  """Health check endpoint"""
202
+ status = {
203
+ "status": "ok",
204
+ "version": "1.0.0",
205
+ "cookie_status": {
206
+ "available": global_data["cookie"] is not None,
207
+ "last_update": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(global_data["last_update"])) if global_data["last_update"] > 0 else None,
208
+ "expires": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(global_data["cookie_expires"])) if global_data["cookie_expires"] > 0 else None
209
+ }
210
+ }
211
+
212
+ html = f"""
213
+ <!DOCTYPE html>
214
+ <html>
215
+ <head>
216
+ <title>Akash API Status</title>
217
+ <style>
218
+ body {{
219
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
220
+ line-height: 1.6;
221
+ margin: 0;
222
+ padding: 20px;
223
+ background-color: #f5f5f5;
224
+ }}
225
+ .container {{
226
+ max-width: 800px;
227
+ margin: 0 auto;
228
+ background-color: white;
229
+ padding: 20px;
230
+ border-radius: 8px;
231
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
232
+ }}
233
+ h1 {{
234
+ color: #333;
235
+ margin-top: 0;
236
+ }}
237
+ .status {{
238
+ display: inline-block;
239
+ padding: 4px 8px;
240
+ border-radius: 4px;
241
+ font-weight: bold;
242
+ background-color: #4CAF50;
243
+ color: white;
244
+ }}
245
+ .info {{
246
+ margin-top: 20px;
247
+ }}
248
+ .info-item {{
249
+ margin-bottom: 10px;
250
+ }}
251
+ .label {{
252
+ font-weight: bold;
253
+ color: #666;
254
+ }}
255
+ .value {{
256
+ color: #333;
257
+ }}
258
+ .cookie-status {{
259
+ margin-top: 20px;
260
+ padding: 15px;
261
+ background-color: #f8f9fa;
262
+ border-radius: 4px;
263
+ }}
264
+ .cookie-status .available {{
265
+ color: {"#4CAF50" if status["cookie_status"]["available"] else "#f44336"};
266
+ }}
267
+ </style>
268
+ </head>
269
+ <body>
270
+ <div class="container">
271
+ <h1>Akash API Status <span class="status">{status["status"]}</span></h1>
272
+
273
+ <div class="info">
274
+ <div class="info-item">
275
+ <span class="label">Version:</span>
276
+ <span class="value">{status["version"]}</span>
277
+ </div>
278
+ </div>
279
+
280
+ <div class="cookie-status">
281
+ <h2>Cookie Status</h2>
282
+ <div class="info-item">
283
+ <span class="label">Available:</span>
284
+ <span class="value available">{str(status["cookie_status"]["available"])}</span>
285
+ </div>
286
+ <div class="info-item">
287
+ <span class="label">Last Update:</span>
288
+ <span class="value">{status["cookie_status"]["last_update"] or "Never"}</span>
289
+ </div>
290
+ <div class="info-item">
291
+ <span class="label">Expires:</span>
292
+ <span class="value">{status["cookie_status"]["expires"] or "Unknown"}</span>
293
+ </div>
294
+ </div>
295
+ </div>
296
+ </body>
297
+ </html>
298
+ """
299
+
300
+ return html
301
 
302
  @app.post("/v1/chat/completions")
303
  async def chat_completions(
304
  request: Request,
305
+ background_tasks: BackgroundTasks,
306
+ api_key: bool = Depends(get_api_key),
307
+ cookie: str = Depends(validate_cookie)
308
  ):
309
  try:
310
  data = await request.json()
 
311
 
312
  chat_id = str(uuid.uuid4()).replace('-', '')[:16]
313
 
 
320
  "topP": data.get('top_p', 0.95)
321
  }
322
 
323
+ # 构建请求头
324
  headers = {
325
  "Content-Type": "application/json",
326
+ "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
 
327
  "Accept": "*/*",
328
+ "Accept-Language": "en-US,en;q=0.9",
329
  "Accept-Encoding": "gzip, deflate, br",
330
  "Origin": "https://chat.akash.network",
331
  "Referer": "https://chat.akash.network/",
332
  "Sec-Fetch-Dest": "empty",
333
  "Sec-Fetch-Mode": "cors",
334
  "Sec-Fetch-Site": "same-origin",
335
+ "Connection": "keep-alive"
 
336
  }
337
 
338
+ # 设置 Cookie
339
+ headers["Cookie"] = cookie
340
 
341
  with requests.Session() as session:
342
  response = session.post(
 
346
  stream=True
347
  )
348
 
349
+ # 检查响应状态码,如果是 401,尝试刷新 cookie 并重试
350
+ if response.status_code == 401:
351
+ logger.info("Cookie expired, refreshing...")
352
+ new_cookie = await refresh_cookie()
353
+ if new_cookie:
354
+ headers["Cookie"] = new_cookie
355
+ response = session.post(
356
+ 'https://chat.akash.network/api/chat',
357
+ json=akash_data,
358
+ headers=headers,
359
+ stream=True
360
+ )
361
+
362
+ if response.status_code != 200:
363
+ logger.error(f"Akash API error: {response.text}")
364
+ raise HTTPException(
365
+ status_code=response.status_code,
366
+ detail=f"Akash API error: {response.text}"
367
+ )
368
+
369
  def generate():
370
  content_buffer = ""
371
  for line in response.iter_lines():
 
402
  if result_messages:
403
  for message in result_messages:
404
  yield f"data: {json.dumps(message)}\n\n"
405
+ continue
406
 
407
  content_buffer += msg_data
408
 
 
424
  "id": f"chatcmpl-{chat_id}",
425
  "object": "chat.completion.chunk",
426
  "created": int(time.time()),
427
+ "model": data.get('model'),
428
  "choices": [{
429
  "delta": {},
430
  "index": 0,
 
450
  )
451
 
452
  except Exception as e:
453
+ print(f"Error in chat_completions: {e}")
454
+ import traceback
455
+ print(traceback.format_exc())
456
  return {"error": str(e)}
457
 
458
  @app.get("/v1/models")
459
+ async def list_models(
460
+ background_tasks: BackgroundTasks,
461
+ cookie: str = Depends(validate_cookie)
462
+ ):
463
  try:
464
  headers = {
465
+ "accept": "application/json",
466
+ "accept-language": "en-US,en;q=0.9",
467
+ "sec-ch-ua": '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
468
+ "sec-ch-ua-mobile": "?0",
469
+ "sec-ch-ua-platform": '"macOS"',
470
+ "sec-fetch-dest": "document",
471
+ "sec-fetch-mode": "cors",
472
+ "sec-fetch-site": "same-origin",
473
+ "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
474
+ "referer": "https://chat.akash.network/"
 
 
475
  }
476
 
477
+ # 设置 Cookie
478
+ headers["Cookie"] = cookie
479
+
480
+ print(f"Using cookie: {headers.get('Cookie', 'None')}")
481
+ print("Sending request to get models...")
482
+
483
  response = requests.get(
484
  'https://chat.akash.network/api/models',
485
  headers=headers
486
  )
487
 
488
+ print(f"Models response status: {response.status_code}")
489
+ print(f"Models response headers: {response.headers}")
490
+
491
+ if response.status_code == 401:
492
+ print("Authentication failed. Please check your API key.")
493
+ return {"error": "Authentication failed. Please check your API key."}
494
+
495
  akash_response = response.json()
496
 
497
  # 添加错误处理和调试信息
 
544
  print(traceback.format_exc())
545
  return {"error": str(e)}
546
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
547
  async def process_image_generation(msg_data: str, session: requests.Session, headers: dict, chat_id: str) -> Optional[list]:
548
  """处理图片生成的逻辑,返回多个消息块"""
549
  match = re.search(r"jobId='([^']+)' prompt='([^']+)' negative='([^']*)'", msg_data)
 
616
  return messages
617
  return None
618
 
619
+ async def upload_to_xinyew(image_base64: str, job_id: str) -> Optional[str]:
620
+ """上传图片到新野图床并返回URL"""
621
+ try:
622
+ print(f"\n=== Starting image upload for job {job_id} ===")
623
+ print(f"Base64 data length: {len(image_base64)}")
624
+
625
+ # 解码base64图片数据
626
+ try:
627
+ image_data = base64.b64decode(image_base64.split(',')[1] if ',' in image_base64 else image_base64)
628
+ print(f"Decoded image data length: {len(image_data)} bytes")
629
+ except Exception as e:
630
+ print(f"Error decoding base64: {e}")
631
+ print(f"First 100 chars of base64: {image_base64[:100]}...")
632
+ return None
633
+
634
+ # 创建临时文件
635
+ with tempfile.NamedTemporaryFile(suffix='.jpeg', delete=False) as temp_file:
636
+ temp_file.write(image_data)
637
+ temp_file_path = temp_file.name
638
+
639
+ try:
640
+ filename = f"{job_id}.jpeg"
641
+ print(f"Using filename: {filename}")
642
+
643
+ # 准备文件上传
644
+ files = {
645
+ 'file': (filename, open(temp_file_path, 'rb'), 'image/jpeg')
646
+ }
647
+
648
+ print("Sending request to xinyew.cn...")
649
+ response = requests.post(
650
+ 'https://api.xinyew.cn/api/jdtc',
651
+ files=files,
652
+ timeout=30
653
+ )
654
+
655
+ print(f"Upload response status: {response.status_code}")
656
+ if response.status_code == 200:
657
+ result = response.json()
658
+ print(f"Upload response: {result}")
659
+
660
+ if result.get('errno') == 0:
661
+ url = result.get('data', {}).get('url')
662
+ if url:
663
+ print(f"Successfully got image URL: {url}")
664
+ return url
665
+ print("No URL in response data")
666
+ else:
667
+ print(f"Upload failed: {result.get('message')}")
668
+ else:
669
+ print(f"Upload failed with status {response.status_code}")
670
+ print(f"Response content: {response.text}")
671
+ return None
672
+
673
+ finally:
674
+ # 清理临时文件
675
+ try:
676
+ os.unlink(temp_file_path)
677
+ except Exception as e:
678
+ print(f"Error removing temp file: {e}")
679
+
680
+ except Exception as e:
681
+ print(f"Error in upload_to_xinyew: {e}")
682
+ import traceback
683
+ print(traceback.format_exc())
684
+ return None
685
+
686
  if __name__ == '__main__':
687
  import uvicorn
688
  uvicorn.run(app, host='0.0.0.0', port=9000)