from fastapi import APIRouter, HTTPException from pydantic import BaseModel from typing import Optional, List from api.db.user import create_user, get_user, get_user_by_telegram, update_user, delete_user, list_users from api.db.subscription import ( create_subscription, get_subscription_by_user, update_subscription, delete_subscription, ) from api.route.subscription import SubscriptionInfo router = APIRouter(prefix="/users", tags=["users"]) class UserOut(BaseModel): id: str telegram_id: str name: Optional[str] subscription: Optional[SubscriptionInfo] = None class UserCreate(BaseModel): telegram_id: str name: Optional[str] class UserUpdate(BaseModel): name: Optional[str] @router.post("/", response_model=UserOut) async def api_create_user(data: UserCreate): existing = await get_user_by_telegram(data.telegram_id) if existing: raise HTTPException(status_code=400, detail="User already exists") u = await create_user(data.telegram_id, data.name) return UserOut(id=u.id, telegram_id=u.telegram_id, name=u.name) @router.get("/{user_id}", response_model=UserOut) async def api_get_user(user_id: str, expand: Optional[str] = None): u = await get_user(user_id) if not u: raise HTTPException(status_code=404, detail="User not found") out = UserOut(id=u.id, telegram_id=u.telegram_id, name=u.name) if expand == "subscription": sub = await get_subscription_by_user(u.id) if sub: out.subscription = SubscriptionInfo(user_id=sub.user_id, uuid=sub.uuid, until=sub.until, active=sub.active, subscription_link=sub.subscription_link, connect_link=sub.connect_link) return out @router.post("/{user_id}/subscription", response_model=SubscriptionInfo) async def api_create_user_subscription(user_id: str, data: dict): # expected keys: months, subscription_link (opt), connect_link (opt) months = int(data.get("months", 1)) subscription_link = data.get("subscription_link") connect_link = data.get("connect_link") import uuid as _uuid sub_id = str(_uuid.uuid4()) from datetime import datetime, timedelta until = datetime.now() + timedelta(days=30 * months) sub = await create_subscription(user_id, sub_id, until, subscription_link=subscription_link, connect_link=connect_link, active=True) return SubscriptionInfo(user_id=sub.user_id, uuid=sub.uuid, until=sub.until, active=sub.active, subscription_link=sub.subscription_link, connect_link=sub.connect_link) @router.patch("/{user_id}/subscription", response_model=SubscriptionInfo) async def api_update_user_subscription(user_id: str, data: dict): sub = await get_subscription_by_user(user_id) if not sub: raise HTTPException(status_code=404, detail="Subscription not found for user") updated = await update_subscription(sub.uuid, until=data.get("until"), user_id=data.get("user_id"), active=data.get("active"), subscription_link=data.get("subscription_link"), connect_link=data.get("connect_link")) return SubscriptionInfo(user_id=updated.user_id, uuid=updated.uuid, until=updated.until, active=updated.active, subscription_link=updated.subscription_link, connect_link=updated.connect_link) @router.delete("/{user_id}/subscription") async def api_delete_user_subscription(user_id: str): sub = await get_subscription_by_user(user_id) if not sub: raise HTTPException(status_code=404, detail="Subscription not found for user") ok = await delete_subscription(sub.uuid) if not ok: raise HTTPException(status_code=500, detail="Failed to delete subscription") return {"ok": True} @router.get("/", response_model=List[UserOut]) async def api_list_users(): users = await list_users() return [UserOut(id=u.id, telegram_id=u.telegram_id, name=u.name) for u in users] @router.patch("/{user_id}", response_model=UserOut) async def api_update_user(user_id: str, data: UserUpdate): u = await update_user(user_id, name=data.name) if not u: raise HTTPException(status_code=404, detail="User not found") return UserOut(id=u.id, telegram_id=u.telegram_id, name=u.name) @router.delete("/{user_id}") async def api_delete_user(user_id: str): ok = await delete_user(user_id) if not ok: raise HTTPException(status_code=404, detail="User not found") return {"ok": True}