3 from bs4 import BeautifulSoup # type: ignore
8 from typing import Dict, List
13 import profanity_filter
17 class stranger_events_renderer(renderer.debuggable_abstaining_renderer):
18 def __init__(self, name_to_timeout_dict: Dict[str, int]):
19 super(stranger_events_renderer, self).__init__(name_to_timeout_dict, True)
20 self.feed_site = "everout.com"
21 self.events = grab_bag.grab_bag()
23 def debug_prefix(self) -> str:
26 def periodic_render(self, key: str) -> bool:
27 self.debug_print("called for action %s" % key)
28 if key == "Fetch Events":
29 return self.fetch_events()
30 elif key == "Shuffle Events":
31 return self.shuffle_events()
33 raise Exception("Unknown operaiton")
41 .calendar-post-title a {
42 text-decoration: none;
49 .calendar-post-category {
51 .calendar-post-location {
53 .calendar-post-price {
55 .calendar-touch-link {
58 background-color:lightyellow;
64 .calendar-post-price-mobile {
69 margin: 10px 10px 10px 10px;
73 def shuffle_events(self) -> bool:
74 layout = page_builder.page_builder()
75 layout.set_layout(page_builder.page_builder.LAYOUT_FOUR_ITEMS)
76 layout.set_title("Stranger Events")
77 layout.set_style(self.get_style())
78 subset = self.events.subset(4)
80 self.debug_print("Not enough events to build page.")
85 with file_writer.file_writer("stranger-events_2_36000.html") as f:
89 def fetch_events(self) -> bool:
92 "/stranger-seattle/events/?page=1",
93 "/stranger-seattle/events/?page=2",
94 "/stranger-seattle/events/?page=3",
96 now = datetime.datetime.now()
97 ts = now + datetime.timedelta(1)
98 tomorrow = datetime.datetime.strftime(ts, "%Y-%m-%d")
99 feed_uris.append(f"/stranger-seattle/events/?start-date={tomorrow}")
100 delta = 5 - now.weekday()
104 ts = now + datetime.timedelta(delta)
105 next_sat = datetime.datetime.strftime(ts, "%Y-%m-%d")
106 feed_uris.append(f"/stranger-seattle/events/?start-date={next_sat}&page=1")
107 feed_uris.append(f"/stranger-seattle/events/?start-date={next_sat}&page=2")
110 ts = now + datetime.timedelta(delta)
111 next_sun = datetime.datetime.strftime(ts, "%Y-%m-%d")
112 feed_uris.append(f"/stranger-seattle/events/?start-date={next_sun}&page=1")
113 feed_uris.append(f"/stranger-seattle/events/?start-date={next_sun}&page=2")
115 filter = profanity_filter.profanity_filter()
116 for uri in feed_uris:
118 self.debug_print("fetching 'https://%s%s'" % (self.feed_site, uri))
119 self.conn = http.client.HTTPSConnection(self.feed_site)
120 self.conn.request("GET", uri, None, {"Accept-Charset": "utf-8"})
121 response = self.conn.getresponse()
122 if response.status != 200:
123 self.debug_print("Connection failed, status %d" % (response.status))
124 self.debug_print(str(response.getheaders()))
126 raw = response.read()
128 self.debug_print("Exception talking to the stranger, ignoring.")
131 soup = BeautifulSoup(raw, "html.parser")
132 for x in soup.find_all("div", class_="row event list-item mb-3 py-3"):
134 if filter.contains_bad_words(text):
137 raw_str = raw_str.replace(
138 'src="/', 'align="left" src="https://www.thestranger.com/'
140 raw_str = raw_str.replace('href="/', 'href="https://www.thestranger.com/')
141 raw_str = raw_str.replace("FREE", "Free")
142 raw_str = raw_str.replace("Save Event", "")
143 raw_str = re.sub("^\s*$", "", raw_str, 0, re.MULTILINE)
145 '<span[^<>]*class="calendar-post-ticket"[^<>]*>.*</#span>',
149 re.DOTALL | re.IGNORECASE,
151 self.events.add(raw_str)
152 self.debug_print(f"fetched {self.events.size()} events so far.")
153 return self.events.size() > 0
157 # x = stranger_events_renderer({"Test", 123})
158 # x.periodic_render("Fetch Events")
159 # x.periodic_render("Shuffle Events")