71 lines
2.1 KiB
Python
71 lines
2.1 KiB
Python
from datetime import datetime
|
|
from typing import Annotated
|
|
|
|
import asyncpg
|
|
from dishka.integrations.fastapi import DishkaRoute, FromDishka
|
|
from fastapi import APIRouter, HTTPException, Query
|
|
from pydantic import BaseModel
|
|
|
|
from utils.read import feed
|
|
from utils.read.feed import CURSOR_PATTERN, FeedChatKind, FeedFilter, FeedKind
|
|
from utils.read.models import DEFAULT_LIMIT, FeedMessagesPage, FeedPage, FeedUnseen
|
|
|
|
router = APIRouter(prefix="/api/feed", tags=["feed"], route_class=DishkaRoute)
|
|
|
|
AccountId = Annotated[int, Query()]
|
|
Limit = Annotated[int, Query(ge=1)]
|
|
Cursor = Annotated[str | None, Query(pattern=CURSOR_PATTERN)]
|
|
|
|
|
|
class SeenRequest(BaseModel):
|
|
account_id: int
|
|
at: datetime | None = None
|
|
|
|
|
|
@router.get("")
|
|
async def list_feed(
|
|
pool: FromDishka[asyncpg.Pool],
|
|
account_id: AccountId,
|
|
kind: Annotated[FeedKind, Query()] = FeedKind.ALL,
|
|
chat_id: Annotated[int | None, Query()] = None,
|
|
chat_kind: Annotated[FeedChatKind | None, Query()] = None,
|
|
since: Annotated[datetime | None, Query()] = None,
|
|
cursor: Cursor = None,
|
|
limit: Limit = DEFAULT_LIMIT,
|
|
) -> FeedPage:
|
|
return await feed.list_feed(
|
|
pool,
|
|
account_id,
|
|
FeedFilter(kind=kind, chat_id=chat_id, chat_kind=chat_kind, since=since),
|
|
limit=limit,
|
|
cursor=cursor,
|
|
)
|
|
|
|
|
|
@router.get("/unseen")
|
|
async def feed_unseen(
|
|
pool: FromDishka[asyncpg.Pool], account_id: AccountId
|
|
) -> FeedUnseen:
|
|
return await feed.unseen(pool, account_id)
|
|
|
|
|
|
@router.post("/seen")
|
|
async def feed_seen(pool: FromDishka[asyncpg.Pool], body: SeenRequest) -> FeedUnseen:
|
|
return await feed.mark_seen(pool, body.account_id, body.at)
|
|
|
|
|
|
@router.get("/{item_id}/messages")
|
|
async def feed_item_messages(
|
|
pool: FromDishka[asyncpg.Pool],
|
|
item_id: int,
|
|
account_id: AccountId,
|
|
cursor: Cursor = None,
|
|
limit: Limit = DEFAULT_LIMIT,
|
|
) -> FeedMessagesPage:
|
|
page = await feed.item_messages(
|
|
pool, account_id, item_id, limit=limit, cursor=cursor
|
|
)
|
|
if page is None:
|
|
raise HTTPException(status_code=404, detail="Feed item not found")
|
|
return page
|