From 5e241dc47e497c547463cecc07946ea6882835a7 Mon Sep 17 00:00:00 2001 From: Scott Gasch Date: Mon, 14 Dec 2020 11:27:34 -0800 Subject: [PATCH] Format codebase w/ black. --- bellevue_reporter_rss_renderer.py | 63 +-- camera_trigger.py | 65 +-- chooser.py | 66 ++- cnn_rss_renderer.py | 32 +- decorators.py | 11 +- file_writer.py | 24 +- gcal_renderer.py | 198 ++++---- gcal_trigger.py | 8 +- gdata_oauth.py | 123 ++--- gdocs_renderer.py | 42 +- generic_news_rss_renderer.py | 100 ++-- gkeep_renderer.py | 81 +-- globals.py | 3 +- google_news_rss_renderer.py | 29 +- grab_bag.py | 8 +- health_renderer.py | 105 ++-- kiosk.py | 133 ++--- local_photos_mirror_renderer.py | 124 ++--- mynorthwest_rss_renderer.py | 19 +- myq_renderer.py | 39 +- myq_trigger.py | 1 + page_builder.py | 6 +- picasa_renderer.py | 161 +++--- pollen_renderer.py | 79 +-- profanity_filter.py | 797 +++++++++++++++--------------- reddit_renderer.py | 77 ++- renderer.py | 23 +- renderer_catalog.py | 244 +++++---- reuters_rss_renderer.py | 66 +-- seattletimes_rss_renderer.py | 55 ++- stevens_renderer.py | 26 +- stock_renderer.py | 74 +-- stranger_renderer.py | 65 ++- trigger.py | 1 - trigger_catalog.py | 9 +- twitter_renderer.py | 46 +- utils.py | 28 +- weather_renderer.py | 185 ++++--- wsj_rss_renderer.py | 24 +- 39 files changed, 1757 insertions(+), 1483 deletions(-) diff --git a/bellevue_reporter_rss_renderer.py b/bellevue_reporter_rss_renderer.py index 78ec694..1bd3514 100644 --- a/bellevue_reporter_rss_renderer.py +++ b/bellevue_reporter_rss_renderer.py @@ -1,13 +1,12 @@ import generic_news_rss_renderer as gnrss import re + class bellevue_reporter_rss_renderer(gnrss.generic_news_rss_renderer): def __init__(self, name_to_timeout_dict, feed_site, feed_uris, page_title): super(bellevue_reporter_rss_renderer, self).__init__( - name_to_timeout_dict, - feed_site, - feed_uris, - page_title) + name_to_timeout_dict, feed_site, feed_uris, page_title + ) self.debug = 1 def debug_prefix(self): @@ -23,20 +22,23 @@ class bellevue_reporter_rss_renderer(gnrss.generic_news_rss_renderer): return True def munge_description(self, description): - description = re.sub('<[^>]+>', '', description) - description = re.sub('Bellevue\s+Reporter\s+Bellevue\s+Reporter', '', - description) - description = re.sub('\s*\-\s*Your local homepage\.\s*', '', description) + description = re.sub("<[^>]+>", "", description) + description = re.sub( + "Bellevue\s+Reporter\s+Bellevue\s+Reporter", "", description + ) + description = re.sub("\s*\-\s*Your local homepage\.\s*", "", description) return description def item_is_interesting_for_headlines(self, title, description, item): if self.is_item_older_than_n_days(item, 10): self.debug_print("%s: is too old!" % title) return False - if (title.find("NFL") != -1 or - re.search("[Ll]ive [Ss]tream", title) != None or - re.search("[Ll]ive[Ss]tream", title) != None or - re.search("[Ll]ive [Ss]tream", description) != None): + if ( + title.find("NFL") != -1 + or re.search("[Ll]ive [Ss]tream", title) != None + or re.search("[Ll]ive[Ss]tream", title) != None + or re.search("[Ll]ive [Ss]tream", description) != None + ): self.debug_print("%s: looks like it's about football." % title) return False return True @@ -45,33 +47,36 @@ class bellevue_reporter_rss_renderer(gnrss.generic_news_rss_renderer): if self.is_item_older_than_n_days(item, 10): self.debug_print("%s: is too old!" % title) return False - if (title.find(" NFL") != -1 or - re.search("[Ll]ive [Ss]tream", title) != None or - re.search("[Ll]ive[Ss]tream", title) != None or - re.search("[Ll]ive [Ss]tream", description) != None): + if ( + title.find(" NFL") != -1 + or re.search("[Ll]ive [Ss]tream", title) != None + or re.search("[Ll]ive[Ss]tream", title) != None + or re.search("[Ll]ive [Ss]tream", description) != None + ): self.debug_print("%s: looks like it's about football." % title) return False return True + # Test -#x = bellevue_reporter_rss_renderer( +# x = bellevue_reporter_rss_renderer( # {"Fetch News" : 1, # "Shuffle News" : 1}, # "www.bellevuereporter.com", # [ "/feed/" ], # "Test" ) -#d = """ -#

-#Task force will tackle issues of racial justice, police reform -#
Bellevue Reporter -#Bellevue Reporter - Your local homepage. -#Inslee names civil rights activists, pastors, and cops to panel that may forge ideas f#or new laws Task force will tackle issues of racial justice, police reform -#Wire Service -#

""" -#d = x.munge_description(d) -#print d -#if x.fetch_news() == 0: +# Task force will tackle issues of racial justice, police reform +#
Bellevue Reporter +# Bellevue Reporter - Your local homepage. +# Inslee names civil rights activists, pastors, and cops to panel that may forge ideas f#or new laws Task force will tackle issues of racial justice, police reform +# Wire Service +# """ +# d = x.munge_description(d) +# print d +# if x.fetch_news() == 0: # print "Error fetching news, no items fetched." -#x.shuffle_news() +# x.shuffle_news() diff --git a/camera_trigger.py b/camera_trigger.py index 64cb638..0f42ca2 100644 --- a/camera_trigger.py +++ b/camera_trigger.py @@ -5,27 +5,28 @@ import trigger import utils from datetime import datetime + class any_camera_trigger(trigger.trigger): def __init__(self): self.triggers_in_the_past_seven_min = { - "driveway" : 0, - "frontdoor" : 0, - "cabin_driveway" : 0, - "backyard" : 0, + "driveway": 0, + "frontdoor": 0, + "cabin_driveway": 0, + "backyard": 0, } self.last_trigger = { - "driveway" : 0, - "frontdoor" : 0, - "cabin_driveway" : 0, - "backyard" : 0, + "driveway": 0, + "frontdoor": 0, + "cabin_driveway": 0, + "backyard": 0, } def choose_priority(self, camera, age): base_priority_by_camera = { - "driveway" : 1, - "frontdoor" : 2, - "cabin_driveway" : 1, - "backyard" : 0, + "driveway": 1, + "frontdoor": 2, + "cabin_driveway": 1, + "backyard": 0, } priority = base_priority_by_camera[camera] if age < 10: @@ -39,10 +40,7 @@ class any_camera_trigger(trigger.trigger): def get_triggered_page_list(self): triggers = [] cameras_with_recent_triggers = 0 - camera_list = [ "driveway", - "frontdoor", - "cabin_driveway", - "backyard" ] + camera_list = ["driveway", "frontdoor", "cabin_driveway", "backyard"] now = time.time() try: @@ -51,8 +49,7 @@ class any_camera_trigger(trigger.trigger): for camera in camera_list: file = "/timestamps/last_camera_motion_%s" % camera ts = os.stat(file).st_ctime - if (ts != self.last_trigger[camera] and - (now - ts) < 10): + if ts != self.last_trigger[camera] and (now - ts) < 10: print("Camera: %s, age %s" % (camera, (now - ts))) self.last_trigger[camera] = ts cameras_with_recent_triggers += 1 @@ -74,17 +71,28 @@ class any_camera_trigger(trigger.trigger): # triggered at the same time. for camera in camera_list: if (now - self.last_trigger[camera]) < 10: - if (self.triggers_in_the_past_seven_min[camera] <= 4 or - cameras_with_recent_triggers > 1): + if ( + self.triggers_in_the_past_seven_min[camera] <= 4 + or cameras_with_recent_triggers > 1 + ): ts = utils.timestamp() p = self.choose_priority(camera, age) - print(("%s: ****** %s[%d] CAMERA TRIGGER ******" % ( - ts, camera, p))) - triggers.append( ( "hidden/%s.html" % camera, - self.choose_priority(camera, age)) ) + print( + ( + "%s: ****** %s[%d] CAMERA TRIGGER ******" + % (ts, camera, p) + ) + ) + triggers.append( + ( + "hidden/%s.html" % camera, + self.choose_priority(camera, age), + ) + ) else: - print(("%s: Camera %s too spammy, squelching it" % ( - ts, camera))) + print( + ("%s: Camera %s too spammy, squelching it" % (ts, camera)) + ) except Exception as e: print(e) pass @@ -94,5 +102,6 @@ class any_camera_trigger(trigger.trigger): else: return triggers -#x = any_camera_trigger() -#print(x.get_triggered_page_list()) + +# x = any_camera_trigger() +# print(x.get_triggered_page_list()) diff --git a/chooser.py b/chooser.py index 9bf98e3..ac8948a 100644 --- a/chooser.py +++ b/chooser.py @@ -8,24 +8,30 @@ import glob import constants import trigger + class chooser(object): """Base class of a thing that chooses pages""" + def get_page_list(self): now = time.time() valid_filename = re.compile("([^_]+)_(\d+)_([^\.]+)\.html") filenames = [] - pages = [ f for f in os.listdir(constants.pages_dir) - if os.path.isfile(os.path.join(constants.pages_dir, f))] + pages = [ + f + for f in os.listdir(constants.pages_dir) + if os.path.isfile(os.path.join(constants.pages_dir, f)) + ] for page in pages: result = re.match(valid_filename, page) if result != None: print(('chooser: candidate page: "%s"' % page)) - if (result.group(3) != "none"): + if result.group(3) != "none": freshness_requirement = int(result.group(3)) - last_modified = int(os.path.getmtime( - os.path.join(constants.pages_dir, page))) - age = (now - last_modified) - if (age > freshness_requirement): + last_modified = int( + os.path.getmtime(os.path.join(constants.pages_dir, page)) + ) + age = now - last_modified + if age > freshness_requirement: print(('chooser: "%s" is too old.' % page)) continue filenames.append(page) @@ -34,8 +40,10 @@ class chooser(object): def choose_next_page(self): pass + class weighted_random_chooser(chooser): """Chooser that does it via weighted RNG.""" + def dont_choose_page_twice_in_a_row_filter(self, choice): if choice == self.last_choice: return False @@ -53,8 +61,7 @@ class weighted_random_chooser(chooser): self.filter_list.append(self.dont_choose_page_twice_in_a_row_filter) def choose_next_page(self): - if (self.pages == None or - self.count % 100 == 0): + if self.pages == None or self.count % 100 == 0: self.pages = self.get_page_list() total_weight = 0 @@ -65,7 +72,7 @@ class weighted_random_chooser(chooser): weight = int(result.group(2)) weights.append(weight) total_weight += weight - if (total_weight <= 0): + if total_weight <= 0: raise error while True: @@ -91,8 +98,10 @@ class weighted_random_chooser(chooser): self.count += 1 return choice + class weighted_random_chooser_with_triggers(weighted_random_chooser): """Same as WRC but has trigger events""" + def __init__(self, trigger_list, filter_list): weighted_random_chooser.__init__(self, filter_list) self.trigger_list = trigger_list @@ -111,14 +120,13 @@ class weighted_random_chooser_with_triggers(weighted_random_chooser): return triggered def choose_next_page(self): - if (self.pages == None or - self.count % 100 == 0): + if self.pages == None or self.count % 100 == 0: self.pages = self.get_page_list() triggered = self.check_for_triggers() # First try to satisfy from the page queue. - if (len(self.page_queue) > 0): + if len(self.page_queue) > 0: print("chooser: Pulling page from queue...") page = None priority = None @@ -133,8 +141,10 @@ class weighted_random_chooser_with_triggers(weighted_random_chooser): else: return weighted_random_chooser.choose_next_page(self), False + class rotating_chooser(chooser): """Chooser that does it in a rotation""" + def __init__(self): self.valid_filename = re.compile("([^_]+)_(\d+)_([^\.]+)\.html") self.pages = None @@ -142,14 +152,13 @@ class rotating_chooser(chooser): self.count = 0 def choose_next_page(self): - if (self.pages == None or - self.count % 100 == 0): + if self.pages == None or self.count % 100 == 0: self.pages = self.get_page_list() if len(self.pages) == 0: raise error - if (self.current >= len(self.pages)): + if self.current >= len(self.pages): self.current = 0 page = self.pages[self.current] @@ -157,18 +166,21 @@ class rotating_chooser(chooser): self.count += 1 return page + # Test def filter_news_during_dinnertime(page): now = datetime.datetime.now() is_dinnertime = now.hour >= 17 and now.hour <= 20 - return (not is_dinnertime or - not ("cnn" in page or - "news" in page or - "mynorthwest" in page or - "seattle" in page or - "stranger" in page or - "twitter" in page or - "wsj" in page)) - -#x = weighted_random_chooser_with_triggers([], [ filter_news_during_dinnertime ]) -#print(x.choose_next_page()) + return not is_dinnertime or not ( + "cnn" in page + or "news" in page + or "mynorthwest" in page + or "seattle" in page + or "stranger" in page + or "twitter" in page + or "wsj" in page + ) + + +# x = weighted_random_chooser_with_triggers([], [ filter_news_during_dinnertime ]) +# print(x.choose_next_page()) diff --git a/cnn_rss_renderer.py b/cnn_rss_renderer.py index 413b58a..c1ae7fd 100644 --- a/cnn_rss_renderer.py +++ b/cnn_rss_renderer.py @@ -1,13 +1,12 @@ import generic_news_rss_renderer import re + class cnn_rss_renderer(generic_news_rss_renderer.generic_news_rss_renderer): def __init__(self, name_to_timeout_dict, feed_site, feed_uris, page_title): super(cnn_rss_renderer, self).__init__( - name_to_timeout_dict, - feed_site, - feed_uris, - page_title) + name_to_timeout_dict, feed_site, feed_uris, page_title + ) self.debug = 1 def debug_prefix(self): @@ -20,16 +19,14 @@ class cnn_rss_renderer(generic_news_rss_renderer.generic_news_rss_renderer): return "cnn-details-%s" % (self.page_title) def munge_description(self, description): - description = re.sub('[Rr]ead full story for latest details.', - '', - description) - description = re.sub('<[^>]+>', '', description) + description = re.sub("[Rr]ead full story for latest details.", "", description) + description = re.sub("<[^>]+>", "", description) return description def find_image(self, item): - image = item.findtext('media:thumbnail') + image = item.findtext("media:thumbnail") if image is not None: - image_url = image.get('url') + image_url = image.get("url") return image_url return None @@ -40,17 +37,20 @@ class cnn_rss_renderer(generic_news_rss_renderer.generic_news_rss_renderer): if self.is_item_older_than_n_days(item, 14): self.debug_print("%s: is too old!" % title) return False - return re.search(r'[Cc][Nn][Nn][A-Za-z]*\.com', title) is None + return re.search(r"[Cc][Nn][Nn][A-Za-z]*\.com", title) is None def item_is_interesting_for_article(self, title, description, item): if self.is_item_older_than_n_days(item, 7): self.debug_print("%s: is too old!" % title) return False - return (re.search(r'[Cc][Nn][Nn][A-Za-z]*\.com', title) is None and - len(description) >= 65) + return ( + re.search(r"[Cc][Nn][Nn][A-Za-z]*\.com", title) is None + and len(description) >= 65 + ) + # Test -#x = cnn_rss_renderer( +# x = cnn_rss_renderer( # {"Fetch News" : 1, # "Shuffle News" : 1}, # "rss.cnn.com", @@ -59,6 +59,6 @@ class cnn_rss_renderer(generic_news_rss_renderer.generic_news_rss_renderer): # "/rss/cnn_tech.rss", # ], # "Test" ) -#if x.fetch_news() == 0: +# if x.fetch_news() == 0: # print("Error fetching news, no items fetched.") -#x.shuffle_news() +# x.shuffle_news() diff --git a/decorators.py b/decorators.py index 7a08879..1f50bf8 100644 --- a/decorators.py +++ b/decorators.py @@ -1,6 +1,7 @@ from datetime import datetime import functools + def invokation_logged(func): @functools.wraps(func) def wrapper(*args, **kwargs): @@ -12,13 +13,15 @@ def invokation_logged(func): timestamp = now.strftime("%d-%b-%Y (%H:%M:%S.%f)") print("%s(%s): Exited function" % (func.__name__, timestamp)) return ret + return wrapper + # Test -#@invokation_logged -#def f(x): +# @invokation_logged +# def f(x): # print(x * x) # return x * x # -#q = f(10) -#print(q) +# q = f(10) +# print(q) diff --git a/file_writer.py b/file_writer.py index 0d95f71..988d0a0 100644 --- a/file_writer.py +++ b/file_writer.py @@ -1,9 +1,10 @@ import constants import os + def remove_tricky_unicode(x): try: - x = x.decode('utf-8') + x = x.decode("utf-8") x = x.replace("\u2018", "'").replace("\u2019", "'") x = x.replace("\u201c", '"').replace("\u201d", '"') x = x.replace("\u2e3a", "-").replace("\u2014", "-") @@ -11,12 +12,12 @@ def remove_tricky_unicode(x): pass return x + class file_writer: def __init__(self, filename): - self.full_filename = os.path.join(constants.pages_dir, - filename) - self.f = open(self.full_filename, 'wb') - self.xforms = [ remove_tricky_unicode ] + self.full_filename = os.path.join(constants.pages_dir, filename) + self.f = open(self.full_filename, "wb") + self.xforms = [remove_tricky_unicode] def add_xform(self, xform): self.xforms.append(xform) @@ -24,7 +25,7 @@ class file_writer: def write(self, data): for xform in self.xforms: data = xform(data) - self.f.write(data.encode('utf-8')) + self.f.write(data.encode("utf-8")) def done(self): self.f.close() @@ -32,11 +33,12 @@ class file_writer: def close(self): self.done() + # Test -#def toupper(x): +# def toupper(x): # return x.upper() # -#fw = file_writer("test") -#fw.add_xform(toupper) -#fw.write(u"This is a \u201ctest\u201d. \n") -#fw.done() +# fw = file_writer("test") +# fw.add_xform(toupper) +# fw.write(u"This is a \u201ctest\u201d. \n") +# fw.done() diff --git a/gcal_renderer.py b/gcal_renderer.py index a248d1d..e665779 100644 --- a/gcal_renderer.py +++ b/gcal_renderer.py @@ -8,25 +8,29 @@ import os import renderer import time + class gcal_renderer(renderer.debuggable_abstaining_renderer): """A renderer to fetch upcoming events from www.google.com/calendar""" - calendar_whitelist = frozenset([ - 'Alex\'s calendar', - 'Family', - 'Holidays in United States', - 'Lynn Gasch', - 'Lynn\'s Work', - 'scott.gasch@gmail.com', - 'Scott Gasch External - Misc', - 'Birthdays', # <-- from g+ contacts - ]) + calendar_whitelist = frozenset( + [ + "Alex's calendar", + "Family", + "Holidays in United States", + "Lynn Gasch", + "Lynn's Work", + "scott.gasch@gmail.com", + "Scott Gasch External - Misc", + "Birthdays", # <-- from g+ contacts + ] + ) class comparable_event(object): """A helper class to sort events.""" + def __init__(self, start_time, end_time, summary, calendar): if start_time is None: - assert(end_time is None) + assert end_time is None self.start_time = start_time self.end_time = end_time self.summary = summary @@ -37,16 +41,15 @@ class gcal_renderer(renderer.debuggable_abstaining_renderer): return self.summary < that.summary if self.start_time is None or that.start_time is None: return self.start_time is None - return (self.start_time, - self.end_time, - self.summary, - self.calendar) < (that.start_time, - that.end_time, - that.summary, - that.calendar) + return (self.start_time, self.end_time, self.summary, self.calendar) < ( + that.start_time, + that.end_time, + that.summary, + that.calendar, + ) def __str__(self): - return '[%s] %s' % (self.timestamp(), self.friendly_name()) + return "[%s] %s" % (self.timestamp(), self.friendly_name()) def friendly_name(self): name = self.summary @@ -56,12 +59,12 @@ class gcal_renderer(renderer.debuggable_abstaining_renderer): def timestamp(self): if self.start_time is None: return "None" - elif (self.start_time.hour == 0): - return datetime.datetime.strftime(self.start_time, - '%a %b %d %Y') + elif self.start_time.hour == 0: + return datetime.datetime.strftime(self.start_time, "%a %b %d %Y") else: - return datetime.datetime.strftime(self.start_time, - '%a %b %d %Y %H:%M%p') + return datetime.datetime.strftime( + self.start_time, "%a %b %d %Y %H:%M%p" + ) def __init__(self, name_to_timeout_dict, oauth): super(gcal_renderer, self).__init__(name_to_timeout_dict, True) @@ -75,17 +78,19 @@ class gcal_renderer(renderer.debuggable_abstaining_renderer): def periodic_render(self, key): self.debug_print('called for "%s"' % key) - if (key == "Render Upcoming Events"): + if key == "Render Upcoming Events": return self.render_upcoming_events() - elif (key == "Look For Triggered Events"): + elif key == "Look For Triggered Events": return self.look_for_triggered_events() else: - raise error('Unexpected operation') + raise error("Unexpected operation") def render_upcoming_events(self): page_token = None + def format_datetime(x): - return datetime.datetime.strftime(x, '%Y-%m-%dT%H:%M:%SZ') + return datetime.datetime.strftime(x, "%Y-%m-%dT%H:%M:%SZ") + now = datetime.datetime.now() time_min = now - datetime.timedelta(1) time_max = now + datetime.timedelta(95) @@ -96,74 +101,87 @@ class gcal_renderer(renderer.debuggable_abstaining_renderer): # Writes 2 files: # + "upcoming events", # + a countdown timer for a subser of events, - f = file_writer.file_writer('gcal_3_86400.html') - f.write('

Upcoming Calendar Events:


\n') - f.write('
\n') + f = file_writer.file_writer("gcal_3_86400.html") + f.write("

Upcoming Calendar Events:


\n") + f.write("
\n") - g = file_writer.file_writer('countdown_3_7200.html') - g.write('

Countdowns:


-\n""" % (event.timestamp(), event.friendly_name())) - f.write('
%s @@ -171,15 +189,17 @@ class gcal_renderer(renderer.debuggable_abstaining_renderer): %s
\n') +\n""" + % (event.timestamp(), event.friendly_name()) + ) + f.write("\n") f.close() self.countdown_events.sort() upcoming_countdown_events = self.countdown_events[:12] now = datetime.datetime.now() count = 0 - timestamps = { } + timestamps = {} for event in upcoming_countdown_events: eventstamp = event.start_time delta = eventstamp - now @@ -190,17 +210,23 @@ class gcal_renderer(renderer.debuggable_abstaining_renderer): days = divmod(x, constants.seconds_per_day) hours = divmod(days[1], constants.seconds_per_hour) minutes = divmod(hours[1], constants.seconds_per_minute) - g.write('
  • %d days, %02d:%02d until %s
  • \n' % (identifier, days[0], hours[0], minutes[0], name)) + g.write( + '
  • %d days, %02d:%02d until %s
  • \n' + % (identifier, days[0], hours[0], minutes[0], name) + ) timestamps[identifier] = time.mktime(eventstamp.timetuple()) count += 1 - self.debug_print("countdown to %s is %dd %dh %dm" % ( - name, days[0], hours[0], minutes[0])) - g.write('') - g.write('"""); +""" + ) g.close() return True except (gdata.service.RequestError, AccessTokenRefreshError): @@ -244,8 +271,8 @@ var fn = setInterval(function() { def look_for_triggered_events(self): f = file_writer.file_writer(constants.gcal_imminent_pagename) - f.write('

    Imminent Upcoming Calendar Events:

    \n
    \n') - f.write('
    \n') + f.write("

    Imminent Upcoming Calendar Events:

    \n
    \n") + f.write("
    \n") now = datetime.datetime.now() count = 0 for event in self.sortable_events: @@ -259,7 +286,10 @@ var fn = setInterval(function() { eventstamp = event.start_time name = event.friendly_name() calendar = event.calendar - f.write("
  • %s (%s) upcoming in %d minutes.\n" % (name, calendar, minutes[0])) + f.write( + "
  • %s (%s) upcoming in %d minutes.\n" + % (name, calendar, minutes[0]) + ) count += 1 f.write("
  • ") f.close() diff --git a/gcal_trigger.py b/gcal_trigger.py index 870020a..de19d1a 100644 --- a/gcal_trigger.py +++ b/gcal_trigger.py @@ -2,6 +2,7 @@ import constants import globals import trigger + class gcal_trigger(trigger.trigger): def get_triggered_page_list(self): if globals.get("gcal_triggered") == True: @@ -10,6 +11,7 @@ class gcal_trigger(trigger.trigger): else: return None -#globals.put('gcal_triggered', True) -#x = gcal_trigger() -#x.get_triggered_page_list() + +# globals.put('gcal_triggered', True) +# x = gcal_trigger() +# x.get_triggered_page_list() diff --git a/gdata_oauth.py b/gdata_oauth.py index f88b2f5..1f9cd67 100644 --- a/gdata_oauth.py +++ b/gdata_oauth.py @@ -5,10 +5,11 @@ import sys import urllib.request, urllib.parse, urllib.error + try: - import http.client # python2 + import http.client # python2 except ImportError: - import http.client # python3 + import http.client # python3 import os.path import json import time @@ -22,29 +23,30 @@ from googleapiclient.discovery import build import datetime import ssl + class OAuth: def __init__(self, client_id, client_secret): print("gdata: initializing oauth token...") self.client_id = client_id self.client_secret = client_secret self.user_code = None - #print 'Client id: %s' % (client_id) - #print 'Client secret: %s' % (client_secret) + # print 'Client id: %s' % (client_id) + # print 'Client secret: %s' % (client_secret) self.token = None self.device_code = None self.verfication_url = None - self.token_file = 'client_secrets.json' + self.token_file = "client_secrets.json" self.scope = [ #'https://www.googleapis.com/auth/calendar', #'https://www.googleapis.com/auth/drive', #'https://docs.google.com/feeds', #'https://www.googleapis.com/auth/calendar.readonly', #'https://picasaweb.google.com/data/', - 'https://www.googleapis.com/auth/photoslibrary.readonly', + "https://www.googleapis.com/auth/photoslibrary.readonly", #'http://picasaweb.google.com/data/', #'https://www.google.com/calendar/feeds/', ] - self.host = 'accounts.google.com' + self.host = "accounts.google.com" self.reset_connection() self.load_token() self.last_action = 0 @@ -54,7 +56,7 @@ class OAuth: # exception, after which we always get httplib.CannotSendRequest errors. # When this happens, we try re-creating the exception. def reset_connection(self): - self.ssl_ctx = ssl.create_default_context(cafile='/usr/local/etc/ssl/cert.pem') + self.ssl_ctx = ssl.create_default_context(cafile="/usr/local/etc/ssl/cert.pem") http.client.HTTPConnection.debuglevel = 2 self.conn = http.client.HTTPSConnection(self.host, context=self.ssl_ctx) @@ -67,7 +69,7 @@ class OAuth: f.close() def save_token(self): - f = open(self.token_file, 'w') + f = open(self.token_file, "w") f.write(json.dumps(self.token)) f.close() @@ -82,18 +84,18 @@ class OAuth: self.conn.request( "POST", "/o/oauth2/device/code", - urllib.parse.urlencode({ - 'client_id': self.client_id, - 'scope' : ' '.join(self.scope) - }), - {"Content-type": "application/x-www-form-urlencoded"}) + urllib.parse.urlencode( + {"client_id": self.client_id, "scope": " ".join(self.scope)} + ), + {"Content-type": "application/x-www-form-urlencoded"}, + ) response = self.conn.getresponse() if response.status == 200: data = json.loads(response.read()) - self.device_code = data['device_code'] - self.user_code = data['user_code'] - self.verification_url = data['verification_url'] - self.retry_interval = data['interval'] + self.device_code = data["device_code"] + self.user_code = data["user_code"] + self.verification_url = data["verification_url"] + self.retry_interval = data["interval"] else: print(("gdata: %d" % response.status)) print((response.read())) @@ -110,17 +112,20 @@ class OAuth: self.conn.request( "POST", "/o/oauth2/token", - urllib.parse.urlencode({ - 'client_id' : self.client_id, - 'client_secret' : self.client_secret, - 'code' : self.device_code, - 'grant_type' : 'http://oauth.net/grant_type/device/1.0' - }), - {"Content-type": "application/x-www-form-urlencoded"}) + urllib.parse.urlencode( + { + "client_id": self.client_id, + "client_secret": self.client_secret, + "code": self.device_code, + "grant_type": "http://oauth.net/grant_type/device/1.0", + } + ), + {"Content-type": "application/x-www-form-urlencoded"}, + ) response = self.conn.getresponse() if response.status == 200: data = json.loads(response.read()) - if 'access_token' in data: + if "access_token" in data: self.token = data self.save_token() else: @@ -135,29 +140,32 @@ class OAuth: print("gdata: not refreshing yet, too soon...") return False else: - print('gdata: trying to refresh oauth token...') + print("gdata: trying to refresh oauth token...") self.reset_connection() - refresh_token = self.token['refresh_token'] + refresh_token = self.token["refresh_token"] self.conn.request( "POST", "/o/oauth2/token", - urllib.parse.urlencode({ - 'client_id' : self.client_id, - 'client_secret' : self.client_secret, - 'refresh_token' : refresh_token, - 'grant_type' : 'refresh_token' - }), - {"Content-type": "application/x-www-form-urlencoded"}) + urllib.parse.urlencode( + { + "client_id": self.client_id, + "client_secret": self.client_secret, + "refresh_token": refresh_token, + "grant_type": "refresh_token", + } + ), + {"Content-type": "application/x-www-form-urlencoded"}, + ) response = self.conn.getresponse() self.last_action = time.time() if response.status == 200: data = json.loads(response.read()) - if 'access_token' in data: + if "access_token" in data: self.token = data # in fact we NEVER get a new refresh token at this point - if not 'refresh_token' in self.token: - self.token['refresh_token'] = refresh_token + if not "refresh_token" in self.token: + self.token["refresh_token"] = refresh_token self.save_token() return True print(("gdata: unexpected response %d to renewal request" % response.status)) @@ -171,35 +179,40 @@ class OAuth: # https://developers.google.com/picasa-web/ def photos_service(self): headers = { - "Authorization": "%s %s" % (self.token['token_type'], self.token['access_token']) + "Authorization": "%s %s" + % (self.token["token_type"], self.token["access_token"]) } client = gdata.photos.service.PhotosService(additional_headers=headers) return client # https://developers.google.com/drive/ def docs_service(self): - cred = OAuth2Credentials(self.token['access_token'], - self.client_id, - self.client_secret, - self.token['refresh_token'], - datetime.datetime.now(), - 'http://accounts.google.com/o/oauth2/token', - 'KitchenKiosk/0.9') + cred = OAuth2Credentials( + self.token["access_token"], + self.client_id, + self.client_secret, + self.token["refresh_token"], + datetime.datetime.now(), + "http://accounts.google.com/o/oauth2/token", + "KitchenKiosk/0.9", + ) http = httplib2.Http(disable_ssl_certificate_validation=True) http = cred.authorize(http) - service = build('drive', 'v2', http) + service = build("drive", "v2", http) return service # https://developers.google.com/google-apps/calendar/ def calendar_service(self): - cred = OAuth2Credentials(self.token['access_token'], - self.client_id, - self.client_secret, - self.token['refresh_token'], - datetime.datetime.now(), - 'http://accounts.google.com/o/oauth2/token', - 'KitchenKiosk/0.9') + cred = OAuth2Credentials( + self.token["access_token"], + self.client_id, + self.client_secret, + self.token["refresh_token"], + datetime.datetime.now(), + "http://accounts.google.com/o/oauth2/token", + "KitchenKiosk/0.9", + ) http = httplib2.Http(disable_ssl_certificate_validation=True) http = cred.authorize(http) - service = build('calendar', 'v3', http) + service = build("calendar", "v3", http) return service diff --git a/gdocs_renderer.py b/gdocs_renderer.py index d734a2d..44203e5 100644 --- a/gdocs_renderer.py +++ b/gdocs_renderer.py @@ -5,6 +5,7 @@ import sets import gdata_oauth import secrets + class gdocs_renderer(renderer.debuggable_abstaining_renderer): """A renderer to fetches and munge docs from drive.google.com""" @@ -25,13 +26,13 @@ class gdocs_renderer(renderer.debuggable_abstaining_renderer): try: param = {} if page_token: - param['pageToken'] = page_token - param['q'] = self.query - print("QUERY: %s" % param['q']) + param["pageToken"] = page_token + param["q"] = self.query + print("QUERY: %s" % param["q"]) files = self.client.files().list(**param).execute() - result.extend(files['items']) - page_token = files.get('nextPageToken') + result.extend(files["items"]) + page_token = files.get("nextPageToken") if not page_token: break except: @@ -47,11 +48,11 @@ class gdocs_renderer(renderer.debuggable_abstaining_renderer): return "font-size:%dpt" % (x) for f in result: - print(f['title']) - print(f['id']) - self.debug_print("%s (%s)\n" % (f['title'], f['id'])) - title = f['title'] - url = f['exportLinks']['text/html'] + print(f["title"]) + print(f["id"]) + self.debug_print("%s (%s)\n" % (f["title"], f["id"])) + title = f["title"] + url = f["exportLinks"]["text/html"] print(f) print("Fetching %s..." % url) resp, contents = self.client._http.request(url) @@ -59,18 +60,21 @@ class gdocs_renderer(renderer.debuggable_abstaining_renderer): print(contents) if resp.status == 200: print("Got contents.") - contents = re.sub('', '', contents) - contents = contents.replace('', '') - contents = re.sub('font-size:([0-9]+)pt', boost_font_size, contents) - f = file_writer.file_writer('%s_2_3600.html' % title) + contents = re.sub('', "", contents) + contents = contents.replace("", "") + contents = re.sub("font-size:([0-9]+)pt", boost_font_size, contents) + f = file_writer.file_writer("%s_2_3600.html" % title) now = datetime.datetime.now() - f.write(""" + f.write( + """

    %s


    %s -
    """ % (title, now, contents)) +""" + % (title, now, contents) + ) f.close() else: self.debug_print("error: %s" % resp) @@ -78,8 +82,8 @@ class gdocs_renderer(renderer.debuggable_abstaining_renderer): return True -#oauth = gdata_oauth.OAuth(secrets.google_client_id, +# oauth = gdata_oauth.OAuth(secrets.google_client_id, # secrets.google_client_secret) -#x = gdocs_renderer({"Testing", 12345}, +# x = gdocs_renderer({"Testing", 12345}, # oauth) -#x.periodic_render("Test") +# x.periodic_render("Test") diff --git a/generic_news_rss_renderer.py b/generic_news_rss_renderer.py index 698f7aa..3bc5f1b 100644 --- a/generic_news_rss_renderer.py +++ b/generic_news_rss_renderer.py @@ -10,10 +10,10 @@ import random import re import xml.etree.ElementTree as ET + class generic_news_rss_renderer(renderer.debuggable_abstaining_renderer): def __init__(self, name_to_timeout_dict, feed_site, feed_uris, page_title): - super(generic_news_rss_renderer, self).__init__(name_to_timeout_dict, - False) + super(generic_news_rss_renderer, self).__init__(name_to_timeout_dict, False) self.debug = 1 self.feed_site = feed_site self.feed_uris = feed_uris @@ -44,32 +44,32 @@ class generic_news_rss_renderer(renderer.debuggable_abstaining_renderer): return False def find_title(self, item): - return item.findtext('title') + return item.findtext("title") def munge_title(self, title): return title def find_description(self, item): - return item.findtext('description') + return item.findtext("description") def munge_description(self, description): - description = re.sub('<[^>]+>', '', description) + description = re.sub("<[^>]+>", "", description) return description def find_link(self, item): - return item.findtext('link') + return item.findtext("link") def munge_link(self, link): return link def find_image(self, item): - return item.findtext('image') + return item.findtext("image") def munge_image(self, image): return image def find_pubdate(self, item): - return item.findtext('pubDate') + return item.findtext("pubDate") def munge_pubdate(self, pubdate): return pubdate @@ -84,7 +84,7 @@ class generic_news_rss_renderer(renderer.debuggable_abstaining_renderer): tzinfo = pubdate.tzinfo now = datetime.datetime.now(tzinfo) delta = (now - pubdate).total_seconds() / (60 * 60 * 24) - if (delta > n): + if delta > n: return True return False @@ -97,7 +97,7 @@ class generic_news_rss_renderer(renderer.debuggable_abstaining_renderer): elif key == "Shuffle News": return self.shuffle_news() else: - raise error('Unexpected operation') + raise error("Unexpected operation") def shuffle_news(self): headlines = page_builder.page_builder() @@ -109,7 +109,8 @@ class generic_news_rss_renderer(renderer.debuggable_abstaining_renderer): return False for msg in subset: headlines.add_item(msg) - headlines.set_custom_html(""" + headlines.set_custom_html( + """ """) - f = file_writer.file_writer('%s_%s_25900.html' % ( - self.get_headlines_page_prefix(), - self.get_headlines_page_priority())) +""" + ) + f = file_writer.file_writer( + "%s_%s_25900.html" + % (self.get_headlines_page_prefix(), self.get_headlines_page_priority()) + ) headlines.render_html(f) f.close() details = page_builder.page_builder() details.set_layout(page_builder.page_builder.LAYOUT_ONE_ITEM) - details.set_custom_html(""" + details.set_custom_html( + """ """) +""" + ) details.set_title("%s" % self.page_title) subset = self.details.subset(1) if subset is None: - self.debug_print("Not enough details to choose from."); + self.debug_print("Not enough details to choose from.") return False for msg in subset: blurb = msg - blurb += u'' + blurb += u"" details.add_item(blurb) - g = file_writer.file_writer('%s_%s_86400.html' % ( - self.get_details_page_prefix(), - self.get_details_page_priority())) + g = file_writer.file_writer( + "%s_%s_86400.html" + % (self.get_details_page_prefix(), self.get_details_page_priority()) + ) details.render_html(g) g.close() return True @@ -185,9 +191,12 @@ a:active { "GET", uri, None, - { "Accept": "*/*", - "Cache-control": "max-age=59", - "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36"}) + { + "Accept": "*/*", + "Cache-control": "max-age=59", + "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36", + }, + ) try: response = self.conn.getresponse() except: @@ -195,8 +204,12 @@ a:active { return False if response.status != 200: - print(("%s: RSS fetch_news error, response: %d" % (self.page_title, - response.status))) + print( + ( + "%s: RSS fetch_news error, response: %d" + % (self.page_title, response.status) + ) + ) self.debug_print(response.read()) return False @@ -206,26 +219,26 @@ a:active { title = self.find_title(item) if title is not None: title = self.munge_title(title) - description = item.findtext('description') + description = item.findtext("description") if description is not None: description = self.munge_description(description) image = self.find_image(item) if image is not None: image = self.munge_image(image) - link = item.findtext('link') + link = item.findtext("link") if link is not None: link = self.munge_link(link) - if (title is None or - not self.item_is_interesting_for_headlines(title, - description, - item)): + if title is None or not self.item_is_interesting_for_headlines( + title, description, item + ): self.debug_print('Item "%s" is not interesting' % title) continue - if (self.should_profanity_filter() and - (self.filter.contains_bad_words(title) or - self.filter.contains_bad_words(description))): + if self.should_profanity_filter() and ( + self.filter.contains_bad_words(title) + or self.filter.contains_bad_words(description) + ): self.debug_print('Found bad words in item "%s"' % title) continue @@ -237,7 +250,7 @@ a:active { blurb += u'style="padding:8px;">' if link is None: - blurb += u'

    %s' % title + blurb += u"

    %s" % title else: blurb += u'

    %s' % (link, title) @@ -246,19 +259,18 @@ a:active { pubdate = self.munge_pubdate(pubdate) ts = parse(pubdate) blurb += u" %s" % ( - ts.strftime("%b %d")) + ts.strftime("%b %d") + ) - if (description is not None and - self.item_is_interesting_for_article(title, - description, - item)): + if description is not None and self.item_is_interesting_for_article( + title, description, item + ): longblurb = blurb longblurb += u"
    " longblurb += description longblurb += u"" - longblurb = longblurb.replace("font-size:34pt", - "font-size:44pt") + longblurb = longblurb.replace("font-size:34pt", "font-size:44pt") self.details.add(longblurb) blurb += u"" diff --git a/gkeep_renderer.py b/gkeep_renderer.py index de1116d..cba8596 100644 --- a/gkeep_renderer.py +++ b/gkeep_renderer.py @@ -8,40 +8,42 @@ import re import renderer import secrets + class gkeep_renderer(renderer.debuggable_abstaining_renderer): def __init__(self, name_to_timeout_dict): super(gkeep_renderer, self).__init__(name_to_timeout_dict, True) self.keep = gkeepapi.Keep() - success = self.keep.login(secrets.google_keep_username, - secrets.google_keep_password) + success = self.keep.login( + secrets.google_keep_username, secrets.google_keep_password + ) if success: self.debug_print("Connected with gkeep.") else: self.debug_print("Error connecting with gkeep.") self.colors_by_name = { - 'white' : '#002222', - 'green' : '#345920', - 'darkblue' : '#1F3A5F', - 'blue' : '#2D545E', - 'orange' : '#604A19', - 'red' : '#5C2B29', - 'purple' : '#42275E', - 'pink' : '#5B2245', - 'yellow' : '#635D19', - 'brown' : '#442F19', - 'gray' : '#3c3f4c', - 'teal' : '#16504B' + "white": "#002222", + "green": "#345920", + "darkblue": "#1F3A5F", + "blue": "#2D545E", + "orange": "#604A19", + "red": "#5C2B29", + "purple": "#42275E", + "pink": "#5B2245", + "yellow": "#635D19", + "brown": "#442F19", + "gray": "#3c3f4c", + "teal": "#16504B", } def debug_prefix(self): return "gkeep" def periodic_render(self, key): - strikethrough = re.compile('(\u2611[^\n]*)\n', re.UNICODE) - linkify = re.compile(r'.*(https?:\/\/\S+).*') + strikethrough = re.compile("(\u2611[^\n]*)\n", re.UNICODE) + linkify = re.compile(r".*(https?:\/\/\S+).*") self.keep.sync() - result_list = self.keep.find(labels=[self.keep.findLabel('kiosk')]) + result_list = self.keep.find(labels=[self.keep.findLabel("kiosk")]) for note in result_list: title = note.title title = title.replace(" ", "-") @@ -50,11 +52,12 @@ class gkeep_renderer(renderer.debuggable_abstaining_renderer): filename = "%s_2_3600.html" % title contents = note.text + "\n" self.debug_print("Note title '%s'" % title) - if contents != '' and not contents.isspace(): - contents = strikethrough.sub('', contents) + if contents != "" and not contents.isspace(): + contents = strikethrough.sub("", contents) self.debug_print("Note contents:\n%s" % contents) - contents = contents.replace(u'\u2610 ', - u'

  •  ') + contents = contents.replace( + u"\u2610 ", u'
  •  ' + ) contents = linkify.sub(r'\1', contents) individual_lines = contents.split("\n") @@ -65,10 +68,10 @@ class gkeep_renderer(renderer.debuggable_abstaining_renderer): length = len(x) if length > max_length: max_length = length - leading_spaces = len(x) - len(x.lstrip(' ')) + leading_spaces = len(x) - len(x.lstrip(" ")) leading_spaces /= 2 leading_spaces = int(leading_spaces) - x = x.lstrip(' ') + x = x.lstrip(" ") # self.debug_print(" * (%d) '%s'" % (leading_spaces, x)) for y in range(0, leading_spaces): x = "