Don't send data if not modified
This commit is contained in:
@@ -4,9 +4,12 @@ from pathlib import Path
|
|||||||
from htmlmin import minify
|
from htmlmin import minify
|
||||||
from time import time
|
from time import time
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
from hashlib import md5
|
||||||
|
from json import dumps
|
||||||
from musicbrainzngs import get_image_front
|
from musicbrainzngs import get_image_front
|
||||||
from flask import (
|
from flask import (
|
||||||
Blueprint,
|
Blueprint,
|
||||||
|
request,
|
||||||
render_template,
|
render_template,
|
||||||
send_file,
|
send_file,
|
||||||
send_from_directory,
|
send_from_directory,
|
||||||
@@ -40,6 +43,12 @@ def utmsmp(unix: int) -> str:
|
|||||||
def rtmsmp(unix: int) -> str:
|
def rtmsmp(unix: int) -> str:
|
||||||
return tmsmp(int(time() - unix))
|
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(
|
bp = Blueprint(
|
||||||
"risdeveau",
|
"risdeveau",
|
||||||
__name__,
|
__name__,
|
||||||
@@ -73,6 +82,8 @@ def mb_cover(mbid):
|
|||||||
return r
|
return r
|
||||||
|
|
||||||
args = {
|
args = {
|
||||||
|
"lb_etag": lb_etag,
|
||||||
|
"steam_etag": steam_etag,
|
||||||
"lb": listens,
|
"lb": listens,
|
||||||
"lb_now": listening,
|
"lb_now": listening,
|
||||||
"recent": recent,
|
"recent": recent,
|
||||||
@@ -88,4 +99,22 @@ def index():
|
|||||||
|
|
||||||
@bp.route("/m/<module>")
|
@bp.route("/m/<module>")
|
||||||
def module(module):
|
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)
|
return render_tmpl(f'{module}.htm', **args)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from flask import Flask, jsonify
|
|||||||
from apscheduler.schedulers.background import BackgroundScheduler
|
from apscheduler.schedulers.background import BackgroundScheduler
|
||||||
from apscheduler.triggers.interval import IntervalTrigger
|
from apscheduler.triggers.interval import IntervalTrigger
|
||||||
import requests
|
import requests
|
||||||
from datetime import datetime
|
from time import time
|
||||||
import atexit
|
import atexit
|
||||||
import re
|
import re
|
||||||
from urllib.parse import urlparse, parse_qs
|
from urllib.parse import urlparse, parse_qs
|
||||||
@@ -63,7 +63,7 @@ def api_request(url: str, cache):
|
|||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
cache.update({
|
cache.update({
|
||||||
'data': parse_listens(response.json().get("payload")),
|
'data': parse_listens(response.json().get("payload")),
|
||||||
'last_updated': datetime.now().isoformat(),
|
'last_updated': time(),
|
||||||
'status': 'success'
|
'status': 'success'
|
||||||
})
|
})
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -17,6 +17,19 @@
|
|||||||
crossorigin="anonymous"
|
crossorigin="anonymous"
|
||||||
></script>
|
></script>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta
|
||||||
|
name="htmx-config"
|
||||||
|
content='{
|
||||||
|
"responseHandling":[
|
||||||
|
{"code":"204", "swap": false},
|
||||||
|
{"code":"304", "swap": false},
|
||||||
|
{"code":"[23]..", "swap": true},
|
||||||
|
{"code":"422", "swap": true},
|
||||||
|
{"code":"[45]..", "swap": false, "error":true},
|
||||||
|
{"code":"...", "swap": true}
|
||||||
|
]
|
||||||
|
}'
|
||||||
|
/>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
|
|||||||
@@ -10,11 +10,16 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% if lb_now.data and lb.data %}
|
||||||
<div
|
<div
|
||||||
class="block"
|
class="block"
|
||||||
hx-get="/m/listenbrainz"
|
hx-get="/m/listenbrainz"
|
||||||
hx-trigger="every 15s"
|
hx-trigger="every 15s"
|
||||||
hx-swap="outerHTML"
|
hx-swap="outerHTML"
|
||||||
|
hx-headers='{
|
||||||
|
"If-Modified-Since": {{ (lb_now.last_updated, lb.last_updated) | max | int }},
|
||||||
|
"If-None-Match": "{{ lb_etag() }}"
|
||||||
|
}'
|
||||||
>
|
>
|
||||||
<h2><a href="https://listenbrainz.org/user/risdeveau/">Listenbrainz</a></h2>
|
<h2><a href="https://listenbrainz.org/user/risdeveau/">Listenbrainz</a></h2>
|
||||||
{% if lb_now.data and lb_now.data.listens.0 %}
|
{% if lb_now.data and lb_now.data.listens.0 %}
|
||||||
@@ -26,3 +31,4 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
hx-get="/m/steam"
|
hx-get="/m/steam"
|
||||||
hx-trigger="every 1m"
|
hx-trigger="every 1m"
|
||||||
hx-swap="outerHTML"
|
hx-swap="outerHTML"
|
||||||
|
hx-headers='{
|
||||||
|
"If-Modified-Since": {{ (recent.last_updated, owned.last_updated) | max | int }},
|
||||||
|
"If-None-Match": "{{ steam_etag() }}"
|
||||||
|
}'
|
||||||
>
|
>
|
||||||
<h2><a href="https://steamcommunity.com/id/risdeveau">Steam</a></h2>
|
<h2><a href="https://steamcommunity.com/id/risdeveau">Steam</a></h2>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user