"""Protocol classes defining each domain's service interface. All cross-domain callers program against these Protocols. Concrete implementations (Sql*Service) and no-op stubs both satisfy them. """ from __future__ import annotations from datetime import datetime from typing import Protocol, runtime_checkable from sqlalchemy.ext.asyncio import AsyncSession from .dtos import ( PostDTO, CalendarDTO, CalendarEntryDTO, TicketDTO, MarketPlaceDTO, ProductDTO, CartItemDTO, CartSummaryDTO, ActorProfileDTO, APActivityDTO, APFollowerDTO, RemoteActorDTO, RemotePostDTO, TimelineItemDTO, NotificationDTO, ) @runtime_checkable class BlogService(Protocol): async def get_post_by_slug(self, session: AsyncSession, slug: str) -> PostDTO | None: ... async def get_post_by_id(self, session: AsyncSession, id: int) -> PostDTO | None: ... async def get_posts_by_ids(self, session: AsyncSession, ids: list[int]) -> list[PostDTO]: ... async def search_posts( self, session: AsyncSession, query: str, page: int = 1, per_page: int = 10, ) -> tuple[list[PostDTO], int]: ... @runtime_checkable class CalendarService(Protocol): async def calendars_for_container( self, session: AsyncSession, container_type: str, container_id: int, ) -> list[CalendarDTO]: ... async def pending_entries( self, session: AsyncSession, *, user_id: int | None, session_id: str | None, ) -> list[CalendarEntryDTO]: ... async def entries_for_page( self, session: AsyncSession, page_id: int, *, user_id: int | None, session_id: str | None, ) -> list[CalendarEntryDTO]: ... async def entry_by_id(self, session: AsyncSession, entry_id: int) -> CalendarEntryDTO | None: ... async def associated_entries( self, session: AsyncSession, content_type: str, content_id: int, page: int, ) -> tuple[list[CalendarEntryDTO], bool]: ... async def toggle_entry_post( self, session: AsyncSession, entry_id: int, content_type: str, content_id: int, ) -> bool: ... async def adopt_entries_for_user( self, session: AsyncSession, user_id: int, session_id: str, ) -> None: ... async def claim_entries_for_order( self, session: AsyncSession, order_id: int, user_id: int | None, session_id: str | None, page_post_id: int | None, ) -> None: ... async def confirm_entries_for_order( self, session: AsyncSession, order_id: int, user_id: int | None, session_id: str | None, ) -> None: ... async def get_entries_for_order( self, session: AsyncSession, order_id: int, ) -> list[CalendarEntryDTO]: ... async def user_tickets( self, session: AsyncSession, *, user_id: int, ) -> list[TicketDTO]: ... async def user_bookings( self, session: AsyncSession, *, user_id: int, ) -> list[CalendarEntryDTO]: ... async def confirmed_entries_for_posts( self, session: AsyncSession, post_ids: list[int], ) -> dict[int, list[CalendarEntryDTO]]: ... async def pending_tickets( self, session: AsyncSession, *, user_id: int | None, session_id: str | None, ) -> list[TicketDTO]: ... async def tickets_for_page( self, session: AsyncSession, page_id: int, *, user_id: int | None, session_id: str | None, ) -> list[TicketDTO]: ... async def claim_tickets_for_order( self, session: AsyncSession, order_id: int, user_id: int | None, session_id: str | None, page_post_id: int | None, ) -> None: ... async def confirm_tickets_for_order( self, session: AsyncSession, order_id: int, ) -> None: ... async def get_tickets_for_order( self, session: AsyncSession, order_id: int, ) -> list[TicketDTO]: ... async def adopt_tickets_for_user( self, session: AsyncSession, user_id: int, session_id: str, ) -> None: ... async def adjust_ticket_quantity( self, session: AsyncSession, entry_id: int, count: int, *, user_id: int | None, session_id: str | None, ticket_type_id: int | None = None, ) -> int: ... async def entry_ids_for_content( self, session: AsyncSession, content_type: str, content_id: int, ) -> set[int]: ... async def upcoming_entries_for_container( self, session: AsyncSession, container_type: str | None = None, container_id: int | None = None, *, page: int = 1, per_page: int = 20, ) -> tuple[list[CalendarEntryDTO], bool]: ... async def visible_entries_for_period( self, session: AsyncSession, calendar_id: int, period_start: datetime, period_end: datetime, *, user_id: int | None, is_admin: bool, session_id: str | None, ) -> list[CalendarEntryDTO]: ... @runtime_checkable class MarketService(Protocol): async def marketplaces_for_container( self, session: AsyncSession, container_type: str, container_id: int, ) -> list[MarketPlaceDTO]: ... async def product_by_id(self, session: AsyncSession, product_id: int) -> ProductDTO | None: ... async def create_marketplace( self, session: AsyncSession, container_type: str, container_id: int, name: str, slug: str, ) -> MarketPlaceDTO: ... async def list_marketplaces( self, session: AsyncSession, container_type: str | None = None, container_id: int | None = None, *, page: int = 1, per_page: int = 20, ) -> tuple[list[MarketPlaceDTO], bool]: ... async def soft_delete_marketplace( self, session: AsyncSession, container_type: str, container_id: int, slug: str, ) -> bool: ... @runtime_checkable class CartService(Protocol): async def cart_summary( self, session: AsyncSession, *, user_id: int | None, session_id: str | None, page_slug: str | None = None, ) -> CartSummaryDTO: ... async def cart_items( self, session: AsyncSession, *, user_id: int | None, session_id: str | None, ) -> list[CartItemDTO]: ... async def adopt_cart_for_user( self, session: AsyncSession, user_id: int, session_id: str, ) -> None: ... @runtime_checkable class FederationService(Protocol): # -- Actor management ----------------------------------------------------- async def get_actor_by_username( self, session: AsyncSession, username: str, ) -> ActorProfileDTO | None: ... async def get_actor_by_user_id( self, session: AsyncSession, user_id: int, ) -> ActorProfileDTO | None: ... async def create_actor( self, session: AsyncSession, user_id: int, preferred_username: str, display_name: str | None = None, summary: str | None = None, ) -> ActorProfileDTO: ... async def username_available( self, session: AsyncSession, username: str, ) -> bool: ... # -- Publishing (core cross-domain API) ----------------------------------- async def publish_activity( self, session: AsyncSession, *, actor_user_id: int, activity_type: str, object_type: str, object_data: dict, source_type: str | None = None, source_id: int | None = None, ) -> APActivityDTO: ... # -- Queries -------------------------------------------------------------- async def get_activity( self, session: AsyncSession, activity_id: str, ) -> APActivityDTO | None: ... async def get_outbox( self, session: AsyncSession, username: str, page: int = 1, per_page: int = 20, origin_app: str | None = None, ) -> tuple[list[APActivityDTO], int]: ... async def get_activity_for_source( self, session: AsyncSession, source_type: str, source_id: int, ) -> APActivityDTO | None: ... async def count_activities_for_source( self, session: AsyncSession, source_type: str, source_id: int, *, activity_type: str, ) -> int: ... # -- Followers ------------------------------------------------------------ async def get_followers( self, session: AsyncSession, username: str, app_domain: str | None = None, ) -> list[APFollowerDTO]: ... async def get_followers_paginated( self, session: AsyncSession, username: str, page: int = 1, per_page: int = 20, app_domain: str | None = None, ) -> tuple[list[RemoteActorDTO], int]: ... async def add_follower( self, session: AsyncSession, username: str, follower_acct: str, follower_inbox: str, follower_actor_url: str, follower_public_key: str | None = None, app_domain: str = "federation", ) -> APFollowerDTO: ... async def remove_follower( self, session: AsyncSession, username: str, follower_acct: str, app_domain: str = "federation", ) -> bool: ... # -- Remote actors -------------------------------------------------------- async def get_or_fetch_remote_actor( self, session: AsyncSession, actor_url: str, ) -> RemoteActorDTO | None: ... async def search_remote_actor( self, session: AsyncSession, acct: str, ) -> RemoteActorDTO | None: ... async def search_actors( self, session: AsyncSession, query: str, page: int = 1, limit: int = 20, ) -> tuple[list[RemoteActorDTO], int]: ... # -- Following (outbound) ------------------------------------------------- async def send_follow( self, session: AsyncSession, local_username: str, remote_actor_url: str, ) -> None: ... async def get_following( self, session: AsyncSession, username: str, page: int = 1, per_page: int = 20, ) -> tuple[list[RemoteActorDTO], int]: ... async def accept_follow_response( self, session: AsyncSession, local_username: str, remote_actor_url: str, ) -> None: ... async def unfollow( self, session: AsyncSession, local_username: str, remote_actor_url: str, ) -> None: ... # -- Remote posts --------------------------------------------------------- async def ingest_remote_post( self, session: AsyncSession, remote_actor_id: int, activity_json: dict, object_json: dict, ) -> None: ... async def delete_remote_post( self, session: AsyncSession, object_id: str, ) -> None: ... async def get_remote_post( self, session: AsyncSession, object_id: str, ) -> RemotePostDTO | None: ... # -- Timelines ------------------------------------------------------------ async def get_home_timeline( self, session: AsyncSession, actor_profile_id: int, before: datetime | None = None, limit: int = 20, ) -> list[TimelineItemDTO]: ... async def get_public_timeline( self, session: AsyncSession, before: datetime | None = None, limit: int = 20, ) -> list[TimelineItemDTO]: ... async def get_actor_timeline( self, session: AsyncSession, remote_actor_id: int, before: datetime | None = None, limit: int = 20, ) -> list[TimelineItemDTO]: ... # -- Local posts ---------------------------------------------------------- async def create_local_post( self, session: AsyncSession, actor_profile_id: int, content: str, visibility: str = "public", in_reply_to: str | None = None, ) -> int: ... async def delete_local_post( self, session: AsyncSession, actor_profile_id: int, post_id: int, ) -> None: ... # -- Interactions --------------------------------------------------------- async def like_post( self, session: AsyncSession, actor_profile_id: int, object_id: str, author_inbox: str, ) -> None: ... async def unlike_post( self, session: AsyncSession, actor_profile_id: int, object_id: str, author_inbox: str, ) -> None: ... async def boost_post( self, session: AsyncSession, actor_profile_id: int, object_id: str, author_inbox: str, ) -> None: ... async def unboost_post( self, session: AsyncSession, actor_profile_id: int, object_id: str, author_inbox: str, ) -> None: ... # -- Notifications -------------------------------------------------------- async def get_notifications( self, session: AsyncSession, actor_profile_id: int, before: datetime | None = None, limit: int = 20, ) -> list[NotificationDTO]: ... async def unread_notification_count( self, session: AsyncSession, actor_profile_id: int, ) -> int: ... async def mark_notifications_read( self, session: AsyncSession, actor_profile_id: int, ) -> None: ... # -- Stats ---------------------------------------------------------------- async def get_stats(self, session: AsyncSession) -> dict: ...