aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xcode_check.sh2
-rw-r--r--cycles.json177
-rwxr-xr-xsendmail-test.py253
-rw-r--r--[-rwxr-xr-x]sjdbmk/daily.py (renamed from daily.py)0
-rw-r--r--[-rwxr-xr-x]sjdbmk/grant.py (renamed from grant.py)0
-rw-r--r--[-rwxr-xr-x]sjdbmk/inspire_approve.py (renamed from inspire_approve.py)0
-rw-r--r--[-rwxr-xr-x]sjdbmk/inspire_dl.py (renamed from inspire_dl.py)0
-rw-r--r--[-rwxr-xr-x]sjdbmk/legacy_wikipedia.py (renamed from legacy_wikipedia.py)0
-rw-r--r--sjdbmk/menuparser.py (renamed from menuparser.py)5
-rw-r--r--[-rwxr-xr-x]sjdbmk/msal_skeleton.py (renamed from msal_skeleton.py)0
-rw-r--r--[-rwxr-xr-x]sjdbmk/pack.py (renamed from pack.py)0
-rw-r--r--[-rwxr-xr-x]sjdbmk/sendmail.py (renamed from sendmail.py)17
-rw-r--r--sjdbmk/sendmail2.py (renamed from sendmail2.py)0
-rw-r--r--[-rwxr-xr-x]sjdbmk/serve.py (renamed from serve.py)0
-rw-r--r--[-rwxr-xr-x]sjdbmk/weekly.py (renamed from weekly.py)19
15 files changed, 19 insertions, 454 deletions
diff --git a/code_check.sh b/code_check.sh
index 750288e..aeb87b5 100755
--- a/code_check.sh
+++ b/code_check.sh
@@ -1,3 +1,3 @@
#!/bin/sh
mypy --strict .
-pylint --disable C0301,W0511,C0114,C0115,C0116,R0913,R0914,C0209,W1201,E1205,R0915,R1728,W0613,C0200,R0912,R1702,E1101,W0621,R1718,R0801,W3101,W1514 *.py
+pylint --disable C0301,W0511,C0114,C0115,C0116,R0913,R0914,C0209,W1201,E1205,R0915,R1728,W0613,C0200,R0912,R1702,E1101,W0621,R1718,R0801,W3101,W1514,C0206 *.py
diff --git a/cycles.json b/cycles.json
deleted file mode 100644
index 59c9e64..0000000
--- a/cycles.json
+++ /dev/null
@@ -1,177 +0,0 @@
-{
- "comment": "This should be replaced by the Outlook Shared Calendar interpretation script later, but should suffice for now.",
- "2023-09-04": "A",
- "2023-09-05": "B",
- "2023-09-06": "C",
- "2023-09-07": "D",
- "2023-09-08": "E",
- "2023-09-11": "F",
- "2023-09-12": "A",
- "2023-09-13": "B",
- "2023-09-14": "C",
- "2023-09-15": "D",
- "2023-09-18": "E",
- "2023-09-19": "F",
- "2023-09-20": "A",
- "2023-09-21": "B",
- "2023-09-22": "C",
- "2023-09-25": "D",
- "2023-09-26": "E",
- "2023-09-27": "F",
- "2023-09-28": "A",
- "2023-10-09": "B",
- "2023-10-10": "C",
- "2023-10-11": "D",
- "2023-10-12": "E",
- "2023-10-13": "F",
- "2023-10-16": "A",
- "2023-10-17": "B",
- "2023-10-18": "C",
- "2023-10-19": "D",
- "2023-10-20": "E",
- "2023-10-23": "F",
- "2023-10-24": "A",
- "2023-10-25": "B",
- "2023-10-26": "C",
- "2023-10-30": "D",
- "2023-10-31": "E",
- "2023-11-01": "F",
- "2023-11-02": "A",
- "2023-11-03": "B",
- "2023-11-06": "C",
- "2023-11-07": "D",
- "2023-11-08": "E",
- "2023-11-09": "F",
- "2023-11-10": "A",
- "2023-11-13": "B",
- "2023-11-14": "C",
- "2023-11-15": "D",
- "2023-11-20": "E",
- "2023-11-21": "F",
- "2023-11-22": "A",
- "2023-11-23": "B",
- "2023-11-24": "C",
- "2023-11-27": "D",
- "2023-11-28": "E",
- "2023-11-29": "F",
- "2023-11-30": "A",
- "2023-12-04": "B",
- "2023-12-05": "C",
- "2023-12-06": "D",
- "2023-12-07": "E",
- "2023-12-08": "F",
- "2023-12-11": "A",
- "2023-12-12": "B",
- "2023-12-13": "C",
- "2023-12-14": "D",
- "2023-12-15": "E",
- "2023-12-18": "F",
- "2023-12-19": "A",
- "2023-12-20": "B",
- "2023-12-21": "C",
- "2024-01-08": "D",
- "2024-01-09": "E",
- "2024-01-10": "F",
- "2024-01-11": "A",
- "2024-01-12": "B",
- "2024-01-15": "C",
- "2024-01-16": "D",
- "2024-01-17": "E",
- "2024-01-18": "F",
- "2024-01-19": "A",
- "2024-01-22": "B",
- "2024-01-23": "C",
- "2024-01-24": "D",
- "2024-01-25": "E",
- "2024-01-26": "F",
- "2024-01-29": "A",
- "2024-01-30": "B",
- "2024-01-31": "C",
- "2024-02-01": "D",
- "2024-02-19": "E",
- "2024-02-20": "F",
- "2024-02-21": "A",
- "2024-02-22": "B",
- "2024-02-23": "C",
- "2024-02-26": "D",
- "2024-02-27": "E",
- "2024-02-28": "F",
- "2024-02-29": "A",
- "2024-03-01": "B",
- "2024-03-04": "C",
- "2024-03-05": "D",
- "2024-03-06": "E",
- "2024-03-07": "F",
- "2024-03-08": "A",
- "2024-03-11": "B",
- "2024-03-12": "C",
- "2024-03-13": "D",
- "2024-03-14": "E",
- "2024-03-15": "F",
- "2024-03-18": "A",
- "2024-03-19": "B",
- "2024-03-20": "C",
- "2024-03-21": "D",
- "2024-03-22": "E",
- "2024-03-25": "F",
- "2024-03-26": "A",
- "2024-03-27": "B",
- "2024-03-28": "C",
- "2024-03-29": "D",
- "2024-04-09": "E",
- "2024-04-10": "F",
- "2024-04-11": "A",
- "2024-04-12": "B",
- "2024-04-15": "C",
- "2024-04-16": "D",
- "2024-04-17": "E",
- "2024-04-18": "F",
- "2024-04-19": "A",
- "2024-04-22": "B",
- "2024-04-23": "C",
- "2024-04-24": "D",
- "2024-04-25": "E",
- "2024-04-26": "F",
- "2024-04-29": "A",
- "2024-04-30": "B",
- "2024-05-02": "C",
- "2024-05-03": "D",
- "2024-05-06": "E",
- "2024-05-07": "F",
- "2024-05-08": "A",
- "2024-05-09": "B",
- "2024-05-10": "C",
- "2024-05-13": "D",
- "2024-05-14": "E",
- "2024-05-15": "F",
- "2024-05-16": "A",
- "2024-05-17": "B",
- "2024-05-20": "C",
- "2024-05-21": "D",
- "2024-05-22": "E",
- "2024-05-23": "F",
- "2024-05-24": "A",
- "2024-05-27": "B",
- "2024-05-28": "C",
- "2024-05-29": "D",
- "2024-05-30": "E",
- "2024-05-31": "F",
- "2024-06-03": "A",
- "2024-06-04": "B",
- "2024-06-05": "C",
- "2024-06-06": "D",
- "2024-06-07": "E",
- "2024-06-11": "F",
- "2024-06-12": "A",
- "2024-06-13": "B",
- "2024-06-14": "C",
- "2024-06-17": "D",
- "2024-06-18": "E",
- "2024-06-19": "F",
- "2024-06-20": "A",
- "2024-06-21": "B",
- "2024-06-24": "C",
- "2024-06-25": "D",
- "2024-06-26": "E",
- "2024-06-27": "F"
-}
diff --git a/sendmail-test.py b/sendmail-test.py
deleted file mode 100755
index 7d366fb..0000000
--- a/sendmail-test.py
+++ /dev/null
@@ -1,253 +0,0 @@
-#!/usr/bin/env python3
-#
-# Send the Daily Bulletin the next morning
-# Copyright (C) 2024 Runxi Yu <https://runxiyu.org>
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see <https://www.gnu.org/licenses/>.
-#
-
-from __future__ import annotations
-from configparser import ConfigParser
-from typing import Optional
-from pprint import pprint
-import datetime
-import zoneinfo
-import argparse
-import os
-
-import requests
-import msal # type: ignore
-
-
-def acquire_token(app: msal.PublicClientApplication, config: ConfigParser) -> str:
- result = app.acquire_token_by_username_password(
- config["credentials"]["username"],
- config["credentials"]["password"],
- scopes=config["credentials"]["scope"].split(" "),
- )
-
- if "access_token" in result:
- assert isinstance(result["access_token"], str)
- return result["access_token"]
- raise ValueError("Authentication error in password login")
-
-
-def sendmail(
- token: str,
- subject: str,
- body: str,
- to: list[str],
- bcc: list[str],
- cc: list[str],
- when: Optional[datetime.datetime] = None,
- content_type: str = "HTML",
- importance: str = "Normal",
- reply_to: Optional[str] = None,
-) -> str:
- data = {
- "subject": subject,
- "importance": importance,
- "body": {"contentType": content_type, "content": body},
- "toRecipients": [{"emailAddress": {"address": a}} for a in to],
- "ccRecipients": [{"emailAddress": {"address": a}} for a in cc],
- "bccRecipients": [{"emailAddress": {"address": a}} for a in bcc],
- }
-
- if when is not None:
- if when.tzinfo is None:
- raise TypeError("Naive datetimes are no longer supported")
- utcwhen = when.astimezone(datetime.timezone.utc)
- isoval = utcwhen.isoformat(timespec="seconds").replace("+00:00", "Z")
- data["singleValueExtendedProperties"] = [
- {"id": "SystemTime 0x3FEF", "value": isoval}
- ]
-
- if not reply_to:
- response = requests.post(
- "https://graph.microsoft.com/v1.0/me/messages",
- json=data,
- headers={
- "Authorization": "Bearer %s" % token,
- "Prefer": 'IdType="ImmutableId"',
- },
- timeout=20,
- ).json()
- else:
- response = requests.post(
- "https://graph.microsoft.com/v1.0/me/messages/%s/createReply" % reply_to,
- json=data,
- headers={
- "Authorization": "Bearer %s" % token,
- "Prefer": 'IdType="ImmutableId"',
- },
- timeout=20,
- ).json()
-
- try:
- msgid = response["id"]
- except KeyError:
- pprint(response)
- raise ValueError("Unable to add email to drafts")
-
- assert isinstance(msgid, str)
-
- response2 = requests.post(
- "https://graph.microsoft.com/v1.0/me/messages/%s/send" % msgid,
- headers={"Authorization": "Bearer " + token},
- timeout=20,
- )
-
- if response2.status_code != 202:
- pprint(response2.content.decode("utf-8", "replace"))
- raise ValueError(
- "Graph response to messages/%s/send returned something other than 202 Accepted"
- % response["id"],
- )
-
- return msgid
-
-
-def main() -> None:
- parser = argparse.ArgumentParser(description="Daily Bulletin Sender")
- parser.add_argument(
- "-d",
- "--date",
- default=None,
- help="the date of the bulletin to send, in local time, in YYYY-MM-DD; defaults to tomorrow",
- )
- parser.add_argument(
- "-r",
- "--reply",
- action="store_true",
- help="Reply to the previous bulletin when sending (BROKEN)",
- )
- parser.add_argument(
- "--config", default="config.ini", help="path to the configuration file"
- )
- args = parser.parse_args()
- config = ConfigParser()
- config.read(args.config)
- if args.date:
- date = datetime.datetime.strptime(args.date, "%Y-%m-%d").replace(
- tzinfo=zoneinfo.ZoneInfo(config["general"]["timezone"])
- )
- else:
- date = datetime.datetime.now(
- zoneinfo.ZoneInfo(config["general"]["timezone"])
- ) + datetime.timedelta(days=1)
-
- os.chdir(config["general"]["build_path"])
-
- html_filename = "sjdb-%s.html" % date.strftime("%Y%m%d")
- with open(html_filename, "r", encoding="utf-8") as html_fd:
- html = html_fd.read()
-
- app = msal.PublicClientApplication(
- config["credentials"]["client_id"],
- authority=config["credentials"]["authority"],
- )
- token = acquire_token(app, config)
-
- if not args.reply:
- a = sendmail(
- token,
- subject=config["sendmail"]["subject_format"]
- % date.strftime(config["sendmail"]["subject_date_format"]),
- body=html,
- to=config["sendmail"]["to_1"].split(" "),
- cc=[],
- bcc=["s22537@ykpaoschool.cn"],
- when=date.replace(
- hour=17,
- minute=20,
- second=0,
- microsecond=0,
- ),
- content_type="HTML",
- importance="Normal",
- )
- assert a
- with open("last-a.txt", "w") as fd:
- fd.write(a)
- b = sendmail(
- token,
- subject=config["sendmail"]["subject_format"]
- % date.strftime(config["sendmail"]["subject_date_format"]),
- body=html,
- to=config["sendmail"]["to_2"].split(" "),
- cc=[],
- bcc=["s22537@ykpaoschool.cn"],
- when=date.replace(
- hour=17,
- minute=20,
- second=0,
- microsecond=0,
- ),
- content_type="HTML",
- importance="Normal",
- )
- assert b
- with open("last-b.txt", "w") as fd:
- fd.write(b)
- else:
- with open("last-a.txt", "r") as fd:
- last_a = fd.read().strip()
- a = sendmail(
- token,
- subject=config["sendmail"]["subject_format"]
- % date.strftime(config["sendmail"]["subject_date_format"]),
- body=html,
- to=config["sendmail"]["to_1"].split(" "),
- cc=[],
- bcc=["s22537@ykpaoschool.cn"],
- when=date.replace(
- hour=17,
- minute=20,
- second=0,
- microsecond=0,
- ),
- content_type="HTML",
- importance="Normal",
- reply_to=last_a,
- )
- assert a
- with open("last-a.txt", "w") as fd:
- fd.write(a)
- with open("last-b.txt", "r") as fd:
- last_b = fd.read().strip()
- b = sendmail(
- token,
- subject=config["sendmail"]["subject_format"]
- % date.strftime(config["sendmail"]["subject_date_format"]),
- body=html,
- to=config["sendmail"]["to_2"].split(" "),
- cc=[],
- bcc=["s22537@ykpaoschool.cn"],
- when=date.replace(
- hour=17,
- minute=20,
- second=0,
- microsecond=0,
- ),
- content_type="HTML",
- importance="Normal",
- reply_to=last_b,
- )
- assert b
- with open("last-b.txt", "w") as fd:
- fd.write(b)
-
-
-if __name__ == "__main__":
- main()
diff --git a/daily.py b/sjdbmk/daily.py
index ce21bce..ce21bce 100755..100644
--- a/daily.py
+++ b/sjdbmk/daily.py
diff --git a/grant.py b/sjdbmk/grant.py
index d55d9d6..d55d9d6 100755..100644
--- a/grant.py
+++ b/sjdbmk/grant.py
diff --git a/inspire_approve.py b/sjdbmk/inspire_approve.py
index 98d202c..98d202c 100755..100644
--- a/inspire_approve.py
+++ b/sjdbmk/inspire_approve.py
diff --git a/inspire_dl.py b/sjdbmk/inspire_dl.py
index 631ea44..631ea44 100755..100644
--- a/inspire_dl.py
+++ b/sjdbmk/inspire_dl.py
diff --git a/legacy_wikipedia.py b/sjdbmk/legacy_wikipedia.py
index c2f60a1..c2f60a1 100755..100644
--- a/legacy_wikipedia.py
+++ b/sjdbmk/legacy_wikipedia.py
diff --git a/menuparser.py b/sjdbmk/menuparser.py
index 71b7f6f..7413ff0 100644
--- a/menuparser.py
+++ b/sjdbmk/menuparser.py
@@ -17,10 +17,11 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
-import openpyxl
from typing import Optional, Any
+import openpyxl
+
def menu_item_fix(s: str) -> Optional[str]:
if not s:
@@ -88,7 +89,7 @@ def parse_menus(filename: str) -> dict[str, dict[str, dict[str, list[str]]]]:
row = rows[i]
if not isinstance(row[1].value, str):
continue
- elif "BREAKFAST" in row[1].value:
+ if "BREAKFAST" in row[1].value:
final["Breakfast"] = parse_meal_table(
rows,
i,
diff --git a/msal_skeleton.py b/sjdbmk/msal_skeleton.py
index 3261341..3261341 100755..100644
--- a/msal_skeleton.py
+++ b/sjdbmk/msal_skeleton.py
diff --git a/pack.py b/sjdbmk/pack.py
index 902e256..902e256 100755..100644
--- a/pack.py
+++ b/sjdbmk/pack.py
diff --git a/sendmail.py b/sjdbmk/sendmail.py
index c118c77..ddd6f32 100755..100644
--- a/sendmail.py
+++ b/sjdbmk/sendmail.py
@@ -30,6 +30,11 @@ import requests
import msal # type: ignore
+def open_and_readlines(filename: str) -> list[str]:
+ with open(filename, "r") as fd:
+ return fd.readlines()
+
+
def acquire_token(app: msal.PublicClientApplication, config: ConfigParser) -> str:
result = app.acquire_token_by_username_password(
config["credentials"]["username"],
@@ -96,9 +101,9 @@ def sendmail(
try:
msgid = response["id"]
- except KeyError:
+ except KeyError as exc:
pprint(response)
- raise ValueError("Unable to add email to drafts")
+ raise ValueError("Unable to add email to drafts") from exc
assert isinstance(msgid, str)
@@ -169,7 +174,7 @@ def main() -> None:
cc=config["sendmail"]["cc_1"].split(" "),
bcc=[
w.strip()
- for w in open(config["sendmail"]["bcc_1_file"], "r").readlines()
+ for w in open_and_readlines(config["sendmail"]["bcc_1_file"])
if w.strip()
],
when=date.replace(
@@ -193,7 +198,7 @@ def main() -> None:
cc=config["sendmail"]["cc_2"].split(" "),
bcc=[
w.strip()
- for w in open(config["sendmail"]["bcc_2_file"], "r").readlines()
+ for w in open_and_readlines(config["sendmail"]["bcc_2_file"])
if w.strip()
],
when=date.replace(
@@ -220,7 +225,7 @@ def main() -> None:
cc=config["sendmail"]["cc_1"].split(" "),
bcc=[
w.strip()
- for w in open(config["sendmail"]["bcc_1_file"], "r").readlines()
+ for w in open_and_readlines(config["sendmail"]["bcc_1_file"])
if w.strip()
],
when=date.replace(
@@ -247,7 +252,7 @@ def main() -> None:
cc=config["sendmail"]["cc_2"].split(" "),
bcc=[
w.strip()
- for w in open(config["sendmail"]["bcc_2_file"], "r").readlines()
+ for w in open_and_readlines(config["sendmail"]["bcc_2_file"])
if w.strip()
],
when=date.replace(
diff --git a/sendmail2.py b/sjdbmk/sendmail2.py
index 6cfda8c..6cfda8c 100644
--- a/sendmail2.py
+++ b/sjdbmk/sendmail2.py
diff --git a/serve.py b/sjdbmk/serve.py
index 492e443..492e443 100755..100644
--- a/serve.py
+++ b/sjdbmk/serve.py
diff --git a/weekly.py b/sjdbmk/weekly.py
index 3923aa8..9c0a0c9 100755..100644
--- a/weekly.py
+++ b/sjdbmk/weekly.py
@@ -55,18 +55,6 @@ import menuparser
logger = logging.getLogger(__name__)
-class MealTableShapeError(ValueError):
- pass
-
-
-def zero_list(lt: list[Any]) -> list[Any]:
- return [(zero_list(i) if (isinstance(i, list)) else "") for i in lt]
-
-
-def equal_shapes(a: list[Any], b: list[Any]) -> bool:
- return zero_list(a) == zero_list(b)
-
-
def generate(
datetime_target: datetime.datetime, # expected to be local time
the_week_ahead_url: str,
@@ -130,7 +118,7 @@ def generate(
logger.info("The Week Ahead already exists at %s" % the_week_ahead_filename)
menu_filename = "menu-%s.xlsx" % datetime_target.strftime("%Y%m%d")
- if not (os.path.isfile(menu_filename)):
+ if not os.path.isfile(menu_filename):
logger.info("Menu not found, downloading")
download_menu(
token,
@@ -489,8 +477,8 @@ def download_menu(
matched_groups[0], "%b" # issues here are probably locales
).month
subject_1st_day = int(matched_groups[1])
- except ValueError:
- raise ValueError(hit["resource"]["subject"], matched_groups[0])
+ except ValueError as exc:
+ raise ValueError(hit["resource"]["subject"], matched_groups[0]) from exc
if (
subject_1st_month == datetime_target.month
and subject_1st_day == datetime_target.day
@@ -519,6 +507,7 @@ def download_menu(
with open(menu_filename, "wb") as w:
w.write(pb)
+ break
else:
raise ValueError("No proper attachment found in email")