3 from bs4 import BeautifulSoup
8 from typing import Dict, List
13 import profanity_filter
15 import renderer_catalog
18 class stranger_events_renderer(renderer.debuggable_abstaining_renderer):
19 def __init__(self, name_to_timeout_dict: Dict[str, int]):
20 super(stranger_events_renderer, self).__init__(name_to_timeout_dict, True)
21 self.feed_site = "everout.com"
22 self.events = grab_bag.grab_bag()
24 def debug_prefix(self) -> str:
27 def periodic_render(self, key: str) -> bool:
28 self.debug_print("called for action %s" % key)
29 if key == "Fetch Events":
30 return self.fetch_events()
31 elif key == "Shuffle Events":
32 return self.shuffle_events()
34 raise error("Unknown operaiton")
42 .calendar-post-title a {
43 text-decoration: none;
50 .calendar-post-category {
52 .calendar-post-location {
54 .calendar-post-price {
56 .calendar-touch-link {
59 background-color:lightyellow;
65 .calendar-post-price-mobile {
70 margin: 10px 10px 10px 10px;
74 def shuffle_events(self) -> bool:
75 layout = page_builder.page_builder()
76 layout.set_layout(page_builder.page_builder.LAYOUT_FOUR_ITEMS)
77 layout.set_title("Stranger Events")
78 layout.set_style(self.get_style())
79 subset = self.events.subset(4)
81 self.debug_print("Not enough events to build page.")
86 with file_writer.file_writer("stranger-events_2_36000.html") as f:
90 def fetch_events(self) -> bool:
93 "/stranger-seattle/events/?page=1",
94 "/stranger-seattle/events/?page=2",
95 "/stranger-seattle/events/?page=3",
97 now = datetime.datetime.now()
98 ts = now + datetime.timedelta(1)
99 tomorrow = datetime.datetime.strftime(ts, "%Y-%m-%d")
100 feed_uris.append(f"/stranger-seattle/events/?start-date={tomorrow}")
101 delta = 5 - now.weekday()
105 ts = now + datetime.timedelta(delta)
106 next_sat = datetime.datetime.strftime(ts, "%Y-%m-%d")
107 feed_uris.append(f"/stranger-seattle/events/?start-date={next_sat}&page=1")
108 feed_uris.append(f"/stranger-seattle/events/?start-date={next_sat}&page=2")
111 ts = now + datetime.timedelta(delta)
112 next_sun = datetime.datetime.strftime(ts, "%Y-%m-%d")
113 feed_uris.append(f"/stranger-seattle/events/?start-date={next_sun}&page=1")
114 feed_uris.append(f"/stranger-seattle/events/?start-date={next_sun}&page=2")
116 filter = profanity_filter.profanity_filter()
117 for uri in feed_uris:
119 self.debug_print("fetching 'https://%s%s'" % (self.feed_site, uri))
120 self.conn = http.client.HTTPSConnection(self.feed_site)
121 self.conn.request("GET", uri, None, {"Accept-Charset": "utf-8"})
122 response = self.conn.getresponse()
123 if response.status != 200:
124 self.debug_print("Connection failed, status %d" % (response.status))
125 self.debug_print(response.getheaders())
127 raw = response.read()
129 self.debug_print("Exception talking to the stranger, ignoring.")
132 soup = BeautifulSoup(raw, "html.parser")
133 for x in soup.find_all("div", class_="row event list-item mb-3 py-3"):
135 if filter.contains_bad_words(text):
139 'src="/', 'align="left" src="https://www.thestranger.com/'
141 raw = raw.replace('href="/', 'href="https://www.thestranger.com/')
142 raw = raw.replace("FREE", "Free")
143 raw = raw.replace("Save Event", "")
144 raw = re.sub("^\s*$", "", raw, 0, re.MULTILINE)
146 '<span[^<>]*class="calendar-post-ticket"[^<>]*>.*</#span>',
150 re.DOTALL | re.IGNORECASE,
153 self.debug_print(f"fetched {self.events.size()} events so far.")
154 return self.events.size() > 0
158 # x = stranger_events_renderer({"Test", 123})
159 # x.periodic_render("Fetch Events")
160 # x.periodic_render("Shuffle Events")