hermes-gateway / app.py
BuildingFutureAssets's picture
feat: airtable lead logging on /webhook
bd64008 verified
Raw
History Blame Contribute Delete
4.41 kB
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."
)
@app.get("/")
def health():
return {
"ok": True,
"service": "BFA Hermes Gateway",
"model": MODEL,
"webhook_path": "/webhook",
}
@app.post("/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}