A community based topic aggregation platform built on atproto
at feat/comment-query-api-phase2a 79 lines 1.8 kB view raw
1""" 2Data models for Kagi News RSS aggregator. 3""" 4from dataclasses import dataclass, field 5from datetime import datetime 6from typing import List, Optional 7 8 9@dataclass 10class Source: 11 """A news source citation.""" 12 title: str 13 url: str 14 domain: str 15 16 17@dataclass 18class Perspective: 19 """A perspective from a particular actor/stakeholder.""" 20 actor: str 21 description: str 22 source_url: str 23 24 25@dataclass 26class Quote: 27 """A notable quote from the story.""" 28 text: str 29 attribution: str 30 31 32@dataclass 33class KagiStory: 34 """ 35 Structured representation of a Kagi News story. 36 37 Parsed from RSS feed item with HTML description. 38 """ 39 # RSS metadata 40 title: str 41 link: str # Kagi story permalink 42 guid: str 43 pub_date: datetime 44 categories: List[str] = field(default_factory=list) 45 46 # Parsed from HTML description 47 summary: str = "" 48 highlights: List[str] = field(default_factory=list) 49 perspectives: List[Perspective] = field(default_factory=list) 50 quote: Optional[Quote] = None 51 sources: List[Source] = field(default_factory=list) 52 image_url: Optional[str] = None 53 image_alt: Optional[str] = None 54 55 def __post_init__(self): 56 """Validate required fields.""" 57 if not self.title: 58 raise ValueError("title is required") 59 if not self.link: 60 raise ValueError("link is required") 61 if not self.guid: 62 raise ValueError("guid is required") 63 64 65@dataclass 66class FeedConfig: 67 """Configuration for a single RSS feed.""" 68 name: str 69 url: str 70 community_handle: str 71 enabled: bool = True 72 73 74@dataclass 75class AggregatorConfig: 76 """Full aggregator configuration.""" 77 coves_api_url: str 78 feeds: List[FeedConfig] 79 log_level: str = "info"