owenrusk.dev

errands

small jobs the runtime does for the studio.

git clone https://owenrusk.dev/errands.git

commit ba320ecb39c81b07c9a26a897ec87d5706fd241c
parent aa5331b9ef5c4a770fdb2f55f9e7a42beaf638c7
author Owen Rusk <owen@papermothgames.com>
date   2026-08-11 12:15:40 -0500
invoices: more payees from the environment
deploy/errands.env.example+1-0
errands/invoices.py+1-1
errands/settings.py+3-0
tests/test_invoices.py+7-0
diff --git a/deploy/errands.env.example b/deploy/errands.env.example
index d04bdb2..6ad5720 100644
--- a/deploy/errands.env.example
+++ b/deploy/errands.env.example
@@ -4,6 +4,7 @@ ERRANDS_MAIL_USER=support@papermothgames.com
 ERRANDS_MAIL_PASSWORD=
 ERRANDS_VAULT_PASSPHRASE=
 ERRANDS_BANK_URL=
+ERRANDS_PAYEES=
 ERRANDS_SITE=/srv/papermoth-site
 ERRANDS_SITE_PUBLISH=make publish
 ERRANDS_STAGING_HOST=staging.lan
diff --git a/errands/invoices.py b/errands/invoices.py
index 1422e90..849c99e 100644
--- a/errands/invoices.py
+++ b/errands/invoices.py
@@ -29,7 +29,7 @@ class Invoice:
 
 
 def read(message: Message) -> Invoice | None:
-    payee = PAYEES.get(message.sender)
+    payee = {**PAYEES, **settings.PAYEES}.get(message.sender)
     found = AMOUNT.search(message.body)
     if payee is None or found is None:
         return None
diff --git a/errands/settings.py b/errands/settings.py
index 29b3b10..b556d0d 100644
--- a/errands/settings.py
+++ b/errands/settings.py
@@ -17,6 +17,9 @@ SUPPORT_NAME = "Paper Moth Games"
 STATE = Path(os.environ.get("ERRANDS_STATE", "/var/lib/errands"))
 LOGS = Path(os.environ.get("ERRANDS_LOGS", "/var/log/errands"))
 
+# bill senders besides the landlord, "address=Name;address=Name"
+PAYEES = dict(pair.split("=", 1) for pair in os.environ.get("ERRANDS_PAYEES", "").split(";") if pair)
+
 # the staging box at the office
 STAGING_HOST = os.environ.get("ERRANDS_STAGING_HOST", "staging.lan")
 STAGING_PATH = "/srv/errands"
diff --git a/tests/test_invoices.py b/tests/test_invoices.py
index f2f3633..bcd3ed0 100644
--- a/tests/test_invoices.py
+++ b/tests/test_invoices.py
@@ -21,6 +21,13 @@ class ReadTest(unittest.TestCase):
     def test_anyone_else_is_just_mail(self):
         self.assertIsNone(invoices.read(message(sender="someone@example.com")))
 
+    def test_payee_from_settings(self):
+        settings.PAYEES["bills@example.com"] = "Example Utilities"
+        try:
+            self.assertEqual(invoices.read(message(sender="bills@example.com", body="Amount due: $64.12")).payee, "Example Utilities")
+        finally:
+            del settings.PAYEES["bills@example.com"]
+
     def test_no_amount(self):
         self.assertIsNone(invoices.read(message(body="the heating is on from monday.\n")))