diff --git a/blueprints/risdeveau/__init__.py b/blueprints/risdeveau/__init__.py index 2ae076c..2933e0d 100644 --- a/blueprints/risdeveau/__init__.py +++ b/blueprints/risdeveau/__init__.py @@ -4,9 +4,12 @@ from pathlib import Path from htmlmin import minify from time import time from datetime import datetime, timedelta +from hashlib import md5 +from json import dumps from musicbrainzngs import get_image_front from flask import ( Blueprint, + request, render_template, send_file, send_from_directory, @@ -40,6 +43,12 @@ def utmsmp(unix: int) -> str: def rtmsmp(unix: int) -> str: return tmsmp(int(time() - unix)) +def lb_etag(): + return md5((dumps(listens.get('data')) + dumps(listening.get('data'))).encode()).hexdigest() + +def steam_etag(): + return md5((dumps(recent.get('data')) + dumps(owned.get('data'))).encode()).hexdigest() + bp = Blueprint( "risdeveau", __name__, @@ -73,6 +82,8 @@ def mb_cover(mbid): return r args = { + "lb_etag": lb_etag, + "steam_etag": steam_etag, "lb": listens, "lb_now": listening, "recent": recent, @@ -88,4 +99,22 @@ def index(): @bp.route("/m/") def module(module): + if modified_since := request.headers.get('if-modified-since'): + modified_since = int(modified_since) + none_match = request.headers.get('if-none-match') + + if any((modified_since, none_match)): + match module: + case "listenbrainz": + if modified_since >= int(max((x.get('last_updated', 0) for x in (listens, listening)))): + return '', 304 + if none_match == lb_etag(): + return '', 304 + + case "steam": + if modified_since >= int(max((x.get('last_updated', 0) for x in (recent, owned)))): + return "Not updated yet", 304 + if none_match == steam_etag(): + return '', 304 + return render_tmpl(f'{module}.htm', **args) diff --git a/blueprints/risdeveau/modules/api/lb.py b/blueprints/risdeveau/modules/api/lb.py index 02fc8f9..8f5dc7a 100644 --- a/blueprints/risdeveau/modules/api/lb.py +++ b/blueprints/risdeveau/modules/api/lb.py @@ -2,7 +2,7 @@ from flask import Flask, jsonify from apscheduler.schedulers.background import BackgroundScheduler from apscheduler.triggers.interval import IntervalTrigger import requests -from datetime import datetime +from time import time import atexit import re from urllib.parse import urlparse, parse_qs @@ -63,7 +63,7 @@ def api_request(url: str, cache): if response.status_code == 200: cache.update({ 'data': parse_listens(response.json().get("payload")), - 'last_updated': datetime.now().isoformat(), + 'last_updated': time(), 'status': 'success' }) else: diff --git a/blueprints/risdeveau/templates/index.html b/blueprints/risdeveau/templates/index.html index 71778ef..9751ccd 100644 --- a/blueprints/risdeveau/templates/index.html +++ b/blueprints/risdeveau/templates/index.html @@ -17,6 +17,19 @@ crossorigin="anonymous" > +
diff --git a/blueprints/risdeveau/templates/listenbrainz.htm b/blueprints/risdeveau/templates/listenbrainz.htm index eee20e3..83ce5d8 100644 --- a/blueprints/risdeveau/templates/listenbrainz.htm +++ b/blueprints/risdeveau/templates/listenbrainz.htm @@ -10,11 +10,16 @@ {% endmacro %} +{% if lb_now.data and lb.data %}

Listenbrainz

{% if lb_now.data and lb_now.data.listens.0 %} @@ -26,3 +31,4 @@ {% endfor %} {% endif %}
+{% endif %} diff --git a/blueprints/risdeveau/templates/steam.htm b/blueprints/risdeveau/templates/steam.htm index 4e8aebe..1a181aa 100644 --- a/blueprints/risdeveau/templates/steam.htm +++ b/blueprints/risdeveau/templates/steam.htm @@ -3,6 +3,10 @@ hx-get="/m/steam" hx-trigger="every 1m" hx-swap="outerHTML" + hx-headers='{ + "If-Modified-Since": {{ (recent.last_updated, owned.last_updated) | max | int }}, + "If-None-Match": "{{ steam_etag() }}" + }' >

Steam