+#!/usr/bin/env python3
+
+import praw # type: ignore
+import random
+from typing import Callable, Dict, Iterable, List, Set
+
import constants
import file_writer
import grab_bag
-import renderer
-import secrets
import page_builder
-import praw
import profanity_filter
-import random
-import renderer_catalog
+import renderer
+import secrets
class reddit_renderer(renderer.debuggable_abstaining_renderer):
"""A renderer to pull text content from reddit."""
- def __init__(self, name_to_timeout_dict, subreddit_list, min_votes, font_size):
+ 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(reddit_renderer, self).__init__(name_to_timeout_dict, True)
self.subreddit_list = subreddit_list
self.praw = praw.Reddit(
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.profanity_filter().contains_bad_words
+ ]
+ self.filters.extend(additional_filters)
+ self.deduper: Set[str] = set()
- def debug_prefix(self):
+ def debug_prefix(self) -> str:
x = ""
for subreddit in self.subreddit_list:
- x += "%s " % subreddit
- return "reddit(%s)" % x.strip()
+ x += f"{subreddit} "
+ return f"reddit({x.strip()})"
- def periodic_render(self, key):
+ def periodic_render(self, key: str) -> bool:
self.debug_print('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 = '<IMG SRC="%s">' % msg.thumbnail
- x = """
-<TABLE STYLE="font-size:%dpt;">
+ 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 != "":
+ print(f'Filter {filtered} struck down "{title}"')
+ continue
+ if msg.ups < self.min_votes:
+ print(f'"{title}" doesn\'t have enough upvotes to be interesting')
+ continue
+
+ try:
+ self.deduper.add(title)
+ content = f"{msg.ups}"
+ if (
+ msg.thumbnail != "self"
+ and msg.thumbnail != "default"
+ and msg.thumbnail != ""
+ ):
+ content = f'<IMG SRC="{msg.thumbnail}">'
+ self.messages.add(
+ f"""
+<TABLE STYLE="font-size:{self.font_size}pt;">
<TR>
<!-- The number of upvotes or item image: -->
<TD STYLE="font-weight:900; padding:8px;">
- <FONT COLOR="maroon" SIZE=40>%s</FONT>
+ <FONT COLOR="maroon" SIZE=40>{content}</FONT>
</TD>
<!-- The content and author: -->
<TD>
- <B>%s</B><BR><FONT COLOR=#bbbbbb>(%s)</FONT>
+ <B>{title}</B><BR><FONT COLOR=#bbbbbb>({msg.author})</FONT>
</TD>
</TR>
-</TABLE>""" % (
- self.font_size,
- content,
- msg.title,
- msg.author,
- )
- self.messages.add(x)
- except:
- self.debug_print("Unexpected exception, skipping message.")
- else:
- self.debug_print(
- 'skipped message "%s" for profanity or low score' % (msg.title)
+</TABLE>"""
)
+ except:
+ self.debug_print("Unexpected exception, skipping message.")
- def scrape_reddit(self):
+ def scrape_reddit(self) -> bool:
self.deduper.clear()
self.messages.clear()
for subreddit in self.subreddit_list:
self.append_message(msg)
except:
pass
- self.debug_print("There are now %d messages" % self.messages.size())
+ self.debug_print(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]"
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):
+ def __init__(self, name_to_timeout_dict: Dict[str, int]):
super(til_reddit_renderer, self).__init__(
- name_to_timeout_dict, ["todayilearned"], 200, 20
+ name_to_timeout_dict, ["todayilearned"], min_votes=200, font_size=20
)
class quotes_reddit_renderer(reddit_renderer):
- def __init__(self, name_to_timeout_dict):
+ def __init__(self, name_to_timeout_dict: Dict[str, int]):
super(quotes_reddit_renderer, self).__init__(
- name_to_timeout_dict, ["quotes"], 200, 20
+ name_to_timeout_dict, ["quotes"], min_votes=200, font_size=20
)
class showerthoughts_reddit_renderer(reddit_renderer):
- def __init__(self, name_to_timeout_dict):
+ @staticmethod
+ def dont_tell_me_about_gift_cards(msg: str) -> bool:
+ return not "IMPORTANT PSA: No, you did not win a gift card" in msg
+
+ def __init__(self, name_to_timeout_dict: Dict[str, int]):
super(showerthoughts_reddit_renderer, self).__init__(
- name_to_timeout_dict, ["showerthoughts"], 350, 24
+ name_to_timeout_dict,
+ ["showerthoughts"],
+ min_votes=250,
+ additional_filters=[
+ showerthoughts_reddit_renderer.dont_tell_me_about_gift_cards
+ ],
)
class seattle_reddit_renderer(reddit_renderer):
- def __init__(self, name_to_timeout_dict):
+ def __init__(self, name_to_timeout_dict: Dict[str, int]):
super(seattle_reddit_renderer, self).__init__(
name_to_timeout_dict,
["seattle", "seattleWA", "SeaWA", "bellevue", "kirkland", "CoronavirusWA"],
- 50,
- 24,
+ min_votes=50,
)
class lifeprotips_reddit_renderer(reddit_renderer):
- def __init__(self, name_to_timeout_dict):
+ def __init__(self, name_to_timeout_dict: Dict[str, int]):
super(lifeprotips_reddit_renderer, self).__init__(
- name_to_timeout_dict, ["lifeprotips"], 100, 24
+ name_to_timeout_dict, ["lifeprotips"], min_votes=100
)
-# x = reddit_renderer({"Test", 1234}, ["seattle","bellevue"], 50, 24)
-# x.periodic_render("Scrape")
-# x.periodic_render("Shuffle")
+#x = reddit_renderer({"Test", 1234}, ["seattle","bellevue"], min_votes=50, font_size=24)
+#x.periodic_render("Scrape")
+#x.periodic_render("Shuffle")