diff options
Diffstat (limited to 'components/subscriptions/main.py')
| -rw-r--r-- | components/subscriptions/main.py | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/components/subscriptions/main.py b/components/subscriptions/main.py new file mode 100644 index 0000000..26b0c64 --- /dev/null +++ b/components/subscriptions/main.py @@ -0,0 +1,64 @@ +from dataclasses import dataclass, field, asdict +from datetime import datetime, UTC +from sys import stderr +from typing import TypedDict, List, cast +from bson.objectid import ObjectId +from feedparser import parse # type: ignore +from pymongo.collection import Collection +from pymongo.results import InsertOneResult, UpdateResult +import schedule +from components.database import subscriptions +from components.subscriptions.typing import SubsDict +from components.videos import VideoTuple + +@dataclass +class Subscription: + _id: str + link: str + time_between_fetches: int + last_fetch: datetime = datetime.min.replace(tzinfo=UTC) + last_video_update: datetime = datetime.min.replace(tzinfo=UTC) + videos: List[VideoTuple] = field(default_factory=list) + subscribers: List[ObjectId] = field(default_factory=list) + + def __post_init__(self) -> None: + self._job: schedule.Job = schedule.every(self.time_between_fetches).minutes.do(self.fetch) + self._collection: Collection[SubsDict] = subscriptions + self._in_db: bool = False + + def fetch(self) -> None: + try: + rss = parse(self.link) + except Exception as e: + print("Ran into an exception while fetching", self._id + ":", e, file=stderr) + return + for vid in map(VideoTuple.from_rss_entry, rss.entries): + if vid.published > self.last_video_update: + self.videos.append(vid) + elif vid.updated > self.last_video_update: + for i, old_vid in enumerate(self.videos): + if vid.id == old_vid.id: + self.videos[i] = vid + break + last_video_update = max((vid.updated for vid in self.videos)) + if last_video_update > self.last_video_update: + print("Updating", self._id) + self.last_video_update = last_video_update + self.update_videos() + self.last_fetch = datetime.now(tz=UTC) + + def asdict(self) -> SubsDict: + return cast(SubsDict, asdict(self)) + + def insert(self) -> InsertOneResult: + return self._collection.insert_one(self.asdict()) + + def update_videos(self) -> UpdateResult: + return self._collection.update_one( + {"_id": self._id}, + {"$set": { + "videos": self.videos, + "last_video_update": self.last_video_update, + "last_fetch": self.last_fetch, + }}, + ) |
