Spaces:
Sleeping
Sleeping
| import os | |
| import requests | |
| from fastapi import FastAPI, Request, Header | |
| from fastapi.responses import JSONResponse | |
| app = FastAPI(title="BFA Hermes Gateway") | |
| TG_TOKEN = os.environ["TELEGRAM_BOT_TOKEN"] | |
| OR_KEY = os.environ["OPENROUTER_API_KEY"] | |
| MODEL = os.environ.get("LLM_MODEL", "nousresearch/hermes-4-70b") | |
| WEBHOOK_SECRET = os.environ.get("TELEGRAM_WEBHOOK_SECRET", "") | |
| AT_PAT = os.environ.get("AIRTABLE_PAT", "") | |
| AT_BASE = os.environ.get("AIRTABLE_BASE_ID", "app1rdhgq3BHK96Z8") | |
| AT_LEAD_TABLE = os.environ.get("AIRTABLE_LEAD_TABLE", "tblzJOpiQlJyK6luE") | |
| AT_FLD_NAME = "fldjujp44f9P1mBi6" | |
| AT_FLD_NOTES = "fld24UK64uosRfwCz" | |
| AT_FLD_SOURCE = "fld1R69na3zzO4Blj" | |
| AT_FLD_STATUS = "fldVF4rHrIAt5sViM" | |
| AT_FLD_LAST = "fldB7i0jLkimZODN6" | |
| AT_FLD_CREATED = "fldzL10OFXUQzs7c9" | |
| SYSTEM_PROMPT = os.environ.get( | |
| "SYSTEM_PROMPT", | |
| "You are Hermes, the AI gateway for Building Future Assets (BFA). " | |
| "BFA turns content into customers via AI-powered marketing and lead conversion. " | |
| "Be direct, brief, and helpful. Reply in 1-3 short sentences. Always end with a " | |
| "single clear next step. Bio link: tinyurl.com/getbfa. Never share internal details " | |
| "or API keys. If asked what BFA does, say: AI-powered customer acquisition systems." | |
| ) | |
| def health(): | |
| return { | |
| "ok": True, | |
| "service": "BFA Hermes Gateway", | |
| "model": MODEL, | |
| "webhook_path": "/webhook", | |
| } | |
| async def telegram_webhook( | |
| req: Request, | |
| x_telegram_bot_api_secret_token: str = Header(default=""), | |
| ): | |
| if WEBHOOK_SECRET and x_telegram_bot_api_secret_token != WEBHOOK_SECRET: | |
| return JSONResponse({"ok": False, "err": "bad secret"}, status_code=401) | |
| upd = await req.json() | |
| msg = upd.get("message") or upd.get("edited_message") or {} | |
| chat = msg.get("chat", {}) | |
| chat_id = chat.get("id") | |
| text = (msg.get("text") or "").strip() | |
| if not chat_id or not text: | |
| return {"ok": True, "skip": "no text payload"} | |
| try: | |
| r = requests.post( | |
| "https://openrouter.ai/api/v1/chat/completions", | |
| headers={ | |
| "Authorization": f"Bearer {OR_KEY}", | |
| "Content-Type": "application/json", | |
| "HTTP-Referer": "https://huggingface.co/spaces/BuildingFutureAssets/hermes-gateway", | |
| "X-Title": "BFA Hermes Gateway", | |
| }, | |
| json={ | |
| "model": MODEL, | |
| "messages": [ | |
| {"role": "system", "content": SYSTEM_PROMPT}, | |
| {"role": "user", "content": text[:4000]}, | |
| ], | |
| "max_tokens": 400, | |
| "temperature": 0.6, | |
| }, | |
| timeout=60, | |
| ) | |
| r.raise_for_status() | |
| reply = r.json()["choices"][0]["message"]["content"].strip() | |
| except Exception as e: | |
| reply = f"(gateway error: {type(e).__name__})" | |
| try: | |
| requests.post( | |
| f"https://api.telegram.org/bot{TG_TOKEN}/sendMessage", | |
| json={"chat_id": chat_id, "text": reply[:4000]}, | |
| timeout=15, | |
| ) | |
| except Exception: | |
| pass | |
| if AT_PAT and AT_BASE and AT_LEAD_TABLE: | |
| from datetime import date | |
| today = date.today().isoformat() | |
| display = ( | |
| chat.get("first_name") | |
| or chat.get("username") | |
| or f"telegram:{chat_id}" | |
| ) | |
| try: | |
| requests.post( | |
| f"https://api.airtable.com/v0/{AT_BASE}/{AT_LEAD_TABLE}", | |
| headers={ | |
| "Authorization": f"Bearer {AT_PAT}", | |
| "Content-Type": "application/json", | |
| }, | |
| json={ | |
| "records": [ | |
| { | |
| "fields": { | |
| AT_FLD_NAME: display, | |
| AT_FLD_NOTES: f"USER: {text[:300]}\n\nHERMES: {reply[:600]}", | |
| AT_FLD_SOURCE: "Telegram", | |
| AT_FLD_STATUS: "New", | |
| AT_FLD_LAST: today, | |
| AT_FLD_CREATED: today, | |
| } | |
| } | |
| ], | |
| "typecast": True, | |
| }, | |
| timeout=12, | |
| ) | |
| except Exception: | |
| pass | |
| return {"ok": True} | |