Spaces:
Sleeping
Sleeping
Update main.py
Browse files
main.py
CHANGED
|
@@ -1,157 +1,19 @@
|
|
| 1 |
import os
|
| 2 |
import requests
|
| 3 |
import sqlite3
|
| 4 |
-
from fastapi import FastAPI, Header, HTTPException, Request
|
| 5 |
-
from fastapi.responses import
|
| 6 |
-
from fastapi.security import HTTPBearer
|
| 7 |
from pydantic import BaseModel
|
| 8 |
from duckduckgo_search import DDGS
|
| 9 |
|
| 10 |
-
app = FastAPI(title="HilmanAI
|
| 11 |
|
|
|
|
| 12 |
MY_SECRET_KEY = os.getenv("MY_SECRET_KEY", "hilman-secret-2026")
|
| 13 |
OPENROUTER_API_KEY = os.getenv("OPENROUTER_API_KEY")
|
| 14 |
ANTIGRAVITY_API_KEY = os.getenv("ANTIGRAVITY_API_KEY")
|
| 15 |
|
| 16 |
-
|
| 17 |
-
active_sessions = set()
|
| 18 |
-
|
| 19 |
-
# --- GİRİŞ EKRANI HTML ---
|
| 20 |
-
HTML_LOGIN = """
|
| 21 |
-
<!DOCTYPE html>
|
| 22 |
-
<html lang="tr">
|
| 23 |
-
<head>
|
| 24 |
-
<meta charset="UTF-8">
|
| 25 |
-
<title>HilmanAI - Güvenli Giriş</title>
|
| 26 |
-
<style>
|
| 27 |
-
body { background-color: #030508; color: #F3F4F6; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; }
|
| 28 |
-
.login-card { background: #080C14; border: 2px solid #1E293B; padding: 40px; border-radius: 20px; width: 380px; text-align: center; box-shadow: 0 15px 35px rgba(0,0,0,0.7); }
|
| 29 |
-
h2 { color: #FF9900; margin-bottom: 10px; font-size: 24px; }
|
| 30 |
-
p { color: #64748B; font-size: 13px; margin-bottom: 25px; }
|
| 31 |
-
input { width: 100%; padding: 14px; margin-bottom: 15px; background: #020408; border: 1px solid #1E293B; color: white; border-radius: 10px; box-sizing: border-box; font-size: 14px; outline: none; }
|
| 32 |
-
input:focus { border-color: #FF9900; }
|
| 33 |
-
button { background: #FF9900; color: #000; border: none; padding: 14px; width: 100%; border-radius: 10px; font-weight: bold; cursor: pointer; transition: 0.2s; font-size: 14px; }
|
| 34 |
-
button:hover { background: #CC7A00; }
|
| 35 |
-
.error { color: #EF4444; font-size: 13px; margin-top: 12px; background: rgba(239, 68, 68, 0.1); padding: 8px; border-radius: 6px; }
|
| 36 |
-
</style>
|
| 37 |
-
</head>
|
| 38 |
-
<body>
|
| 39 |
-
<div class="login-card">
|
| 40 |
-
<h2>HILMAN AI</h2>
|
| 41 |
-
<p>Sisteme erişmek için Secret Key giriniz.</p>
|
| 42 |
-
<form method="POST" action="/login">
|
| 43 |
-
<input type="password" name="password" placeholder="Secret Key (Şifre)" required>
|
| 44 |
-
<button type="submit">GİRİŞ YAP</button>
|
| 45 |
-
</form>
|
| 46 |
-
%ERROR_BLOCK%
|
| 47 |
-
</div>
|
| 48 |
-
</body>
|
| 49 |
-
</html>
|
| 50 |
-
"""
|
| 51 |
-
|
| 52 |
-
# --- HİZMET YAPILANDIRMASI / PROXY PANELİ HTML ---
|
| 53 |
-
HTML_DASHBOARD = """
|
| 54 |
-
<!DOCTYPE html>
|
| 55 |
-
<html lang="tr">
|
| 56 |
-
<head>
|
| 57 |
-
<meta charset="UTF-8">
|
| 58 |
-
<title>HilmanAI - Hizmet Yapılandırması</title>
|
| 59 |
-
<style>
|
| 60 |
-
body { background-color: #030508; color: #F3F4F6; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 0; padding: 30px; }
|
| 61 |
-
.container { max-width: 950px; margin: auto; background: #080C14; border: 2px solid #1E293B; border-radius: 20px; padding: 30px; box-shadow: 0 15px 35px rgba(0,0,0,0.7); }
|
| 62 |
-
.header { display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid #1E293B; padding-bottom: 20px; margin-bottom: 25px; flex-wrap: wrap; gap: 15px; }
|
| 63 |
-
.title { font-size: 18px; font-weight: bold; color: #F3F4F6; display: flex; align-items: center; gap: 10px; }
|
| 64 |
-
.status { background: rgba(34, 197, 94, 0.1); color: #22C55E; padding: 6px 14px; border-radius: 20px; font-size: 13px; font-weight: bold; display: flex; align-items: center; gap: 8px; border: 1px solid rgba(34, 197, 94, 0.2); }
|
| 65 |
-
.stop-btn { background: #EF4444; color: white; border: none; padding: 10px 18px; border-radius: 8px; font-weight: bold; cursor: pointer; display: flex; align-items: center; gap: 6px; transition: 0.2s; }
|
| 66 |
-
.stop-btn:hover { background: #DC2626; }
|
| 67 |
-
.section { background: #020408; border: 1px solid #1E293B; border-radius: 12px; padding: 20px; margin-bottom: 20px; }
|
| 68 |
-
.row { display: flex; gap: 20px; flex-wrap: wrap; }
|
| 69 |
-
.col { flex: 1; min-width: 250px; }
|
| 70 |
-
label { display: block; color: #64748B; font-size: 11px; font-weight: bold; margin-bottom: 8px; text-transform: uppercase; letter-spacing: 0.5px; }
|
| 71 |
-
input { width: 100%; padding: 12px; background: #080C14; border: 1px solid #1E293B; color: #F3F4F6; border-radius: 8px; box-sizing: border-box; font-size: 14px; outline: none; }
|
| 72 |
-
.input-group { display: flex; gap: 8px; }
|
| 73 |
-
.icon-btn { background: #1E293B; border: none; color: #F3F4F6; padding: 0 15px; border-radius: 8px; cursor: pointer; transition: 0.2s; }
|
| 74 |
-
.icon-btn:hover { background: #334155; }
|
| 75 |
-
.toggle-row { display: flex; justify-content: space-between; align-items: center; }
|
| 76 |
-
.switch { position: relative; display: inline-block; width: 46px; height: 24px; }
|
| 77 |
-
.switch input { opacity: 0; width: 0; height: 0; }
|
| 78 |
-
.slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #1E293B; transition: .4s; border-radius: 24px; }
|
| 79 |
-
.slider:before { position: absolute; content: ""; height: 18px; width: 18px; left: 3px; bottom: 3px; background-color: white; transition: .4s; border-radius: 50%; }
|
| 80 |
-
input:checked + .slider { background-color: #22C55E; }
|
| 81 |
-
input:checked + .slider:before { transform: translateX(22px); }
|
| 82 |
-
.footer-note { color: #64748B; font-size: 12px; margin-top: 8px; }
|
| 83 |
-
.warning-text { color: #F59E0B; font-size: 12px; margin-top: 8px; }
|
| 84 |
-
</style>
|
| 85 |
-
</head>
|
| 86 |
-
<body>
|
| 87 |
-
<div class="container">
|
| 88 |
-
<div class="header">
|
| 89 |
-
<div class="title">⚙️ Hizmet Yapılandırması</div>
|
| 90 |
-
<div class="status">● Hizmet Çalışıyor (7/24 Bulut Aktif)</div>
|
| 91 |
-
<button class="stop-btn" onclick="alert('Bulut sunucu 7/24 kesintisiz çalışmaktadır, Halil!')">⛔ Hizmeti Durdur</button>
|
| 92 |
-
</div>
|
| 93 |
-
|
| 94 |
-
<div class="section">
|
| 95 |
-
<div class="row">
|
| 96 |
-
<div class="col">
|
| 97 |
-
<label>Dinleme Portu</label>
|
| 98 |
-
<input type="text" value="7860" readonly>
|
| 99 |
-
<div class="footer-note">Hugging Face Space varsayılan portu 7860</div>
|
| 100 |
-
</div>
|
| 101 |
-
<div class="col">
|
| 102 |
-
<label>İstek Zaman Aşımı</label>
|
| 103 |
-
<input type="text" value="120" readonly>
|
| 104 |
-
<div class="footer-note">Varsayılan 120s, aralık 30-7200s.</div>
|
| 105 |
-
</div>
|
| 106 |
-
</div>
|
| 107 |
-
</div>
|
| 108 |
-
|
| 109 |
-
<div class="section">
|
| 110 |
-
<div class="toggle-row">
|
| 111 |
-
<div>
|
| 112 |
-
<label>Yetkilendirme (Bearer Token)</label>
|
| 113 |
-
<div class="footer-note">Etkinleştirildiğinde, istemciler API anahtarını Authorization: Bearer ... ile göndermelidir.</div>
|
| 114 |
-
</div>
|
| 115 |
-
<label class="switch">
|
| 116 |
-
<input type="checkbox" checked disabled>
|
| 117 |
-
<span class="slider"></span>
|
| 118 |
-
</label>
|
| 119 |
-
</div>
|
| 120 |
-
</div>
|
| 121 |
-
|
| 122 |
-
<div class="section">
|
| 123 |
-
<label>API Anahtarı (Secret Key)</label>
|
| 124 |
-
<div class="input-group">
|
| 125 |
-
<input type="password" id="apiKey" value="%SECRET_KEY%" readonly>
|
| 126 |
-
<button class="icon-btn" onclick="togglePass()" title="Göster/Gizle">👁️</button>
|
| 127 |
-
<button class="icon-btn" onclick="copyKey()" title="Kopyala">📋</button>
|
| 128 |
-
</div>
|
| 129 |
-
<div class="warning-text">Not: API anahtarınızı güvende tutun. Paylaşmayın.</div>
|
| 130 |
-
</div>
|
| 131 |
-
|
| 132 |
-
<div class="section" style="margin-bottom: 0;">
|
| 133 |
-
<label>Web UI Yönetici Parolası</label>
|
| 134 |
-
<input type="text" value="(Secret Key ile korunmaktadır)" readonly>
|
| 135 |
-
<div class="footer-note">İpucu: Bulut dağıtım senaryolarında, API Anahtarınızın güvenliğini artırmak için şifre koruması aktiftir.</div>
|
| 136 |
-
</div>
|
| 137 |
-
</div>
|
| 138 |
-
|
| 139 |
-
<script>
|
| 140 |
-
function togglePass() {
|
| 141 |
-
var x = document.getElementById("apiKey");
|
| 142 |
-
x.type = x.type === "password" ? "text" : "password";
|
| 143 |
-
}
|
| 144 |
-
function copyKey() {
|
| 145 |
-
var x = document.getElementById("apiKey");
|
| 146 |
-
navigator.clipboard.writeText(x.value);
|
| 147 |
-
alert("API Anahtarı panoya kopyalandı Halil!");
|
| 148 |
-
}
|
| 149 |
-
</script>
|
| 150 |
-
</body>
|
| 151 |
-
</html>
|
| 152 |
-
"""
|
| 153 |
-
|
| 154 |
-
# --- VERİTABANI VE KALICI HAFIZA ---
|
| 155 |
DB_PATH = "hilman_space_memory.db"
|
| 156 |
|
| 157 |
def init_db():
|
|
@@ -205,40 +67,18 @@ class ChatRequest(BaseModel):
|
|
| 205 |
model: str = "gemini-2.0-flash"
|
| 206 |
messages: list
|
| 207 |
|
| 208 |
-
# ---
|
| 209 |
-
@app.get("/"
|
| 210 |
-
|
| 211 |
-
|
| 212 |
-
|
| 213 |
-
|
| 214 |
-
|
| 215 |
-
|
| 216 |
-
except Exception as e:
|
| 217 |
-
return f"<h3>Sunucu Hatası (/): {str(e)}</h3>"
|
| 218 |
-
|
| 219 |
-
@app.post("/login", response_class=HTMLResponse)
|
| 220 |
-
async def login(request: Request, password: str = Form(...)):
|
| 221 |
-
try:
|
| 222 |
-
if password == MY_SECRET_KEY:
|
| 223 |
-
session_id = "token_active_" + MY_SECRET_KEY
|
| 224 |
-
active_sessions.add(session_id)
|
| 225 |
-
response = RedirectResponse(url="/", status_code=303)
|
| 226 |
-
# Hugging Face iframe yapısı için güvenli çerez ayarları
|
| 227 |
-
response.set_cookie(
|
| 228 |
-
key="session",
|
| 229 |
-
value=session_id,
|
| 230 |
-
httponly=True,
|
| 231 |
-
secure=True,
|
| 232 |
-
samesite="none"
|
| 233 |
-
)
|
| 234 |
-
return response
|
| 235 |
-
return HTML_LOGIN.replace("%ERROR_BLOCK%", '<div class="error">Hatalı Secret Key! Erişim engellendi.</div>')
|
| 236 |
-
except Exception as e:
|
| 237 |
-
return HTML_LOGIN.replace("%ERROR_BLOCK%", f'<div class="error">Giriş Hatası: {str(e)}</div>')
|
| 238 |
|
| 239 |
@app.get("/server-status")
|
| 240 |
-
def
|
| 241 |
-
return {"status": "
|
| 242 |
|
| 243 |
# --- ORTAK YAPAY ZEKA VE ARAMA ENTEGRASYONU ---
|
| 244 |
def call_ai_backend(messages_list):
|
|
@@ -248,7 +88,7 @@ def call_ai_backend(messages_list):
|
|
| 248 |
last_user_msg = m.get("content", "")
|
| 249 |
break
|
| 250 |
|
| 251 |
-
search_keywords = ["bul", "ara", "fiyat", "en ucuz", "nerede", "satın al", "karşılaştır", "incele"
|
| 252 |
search_context = ""
|
| 253 |
|
| 254 |
if any(kw in last_user_msg.lower() for kw in search_keywords):
|
|
@@ -287,7 +127,7 @@ def call_ai_backend(messages_list):
|
|
| 287 |
}
|
| 288 |
try:
|
| 289 |
print("[SİSTEM]: Antigravity API deneniyor...")
|
| 290 |
-
ag_res = requests.post("https://api.antigravity.dev/v1/chat/completions", json=ag_payload, headers=ag_headers, timeout=
|
| 291 |
if ag_res.status_code == 200:
|
| 292 |
print("[BAŞARILI]: Antigravity yanıt verdi!")
|
| 293 |
data = ag_res.json()
|
|
@@ -315,7 +155,7 @@ def call_ai_backend(messages_list):
|
|
| 315 |
"https://openrouter.ai/api/v1/chat/completions",
|
| 316 |
json={"model": m, "messages": full_messages, "temperature": 0.2},
|
| 317 |
headers=or_headers,
|
| 318 |
-
timeout=
|
| 319 |
)
|
| 320 |
if or_res.status_code == 200:
|
| 321 |
print(f"[BAŞARILI]: OpenRouter ({m}) yanıt verdi!")
|
|
@@ -326,11 +166,11 @@ def call_ai_backend(messages_list):
|
|
| 326 |
|
| 327 |
return "Tüm yapay zeka servisleri şu an meşgul veya internet araması yapılamadı, Halil."
|
| 328 |
|
| 329 |
-
# ---
|
| 330 |
@app.post("/v1/chat/completions")
|
| 331 |
def chat_proxy(req: ChatRequest, authorization: str = Header(None)):
|
| 332 |
if not authorization or authorization != f"Bearer {MY_SECRET_KEY}":
|
| 333 |
-
raise HTTPException(status_code=401, detail="Yetkisiz erişim!")
|
| 334 |
|
| 335 |
for m in req.messages:
|
| 336 |
if isinstance(m, dict) and "role" in m and "content" in m:
|
|
|
|
| 1 |
import os
|
| 2 |
import requests
|
| 3 |
import sqlite3
|
| 4 |
+
from fastapi import FastAPI, Header, HTTPException, Request
|
| 5 |
+
from fastapi.responses import JSONResponse
|
|
|
|
| 6 |
from pydantic import BaseModel
|
| 7 |
from duckduckgo_search import DDGS
|
| 8 |
|
| 9 |
+
app = FastAPI(title="HilmanAI 24/7 Cloud Proxy Gateway")
|
| 10 |
|
| 11 |
+
# --- ÇEVRE DEĞİŞKENLERİ (Hugging Face Secrets'tan okunur) ---
|
| 12 |
MY_SECRET_KEY = os.getenv("MY_SECRET_KEY", "hilman-secret-2026")
|
| 13 |
OPENROUTER_API_KEY = os.getenv("OPENROUTER_API_KEY")
|
| 14 |
ANTIGRAVITY_API_KEY = os.getenv("ANTIGRAVITY_API_KEY")
|
| 15 |
|
| 16 |
+
# --- VERİTABANI VE KALICI HAFIZA (VDS Tabanlı) ---
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
DB_PATH = "hilman_space_memory.db"
|
| 18 |
|
| 19 |
def init_db():
|
|
|
|
| 67 |
model: str = "gemini-2.0-flash"
|
| 68 |
messages: list
|
| 69 |
|
| 70 |
+
# --- SAĞLIK KONTROLÜ (VDS Ayakta mı?) ---
|
| 71 |
+
@app.get("/")
|
| 72 |
+
def root():
|
| 73 |
+
return {
|
| 74 |
+
"status": "Online",
|
| 75 |
+
"system": "HilmanAI 24/7 Cloud Proxy Gateway is running smoothly, Halil.",
|
| 76 |
+
"endpoint": "/v1/chat/completions"
|
| 77 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
|
| 79 |
@app.get("/server-status")
|
| 80 |
+
def server_status():
|
| 81 |
+
return {"status": "Active", "mode": "VDS-Emulated Cloud Proxy"}
|
| 82 |
|
| 83 |
# --- ORTAK YAPAY ZEKA VE ARAMA ENTEGRASYONU ---
|
| 84 |
def call_ai_backend(messages_list):
|
|
|
|
| 88 |
last_user_msg = m.get("content", "")
|
| 89 |
break
|
| 90 |
|
| 91 |
+
search_keywords = ["bul", "ara", "fiyat", "en ucuz", "nerede", "satın al", "karşılaştır", "incele"]
|
| 92 |
search_context = ""
|
| 93 |
|
| 94 |
if any(kw in last_user_msg.lower() for kw in search_keywords):
|
|
|
|
| 127 |
}
|
| 128 |
try:
|
| 129 |
print("[SİSTEM]: Antigravity API deneniyor...")
|
| 130 |
+
ag_res = requests.post("https://api.antigravity.dev/v1/chat/completions", json=ag_payload, headers=ag_headers, timeout=12)
|
| 131 |
if ag_res.status_code == 200:
|
| 132 |
print("[BAŞARILI]: Antigravity yanıt verdi!")
|
| 133 |
data = ag_res.json()
|
|
|
|
| 155 |
"https://openrouter.ai/api/v1/chat/completions",
|
| 156 |
json={"model": m, "messages": full_messages, "temperature": 0.2},
|
| 157 |
headers=or_headers,
|
| 158 |
+
timeout=12
|
| 159 |
)
|
| 160 |
if or_res.status_code == 200:
|
| 161 |
print(f"[BAŞARILI]: OpenRouter ({m}) yanıt verdi!")
|
|
|
|
| 166 |
|
| 167 |
return "Tüm yapay zeka servisleri şu an meşgul veya internet araması yapılamadı, Halil."
|
| 168 |
|
| 169 |
+
# --- ASIL PROXY ENDPOINT (24/7 VDS Gibi Çalışır) ---
|
| 170 |
@app.post("/v1/chat/completions")
|
| 171 |
def chat_proxy(req: ChatRequest, authorization: str = Header(None)):
|
| 172 |
if not authorization or authorization != f"Bearer {MY_SECRET_KEY}":
|
| 173 |
+
raise HTTPException(status_code=401, detail="Yetkisiz erişim! Geçersiz Secret Key.")
|
| 174 |
|
| 175 |
for m in req.messages:
|
| 176 |
if isinstance(m, dict) and "role" in m and "content" in m:
|