Format codebase w/ black.
[kiosk.git] / reddit_renderer.py
1 import constants
2 import file_writer
3 import grab_bag
4 import renderer
5 import secrets
6 import page_builder
7 import praw
8 import profanity_filter
9 import random
10 import renderer_catalog
11
12
13 class reddit_renderer(renderer.debuggable_abstaining_renderer):
14     """A renderer to pull text content from reddit."""
15
16     def __init__(self, name_to_timeout_dict, subreddit_list, min_votes, font_size):
17         super(reddit_renderer, self).__init__(name_to_timeout_dict, True)
18         self.subreddit_list = subreddit_list
19         self.praw = praw.Reddit(
20             client_id=secrets.reddit_client_id,
21             client_secret=secrets.reddit_client_secret,
22             user_agent=secrets.reddit_user_agent,
23         )
24         self.min_votes = min_votes
25         self.font_size = font_size
26         self.messages = grab_bag.grab_bag()
27         self.filter = profanity_filter.profanity_filter()
28         self.deduper = set()
29
30     def debug_prefix(self):
31         x = ""
32         for subreddit in self.subreddit_list:
33             x += "%s " % subreddit
34         return "reddit(%s)" % x.strip()
35
36     def periodic_render(self, key):
37         self.debug_print('called for "%s"' % key)
38         if key == "Scrape":
39             return self.scrape_reddit()
40         elif key == "Shuffle":
41             return self.shuffle_messages()
42         else:
43             raise error("Unexpected operation")
44
45     def append_message(self, messages):
46         for msg in messages:
47             if (
48                 not self.filter.contains_bad_words(msg.title)
49                 and msg.ups > self.min_votes
50                 and not msg.title in self.deduper
51             ):
52                 try:
53                     self.deduper.add(msg.title)
54                     content = "%d" % msg.ups
55                     if (
56                         msg.thumbnail != "self"
57                         and msg.thumbnail != "default"
58                         and msg.thumbnail != ""
59                     ):
60                         content = '<IMG SRC="%s">' % msg.thumbnail
61                     x = """
62 <TABLE STYLE="font-size:%dpt;">
63   <TR>
64     <!-- The number of upvotes or item image: -->
65     <TD STYLE="font-weight:900; padding:8px;">
66       <FONT COLOR="maroon" SIZE=40>%s</FONT>
67     </TD>
68
69     <!-- The content and author: -->
70     <TD>
71       <B>%s</B><BR><FONT COLOR=#bbbbbb>(%s)</FONT>
72     </TD>
73   </TR>
74 </TABLE>""" % (
75                         self.font_size,
76                         content,
77                         msg.title,
78                         msg.author,
79                     )
80                     self.messages.add(x)
81                 except:
82                     self.debug_print("Unexpected exception, skipping message.")
83             else:
84                 self.debug_print(
85                     'skipped message "%s" for profanity or low score' % (msg.title)
86                 )
87
88     def scrape_reddit(self):
89         self.deduper.clear()
90         self.messages.clear()
91         for subreddit in self.subreddit_list:
92             try:
93                 msg = self.praw.subreddit(subreddit).hot()
94                 self.append_message(msg)
95             except:
96                 pass
97             try:
98                 msg = self.praw.subreddit(subreddit).new()
99                 self.append_message(msg)
100             except:
101                 pass
102             try:
103                 msg = self.praw.subreddit(subreddit).rising()
104                 self.append_message(msg)
105             except:
106                 pass
107             try:
108                 msg = self.praw.subreddit(subreddit).controversial("week")
109                 self.append_message(msg)
110             except:
111                 pass
112             try:
113                 msg = self.praw.subreddit(subreddit).top("day")
114                 self.append_message(msg)
115             except:
116                 pass
117             self.debug_print("There are now %d messages" % self.messages.size())
118         return True
119
120     def shuffle_messages(self):
121         layout = page_builder.page_builder()
122         layout.set_layout(page_builder.page_builder.LAYOUT_FOUR_ITEMS)
123         x = ""
124         for subreddit in self.subreddit_list:
125             x += "%s " % subreddit
126         if len(x) > 30:
127             if "SeaWA" in x:
128                 x = "[local interests]"
129             else:
130                 x = "Unknown, fixme"
131         layout.set_title("Reddit /r/%s" % x.strip())
132         subset = self.messages.subset(4)
133         if subset is None:
134             self.debug_print("Not enough messages to pick from.")
135             return False
136         for msg in subset:
137             layout.add_item(msg)
138         f = file_writer.file_writer("%s_4_10800.html" % self.subreddit_list[0])
139         layout.render_html(f)
140         f.close()
141         return True
142
143
144 class til_reddit_renderer(reddit_renderer):
145     def __init__(self, name_to_timeout_dict):
146         super(til_reddit_renderer, self).__init__(
147             name_to_timeout_dict, ["todayilearned"], 200, 20
148         )
149
150
151 class quotes_reddit_renderer(reddit_renderer):
152     def __init__(self, name_to_timeout_dict):
153         super(quotes_reddit_renderer, self).__init__(
154             name_to_timeout_dict, ["quotes"], 200, 20
155         )
156
157
158 class showerthoughts_reddit_renderer(reddit_renderer):
159     def __init__(self, name_to_timeout_dict):
160         super(showerthoughts_reddit_renderer, self).__init__(
161             name_to_timeout_dict, ["showerthoughts"], 350, 24
162         )
163
164
165 class seattle_reddit_renderer(reddit_renderer):
166     def __init__(self, name_to_timeout_dict):
167         super(seattle_reddit_renderer, self).__init__(
168             name_to_timeout_dict,
169             ["seattle", "seattleWA", "SeaWA", "bellevue", "kirkland", "CoronavirusWA"],
170             50,
171             24,
172         )
173
174
175 class lifeprotips_reddit_renderer(reddit_renderer):
176     def __init__(self, name_to_timeout_dict):
177         super(lifeprotips_reddit_renderer, self).__init__(
178             name_to_timeout_dict, ["lifeprotips"], 100, 24
179         )
180
181
182 # x = reddit_renderer({"Test", 1234}, ["seattle","bellevue"], 50, 24)
183 # x.periodic_render("Scrape")
184 # x.periodic_render("Shuffle")