Paginated query for market listings — supports optional container filtering and returns (dtos, has_more) for infinite scroll. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
361 lines
12 KiB
Python
361 lines
12 KiB
Python
"""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,
|
|
) -> 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,
|
|
) -> list[APFollowerDTO]: ...
|
|
|
|
async def get_followers_paginated(
|
|
self, session: AsyncSession, username: str,
|
|
page: int = 1, per_page: int = 20,
|
|
) -> 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,
|
|
) -> APFollowerDTO: ...
|
|
|
|
async def remove_follower(
|
|
self, session: AsyncSession, username: str, follower_acct: str,
|
|
) -> 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: ...
|
|
|
|
# -- 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: ...
|