feat: Telegram QR-Code Invite-Link + WhatsApp Empfang-Fix

Telegram:
- /start <contact_id> Deep-Link Handler: verknüpft Kontakt automatisch mit chat_id
- QR-Code Endpunkt GET /api/v1/contacts/{id}/telegram-qr (PNG)
- TUI: Taste T öffnet QR-Code im Browser (HTML mit eingebettetem PNG)
- config.py + .env.example: TELEGRAM_BOT_USERNAME=mcm_bot
- qrcode[pil] zu requirements.txt hinzugefügt

WhatsApp:
- receiveTimeout 5→3s, HTTP-Timeout 8s → verhindert Polling-Overlap
This commit is contained in:
2026-03-13 14:45:06 +01:00
parent 73619fbc9c
commit 18ad0735ef
9 changed files with 155 additions and 7 deletions

View File

@@ -1,7 +1,12 @@
import io
import qrcode
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.responses import StreamingResponse
from sqlalchemy.orm import Session
from api.auth import require_api_key
from config import settings
from db.database import get_db
from schemas import ContactCreate, ContactResponse, ContactUpdate
from services import contact_service
@@ -58,3 +63,28 @@ def delete_contact(
if not contact:
raise HTTPException(status_code=404, detail="Contact not found")
contact_service.delete(db, contact)
@router.get("/{contact_id}/telegram-qr", tags=["contacts"])
def telegram_qr(
contact_id: str,
db: Session = Depends(get_db),
_: str = Depends(require_api_key),
):
"""QR-Code als PNG: Invite-Link für Telegram-Bot mit Kontakt-ID als Deep-Link-Parameter."""
contact = contact_service.get_by_id(db, contact_id)
if not contact:
raise HTTPException(status_code=404, detail="Contact not found")
bot_username = settings.telegram_bot_username.lstrip("@")
invite_url = f"https://t.me/{bot_username}?start={contact_id}"
img = qrcode.make(invite_url)
buf = io.BytesIO()
img.save(buf, format="PNG")
buf.seek(0)
return StreamingResponse(
buf,
media_type="image/png",
headers={"Content-Disposition": f'attachment; filename="telegram_qr_{contact_id}.png"'},
)