yuoop commited on
Commit
ef881c7
·
verified ·
1 Parent(s): 1d33d55

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +229 -0
app.py ADDED
@@ -0,0 +1,229 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import time
3
+ import hashlib
4
+ import base64
5
+ import asyncio
6
+ import aiohttp
7
+ from fastapi import FastAPI, Request, Response
8
+ from typing import Optional, Dict, List, Any
9
+ import uvicorn
10
+ from pydantic import BaseModel
11
+
12
+ # Configuration
13
+ API_CHALLENGE_URL = 'https://api.eqing.tech/api/altcaptcha/challenge'
14
+ NEXTWAY_CHAT_URL = 'https://origin.eqing.tech/api/openai/v1/chat/completions'
15
+ CREDENTIAL_EXPIRY_MARGIN = 60 * 1000 # 60 seconds in milliseconds
16
+ PORT = 8080
17
+ API_ENDPOINT = '/v1/chat/completions'
18
+ MODEL_NAME = "gpt-4o-free"
19
+ REQUEST_TIMEOUT = 480 # seconds
20
+ MAX_RETRIES = 3
21
+ RETRY_DELAY = 1 # seconds
22
+
23
+ # Global variables
24
+ current_credential = None
25
+ credential_expiry = None
26
+ is_refreshing_credential = False
27
+
28
+ # Model mappings
29
+ MODEL_MAPPING = {
30
+ 'gpt-4o-all-lite': 'gpt-4o-mini',
31
+ 'gpt-4o-image': 'gpt-4o-mini-image-free',
32
+ 'grok-3-re': 'grok-3-free',
33
+ 'gemini-2.0-flash': 'gemini-2.0-flash-free'
34
+ }
35
+
36
+ app = FastAPI()
37
+
38
+ class ChatRequest(BaseModel):
39
+ messages: List[Dict[str, str]]
40
+ model: Optional[str]
41
+ stream: Optional[bool] = True
42
+ temperature: Optional[float] = 0.5
43
+ presence_penalty: Optional[float] = 0
44
+ frequency_penalty: Optional[float] = 0
45
+ top_p: Optional[float] = 1
46
+ max_tokens: Optional[int] = 4000
47
+
48
+ def extract_content(text: str) -> str:
49
+ lines = text.split('\n')
50
+ ai_response = ''
51
+ ignored_id = 'chatcmpl-nxaTnETiUyAVBjdRwlr38Yt3'
52
+ created = 1687070102
53
+
54
+ for line in lines:
55
+ line = line.strip()
56
+ if line.startswith('data:'):
57
+ data_str = line[5:].strip()
58
+ if not data_str or data_str in ['[ORIGIN]', '[DONE]']:
59
+ continue
60
+
61
+ try:
62
+ json_data = json.loads(data_str)
63
+ if json_data.get('id') == ignored_id or json_data.get('created') == created:
64
+ continue
65
+
66
+ if (json_data.get('choices') and json_data['choices'][0].get('delta') and
67
+ 'content' in json_data['choices'][0]['delta']):
68
+ ai_response += json_data['choices'][0]['delta']['content']
69
+
70
+ except json.JSONDecodeError:
71
+ print(f'Skipping non-JSON data')
72
+
73
+ return ai_response
74
+
75
+ async def solve_challenge(challenge: str, salt: str, algorithm: str = "SHA-512", max_number: int = 1000000):
76
+ start_time = time.time()
77
+
78
+ for number in range(max_number):
79
+ hash_value = await verify_hash(salt, number, algorithm)
80
+ if hash_value == challenge:
81
+ return {"number": number, "took": int((time.time() - start_time) * 1000)}
82
+
83
+ return None
84
+
85
+ async def verify_hash(salt: str, number: int, algorithm: str) -> str:
86
+ input_str = f"{salt}{number}"
87
+
88
+ if algorithm == "SHA-512":
89
+ hash_obj = hashlib.sha512(input_str.encode())
90
+ return hash_obj.hexdigest()
91
+ elif algorithm == "SHA-256":
92
+ hash_obj = hashlib.sha256(input_str.encode())
93
+ return hash_obj.hexdigest()
94
+ else:
95
+ raise ValueError(f"Unsupported algorithm: {algorithm}")
96
+
97
+ async def generate_credential():
98
+ global current_credential, credential_expiry
99
+
100
+ async with aiohttp.ClientSession() as session:
101
+ try:
102
+ async with session.get(API_CHALLENGE_URL) as response:
103
+ if response.status != 200:
104
+ print(f"Challenge request failed with status {response.status}")
105
+ return None
106
+
107
+ data = await response.json()
108
+ solution = await solve_challenge(
109
+ data['challenge'],
110
+ data['salt'],
111
+ data['algorithm'],
112
+ data['maxnumber']
113
+ )
114
+
115
+ if not solution:
116
+ print("Failed to solve challenge")
117
+ return None
118
+
119
+ credential_obj = {
120
+ "algorithm": data['algorithm'],
121
+ "challenge": data['challenge'],
122
+ "number": solution['number'],
123
+ "salt": data['salt'],
124
+ "signature": data['signature'],
125
+ "took": solution['took']
126
+ }
127
+
128
+ credential = base64.b64encode(json.dumps(credential_obj).encode()).decode()
129
+ expiry = int(data['salt'].split('?expires=')[1]) * 1000
130
+
131
+ return {"credential": credential, "expiry": expiry}
132
+
133
+ except Exception as e:
134
+ print(f"Error generating credential: {e}")
135
+ return None
136
+
137
+ async def get_credential():
138
+ global current_credential, credential_expiry, is_refreshing_credential
139
+
140
+ if (not current_credential or
141
+ not credential_expiry or
142
+ credential_expiry <= time.time() * 1000 + CREDENTIAL_EXPIRY_MARGIN):
143
+
144
+ if not is_refreshing_credential:
145
+ is_refreshing_credential = True
146
+ try:
147
+ cred_data = await generate_credential()
148
+ if cred_data:
149
+ current_credential = cred_data['credential']
150
+ credential_expiry = cred_data['expiry']
151
+ finally:
152
+ is_refreshing_credential = False
153
+ else:
154
+ await asyncio.sleep(2)
155
+
156
+ return current_credential
157
+
158
+ @app.post(API_ENDPOINT)
159
+ async def chat_endpoint(request: ChatRequest):
160
+ try:
161
+ model = MODEL_MAPPING.get(request.model, request.model or MODEL_NAME)
162
+ response_content = await handle_chat_request(model, request.messages)
163
+
164
+ if response_content is None:
165
+ return Response(
166
+ content="Failed to get response from API",
167
+ status_code=500
168
+ )
169
+
170
+ return {
171
+ "choices": [{
172
+ "message": {
173
+ "role": "assistant",
174
+ "content": response_content.strip()
175
+ },
176
+ "finish_reason": "stop",
177
+ "index": 0
178
+ }],
179
+ "model": model,
180
+ "object": "chat.completion"
181
+ }
182
+
183
+ except Exception as e:
184
+ print(f"Error handling chat request: {e}")
185
+ return Response(content="Internal server error", status_code=500)
186
+
187
+ async def handle_chat_request(model: str, messages: List[Dict[str, str]]):
188
+ captcha_token = await get_credential()
189
+ if not captcha_token:
190
+ return None
191
+
192
+ body = {
193
+ "messages": messages,
194
+ "stream": True,
195
+ "model": model,
196
+ "temperature": 0.5,
197
+ "presence_penalty": 0,
198
+ "frequency_penalty": 0,
199
+ "top_p": 1,
200
+ "max_tokens": 4000,
201
+ "captchaToken": captcha_token
202
+ }
203
+
204
+ async with aiohttp.ClientSession() as session:
205
+ try:
206
+ async with session.post(
207
+ NEXTWAY_CHAT_URL,
208
+ json=body,
209
+ timeout=REQUEST_TIMEOUT
210
+ ) as response:
211
+ if response.status != 200:
212
+ return None
213
+
214
+ complete_response = ""
215
+ async for chunk in response.content:
216
+ chunk_text = chunk.decode()
217
+ content = extract_content(chunk_text)
218
+ if content:
219
+ complete_response += content
220
+
221
+ return complete_response
222
+
223
+ except Exception as e:
224
+ print(f"Error in chat request: {e}")
225
+ await get_credential() # Refresh credential on error
226
+ return None
227
+
228
+ if __name__ == "__main__":
229
+ uvicorn.run(app, host="0.0.0.0", port=PORT)