X-Git-Url: https://wannabe.guru.org/gitweb/?a=blobdiff_plain;f=generic_news_rss_renderer.py;h=e73db4e7f983db3321432a06c74166236eb71149;hb=c06bfef53f70551e7920bc4facce27f47b89e2ba;hp=3bc5f1be147026b7cac5f95eddfc569951f6e506;hpb=6cc940e0df9b8ea937fb955f959fa878c80f0d7c;p=kiosk.git diff --git a/generic_news_rss_renderer.py b/generic_news_rss_renderer.py index 3bc5f1b..e73db4e 100644 --- a/generic_news_rss_renderer.py +++ b/generic_news_rss_renderer.py @@ -1,20 +1,31 @@ +#!/usr/bin/env python3 + +from abc import abstractmethod import datetime from dateutil.parser import parse +import http.client +import random +import re +from typing import Dict, List +import xml.etree.ElementTree as ET + import file_writer import grab_bag import renderer -import http.client import page_builder import profanity_filter -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): + def __init__( + self, + name_to_timeout_dict: Dict[str, int], + feed_site: str, + feed_uris: List[str], + page_title: str, + ): super(generic_news_rss_renderer, self).__init__(name_to_timeout_dict, False) - self.debug = 1 + self.debug = True self.feed_site = feed_site self.feed_uris = feed_uris self.page_title = page_title @@ -22,76 +33,83 @@ class generic_news_rss_renderer(renderer.debuggable_abstaining_renderer): self.details = grab_bag.grab_bag() self.filter = profanity_filter.profanity_filter() - def debug_prefix(self): + @abstractmethod + def debug_prefix(self) -> str: pass - def get_headlines_page_prefix(self): + @abstractmethod + def get_headlines_page_prefix(self) -> str: pass - def get_details_page_prefix(self): + @abstractmethod + def get_details_page_prefix(self) -> str: pass - def get_headlines_page_priority(self): + def get_headlines_page_priority(self) -> str: return "4" - def get_details_page_priority(self): + def get_details_page_priority(self) -> str: return "6" - def should_use_https(self): + @abstractmethod + def should_use_https(self) -> bool: pass - def should_profanity_filter(self): + def should_profanity_filter(self) -> bool: return False - def find_title(self, item): + def find_title(self, item: ET.Element) -> str: return item.findtext("title") - def munge_title(self, title): + def munge_title(self, title: str) -> str: return title - def find_description(self, item): + def find_description(self, item: ET.Element) -> str: return item.findtext("description") - def munge_description(self, description): + def munge_description(self, description: str) -> str: description = re.sub("<[^>]+>", "", description) return description - def find_link(self, item): + def find_link(self, item: ET.Element) -> str: return item.findtext("link") - def munge_link(self, link): + def munge_link(self, link: str) -> str: return link - def find_image(self, item): + def find_image(self, item: ET.Element) -> str: return item.findtext("image") - def munge_image(self, image): + def munge_image(self, image: str) -> str: return image - def find_pubdate(self, item): + def find_pubdate(self, item: ET.Element) -> str: return item.findtext("pubDate") - def munge_pubdate(self, pubdate): + def munge_pubdate(self, pubdate: str) -> str: return pubdate - def item_is_interesting_for_headlines(self, title, description, item): + def item_is_interesting_for_headlines( + self, title: str, description: str, item: ET.Element + ) -> bool: return True - def is_item_older_than_n_days(self, item, n): + def is_item_older_than_n_days(self, item: ET.Element, n: int) -> bool: pubdate = self.find_pubdate(item) - if pubdate is not None: - pubdate = parse(pubdate) - tzinfo = pubdate.tzinfo - now = datetime.datetime.now(tzinfo) - delta = (now - pubdate).total_seconds() / (60 * 60 * 24) - if delta > n: - return True - return False - - def item_is_interesting_for_article(self, title, description, item): + if pubdate is None: + return False + pubdate = parse(pubdate) + tzinfo = pubdate.tzinfo + now = datetime.datetime.now(tzinfo) + delta = (now - pubdate).total_seconds() / (60 * 60 * 24) + return delta > n + + def item_is_interesting_for_article( + self, title: str, description: str, item: ET.Element + ) -> bool: return True - def periodic_render(self, key): + def periodic_render(self, key: str) -> bool: if key == "Fetch News": return self.fetch_news() elif key == "Shuffle News": @@ -99,7 +117,7 @@ class generic_news_rss_renderer(renderer.debuggable_abstaining_renderer): else: raise error("Unexpected operation") - def shuffle_news(self): + def shuffle_news(self) -> bool: headlines = page_builder.page_builder() headlines.set_layout(page_builder.page_builder.LAYOUT_FOUR_ITEMS) headlines.set_title("%s" % self.page_title) @@ -129,12 +147,9 @@ a:active { } """ ) - 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() + _ = f"{self.get_headlines_page_prefix()}_{self.get_headlines_page_priority()}_25900.html" + with file_writer.file_writer(_) as f: + headlines.render_html(f) details = page_builder.page_builder() details.set_layout(page_builder.page_builder.LAYOUT_ONE_ITEM) @@ -158,24 +173,21 @@ a:active { } """ ) - details.set_title("%s" % self.page_title) + details.set_title(f"{self.page_title}") subset = self.details.subset(1) if subset is None: self.debug_print("Not enough details to choose from.") return False for msg in subset: blurb = msg - blurb += u"" + blurb += "" details.add_item(blurb) - 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() + _ = f"{self.get_details_page_prefix()}_{self.get_details_page_priority()}_86400.html" + with file_writer.file_writer(_) as g: + details.render_html(g) return True - def fetch_news(self): + def fetch_news(self) -> bool: count = 0 self.news.clear() self.details.clear() @@ -205,10 +217,7 @@ a:active { if response.status != 200: print( - ( - "%s: RSS fetch_news error, response: %d" - % (self.page_title, response.status) - ) + f"{self.page_title}: RSS fetch_news error, response: {response.status}" ) self.debug_print(response.read()) return False @@ -232,48 +241,44 @@ a:active { if title is None or not self.item_is_interesting_for_headlines( title, description, item ): - self.debug_print('Item "%s" is not interesting' % title) + self.debug_print(f'Item "{title}" is not interesting') continue 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) + self.debug_print(f'Found bad words in item "{title}"') continue - blurb = u"""
""" if image is not None: - blurb += u'' + blurb += f'%s" % title + blurb += f"

{title}" else: - blurb += u'

%s' % (link, title) + blurb += f'

{title}' pubdate = self.find_pubdate(item) if pubdate is not None: pubdate = self.munge_pubdate(pubdate) ts = parse(pubdate) - blurb += u" %s" % ( - ts.strftime("%b %d") - ) + blurb += f' {ts.strftime("%b %d")}' if description is not None and self.item_is_interesting_for_article( title, description, item ): longblurb = blurb - - longblurb += u"
" + longblurb += "
" longblurb += description - longblurb += u"

" + longblurb += "" longblurb = longblurb.replace("font-size:34pt", "font-size:44pt") self.details.add(longblurb) - - blurb += u"" + blurb += "" self.news.add(blurb) count += 1 return count > 0