Spaces:
Running
Running
Update telegram_preview.py
Browse files- telegram_preview.py +33 -63
telegram_preview.py
CHANGED
@@ -2,11 +2,10 @@
|
|
2 |
Reusable Telegramβbot preview router.
|
3 |
|
4 |
Exposes:
|
5 |
-
β’ GET /
|
6 |
-
β’ GET /avatar.jpg
|
7 |
|
8 |
To use: `from telegram_preview import router` and include it in your FastAPI app.
|
9 |
-
Compatible with PythonΒ 3.8+ (uses typing.Optional, no PEPβ―604 syntax).
|
10 |
"""
|
11 |
|
12 |
import io
|
@@ -14,22 +13,23 @@ import os
|
|
14 |
import requests
|
15 |
from typing import Optional
|
16 |
|
17 |
-
from fastapi import APIRouter, Response
|
18 |
from fastapi.responses import HTMLResponse, StreamingResponse
|
|
|
|
|
|
|
19 |
|
20 |
# βββ Environment βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
21 |
-
TOKEN = os.getenv("BOT_TOKEN")
|
22 |
-
|
23 |
-
FALLBACK_IMG = "https://telegram.org/img/t_logo.png" # fallback logo URL
|
24 |
|
25 |
if not TOKEN:
|
26 |
-
raise RuntimeError("
|
27 |
|
28 |
API_ROOT = f"https://api.telegram.org/bot{TOKEN}"
|
29 |
|
30 |
router = APIRouter()
|
31 |
|
32 |
-
|
33 |
# βββ Helpers βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
34 |
def _get_description() -> str:
|
35 |
"""Try short β full β empty string."""
|
@@ -79,63 +79,33 @@ def _fetch_avatar_bytes() -> Optional[bytes]:
|
|
79 |
return None
|
80 |
|
81 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
82 |
# βββ Routes ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
83 |
@router.get("/", include_in_schema=False, response_class=HTMLResponse)
|
84 |
-
def bot_preview():
|
85 |
description = _get_description()
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
}}
|
99 |
-
.card {{
|
100 |
-
max-width: 420px;
|
101 |
-
background: #fff;
|
102 |
-
padding: 24px;
|
103 |
-
text-align: center;
|
104 |
-
border-radius: 12px;
|
105 |
-
box-shadow: 0 4px 12px rgba(0,0,0,.1);
|
106 |
-
}}
|
107 |
-
.avatar {{
|
108 |
-
width: 120px;
|
109 |
-
height: 120px;
|
110 |
-
border-radius: 50%;
|
111 |
-
object-fit: cover;
|
112 |
-
background: #ddd;
|
113 |
-
}}
|
114 |
-
.btn {{
|
115 |
-
display: inline-block;
|
116 |
-
margin-top: 16px;
|
117 |
-
padding: 12px 24px;
|
118 |
-
background: #2AABEE;
|
119 |
-
color: #fff;
|
120 |
-
border-radius: 8px;
|
121 |
-
text-decoration: none;
|
122 |
-
font-weight: bold;
|
123 |
-
}}
|
124 |
-
</style>
|
125 |
-
</head>
|
126 |
-
<body>
|
127 |
-
<div class="card">
|
128 |
-
<img src="avatar.jpg" class="avatar" alt="avatar">
|
129 |
-
<h2>@{BOT_USERNAME}</h2>
|
130 |
-
<p>{description}</p>
|
131 |
-
<a class="btn" href="https://t.me/{BOT_USERNAME}" target="_blank">
|
132 |
-
StartΒ Bot
|
133 |
-
</a>
|
134 |
-
</div>
|
135 |
-
</body>
|
136 |
-
</html>
|
137 |
-
"""
|
138 |
-
return HTMLResponse(html)
|
139 |
|
140 |
|
141 |
@router.get("/avatar.jpg", include_in_schema=False)
|
|
|
2 |
Reusable Telegramβbot preview router.
|
3 |
|
4 |
Exposes:
|
5 |
+
β’ GET / β HTML preview card
|
6 |
+
β’ GET /avatar.jpg β bot avatar (streamed, inβmemory)
|
7 |
|
8 |
To use: `from telegram_preview import router` and include it in your FastAPI app.
|
|
|
9 |
"""
|
10 |
|
11 |
import io
|
|
|
13 |
import requests
|
14 |
from typing import Optional
|
15 |
|
16 |
+
from fastapi import APIRouter, Response, Request
|
17 |
from fastapi.responses import HTMLResponse, StreamingResponse
|
18 |
+
from fastapi.templating import Jinja2Templates
|
19 |
+
|
20 |
+
templates = Jinja2Templates(directory="templates")
|
21 |
|
22 |
# βββ Environment βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
23 |
+
TOKEN = os.getenv("BOT_TOKEN")
|
24 |
+
FALLBACK_IMG = "https://telegram.org/img/t_logo.png"
|
|
|
25 |
|
26 |
if not TOKEN:
|
27 |
+
raise RuntimeError("BOT_TOKEN environment variable not set")
|
28 |
|
29 |
API_ROOT = f"https://api.telegram.org/bot{TOKEN}"
|
30 |
|
31 |
router = APIRouter()
|
32 |
|
|
|
33 |
# βββ Helpers βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
34 |
def _get_description() -> str:
|
35 |
"""Try short β full β empty string."""
|
|
|
79 |
return None
|
80 |
|
81 |
|
82 |
+
def _get_bot_identity() -> dict:
|
83 |
+
"""Return {'first_name': ..., 'username': ...} from getMe"""
|
84 |
+
try:
|
85 |
+
r = requests.get(f"{API_ROOT}/getMe", timeout=5).json()
|
86 |
+
return {
|
87 |
+
"first_name": r["result"].get("first_name", "Telegram Bot"),
|
88 |
+
"username": r["result"].get("username", "unknown_bot"),
|
89 |
+
}
|
90 |
+
except Exception:
|
91 |
+
return {"first_name": "Telegram Bot", "username": "unknown_bot"}
|
92 |
+
|
93 |
# βββ Routes ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
94 |
@router.get("/", include_in_schema=False, response_class=HTMLResponse)
|
95 |
+
def bot_preview(request: Request):
|
96 |
description = _get_description()
|
97 |
+
identity = _get_bot_identity()
|
98 |
+
|
99 |
+
return templates.TemplateResponse(
|
100 |
+
"preview.html",
|
101 |
+
{
|
102 |
+
"request": request,
|
103 |
+
"title": f"@{identity['username']}",
|
104 |
+
"username": identity["username"],
|
105 |
+
"first_name": identity["first_name"],
|
106 |
+
"description": description,
|
107 |
+
},
|
108 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
109 |
|
110 |
|
111 |
@router.get("/avatar.jpg", include_in_schema=False)
|