Рабочий пайплайн: YouTube -> транскрипция -> выжимка -> Postgres

- новый api/: /pipeline/process (yt-dlp, субтитры или Vosk, LLM/экстрактивная
  суммаризация), /videos, /llm; старый код перенесён в api_legacy/
- web/: Flet UI (flet 0.28.3 + flet-web, порт 8550)
- Dockerfile.api: ffmpeg слоем из mwader/static-ffmpeg, pip с кэш-маунтом
- requirements/pyproject: убраны moviepy, imageio-ffmpeg, битый asyncio
- README с инструкцией запуска и загрузкой Vosk-модели

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
jze9
2026-07-14 11:12:46 +05:00
parent 564c9c2d2f
commit 2697e01714
51 changed files with 2313 additions and 284 deletions

View File

@@ -0,0 +1,94 @@
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel
from typing import Optional, List
from api.db.subscription import (
create_subscription,
get_subscription_by_user,
get_subscription_by_uuid,
update_subscription,
delete_subscription,
list_subscriptions,
extend_subscription_by_user,
)
import uuid
from datetime import datetime, timedelta
router = APIRouter(prefix="/subscription", tags=["subscription"])
class SubscriptionInfo(BaseModel):
user_id: str
uuid: str
until: datetime
active: bool
subscription_link: Optional[str] = None
connect_link: Optional[str] = None
class SubscriptionCreate(BaseModel):
user_id: str
months: int
subscription_link: Optional[str] = None
connect_link: Optional[str] = None
class SubscriptionUpdate(BaseModel):
until: Optional[datetime]
user_id: Optional[str]
active: Optional[bool] = None
subscription_link: Optional[str] = None
connect_link: Optional[str] = None
@router.get("/{user_id}", response_model=Optional[SubscriptionInfo])
async def get_user_subscription(user_id: str):
sub = await get_subscription_by_user(user_id)
if not sub:
return None
return SubscriptionInfo(user_id=sub.user_id, uuid=sub.uuid, until=sub.until)
@router.post("/new", response_model=SubscriptionInfo)
async def create_subscription_endpoint(data: SubscriptionCreate):
sub_id = str(uuid.uuid4())
until = datetime.now() + timedelta(days=30 * data.months)
sub = await create_subscription(data.user_id, sub_id, until, subscription_link=data.subscription_link, connect_link=data.connect_link, active=True)
return SubscriptionInfo(user_id=sub.user_id, uuid=sub.uuid, until=sub.until)
@router.post("/extend", response_model=SubscriptionInfo)
async def extend_user_subscription(data: SubscriptionCreate):
sub = await extend_subscription_by_user(data.user_id, data.months)
if not sub:
raise HTTPException(status_code=404, detail="Subscription not found")
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.get("/by-uuid/{sub_uuid}", response_model=Optional[SubscriptionInfo])
async def get_subscription_uuid(sub_uuid: str):
sub = await get_subscription_by_uuid(sub_uuid)
if not sub:
raise HTTPException(status_code=404, detail="Subscription not found")
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("/{sub_uuid}", response_model=SubscriptionInfo)
async def update_subscription_endpoint(sub_uuid: str, data: SubscriptionUpdate):
sub = await update_subscription(sub_uuid, until=data.until, user_id=data.user_id, active=data.active, subscription_link=data.subscription_link, connect_link=data.connect_link)
if not sub:
raise HTTPException(status_code=404, detail="Subscription not found")
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.delete("/{sub_uuid}")
async def delete_subscription_endpoint(sub_uuid: str):
ok = await delete_subscription(sub_uuid)
if not ok:
raise HTTPException(status_code=404, detail="Subscription not found")
return {"ok": True}
@router.get("/", response_model=List[SubscriptionInfo])
async def list_all_subscriptions():
subs = await list_subscriptions()
return [SubscriptionInfo(user_id=s.user_id, uuid=s.uuid, until=s.until) for s in subs]