AstraOS commited on
Commit
11c0500
Β·
verified Β·
1 Parent(s): 78f1e54

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +86 -99
app.py CHANGED
@@ -463,132 +463,120 @@ def execute_command(message):
463
  # url="https://t.me/python3463_bot",
464
  # status_code=status.HTTP_302_FOUND # 302 is fine too
465
  # )
466
- from fastapi import FastAPI, HTTPException
467
- from fastapi.responses import HTMLResponse, FileResponse
468
- import requests, os, time, pathlib
469
-
470
- # ──────────────────────────────
471
- # Config
472
- # ──────────────────────────────
473
- # BOT_TOKEN = os.getenv("BOT_TOKEN") # required
474
- BOT_USERNAME = os.getenv("BOT_USERNAME", "live_logger_bot")
475
- AVATAR_TTL = int(os.getenv("AVATAR_TTL", "3600")) # seconds to keep avatar fresh
476
- DATA_DIR = pathlib.Path("/tmp") # change if you prefer
477
- AVATAR_PATH = DATA_DIR / "bot_avatar.jpg"
478
- AVATAR_META = {"ts": 0} # keeps timestamp of last download
479
-
480
- if not TOKEN:
481
- raise RuntimeError("TOKEN environment variable not set")
482
-
483
- app = FastAPI(title="Telegram Bot Preview")
484
-
485
-
486
- # ──────────────────────────────
487
- # Helper: refresh avatar if needed
488
- # ──────────────────────────────
489
- def refresh_avatar(force: bool = False) -> None:
490
- """
491
- Download the bot's avatar if it's missing or stale.
492
- Saves it to AVATAR_PATH and updates AVATAR_META['ts'].
493
- """
494
- now = time.time()
495
- if not force and AVATAR_PATH.exists() and now - AVATAR_META["ts"] < AVATAR_TTL:
496
- return # still fresh
497
 
498
  try:
499
- # 1. get bot id
500
- me = requests.get(f"https://api.telegram.org/bot{TOKEN}/getMe").json()
 
 
 
 
 
 
 
 
 
 
501
  user_id = me["result"]["id"]
502
 
503
- # 2. get latest profile photo
504
  photos = requests.get(
505
- f"https://api.telegram.org/bot{TOKEN}/getUserProfilePhotos",
506
  params={"user_id": user_id, "limit": 1},
507
- timeout=5,
508
  ).json()
509
 
510
  if photos["result"]["total_count"] == 0:
511
- return # bot has no avatar
512
 
513
- file_id = photos["result"]["photos"][0][-1]["file_id"] # biggest size
514
-
515
- # 3. resolve file path
516
  file_obj = requests.get(
517
- f"https://api.telegram.org/bot{TOKEN}/getFile",
518
  params={"file_id": file_id},
519
- timeout=5,
520
  ).json()
521
- file_path = file_obj["result"]["file_path"]
522
-
523
- # 4. download the actual image
524
- file_url = f"https://api.telegram.org/file/bot{TOKEN}/{file_path}"
525
- img_bytes = requests.get(file_url, timeout=10).content
526
-
527
- DATA_DIR.mkdir(parents=True, exist_ok=True)
528
- with open(AVATAR_PATH, "wb") as f:
529
- f.write(img_bytes)
530
-
531
- AVATAR_META["ts"] = now
532
- print("Avatar refreshed")
533
- except Exception as exc:
534
- # If something goes wrong, keep the old one
535
- print("Avatar refresh failed:", exc)
536
-
537
-
538
- # ──────────────────────────────
539
- # Helper: bot description (once)
540
- # ──────────────────────────────
541
- def get_bot_description() -> str:
542
- resp = requests.get(
543
- f"https://api.telegram.org/bot{TOKEN}/getMyShortDescription"
544
- ).json()
545
- return resp["result"].get("short_description", "")
546
 
 
 
 
 
547
 
548
- # ─────────────────────────��────
549
- # Startup: fetch avatar once
550
- # ──────────────────────────────
551
- @app.on_event("startup")
552
- def on_startup():
553
- refresh_avatar(force=True)
554
 
555
 
556
- # ──────────────────────────────
557
- # Route: preview card
558
- # ──────────────────────────────
559
- @app.get("/", include_in_schema=False, response_class=HTMLResponse)
560
  def preview():
561
- refresh_avatar() # refresh if stale
562
-
563
- avatar_src = "/avatar.jpg" if AVATAR_PATH.exists() else "https://telegram.org/img/t_logo.png"
564
- description = get_bot_description()
565
 
566
  html = f"""
567
  <html>
568
  <head>
569
- <title>{BOT_USERNAME}</title>
570
  <style>
571
  body {{
572
- font-family: sans-serif; display: flex; justify-content: center;
573
- padding: 40px; background: #f7f7f7;
 
 
 
574
  }}
575
  .card {{
576
- max-width: 420px; background: #fff; padding: 24px; text-align: center;
577
- border-radius: 12px; box-shadow: 0 4px 12px rgba(0,0,0,.1);
 
 
 
 
578
  }}
579
  .avatar {{
580
- width: 120px; height: 120px; border-radius: 50%; object-fit: cover;
 
 
 
 
581
  }}
582
  .btn {{
583
- display: inline-block; margin-top: 16px; padding: 12px 24px;
584
- background: #2AABEE; color: #fff; border-radius: 8px;
585
- text-decoration: none; font-weight: bold;
 
 
 
 
 
586
  }}
587
  </style>
588
  </head>
589
  <body>
590
  <div class="card">
591
- <img src="{avatar_src}" alt="avatar" class="avatar">
592
  <h2>@{BOT_USERNAME}</h2>
593
  <p>{description}</p>
594
  <a class="btn" href="https://t.me/{BOT_USERNAME}" target="_blank">StartΒ Bot</a>
@@ -599,15 +587,14 @@ def preview():
599
  return HTMLResponse(html)
600
 
601
 
602
- # ──────────────────────────────
603
- # Route: serve avatar file
604
- # ──────────────────────────────
605
  @app.get("/avatar.jpg", include_in_schema=False)
606
- def avatar():
607
- refresh_avatar() # make sure it's fresh
608
- if not AVATAR_PATH.exists():
609
- raise HTTPException(status_code=404, detail="Avatar not found")
610
- return FileResponse(AVATAR_PATH, media_type="image/jpeg")
 
 
611
 
612
 
613
  @app.on_event("startup")
 
463
  # url="https://t.me/python3463_bot",
464
  # status_code=status.HTTP_302_FOUND # 302 is fine too
465
  # )
466
+
467
+
468
+ from fastapi import FastAPI, Response
469
+ from fastapi.responses import HTMLResponse, StreamingResponse
470
+ import requests, os, io
471
+
472
+ app = FastAPI()
473
+
474
+ BOT_TOKEN = os.getenv("BOT_TOKEN")
475
+ BOT_USERNAME = os.getenv("BOT_USERNAME", "python3463_bot")
476
+ FALLBACK_IMG = "https://telegram.org/img/t_logo.png"
477
+
478
+ if not BOT_TOKEN:
479
+ raise RuntimeError("BOT_TOKEN environment variable not set")
480
+
481
+ TELEGRAM_API = f"https://api.telegram.org/bot{BOT_TOKEN}"
482
+
483
+
484
+ def get_description() -> str:
485
+ """Try getMyShortDescription β†’ fallback to getMyDescription β†’ """""
486
+ try:
487
+ r = requests.get(f"{TELEGRAM_API}/getMyShortDescription").json()
488
+ if desc := r["result"].get("short_description"):
489
+ return desc
490
+ except: pass
 
 
 
 
 
 
491
 
492
  try:
493
+ r = requests.get(f"{TELEGRAM_API}/getMyDescription").json()
494
+ if desc := r["result"].get("description"):
495
+ return desc
496
+ except: pass
497
+
498
+ return ""
499
+
500
+
501
+ def fetch_avatar_bytes() -> bytes | None:
502
+ """Get latest profile photo of the bot as bytes (or None if unavailable)"""
503
+ try:
504
+ me = requests.get(f"{TELEGRAM_API}/getMe", timeout=5).json()
505
  user_id = me["result"]["id"]
506
 
 
507
  photos = requests.get(
508
+ f"{TELEGRAM_API}/getUserProfilePhotos",
509
  params={"user_id": user_id, "limit": 1},
510
+ timeout=5
511
  ).json()
512
 
513
  if photos["result"]["total_count"] == 0:
514
+ return None
515
 
516
+ file_id = photos["result"]["photos"][0][-1]["file_id"] # highest res
 
 
517
  file_obj = requests.get(
518
+ f"{TELEGRAM_API}/getFile",
519
  params={"file_id": file_id},
520
+ timeout=5
521
  ).json()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
522
 
523
+ file_path = file_obj["result"]["file_path"]
524
+ file_url = f"https://api.telegram.org/file/bot{BOT_TOKEN}/{file_path}"
525
+ response = requests.get(file_url, timeout=10)
526
+ return response.content if response.status_code == 200 else None
527
 
528
+ except Exception as e:
529
+ print("Avatar fetch failed:", e)
530
+ return None
 
 
 
531
 
532
 
533
+ @app.get("/", include_in_schema=False)
 
 
 
534
  def preview():
535
+ avatar_url = "/avatar.jpg"
536
+ description = get_description()
 
 
537
 
538
  html = f"""
539
  <html>
540
  <head>
541
+ <title>@{BOT_USERNAME}</title>
542
  <style>
543
  body {{
544
+ font-family: sans-serif;
545
+ display: flex;
546
+ justify-content: center;
547
+ padding: 40px;
548
+ background: #f7f7f7;
549
  }}
550
  .card {{
551
+ max-width: 420px;
552
+ background: #fff;
553
+ padding: 24px;
554
+ text-align: center;
555
+ border-radius: 12px;
556
+ box-shadow: 0 4px 12px rgba(0,0,0,.1);
557
  }}
558
  .avatar {{
559
+ width: 120px;
560
+ height: 120px;
561
+ border-radius: 50%;
562
+ object-fit: cover;
563
+ background: #ddd;
564
  }}
565
  .btn {{
566
+ display: inline-block;
567
+ margin-top: 16px;
568
+ padding: 12px 24px;
569
+ background: #2AABEE;
570
+ color: #fff;
571
+ border-radius: 8px;
572
+ text-decoration: none;
573
+ font-weight: bold;
574
  }}
575
  </style>
576
  </head>
577
  <body>
578
  <div class="card">
579
+ <img src="{avatar_url}" alt="avatar" class="avatar">
580
  <h2>@{BOT_USERNAME}</h2>
581
  <p>{description}</p>
582
  <a class="btn" href="https://t.me/{BOT_USERNAME}" target="_blank">StartΒ Bot</a>
 
587
  return HTMLResponse(html)
588
 
589
 
 
 
 
590
  @app.get("/avatar.jpg", include_in_schema=False)
591
+ def serve_avatar():
592
+ img_bytes = fetch_avatar_bytes()
593
+ if img_bytes:
594
+ return StreamingResponse(io.BytesIO(img_bytes), media_type="image/jpeg")
595
+ # fallback
596
+ fallback = requests.get(FALLBACK_IMG)
597
+ return Response(content=fallback.content, media_type="image/png")
598
 
599
 
600
  @app.on_event("startup")