bahi-bh commited on
Commit
a0f406c
Β·
verified Β·
1 Parent(s): e95285d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +351 -66
app.py CHANGED
@@ -1,14 +1,23 @@
 
 
 
1
  import time
2
  import random
3
  import traceback
4
  import logging
5
 
6
  from fastapi import FastAPI, HTTPException, Request
 
7
  from pydantic import BaseModel
8
  import uvicorn
9
 
10
  from g4f.client import Client
11
- from g4f.Provider import __providers__
 
 
 
 
 
12
 
13
  # =====================================================
14
  # CONFIG
@@ -38,36 +47,57 @@ logger = logging.getLogger("smart-g4f")
38
 
39
  app = FastAPI(
40
  title="Smart G4F Gateway",
41
- version="1.1"
42
  )
43
 
44
  # =====================================================
45
- # AUTH
 
 
 
 
 
 
 
 
 
 
 
 
46
  # =====================================================
47
 
48
  def verify_api_key(req: Request):
49
 
 
 
 
 
50
  auth = req.headers.get("Authorization")
51
 
52
- if not auth:
53
- raise HTTPException(
54
- status_code=401,
55
- detail="Missing Authorization Header"
56
- )
57
 
58
- if not auth.startswith("Bearer "):
59
- raise HTTPException(
60
- status_code=401,
61
- detail="Invalid Authorization Format"
62
- )
63
 
64
- token = auth.replace("Bearer ", "").strip()
 
65
 
66
- if token != API_KEY:
67
- raise HTTPException(
68
- status_code=403,
69
- detail="Invalid API Key"
70
- )
 
 
 
 
 
 
 
 
 
 
 
 
71
 
72
  # =====================================================
73
  # SAFE PROVIDERS
@@ -75,41 +105,35 @@ def verify_api_key(req: Request):
75
 
76
  SAFE_PROVIDERS = []
77
 
78
- for provider in __providers__:
79
-
80
- try:
81
-
82
- name = provider.__name__.lower()
83
-
84
- if not getattr(provider, "working", False):
85
- continue
86
 
87
- if getattr(provider, "needs_auth", False):
88
- continue
89
 
90
- if getattr(provider, "use_nodriver", False):
91
- continue
92
 
93
- blocked = [
94
- "openai",
95
- "qwen",
96
- "copilot",
97
- "gemini",
98
- "claude",
99
- ]
100
 
101
- if any(x in name for x in blocked):
102
- continue
 
 
103
 
104
- SAFE_PROVIDERS.append(provider)
105
 
106
- except Exception:
107
- continue
108
 
109
  random.shuffle(SAFE_PROVIDERS)
110
 
111
  logger.info(f"[+] SAFE PROVIDERS: {len(SAFE_PROVIDERS)}")
112
 
 
 
 
 
113
  client = Client()
114
 
115
  # =====================================================
@@ -120,13 +144,16 @@ class SmartG4F:
120
 
121
  def __init__(self):
122
 
123
- self.good = []
124
  self.bad = {}
125
 
 
 
126
  def mark_bad(self, provider, cooldown=300):
127
 
128
  self.bad[provider.__name__] = time.time() + cooldown
129
 
 
 
130
  def is_bad(self, provider):
131
 
132
  if provider.__name__ not in self.bad:
@@ -134,34 +161,47 @@ class SmartG4F:
134
 
135
  return time.time() < self.bad[provider.__name__]
136
 
 
 
137
  def get_provider(self):
138
 
139
  random.shuffle(SAFE_PROVIDERS)
140
 
141
- for provider in SAFE_PROVIDERS:
 
 
142
 
143
  if self.is_bad(provider):
144
  continue
145
 
146
- return provider
147
 
148
  return None
149
 
 
 
150
  def ask(self, prompt):
151
 
 
 
152
  for _ in range(MAX_RETRIES):
153
 
154
- provider = self.get_provider()
155
 
156
- if not provider:
157
  break
158
 
 
 
 
159
  try:
160
 
161
- logger.info(f"[+] Trying: {provider.__name__}")
 
 
162
 
163
  response = client.chat.completions.create(
164
- model=MODEL,
165
  provider=provider,
166
  messages=[
167
  {
@@ -172,24 +212,40 @@ class SmartG4F:
172
  timeout=TIMEOUT
173
  )
174
 
175
- text = response.choices[0].message.content
 
 
 
 
 
176
 
177
- if text:
178
 
179
- logger.info(f"[+] Success: {provider.__name__}")
 
 
180
 
181
  return {
182
  "provider": provider.__name__,
 
183
  "response": text
184
  }
185
 
186
  except Exception as e:
187
 
188
- logger.warning(f"[-] Failed: {provider.__name__} -> {e}")
 
 
 
 
189
 
190
  self.mark_bad(provider)
191
 
192
- raise Exception("All providers failed")
 
 
 
 
193
 
194
  smart = SmartG4F()
195
 
@@ -202,7 +258,7 @@ class ChatRequest(BaseModel):
202
  prompt: str
203
 
204
  # =====================================================
205
- # ROUTES
206
  # =====================================================
207
 
208
  @app.get("/")
@@ -211,18 +267,53 @@ async def root():
211
 
212
  return {
213
  "status": "online",
 
 
214
  "providers": len(SAFE_PROVIDERS),
215
- "model": MODEL
 
 
 
216
  }
217
 
 
 
 
 
218
  @app.get("/health")
219
 
220
  async def health():
221
 
222
  return {
223
- "ok": True
 
224
  }
225
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
226
  @app.post("/chat")
227
 
228
  async def chat(req: Request, body: ChatRequest):
@@ -236,6 +327,7 @@ async def chat(req: Request, body: ChatRequest):
236
  return {
237
  "success": True,
238
  "provider": result["provider"],
 
239
  "response": result["response"]
240
  }
241
 
@@ -248,6 +340,195 @@ async def chat(req: Request, body: ChatRequest):
248
  detail=str(e)
249
  )
250
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
251
  # =====================================================
252
  # RUN
253
  # =====================================================
@@ -255,14 +536,18 @@ async def chat(req: Request, body: ChatRequest):
255
  if __name__ == "__main__":
256
 
257
  print("""
258
- ╔══════════════════════════════╗
259
- β•‘ Smart G4F Gateway β•‘
260
- ╠══════════════════════════════╣
261
- β•‘ API KEY ENABLED β•‘
262
- β•‘ MODEL: gpt-4o-mini β•‘
263
- β•‘ /chat β•‘
264
- β•‘ /health β•‘
265
- β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
 
 
 
 
266
  """)
267
 
268
  uvicorn.run(
 
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+
4
  import time
5
  import random
6
  import traceback
7
  import logging
8
 
9
  from fastapi import FastAPI, HTTPException, Request
10
+ from fastapi.middleware.cors import CORSMiddleware
11
  from pydantic import BaseModel
12
  import uvicorn
13
 
14
  from g4f.client import Client
15
+
16
+ # =====================================================
17
+ # IMPORT SAFE PROVIDERS ONLY
18
+ # =====================================================
19
+
20
+ import g4f.Provider as Provider
21
 
22
  # =====================================================
23
  # CONFIG
 
47
 
48
  app = FastAPI(
49
  title="Smart G4F Gateway",
50
+ version="2.0"
51
  )
52
 
53
  # =====================================================
54
+ # CORS
55
+ # =====================================================
56
+
57
+ app.add_middleware(
58
+ CORSMiddleware,
59
+ allow_origins=["*"],
60
+ allow_credentials=True,
61
+ allow_methods=["*"],
62
+ allow_headers=["*"],
63
+ )
64
+
65
+ # =====================================================
66
+ # API KEY AUTH
67
  # =====================================================
68
 
69
  def verify_api_key(req: Request):
70
 
71
+ # =========================================
72
+ # Authorization: Bearer
73
+ # =========================================
74
+
75
  auth = req.headers.get("Authorization")
76
 
77
+ if auth and auth.startswith("Bearer "):
 
 
 
 
78
 
79
+ token = auth.replace("Bearer ", "").strip()
 
 
 
 
80
 
81
+ if token == API_KEY:
82
+ return True
83
 
84
+ # =========================================
85
+ # x-api-key
86
+ # =========================================
87
+
88
+ x_api_key = req.headers.get("x-api-key")
89
+
90
+ if x_api_key and x_api_key.strip() == API_KEY:
91
+ return True
92
+
93
+ # =========================================
94
+ # FAILED
95
+ # =========================================
96
+
97
+ raise HTTPException(
98
+ status_code=403,
99
+ detail="Invalid API Key"
100
+ )
101
 
102
  # =====================================================
103
  # SAFE PROVIDERS
 
105
 
106
  SAFE_PROVIDERS = []
107
 
108
+ PREFERRED = [
109
+ ("Blackbox", "blackboxai"),
110
+ ("Free2GPT", "gpt-4o-mini"),
111
+ ("DuckDuckGo", "gpt-4o-mini"),
112
+ ]
 
 
 
113
 
114
+ for provider_name, provider_model in PREFERRED:
 
115
 
116
+ try:
 
117
 
118
+ provider = getattr(Provider, provider_name)
 
 
 
 
 
 
119
 
120
+ SAFE_PROVIDERS.append({
121
+ "provider": provider,
122
+ "model": provider_model
123
+ })
124
 
125
+ except Exception as e:
126
 
127
+ logger.warning(f"Provider load failed: {provider_name} -> {e}")
 
128
 
129
  random.shuffle(SAFE_PROVIDERS)
130
 
131
  logger.info(f"[+] SAFE PROVIDERS: {len(SAFE_PROVIDERS)}")
132
 
133
+ # =====================================================
134
+ # CLIENT
135
+ # =====================================================
136
+
137
  client = Client()
138
 
139
  # =====================================================
 
144
 
145
  def __init__(self):
146
 
 
147
  self.bad = {}
148
 
149
+ # =================================================
150
+
151
  def mark_bad(self, provider, cooldown=300):
152
 
153
  self.bad[provider.__name__] = time.time() + cooldown
154
 
155
+ # =================================================
156
+
157
  def is_bad(self, provider):
158
 
159
  if provider.__name__ not in self.bad:
 
161
 
162
  return time.time() < self.bad[provider.__name__]
163
 
164
+ # =================================================
165
+
166
  def get_provider(self):
167
 
168
  random.shuffle(SAFE_PROVIDERS)
169
 
170
+ for item in SAFE_PROVIDERS:
171
+
172
+ provider = item["provider"]
173
 
174
  if self.is_bad(provider):
175
  continue
176
 
177
+ return item
178
 
179
  return None
180
 
181
+ # =================================================
182
+
183
  def ask(self, prompt):
184
 
185
+ last_error = None
186
+
187
  for _ in range(MAX_RETRIES):
188
 
189
+ item = self.get_provider()
190
 
191
+ if not item:
192
  break
193
 
194
+ provider = item["provider"]
195
+ model = item["model"]
196
+
197
  try:
198
 
199
+ logger.info(
200
+ f"[+] Trying provider={provider.__name__} model={model}"
201
+ )
202
 
203
  response = client.chat.completions.create(
204
+ model=model,
205
  provider=provider,
206
  messages=[
207
  {
 
212
  timeout=TIMEOUT
213
  )
214
 
215
+ text = None
216
+
217
+ try:
218
+ text = response.choices[0].message.content
219
+ except:
220
+ text = str(response)
221
 
222
+ if text and text.strip():
223
 
224
+ logger.info(
225
+ f"[+] Success provider={provider.__name__}"
226
+ )
227
 
228
  return {
229
  "provider": provider.__name__,
230
+ "model": model,
231
  "response": text
232
  }
233
 
234
  except Exception as e:
235
 
236
+ last_error = str(e)
237
+
238
+ logger.warning(
239
+ f"[-] Failed provider={provider.__name__} error={e}"
240
+ )
241
 
242
  self.mark_bad(provider)
243
 
244
+ raise Exception(last_error or "All providers failed")
245
+
246
+ # =====================================================
247
+ # INSTANCE
248
+ # =====================================================
249
 
250
  smart = SmartG4F()
251
 
 
258
  prompt: str
259
 
260
  # =====================================================
261
+ # ROOT
262
  # =====================================================
263
 
264
  @app.get("/")
 
267
 
268
  return {
269
  "status": "online",
270
+ "service": "Smart G4F Gateway",
271
+ "version": "2.0",
272
  "providers": len(SAFE_PROVIDERS),
273
+ "auth": [
274
+ "Authorization: Bearer",
275
+ "x-api-key"
276
+ ]
277
  }
278
 
279
+ # =====================================================
280
+ # HEALTH
281
+ # =====================================================
282
+
283
  @app.get("/health")
284
 
285
  async def health():
286
 
287
  return {
288
+ "ok": True,
289
+ "providers": len(SAFE_PROVIDERS)
290
  }
291
 
292
+ # =====================================================
293
+ # MODELS
294
+ # =====================================================
295
+
296
+ @app.get("/v1/models")
297
+
298
+ async def models():
299
+
300
+ return {
301
+ "object": "list",
302
+ "data": [
303
+ {
304
+ "id": item["model"],
305
+ "object": "model",
306
+ "owned_by": item["provider"].__name__,
307
+ "created": int(time.time())
308
+ }
309
+ for item in SAFE_PROVIDERS
310
+ ]
311
+ }
312
+
313
+ # =====================================================
314
+ # CHAT
315
+ # =====================================================
316
+
317
  @app.post("/chat")
318
 
319
  async def chat(req: Request, body: ChatRequest):
 
327
  return {
328
  "success": True,
329
  "provider": result["provider"],
330
+ "model": result["model"],
331
  "response": result["response"]
332
  }
333
 
 
340
  detail=str(e)
341
  )
342
 
343
+ # =====================================================
344
+ # OPENAI STYLE ENDPOINT
345
+ # =====================================================
346
+
347
+ @app.post("/v1/chat/completions")
348
+
349
+ async def openai_chat(req: Request, body: ChatRequest):
350
+
351
+ verify_api_key(req)
352
+
353
+ try:
354
+
355
+ result = smart.ask(body.prompt)
356
+
357
+ return {
358
+ "id": f"chatcmpl-{random.randint(100000,999999)}",
359
+ "object": "chat.completion",
360
+ "created": int(time.time()),
361
+ "model": result["model"],
362
+ "choices": [
363
+ {
364
+ "index": 0,
365
+ "message": {
366
+ "role": "assistant",
367
+ "content": result["response"]
368
+ },
369
+ "finish_reason": "stop"
370
+ }
371
+ ]
372
+ }
373
+
374
+ except Exception as e:
375
+
376
+ logger.error(traceback.format_exc())
377
+
378
+ raise HTTPException(
379
+ status_code=500,
380
+ detail=str(e)
381
+ )
382
+
383
+ # =====================================================
384
+ # TEST PAGE
385
+ # =====================================================
386
+
387
+ @app.get("/test")
388
+
389
+ async def test_page():
390
+
391
+ return f"""
392
+ <!DOCTYPE html>
393
+ <html>
394
+ <head>
395
+ <title>Smart G4F Gateway</title>
396
+ <meta charset="utf-8">
397
+
398
+ <style>
399
+
400
+ body {{
401
+ background: #0f172a;
402
+ color: white;
403
+ font-family: Arial;
404
+ max-width: 900px;
405
+ margin: auto;
406
+ padding: 20px;
407
+ }}
408
+
409
+ #chat {{
410
+ height: 500px;
411
+ overflow-y: auto;
412
+ border: 1px solid #334155;
413
+ padding: 15px;
414
+ border-radius: 10px;
415
+ margin-bottom: 10px;
416
+ background: #111827;
417
+ }}
418
+
419
+ .user {{
420
+ background: #2563eb;
421
+ padding: 10px;
422
+ border-radius: 10px;
423
+ margin: 10px;
424
+ text-align: right;
425
+ }}
426
+
427
+ .bot {{
428
+ background: #1e293b;
429
+ padding: 10px;
430
+ border-radius: 10px;
431
+ margin: 10px;
432
+ }}
433
+
434
+ .input {{
435
+ display: flex;
436
+ gap: 10px;
437
+ }}
438
+
439
+ input {{
440
+ flex: 1;
441
+ padding: 12px;
442
+ border-radius: 10px;
443
+ border: none;
444
+ }}
445
+
446
+ button {{
447
+ padding: 12px 20px;
448
+ border: none;
449
+ border-radius: 10px;
450
+ background: #2563eb;
451
+ color: white;
452
+ cursor: pointer;
453
+ }}
454
+
455
+ </style>
456
+ </head>
457
+
458
+ <body>
459
+
460
+ <h2>πŸ€– Smart G4F Gateway</h2>
461
+
462
+ <div id="chat"></div>
463
+
464
+ <div class="input">
465
+ <input id="message" placeholder="Type message..." />
466
+ <button onclick="send()">Send</button>
467
+ </div>
468
+
469
+ <script>
470
+
471
+ const API_KEY = "{API_KEY}";
472
+
473
+ async function send() {{
474
+
475
+ const input = document.getElementById("message");
476
+
477
+ const text = input.value.trim();
478
+
479
+ if (!text) return;
480
+
481
+ const chat = document.getElementById("chat");
482
+
483
+ chat.innerHTML += `
484
+ <div class="user">${{text}}</div>
485
+ `;
486
+
487
+ input.value = "";
488
+
489
+ const bot = document.createElement("div");
490
+
491
+ bot.className = "bot";
492
+
493
+ bot.innerHTML = "Thinking...";
494
+
495
+ chat.appendChild(bot);
496
+
497
+ try {{
498
+
499
+ const response = await fetch("/chat", {{
500
+
501
+ method: "POST",
502
+
503
+ headers: {{
504
+ "Content-Type": "application/json",
505
+ "x-api-key": API_KEY
506
+ }},
507
+
508
+ body: JSON.stringify({{
509
+ prompt: text
510
+ }})
511
+ }});
512
+
513
+ const data = await response.json();
514
+
515
+ bot.innerHTML = data.response || data.detail || "Error";
516
+
517
+ }} catch(e) {{
518
+
519
+ bot.innerHTML = "Error: " + e.message;
520
+
521
+ }}
522
+
523
+ chat.scrollTop = chat.scrollHeight;
524
+ }}
525
+
526
+ </script>
527
+
528
+ </body>
529
+ </html>
530
+ """
531
+
532
  # =====================================================
533
  # RUN
534
  # =====================================================
 
536
  if __name__ == "__main__":
537
 
538
  print("""
539
+
540
+ ╔══════════════════════════════════════╗
541
+ β•‘ SMART G4F GATEWAY β•‘
542
+ ╠══════════════════════════════════════╣
543
+ β•‘ VERSION : 2.0 β•‘
544
+ β•‘ AUTH : ENABLED β•‘
545
+ β•‘ MODEL : gpt-4o-mini β•‘
546
+ β•‘ TEST UI : /test β•‘
547
+ β•‘ CHAT : /chat β•‘
548
+ β•‘ OPENAI : /v1/chat/completions β•‘
549
+ β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
550
+
551
  """)
552
 
553
  uvicorn.run(