Bläddra i källkod

cache HTTP responses

raylu 1 månad sedan
förälder
incheckning
ccbd16fb8a
4 ändrade filer med 39 tillägg och 9 borttagningar
  1. 1 0
      .gitignore
  2. 33 0
      cache.py
  3. 1 0
      pyproject.toml
  4. 4 9
      supply.py

+ 1 - 0
.gitignore

@@ -1,2 +1,3 @@
+cache/
 config.toml
 uv.lock

+ 33 - 0
cache.py

@@ -0,0 +1,33 @@
+import lzma
+import pathlib
+import time
+import typing
+
+import cbor2
+import httpx
+import urllib.parse
+
+if typing.TYPE_CHECKING:
+	import httpx._types
+
+CACHE_DIR = pathlib.Path(__file__).parent / 'cache'
+client = httpx.Client()
+
+def get(url: str, *, headers: httpx._types.HeaderTypes|None=None) -> typing.Any:
+	parsed = urllib.parse.urlparse(url)
+	assert parsed.hostname is not None
+	cache_path = CACHE_DIR / parsed.hostname / (urllib.parse.quote(parsed.path.removeprefix('/'), safe='') + '.cbor.xz')
+
+	try:
+		if cache_path.stat().st_mtime > time.time() - 600: # less than 10 minutes old
+			with lzma.open(cache_path, 'rb') as f:
+				return cbor2.load(f)
+	except FileNotFoundError:
+		pass # fall through
+
+	r = client.get(url, headers=headers).raise_for_status()
+	cache_path.parent.mkdir(parents=True, exist_ok=True)
+	with lzma.open(cache_path, 'wb') as f:
+		data = r.json()
+		cbor2.dump(data, f)
+	return data

+ 1 - 0
pyproject.toml

@@ -3,5 +3,6 @@ name = 'pruncalc'
 version = '0'
 requires-python = '>=3.13'
 dependencies = [
+    'cbor2',
     'httpx',
 ]

+ 4 - 9
supply.py

@@ -4,7 +4,7 @@ import sys
 import tomllib
 import typing
 
-import httpx
+import cache
 
 def main() -> None:
 	planet = sys.argv[1].casefold()
@@ -66,11 +66,9 @@ def main() -> None:
 def fio_data(planet: str) -> tuple[PlanetData, typing.Sequence[Material]]:
 	with open('config.toml', 'rb') as f:
 		config = tomllib.load(f)
-	client = httpx.Client(headers={'Authorization': config['fio_api_key']})
 
-	r = client.get('https://rest.fnar.net/fioweb/burn/user/' + config['username'])
-	r.raise_for_status()
-	planets: list[PlanetData] = r.json()
+	planets: list[PlanetData] = cache.get('https://rest.fnar.net/fioweb/burn/user/' + config['username'],
+			headers={'Authorization': config['fio_api_key']})
 	for planet_data in planets:
 		name = planet_data['PlanetName']
 		if name.casefold() == planet:
@@ -79,10 +77,7 @@ def fio_data(planet: str) -> tuple[PlanetData, typing.Sequence[Material]]:
 	else:
 		raise ValueError(planet + ' not found')
 
-	r = client.get('https://rest.fnar.net/material/allmaterials')
-	materials: list[Material] = r.json()
-	r.raise_for_status()
-
+	materials: list[Material] = cache.get('https://rest.fnar.net/material/allmaterials')
 	return planet_data, materials
 
 class PlanetData(typing.TypedDict):