owenrusk.dev

errands

small jobs the runtime does for the studio.

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

commit f6f3edbe66fe0e3571b80fd1a6f6595032dcc411
parent 70b7d0e9e4bdee176923ae740c32a3b88f648ae3
author Owen Rusk <owen@papermothgames.com>
date   2024-12-17 15:55:26 -0600
hosting: stillwater's balance from their account lookup
errands/hosting.py+18-0
errands/settings.py+4-0
tests/test_hosting.py+23-0
diff --git a/errands/hosting.py b/errands/hosting.py
new file mode 100644
index 0000000..2cdb5cc
--- /dev/null
+++ b/errands/hosting.py
@@ -0,0 +1,18 @@
+# stillwater, account 20417. the balance is on their public account lookup.
+import json
+import urllib.request
+
+from . import settings
+
+
+def url() -> str:
+    return f"{settings.STILLWATER}/api/accounts/{settings.STILLWATER_ACCOUNT}"
+
+
+def account(fetch=urllib.request.urlopen) -> dict:
+    with fetch(url(), timeout=30) as response:
+        return json.load(response)
+
+
+def balance(fetch=urllib.request.urlopen) -> float:
+    return float(account(fetch)["balance"].lstrip("$").replace(",", ""))
diff --git a/errands/settings.py b/errands/settings.py
index 802d2a1..f2c164f 100644
--- a/errands/settings.py
+++ b/errands/settings.py
@@ -13,6 +13,10 @@ def env(name: str, default: str | None = None) -> str:
 SUPPORT_ADDRESS = "support@papermothgames.com"
 SUPPORT_NAME = "Paper Moth Games"
 
+# stillwater
+STILLWATER = "https://stillwater-hosting.com"
+STILLWATER_ACCOUNT = "20417"
+
 # the site's checkout, and how it publishes
 SITE = Path(os.environ.get("ERRANDS_SITE", "/srv/papermoth-site"))
 SITE_PUBLISH = os.environ.get("ERRANDS_SITE_PUBLISH", "make publish")
diff --git a/tests/test_hosting.py b/tests/test_hosting.py
new file mode 100644
index 0000000..74ea2a8
--- /dev/null
+++ b/tests/test_hosting.py
@@ -0,0 +1,23 @@
+import io
+import json
+import unittest
+
+from errands import hosting
+
+LOOKUP = {"account": "20417", "balance": "$1,204.50", "history": []}
+
+
+def fake(payload, seen=None):
+    def fetch(request, timeout=None):
+        if seen is not None:
+            seen.append(request)
+        return io.BytesIO(json.dumps(payload).encode())
+
+    return fetch
+
+
+class BalanceTest(unittest.TestCase):
+    def test_reads_the_lookup(self):
+        seen = []
+        self.assertEqual(hosting.balance(fake(LOOKUP, seen)), 1204.5)
+        self.assertEqual(seen, ["https://stillwater-hosting.com/api/accounts/20417"])