def Diff(self: Any, mode: str, newData: List[dict]): """ Determine changes between local and remote news feeds, generate a Tweet for any new items. """ if os.path.isfile(f"{mode}.json") is False: Utility.WriteFile(self, mode, "json", newData) log.info(f"Created {mode}.json") return oldData: Optional[dict] = Utility.ReadFile(self, mode, "json") oldMotds: List[Optional[str]] = [] changed: bool = False motd: dict for motd in oldData: if motd.get("id") is not None: oldMotds.append(motd.get("id")) for motd in newData: if motd.get("id") in oldMotds: continue elif motd.get("id") is None: continue elif (_title := motd.get("title")) in self.ignoredTitles: log.info( f'Ignoring news feed item "{_title}" due to ignored title configuration' ) continue else: for _body in self.ignoredBodies: if _body.lower() in motd["body"].lower(): log.info( f'Ignoring news feed item "{_title}" due to ignored body configuration' ) continue body = f"{motd['title']}\n{motd['body']}" for hashtag in self.hashtags: # This allows for multi-word strings to be hashtagged hashtagged = hashtag.replace(" ", "") body = body.replace(hashtag, f"#{hashtagged}", 1) # Trim Tweet body to <280 characters (275 plus ellipses), as per # Twitter's requirements. body = body[:275] + (body[275:] and "...") log.info(body.replace("\n", " | ")) if self.twitterEnabled is True: Sleuth.Tweet(self, body, motd["image"]) changed = True
def init(self: Any) -> None: print("Snoopy - Redditor watching service") print("https://github.com/EthanC/Snoopy\n") self.configuration: dict = Utility.ReadFile(self, "configuration", "json") configured: Optional[bool] = Snoopy.LoadConfiguration(self) if path.isfile("database.json") is False: log.warning("Could not find database, creating it") Utility.WriteFile(self, "database", "json", {}) self.database: dict = Utility.ReadFile(self, "database", "json") if (configured is True) and (self.database is not None): log.info("Loaded configuration and database") try: self.reddit: praw.reddit.Reddit = praw.Reddit( username=self.username, password=self.password, client_id=self.clientId, client_secret=self.clientSecret, user_agent="Snoopy by /u/LackingAGoodName (https://github.com/EthanC/Snoopy)", ) if self.reddit.read_only is True: raise Exception("read-only mode is active") except Exception as e: log.critical(f"Failed to authenticate with Reddit, {e}") return log.info(f"Authenticated with Reddit as /u/{self.reddit.user.me().name}") for configuration in self.configurations: Snoopy.CheckComments(self, configuration)
class Sleuth: """ Utility which watches the Fortnite News Feed for changes then shares it on Twitter. """ def main(self: Any): print("Sleuth - Fortnite News Feed watcher") print("https://github.com/EthanC/Sleuth\n") initialized: Optional[bool] = Sleuth.LoadConfiguration(self) if initialized is True: news: Optional[dict] = Utility.GET( self, "https://fortnite-api.com/news", {"x-api-key": self.apiKey}, {"language": self.language}, ) if news is not None: log.info("Retrieved the current news feed") # Save The World still uses the messages key, which is # not supported in Sleuth at this time. # if self.saveTheWorld is True: # Sleuth.Diff(self, "saveTheWorld", news["data"]["stw"]["motds"]) if self.battleRoyale is True: Sleuth.Diff(self, "battleRoyale", news["data"]["br"]["motds"]) if self.creative is True: Sleuth.Diff(self, "creative", news["data"]["creative"]["motds"]) def LoadConfiguration(self: Any) -> Optional[bool]: """ Set the configuration values specified in configuration.json Return True if configuration sucessfully loaded. """ configuration: Optional[Union[dict, str]] = Utility.ReadFile( self, "configuration", "json") try: # self.saveTheWorld: bool = configuration["saveTheWorld"] self.battleRoyale: bool = configuration["battleRoyale"] self.creative: bool = configuration["creative"] self.language: str = configuration["language"] self.apiKey: str = configuration["fortniteAPI"]["apiKey"] self.twitterEnabled: bool = configuration["twitter"]["enabled"] self.twitterAPIKey: str = configuration["twitter"]["apiKey"] self.twitterAPISecret: str = configuration["twitter"]["apiSecret"] self.twitterAccessToken: str = configuration["twitter"][ "accessToken"] self.twitterAccessSecret: str = configuration["twitter"][ "accessSecret"] self.hashtags: List[str] = configuration["hashtags"] self.ignoredTitles: List[str] = configuration["ignoredTitles"] self.ignoredBodies: List[str] = configuration["ignoredBodies"] log.info("Loaded configuration") return True except Exception as e: log.critical(f"Failed to load configuration, {e}") def Diff(self: Any, mode: str, newData: List[dict]): """ Determine changes between local and remote news feeds, generate a Tweet for any new items. """ if os.path.isfile(f"{mode}.json") is False: Utility.WriteFile(self, mode, "json", newData) log.info(f"Created {mode}.json") return oldData: Optional[dict] = Utility.ReadFile(self, mode, "json") oldMotds: List[Optional[str]] = [] changed: bool = False motd: dict for motd in oldData: if motd.get("id") is not None: oldMotds.append(motd.get("id")) for motd in newData: if motd.get("id") in oldMotds: continue elif motd.get("id") is None: continue elif (_title := motd.get("title")) in self.ignoredTitles: log.info( f'Ignoring news feed item "{_title}" due to ignored title configuration' ) continue else: for _body in self.ignoredBodies: if _body.lower() in motd["body"].lower(): log.info( f'Ignoring news feed item "{_title}" due to ignored body configuration' ) continue body = f"{motd['title']}\n{motd['body']}" for hashtag in self.hashtags: # This allows for multi-word strings to be hashtagged hashtagged = hashtag.replace(" ", "") body = body.replace(hashtag, f"#{hashtagged}", 1) # Trim Tweet body to <280 characters (275 plus ellipses), as per # Twitter's requirements. body = body[:275] + (body[275:] and "...") log.info(body.replace("\n", " | ")) if self.twitterEnabled is True: Sleuth.Tweet(self, body, motd["image"]) changed = True if changed is True: Utility.WriteFile(self, mode, "json", newData) log.info(f"Saved {mode}.json")
def UpdateDatabase(self: Any, subreddit: str, commentTime: int) -> None: """Add the latest seen comment's timestamp to database.json""" self.database.update({subreddit.lower(): commentTime}) Utility.WriteFile(self, "database", "json", self.database)