diff --git a/core/__init__.py b/core/__init__.py index 2d99708..d15e619 100644 --- a/core/__init__.py +++ b/core/__init__.py @@ -6,10 +6,18 @@ from core.models import ( RoomData, TrackingData, ) +from core.ports import ( + RoomStorage, + PersonalStorage, + TrackingStorage, +) __all__ = [ "Bounty", "TrackedBounty", "RoomData", "TrackingData", + "RoomStorage", + "PersonalStorage", + "TrackingStorage", ] diff --git a/core/ports.py b/core/ports.py new file mode 100644 index 0000000..a671d22 --- /dev/null +++ b/core/ports.py @@ -0,0 +1,91 @@ +"""Abstract storage interfaces (Ports) for JIGAIDO storage adapters.""" + +from typing import Protocol + +from core.models import Bounty, RoomData, TrackingData, TrackedBounty + + +class RoomStorage(Protocol): + """Storage port for room (group) bounties. + + Implement this protocol to provide room bounty storage capability. + """ + + def load(self, room_id: int) -> RoomData | None: + """Load all data for a room. Returns None if room doesn't exist.""" + ... + + def save(self, room_data: RoomData) -> None: + """Save all data for a room.""" + ... + + def add_bounty(self, room_id: int, bounty: Bounty) -> None: + """Add a new bounty to a room.""" + ... + + def update_bounty(self, room_id: int, bounty: Bounty) -> None: + """Update an existing bounty in a room.""" + ... + + def delete_bounty(self, room_id: int, bounty_id: int) -> None: + """Delete a bounty from a room.""" + ... + + def get_bounty(self, room_id: int, bounty_id: int) -> Bounty | None: + """Get a specific bounty from a room by ID.""" + ... + + +class PersonalStorage(Protocol): + """Storage port for personal (DM) bounties. + + Personal bounties are stored in RoomData with a positive room_id (user's ID). + This port provides the same operations as RoomStorage but for personal context. + """ + + def load(self, user_id: int) -> RoomData | None: + """Load personal bounty data for a user. Returns None if not found.""" + ... + + def save(self, room_data: RoomData) -> None: + """Save personal bounty data for a user.""" + ... + + def add_bounty(self, user_id: int, bounty: Bounty) -> None: + """Add a new bounty to a user's personal storage.""" + ... + + def update_bounty(self, user_id: int, bounty: Bounty) -> None: + """Update an existing bounty in personal storage.""" + ... + + def delete_bounty(self, user_id: int, bounty_id: int) -> None: + """Delete a bounty from personal storage.""" + ... + + def get_bounty(self, user_id: int, bounty_id: int) -> Bounty | None: + """Get a specific bounty from personal storage by ID.""" + ... + + +class TrackingStorage(Protocol): + """Storage port for tracking data. + + Tracks which bounties a user is tracking in a specific room. + """ + + def load(self, room_id: int, user_id: int) -> TrackingData | None: + """Load tracking data for a user in a room. Returns None if not tracking anything.""" + ... + + def save(self, tracking_data: TrackingData) -> None: + """Save tracking data.""" + ... + + def track_bounty(self, room_id: int, user_id: int, tracked: TrackedBounty) -> None: + """Add a bounty to a user's tracking list.""" + ... + + def untrack_bounty(self, room_id: int, user_id: int, bounty_id: int) -> None: + """Remove a bounty from a user's tracking list.""" + ...