import asyncpg from utils.read.models import Page, PeerHistoryView, PeerView, StoryView _PEER_COLS = ( "peer_id, first_name, last_name, username, phone, photo_unique_id, " "is_deleted_account, updated_at, " "EXISTS (SELECT 1 FROM avatars a WHERE a.account_id = peers.account_id " "AND a.owner_id = peers.peer_id) AS has_avatar" ) async def get_peer( pool: asyncpg.Pool, account_id: int, peer_id: int ) -> PeerView | None: row = await pool.fetchrow( f"SELECT {_PEER_COLS} FROM peers " # noqa: S608 "WHERE account_id = $1 AND peer_id = $2", account_id, peer_id, ) return PeerView(**dict(row)) if row else None async def get_peers( pool: asyncpg.Pool, account_id: int, ids: list[int] ) -> list[PeerView]: if not ids: return [] rows = await pool.fetch( f"SELECT {_PEER_COLS} FROM peers " # noqa: S608 "WHERE account_id = $1 AND peer_id = ANY($2)", account_id, ids, ) return [PeerView(**dict(row)) for row in rows] async def get_peer_history( pool: asyncpg.Pool, account_id: int, peer_id: int ) -> list[PeerHistoryView]: rows = await pool.fetch( "SELECT observed_at, first_name, last_name, username, phone, " "photo_unique_id, is_deleted_account FROM peer_history " "WHERE account_id = $1 AND peer_id = $2 " "ORDER BY observed_at DESC LIMIT 500", account_id, peer_id, ) return [PeerHistoryView(**dict(row)) for row in rows] async def get_stories( pool: asyncpg.Pool, account_id: int, page: Page, *, peer_id: int | None = None ) -> list[StoryView]: params: list[object] = [account_id] where = "account_id = $1" if peer_id is not None: params.append(peer_id) where += f" AND peer_id = ${len(params)}" params.append(page.capped_limit) params.append(page.offset) rows = await pool.fetch( "SELECT peer_id, story_id, date, expire_date, caption, media_kind, " # noqa: S608 "storage_key, downloaded, views, pinned, deleted FROM stories " f"WHERE {where} " f"ORDER BY date DESC NULLS LAST LIMIT ${len(params) - 1} " f"OFFSET ${len(params)}", *params, ) return [StoryView(**dict(row)) for row in rows] async def get_story( pool: asyncpg.Pool, account_id: int, peer_id: int, story_id: int ) -> StoryView | None: row = await pool.fetchrow( "SELECT peer_id, story_id, date, expire_date, caption, media_kind, " "storage_key, downloaded, views, pinned, deleted FROM stories " "WHERE account_id = $1 AND peer_id = $2 AND story_id = $3", account_id, peer_id, story_id, ) return StoryView(**dict(row)) if row else None