base.py 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. """Formal platform adapter contracts for acquisition."""
  2. from __future__ import annotations
  3. from typing import Any, Protocol
  4. from pydantic import BaseModel, ConfigDict, Field
  5. from core.config import Settings
  6. class PlatformCandidate(BaseModel):
  7. model_config = ConfigDict(extra="forbid")
  8. rank: int
  9. platform: str
  10. source_id: str = ""
  11. url: str = ""
  12. title: str = ""
  13. author: str = ""
  14. cover_url: str = ""
  15. raw: dict[str, Any] = Field(default_factory=dict)
  16. class PlatformItem(BaseModel):
  17. model_config = ConfigDict(extra="forbid")
  18. platform: str
  19. source_id: str = ""
  20. url: str = ""
  21. content_type: str = ""
  22. title: str = ""
  23. author: str = ""
  24. body_text: str = ""
  25. image_urls: list[str] = Field(default_factory=list)
  26. video_urls: list[str] = Field(default_factory=list)
  27. raw: dict[str, Any] = Field(default_factory=dict)
  28. class PlatformAdapter(Protocol):
  29. platform: str
  30. def search(
  31. self,
  32. query: str,
  33. *,
  34. settings: Settings,
  35. limit: int,
  36. rate_limiter: Any,
  37. ) -> list[PlatformCandidate]:
  38. ...
  39. def fetch_detail(
  40. self,
  41. candidate: PlatformCandidate,
  42. *,
  43. settings: Settings,
  44. rate_limiter: Any,
  45. ) -> PlatformItem:
  46. ...