Update app.py
Browse files
app.py
CHANGED
|
@@ -16,6 +16,9 @@ from starlette.requests import Request
|
|
| 16 |
from starlette.responses import JSONResponse, Response
|
| 17 |
from starlette.routing import Mount, Route
|
| 18 |
|
|
|
|
|
|
|
|
|
|
| 19 |
# -----------------------------------------------------------------------------
|
| 20 |
# HF Hub persistence (FREE): save/load cards_state.json from a dataset repo
|
| 21 |
# -----------------------------------------------------------------------------
|
|
@@ -65,6 +68,29 @@ STATE_LOCK = asyncio.Lock()
|
|
| 65 |
|
| 66 |
SERVER_PASSWORD = (os.environ.get("password") or "").strip()
|
| 67 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 68 |
|
| 69 |
def _hub_pull_into_local() -> None:
|
| 70 |
"""If local state missing, download cards_state.json from dataset repo."""
|
|
@@ -234,8 +260,20 @@ async def api_cards(request: Request) -> Response:
|
|
| 234 |
state["cards"].append(card)
|
| 235 |
state["version"] += 1
|
| 236 |
await set_state(state)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 237 |
return _json(state)
|
| 238 |
|
|
|
|
| 239 |
return _json({"error": "Method not allowed"}, status_code=405)
|
| 240 |
|
| 241 |
|
|
|
|
| 16 |
from starlette.responses import JSONResponse, Response
|
| 17 |
from starlette.routing import Mount, Route
|
| 18 |
|
| 19 |
+
import smtplib
|
| 20 |
+
from email.message import EmailMessage
|
| 21 |
+
|
| 22 |
# -----------------------------------------------------------------------------
|
| 23 |
# HF Hub persistence (FREE): save/load cards_state.json from a dataset repo
|
| 24 |
# -----------------------------------------------------------------------------
|
|
|
|
| 68 |
|
| 69 |
SERVER_PASSWORD = (os.environ.get("password") or "").strip()
|
| 70 |
|
| 71 |
+
SMTP_HOST = os.environ.get("SMTP_HOST", "").strip()
|
| 72 |
+
SMTP_PORT = int(os.environ.get("SMTP_PORT", "587"))
|
| 73 |
+
SMTP_USER = os.environ.get("SMTP_USER", "").strip()
|
| 74 |
+
SMTP_PASS = os.environ.get("SMTP_PASS", "").strip()
|
| 75 |
+
SMTP_FROM = os.environ.get("SMTP_FROM", SMTP_USER).strip()
|
| 76 |
+
SMTP_TO = [x.strip() for x in os.environ.get("SMTP_TO", "").split(",") if x.strip()]
|
| 77 |
+
|
| 78 |
+
EMAIL_ENABLED = bool(SMTP_HOST and SMTP_USER and SMTP_PASS and SMTP_TO)
|
| 79 |
+
|
| 80 |
+
def _send_email(subject: str, body: str) -> None:
|
| 81 |
+
if not EMAIL_ENABLED:
|
| 82 |
+
return
|
| 83 |
+
msg = EmailMessage()
|
| 84 |
+
msg["Subject"] = subject
|
| 85 |
+
msg["From"] = SMTP_FROM
|
| 86 |
+
msg["To"] = ", ".join(SMTP_TO)
|
| 87 |
+
msg.set_content(body)
|
| 88 |
+
|
| 89 |
+
with smtplib.SMTP(SMTP_HOST, SMTP_PORT, timeout=20) as s:
|
| 90 |
+
s.starttls()
|
| 91 |
+
s.login(SMTP_USER, SMTP_PASS)
|
| 92 |
+
s.send_message(msg)
|
| 93 |
+
|
| 94 |
|
| 95 |
def _hub_pull_into_local() -> None:
|
| 96 |
"""If local state missing, download cards_state.json from dataset repo."""
|
|
|
|
| 260 |
state["cards"].append(card)
|
| 261 |
state["version"] += 1
|
| 262 |
await set_state(state)
|
| 263 |
+
|
| 264 |
+
if EMAIL_ENABLED:
|
| 265 |
+
subject = f"New model card posted: {card.get('model','')}"
|
| 266 |
+
body = (
|
| 267 |
+
f"Model: {card.get('model','')}\n"
|
| 268 |
+
f"Tags: {', '.join(card.get('tags', []) or [])}\n"
|
| 269 |
+
f"By: {card.get('author','')}\n"
|
| 270 |
+
f"Link: {card.get('link','')}\n"
|
| 271 |
+
)
|
| 272 |
+
asyncio.create_task(asyncio.to_thread(_send_email, subject, body))
|
| 273 |
+
|
| 274 |
return _json(state)
|
| 275 |
|
| 276 |
+
|
| 277 |
return _json({"error": "Method not allowed"}, status_code=405)
|
| 278 |
|
| 279 |
|