From 708c5d6f583c4653fd2041ac03f4b0962478eaaa Mon Sep 17 00:00:00 2001 From: Edward Betts Date: Sun, 14 Jul 2024 23:28:16 +0800 Subject: [PATCH 1/3] urllib3 now has types --- check.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/check.py b/check.py index 6b08255..ee0b3de 100755 --- a/check.py +++ b/check.py @@ -15,8 +15,8 @@ from email.utils import formatdate, make_msgid import requests import yaml from requests.adapters import HTTPAdapter -from urllib3.exceptions import InsecureRequestWarning # type: ignore -from urllib3.util.url import parse_url # type: ignore +from urllib3.exceptions import InsecureRequestWarning +from urllib3.util.url import parse_url class LiveConference(typing.TypedDict): From 87009c2247ab63d7f99c6b7b24c5c3524f290096 Mon Sep 17 00:00:00 2001 From: Edward Betts Date: Mon, 15 Jul 2024 00:55:18 +0800 Subject: [PATCH 2/3] Make mypy happy --- check.py | 1 + 1 file changed, 1 insertion(+) diff --git a/check.py b/check.py index ee0b3de..0e36410 100755 --- a/check.py +++ b/check.py @@ -36,6 +36,7 @@ class AbsoluteDNSAdapter(HTTPAdapter): # Append a dot to the hostname if it's not already there. hostname = parsed_url.host + assert hostname if not hostname.endswith("."): hostname += "." From 187214cfa1c76168f0f51580f714e8e9e2461d8b Mon Sep 17 00:00:00 2001 From: Edward Betts Date: Sun, 21 Jul 2024 10:53:22 +0900 Subject: [PATCH 3/3] Add Web UI to see when conference websites appeared Closes: #4 --- check.py | 28 ++-------------------- conference/__init__.py | 34 +++++++++++++++++++++++++++ templates/index.html | 53 ++++++++++++++++++++++++++++++++++++++++++ web_view.py | 25 ++++++++++++++++++++ 4 files changed, 114 insertions(+), 26 deletions(-) create mode 100644 conference/__init__.py create mode 100644 templates/index.html create mode 100755 web_view.py diff --git a/check.py b/check.py index 0e36410..ca78184 100755 --- a/check.py +++ b/check.py @@ -2,11 +2,9 @@ """Check if conference websites are live.""" -import configparser import os import re import smtplib -import typing import warnings from datetime import date from email.mime.text import MIMEText @@ -18,13 +16,7 @@ from requests.adapters import HTTPAdapter from urllib3.exceptions import InsecureRequestWarning from urllib3.util.url import parse_url - -class LiveConference(typing.TypedDict): - """Live conference.""" - - conference: str - year: int - live: date +from conference import LiveConference, config, load_yaml class AbsoluteDNSAdapter(HTTPAdapter): @@ -51,16 +43,6 @@ class AbsoluteDNSAdapter(HTTPAdapter): return super().send(request, **kwargs) -config_file_path = os.path.expanduser( - os.path.join( - os.getenv("XDG_CONFIG_HOME", "~/.config"), "conference-check", "config" - ) -) - -config = configparser.ConfigParser() -config.read(os.path.expanduser(config_file_path)) - - # Suppress only the single InsecureRequestWarning from urllib3 warnings.filterwarnings("ignore", category=InsecureRequestWarning) @@ -96,6 +78,7 @@ not_here_list = [ "Wikimedia Error", "The page you requested could not be found", "Ooops! Could Not Find It", + "OpenStreetMap Authentication Proxy", ] @@ -145,13 +128,6 @@ def send_mail(subject: str, body: str) -> None: s.quit() -def load_yaml(name: str) -> typing.Any: - """Load YAML.""" - filename = os.path.expanduser(config["data"][name]) - assert os.path.exists(filename) - return yaml.safe_load(open(filename)) - - def check_conference_web_site(name: str, src_url: str, year: int) -> bool: """Check if an individual web site is live.""" assert "{year}" in src_url diff --git a/conference/__init__.py b/conference/__init__.py new file mode 100644 index 0000000..6891012 --- /dev/null +++ b/conference/__init__.py @@ -0,0 +1,34 @@ +"""Conference classes and functions.""" + +import configparser +import os +import typing +from datetime import date + +import yaml + +config_file_path = os.path.expanduser( + os.path.join( + os.getenv("XDG_CONFIG_HOME", "~/.config"), "conference-check", "config" + ) +) +assert os.path.exists(config_file_path) + +config = configparser.ConfigParser() +config.read(os.path.expanduser(config_file_path)) + + +class LiveConference(typing.TypedDict, total=False): + """Live conference.""" + + conference: str + year: int + live: date + url: str | None + + +def load_yaml(name: str) -> typing.Any: + """Load YAML.""" + filename = os.path.expanduser(config["data"][name]) + assert os.path.exists(filename) + return yaml.safe_load(open(filename)) diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..bcba09c --- /dev/null +++ b/templates/index.html @@ -0,0 +1,53 @@ + + + + + Conference check + + + + + +

Conference check

+

Date when website went live.

+ + {% for l in live %} + + + + {% endfor %} +
+ {{ l.live.strftime("%a, %d %b %Y") }} + 🌍🎉 + + {{ l.conference }} {{ l.year }} +
+ + + diff --git a/web_view.py b/web_view.py new file mode 100755 index 0000000..9d0786b --- /dev/null +++ b/web_view.py @@ -0,0 +1,25 @@ +#!/usr/bin/python3 +"""When conference websites appeared.""" + +import flask + +from conference import LiveConference, load_yaml + +app = flask.Flask(__name__) +app.debug = False + + +@app.route("/") +async def index() -> str: + """Index page.""" + conferences = load_yaml("conferences") + live: list[LiveConference] = load_yaml("live") + + for c in live: + c["url"] = conferences[c["conference"]].format(year=c["year"]) + + return flask.render_template("index.html", live=live, conferences=conferences) + + +if __name__ == "__main__": + app.run(host="0.0.0.0")