X-Git-Url: https://wannabe.guru.org/gitweb/?a=blobdiff_plain;f=reddit_renderer.py;h=74428ef332cab00e3a5153822233d5ad2259f1d6;hb=addd4980077f6e3857c5c035b49784dc3ceca49a;hp=05b641d30f806f8850ea8fc62e8527d4c6ec93be;hpb=4b1f3d8a8b278ca6d62f461ea80c8ea21080c301;p=kiosk.git diff --git a/reddit_renderer.py b/reddit_renderer.py index 05b641d..74428ef 100644 --- a/reddit_renderer.py +++ b/reddit_renderer.py @@ -1,77 +1,106 @@ -import constants +#!/usr/bin/env python3 + +import logging +from typing import Callable, Dict, Iterable, List, Set + +import praw # type: ignore + +from scottutilz import profanity_filter + import file_writer import grab_bag -import renderer -import secrets import page_builder -import praw -import profanity_filter -import random +import renderer +import kiosk_secrets as secrets -class reddit_renderer(renderer.debuggable_abstaining_renderer): + +logger = logging.getLogger(__file__) + + +class reddit_renderer(renderer.abstaining_renderer): """A renderer to pull text content from reddit.""" - def __init__(self, name_to_timeout_dict, subreddit_list, min_votes, font_size): - super(reddit_renderer, self).__init__(name_to_timeout_dict, True) + def __init__( + self, + name_to_timeout_dict: Dict[str, int], + subreddit_list: List[str], + *, + min_votes: int = 20, + font_size: int = 24, + additional_filters: Iterable[Callable[[str], bool]] = [], + ): + super().__init__(name_to_timeout_dict) self.subreddit_list = subreddit_list - self.praw = praw.Reddit(client_id=secrets.reddit_client_id, - client_secret=secrets.reddit_client_secret, - user_agent="Yoshiatsu's Kitchen Kiosk by u/yoshiatsu ver 0.1, See http://wannabe.guru.org/svn/kiosk/trunk/reddit_renderer.py") + self.praw = praw.Reddit( + client_id=secrets.reddit_client_id, + client_secret=secrets.reddit_client_secret, + user_agent=secrets.reddit_user_agent, + ) self.min_votes = min_votes self.font_size = font_size self.messages = grab_bag.grab_bag() - self.filter = profanity_filter.profanity_filter() - self.deduper = set() + self.filters: List[Callable[..., bool]] = [ + profanity_filter.ProfanityFilter().contains_bad_word + ] + self.filters.extend(additional_filters) + self.deduper: Set[str] = set() - def debug_prefix(self): - x = "" - for subreddit in self.subreddit_list: - x += ("%s " % subreddit) - return "reddit(%s)" % x.strip() - - def periodic_render(self, key): - self.debug_print('called for "%s"' % key) + def periodic_render(self, key: str) -> bool: + logger.debug('called for "%s"' % key) if key == "Scrape": return self.scrape_reddit() elif key == "Shuffle": return self.shuffle_messages() else: - raise error('Unexpected operation') + raise Exception("Unexpected operation") - def append_message(self, messages): + def append_message(self, messages: List[str]) -> None: for msg in messages: - if (not self.filter.contains_bad_words(msg.title) - and msg.ups > self.min_votes - and not msg.title in self.deduper): - try: - self.deduper.add(msg.title) - content = "%d" % msg.ups - if (msg.thumbnail != "self" and - msg.thumbnail != "default" and - msg.thumbnail != ""): - content = '' % msg.thumbnail - x = u""" - + title = str(msg.title) + if title in self.deduper: + continue + filtered = "" + for filt in self.filters: + if filt(title) is True: + filtered = filt.__name__ + break + if filtered != "": + logger.info( + f'Filter {filtered} struck down "{title}"' + ) + continue + if msg.ups < self.min_votes: + logger.debug( + f'"{title}" doesn\'t have enough upvotes to be interesting' + ) + continue + + self.deduper.add(title) + content = f"{msg.ups}" + if ( + msg.thumbnail != "self" + and msg.thumbnail != "default" + and msg.thumbnail != "" + ): + content = f'' + self.messages.add( +f""" +
-
- %s + {content} - %s
(%s) + {title}
({msg.author})
""" % (self.font_size, content, msg.title, msg.author) - self.messages.add(x.encode('utf8')) - except: - self.debug_print('Unexpected exception, skipping message.') - else: - self.debug_print('skipped message "%s" for profanity or low score' % ( - msg.title.encode('utf8'))) +""" + ) - def scrape_reddit(self): + def scrape_reddit(self) -> bool: self.deduper.clear() self.messages.clear() for subreddit in self.subreddit_list: @@ -91,24 +120,24 @@ class reddit_renderer(renderer.debuggable_abstaining_renderer): except: pass try: - msg = self.praw.subreddit(subreddit).controversial('week') + msg = self.praw.subreddit(subreddit).controversial("week") self.append_message(msg) except: pass try: - msg = self.praw.subreddit(subreddit).top('day') + msg = self.praw.subreddit(subreddit).top("day") self.append_message(msg) except: pass - self.debug_print("There are now %d messages" % self.messages.size()) + logger.debug(f"There are now {self.messages.size()} messages") return True - def shuffle_messages(self): + def shuffle_messages(self) -> bool: layout = page_builder.page_builder() layout.set_layout(page_builder.page_builder.LAYOUT_FOUR_ITEMS) x = "" for subreddit in self.subreddit_list: - x += ("%s " % subreddit) + x += f"{subreddit} " if len(x) > 30: if "SeaWA" in x: x = "[local interests]" @@ -117,40 +146,61 @@ class reddit_renderer(renderer.debuggable_abstaining_renderer): layout.set_title("Reddit /r/%s" % x.strip()) subset = self.messages.subset(4) if subset is None: - self.debug_print("Not enough messages to pick from.") + logger.debug("Not enough messages to pick from.") return False for msg in subset: layout.add_item(msg) - f = file_writer.file_writer("%s_4_10800.html" % self.subreddit_list[0]) - layout.render_html(f) - f.close() + with file_writer.file_writer("%s_4_10800.html" % self.subreddit_list[0]) as f: + layout.render_html(f) return True + class til_reddit_renderer(reddit_renderer): - def __init__(self, name_to_timeout_dict): - super(til_reddit_renderer, self).__init__( - name_to_timeout_dict, ["todayilearned"], 200, 20) + def __init__(self, name_to_timeout_dict: Dict[str, int]): + super().__init__( + name_to_timeout_dict, ["todayilearned"], min_votes=100, font_size=20 + ) + class quotes_reddit_renderer(reddit_renderer): - def __init__(self, name_to_timeout_dict): - super(quotes_reddit_renderer, self).__init__( - name_to_timeout_dict, ["quotes"], 200, 20) + def __init__(self, name_to_timeout_dict: Dict[str, int]): + super().__init__( + name_to_timeout_dict, ["quotes"], min_votes=100, font_size=20 + ) + class showerthoughts_reddit_renderer(reddit_renderer): - def __init__(self, name_to_timeout_dict): - super(showerthoughts_reddit_renderer, self).__init__( - name_to_timeout_dict, ["showerthoughts"], 350, 24) + @staticmethod + def dont_tell_me_about_gift_cards(msg: str) -> bool: + return "gift card" in msg + + def __init__(self, name_to_timeout_dict: Dict[str, int]): + super().__init__( + name_to_timeout_dict, + ["showerthoughts"], + min_votes=150, + additional_filters=[ + showerthoughts_reddit_renderer.dont_tell_me_about_gift_cards + ], + ) + class seattle_reddit_renderer(reddit_renderer): - def __init__(self, name_to_timeout_dict): - super(seattle_reddit_renderer, self).__init__( - name_to_timeout_dict, ["seattle","seattleWA","SeaWA","bellevue","kirkland", "CoronavirusWA"], 50, 24) + def __init__(self, name_to_timeout_dict: Dict[str, int]): + super().__init__( + name_to_timeout_dict, + ["seattle", "seattleWA", "SeaWA", "bellevue", "kirkland", "CoronavirusWA"], + min_votes=50, + ) + class lifeprotips_reddit_renderer(reddit_renderer): - def __init__(self, name_to_timeout_dict): - super(lifeprotips_reddit_renderer, self).__init__( - name_to_timeout_dict, ["lifeprotips"], 100, 24) + def __init__(self, name_to_timeout_dict: Dict[str, int]): + super().__init__( + name_to_timeout_dict, ["lifeprotips"], min_votes=50 + ) + -#x = reddit_renderer({"Test", 1234}, ["seattle","bellevue"], 50, 24) +#x = reddit_renderer({"Test", 1234}, ["seattle","bellevue"], min_votes=50, font_size=24) #x.periodic_render("Scrape") #x.periodic_render("Shuffle")