| from __future__ import annotations |
|
|
| from typing import Optional |
|
|
| from fastapi import APIRouter, Query |
| from pydantic import BaseModel |
|
|
| from app.services.trend_subscription import TrendSubscriptionService |
| from app.utils.response import ResponseWrapper as R |
|
|
| router = APIRouter() |
|
|
|
|
| class CreateSubscriptionRequest(BaseModel): |
| name: str |
| keywords: list[str] |
| platforms: Optional[list[str]] = None |
| match_mode: str = "any" |
| push_enabled: bool = False |
| push_channel_ids: Optional[list[int]] = None |
|
|
|
|
| class UpdateSubscriptionRequest(BaseModel): |
| name: Optional[str] = None |
| keywords: Optional[list[str]] = None |
| platforms: Optional[list[str]] = None |
| match_mode: Optional[str] = None |
| enabled: Optional[bool] = None |
| push_enabled: Optional[bool] = None |
| push_channel_ids: Optional[list[int]] = None |
|
|
|
|
| |
|
|
| @router.get("/trend_subscriptions") |
| def get_trend_subscriptions(): |
| return R.success(TrendSubscriptionService().list_subscriptions()) |
|
|
|
|
| @router.post("/trend_subscriptions") |
| def create_trend_subscription(data: CreateSubscriptionRequest): |
| return R.success( |
| TrendSubscriptionService().create_subscription( |
| name=data.name, |
| keywords=data.keywords, |
| platforms=data.platforms, |
| match_mode=data.match_mode, |
| push_enabled=data.push_enabled, |
| push_channel_ids=data.push_channel_ids, |
| ) |
| ) |
|
|
|
|
| @router.post("/trend_subscriptions/match_all") |
| def match_all_subscriptions(): |
| from app.services.scheduler import get_scheduler |
|
|
| summary = get_scheduler().run_now() |
| return R.success(summary) |
|
|
|
|
| @router.get("/trend_matches") |
| def get_all_matches( |
| limit: int = Query(100, ge=1, le=500), |
| unread_only: bool = Query(False), |
| ): |
| return R.success( |
| TrendSubscriptionService().list_matches(subscription_id=None, limit=limit, unread_only=unread_only) |
| ) |
|
|
|
|
| |
|
|
| @router.get("/trend_subscriptions/{subscription_id}") |
| def get_trend_subscription(subscription_id: int): |
| result = TrendSubscriptionService().get_subscription(subscription_id) |
| if result is None: |
| return R.error(msg=f"่ฎข้
{subscription_id} ไธๅญๅจ", code=404) |
| return R.success(result) |
|
|
|
|
| @router.put("/trend_subscriptions/{subscription_id}") |
| def update_trend_subscription(subscription_id: int, data: UpdateSubscriptionRequest): |
| result = TrendSubscriptionService().update_subscription( |
| subscription_id=subscription_id, |
| name=data.name, |
| keywords=data.keywords, |
| platforms=data.platforms, |
| match_mode=data.match_mode, |
| enabled=data.enabled, |
| push_enabled=data.push_enabled, |
| push_channel_ids=data.push_channel_ids, |
| ) |
| if result is None: |
| return R.error(msg=f"่ฎข้
{subscription_id} ไธๅญๅจ", code=404) |
| return R.success(result) |
|
|
|
|
| @router.delete("/trend_subscriptions/{subscription_id}") |
| def delete_trend_subscription(subscription_id: int): |
| ok = TrendSubscriptionService().delete_subscription(subscription_id) |
| if not ok: |
| return R.error(msg=f"่ฎข้
{subscription_id} ไธๅญๅจ", code=404) |
| return R.success(msg="ๅทฒๅ ้ค") |
|
|
|
|
| @router.post("/trend_subscriptions/{subscription_id}/match") |
| def match_trend_subscription(subscription_id: int): |
| try: |
| result = TrendSubscriptionService().match_subscription(subscription_id) |
| |
| if result["new_matches"] > 0: |
| try: |
| from app.services.notification import NotificationService |
| sub = TrendSubscriptionService().get_subscription(subscription_id) |
| if sub and sub.get("push_enabled") and sub.get("push_channel_ids"): |
| match_titles = [m["title"] for m in result["matches"]] |
| title = f"๐ฅ VideoMemo: {sub['name']} โ {len(match_titles)} ๆกๆฐ็ญ็น" |
| body = "\n\n".join(f"โข {t}" for t in match_titles[:10]) |
| if len(match_titles) > 10: |
| body += f"\n\nโฆๅ
ฑ {len(match_titles)} ๆก" |
| NotificationService().send_batch(sub["push_channel_ids"], title, body) |
| result["push_sent"] = True |
| except Exception: |
| result["push_sent"] = False |
| return R.success(result) |
| except ValueError as exc: |
| return R.error(msg=str(exc), code=404) |
|
|
|
|
| @router.get("/trend_subscriptions/{subscription_id}/matches") |
| def get_subscription_matches( |
| subscription_id: int, |
| limit: int = Query(100, ge=1, le=500), |
| unread_only: bool = Query(False), |
| ): |
| return R.success( |
| TrendSubscriptionService().list_matches( |
| subscription_id=subscription_id, |
| limit=limit, |
| unread_only=unread_only, |
| ) |
| ) |
|
|
|
|
| @router.post("/trend_subscriptions/{subscription_id}/matches/read-all") |
| def mark_subscription_matches_read(subscription_id: int): |
| count = TrendSubscriptionService().mark_all_read(subscription_id) |
| return R.success({"marked_read": count}) |
|
|