7 from typing import Dict
9 from bs4 import BeautifulSoup # type: ignore
14 import profanity_filter
18 logger = logging.getLogger(__file__)
21 class stranger_events_renderer(renderer.abstaining_renderer):
22 def __init__(self, name_to_timeout_dict: Dict[str, int]):
23 super().__init__(name_to_timeout_dict)
24 self.feed_site = "everout.com"
25 self.events = grab_bag.grab_bag()
27 def debug_prefix(self) -> str:
30 def periodic_render(self, key: str) -> bool:
31 logger.debug("called for action %s" % key)
32 if key == "Fetch Events":
33 return self.fetch_events()
34 elif key == "Shuffle Events":
35 return self.shuffle_events()
37 raise Exception("Unknown operaiton")
45 .calendar-post-title a {
46 text-decoration: none;
53 .calendar-post-category {
55 .calendar-post-location {
57 .calendar-post-price {
59 .calendar-touch-link {
62 background-color:lightyellow;
68 .calendar-post-price-mobile {
73 margin: 10px 10px 10px 10px;
77 def shuffle_events(self) -> bool:
78 layout = page_builder.page_builder()
79 layout.set_layout(page_builder.page_builder.LAYOUT_FOUR_ITEMS)
80 layout.set_title("Stranger Events")
81 layout.set_style(self.get_style())
82 subset = self.events.subset(4)
84 logger.debug("Not enough events to build page.")
89 with file_writer.file_writer("stranger-events_2_36000.html") as f:
93 def fetch_events(self) -> bool:
96 "/seattle/events/?page=1",
97 "/seattle/events/?page=2",
98 "/seattle/events/?page=3",
100 now = datetime.datetime.now()
101 ts = now + datetime.timedelta(1)
102 tomorrow = datetime.datetime.strftime(ts, "%Y-%m-%d")
103 feed_uris.append(f"/seattle/events/?start-date={tomorrow}")
104 delta = 5 - now.weekday()
108 ts = now + datetime.timedelta(delta)
109 next_sat = datetime.datetime.strftime(ts, "%Y-%m-%d")
110 feed_uris.append(f"/seattle/events/?start-date={next_sat}&page=1")
111 feed_uris.append(f"/seattle/events/?start-date={next_sat}&page=2")
114 ts = now + datetime.timedelta(delta)
115 next_sun = datetime.datetime.strftime(ts, "%Y-%m-%d")
116 feed_uris.append(f"/seattle/events/?start-date={next_sun}&page=1")
117 feed_uris.append(f"/seattle/events/?start-date={next_sun}&page=2")
119 filter = profanity_filter.ProfanityFilter()
120 for uri in feed_uris:
122 logger.debug("fetching 'https://%s%s'" % (self.feed_site, uri))
123 self.conn = http.client.HTTPSConnection(self.feed_site)
124 self.conn.request("GET", uri, None, {"Accept-Charset": "utf-8"})
125 response = self.conn.getresponse()
126 if response.status != 200:
127 logger.debug("Connection failed, status %d" % (response.status))
128 logger.debug(str(response.getheaders()))
130 raw = response.read()
132 logger.debug("Exception talking to the stranger, ignoring.")
135 soup = BeautifulSoup(raw, "html.parser")
136 for x in soup.find_all("div", class_="row event list-item mb-3 py-3"):
138 if filter.contains_bad_word(text):
141 raw_str = raw_str.replace(
142 'src="/', 'align="left" src="https://www.thestranger.com/'
144 raw_str = raw_str.replace('href="/', 'href="https://www.thestranger.com/')
145 raw_str = raw_str.replace("FREE", "Free")
146 raw_str = raw_str.replace("Save Event", "")
147 raw_str = re.sub("^\s*$", "", raw_str, 0, re.MULTILINE)
149 '<span[^<>]*class="calendar-post-ticket"[^<>]*>.*</#span>',
153 re.DOTALL | re.IGNORECASE,
155 self.events.add(raw_str)
156 logger.debug(f"fetched {self.events.size()} events so far.")
157 return self.events.size() > 0
161 #x = stranger_events_renderer({"Test", 123})
162 #x.periodic_render("Fetch Events")
163 #x.periodic_render("Shuffle Events")