#!/usr/bin/env python3 import datetime import http.client import logging import re from typing import Dict from bs4 import BeautifulSoup # type: ignore from scottutilz import profanity_filter import file_writer import grab_bag import page_builder import renderer logger = logging.getLogger(__name__) class stranger_events_renderer(renderer.abstaining_renderer): def __init__(self, name_to_timeout_dict: Dict[str, int]): super().__init__(name_to_timeout_dict) self.feed_site = "everout.com" self.events = grab_bag.grab_bag() self.pfilter = profanity_filter.ProfanityFilter() def debug_prefix(self) -> str: return "stranger" def periodic_render(self, key: str) -> bool: logger.debug("called for action %s" % key) if key == "Fetch Events": return self.fetch_events() elif key == "Shuffle Events": return self.shuffle_events() else: raise Exception("Unknown operaiton") def get_style(self): return """ """ def shuffle_events(self) -> bool: layout = page_builder.page_builder() layout.set_layout(page_builder.page_builder.LAYOUT_FOUR_ITEMS) layout.set_title("Stranger Events") layout.set_style(self.get_style()) subset = self.events.subset(4) if subset is None: logger.debug("Not enough events to build page.") return False for msg in subset: layout.add_item(msg) with file_writer.file_writer("stranger-events_2_36000.html") as f: layout.render_html(f) return True def fetch_events(self) -> bool: self.events.clear() feed_uris = [] now = datetime.datetime.now() ts = now + datetime.timedelta(1) tomorrow = datetime.datetime.strftime(ts, "%Y-%m-%d") feed_uris.append(f"/seattle/events/?start-date={tomorrow}") delta = 5 - now.weekday() if delta <= 0: delta += 7 if delta > 1: ts = now + datetime.timedelta(delta) next_sat = datetime.datetime.strftime(ts, "%Y-%m-%d") feed_uris.append(f"/seattle/events/?start-date={next_sat}&page=1") feed_uris.append(f"/seattle/events/?start-date={next_sat}&page=2") delta += 1 if delta > 1: ts = now + datetime.timedelta(delta) next_sun = datetime.datetime.strftime(ts, "%Y-%m-%d") feed_uris.append(f"/seattle/events/?start-date={next_sun}&page=1") feed_uris.append(f"/seattle/events/?start-date={next_sun}&page=2") for uri in feed_uris: try: logger.debug("fetching 'https://%s%s'" % (self.feed_site, uri)) self.conn = http.client.HTTPSConnection(self.feed_site) self.conn.request("GET", uri, None, {"Accept-Charset": "utf-8"}) response = self.conn.getresponse() if response.status != 200: logger.debug("Connection failed, status %d" % (response.status)) logger.debug(str(response.getheaders())) continue raw = response.read() except Exception: logger.debug("Exception talking to the stranger, ignoring.") continue soup = BeautifulSoup(raw, "html.parser") for x in soup.find_all("div", class_="row event list-item mb-3 py-3"): text = x.get_text() if self.pfilter.contains_bad_word(text): continue raw_str = str(x) raw_str = raw_str.replace( 'src="/', 'align="left" src="https://www.thestranger.com/' ) raw_str = raw_str.replace( 'href="/', 'href="https://www.thestranger.com/' ) raw_str = raw_str.replace("FREE", "Free") raw_str = raw_str.replace("Save Event", "") raw_str = re.sub("^\s*$", "", raw_str, 0, re.MULTILINE) raw_str = re.sub( ']*class="calendar-post-ticket"[^<>]*>.*', "", raw_str, 0, re.DOTALL | re.IGNORECASE, ) self.events.add(raw_str) logger.debug(f"fetched {self.events.size()} events so far.") return self.events.size() > 0 # Test x = stranger_events_renderer({"Test", 123}) x.periodic_render("Fetch Events") x.periodic_render("Shuffle Events")