Centralize remaining magic numbers in settings.py
All checks were successful
Build and push Docker image / build (push) Successful in 13s
Test / test (push) Successful in 15s

- HIGHLIGHTS_MAX_BYTES, BOOKMARKS_MAX_BYTES: books size limits now in settings
- PODCAST_INBOX_PAGE_SIZE: shared between podcasts/views.py and app.js via DIORA_CONFIG
- VOLUME_DEFAULT: radio stream player default volume
- ITUNES_TIMEOUT: unified iTunes API timeout (was 5s vs 6s inconsistency)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
marwin 2026-04-04 21:10:14 +02:00
parent 0a6ba6feac
commit e9c5b8058b
7 changed files with 18 additions and 10 deletions

View file

@ -181,7 +181,7 @@ def book_highlights(request, pk):
raw_size = len(base64.b64decode(ct)) raw_size = len(base64.b64decode(ct))
except Exception: except Exception:
return JsonResponse({'error': 'invalid base64 in ct'}, status=400) return JsonResponse({'error': 'invalid base64 in ct'}, status=400)
if raw_size > 700 * 1024: if raw_size > getattr(settings, 'HIGHLIGHTS_MAX_BYTES', 700 * 1024):
return JsonResponse({'error': 'highlights data too large (max 700 KB)'}, status=400) return JsonResponse({'error': 'highlights data too large (max 700 KB)'}, status=400)
row, _ = EBookHighlights.objects.get_or_create(user=request.user, book=book) row, _ = EBookHighlights.objects.get_or_create(user=request.user, book=book)
@ -226,7 +226,7 @@ def book_bookmarks(request, pk):
raw_size = len(base64.b64decode(ct)) raw_size = len(base64.b64decode(ct))
except Exception: except Exception:
return JsonResponse({'error': 'invalid base64 in ct'}, status=400) return JsonResponse({'error': 'invalid base64 in ct'}, status=400)
if raw_size > 100 * 1024: if raw_size > getattr(settings, 'BOOKMARKS_MAX_BYTES', 100 * 1024):
return JsonResponse({'error': 'bookmarks data too large (max 100 KB)'}, status=400) return JsonResponse({'error': 'bookmarks data too large (max 100 KB)'}, status=400)
row, _ = EBookBookmarks.objects.get_or_create(user=request.user, book=book) row, _ = EBookBookmarks.objects.get_or_create(user=request.user, book=book)

View file

@ -9,4 +9,5 @@ def upload_limits(request):
return { return {
'EBOOK_MAX_BYTES': getattr(settings, 'EBOOK_MAX_BYTES', 10 * 1024 * 1024), 'EBOOK_MAX_BYTES': getattr(settings, 'EBOOK_MAX_BYTES', 10 * 1024 * 1024),
'BG_MAX_BYTES': getattr(settings, 'BG_MAX_BYTES', 5 * 1024 * 1024), 'BG_MAX_BYTES': getattr(settings, 'BG_MAX_BYTES', 5 * 1024 * 1024),
'PODCAST_INBOX_PAGE_SIZE': getattr(settings, 'PODCAST_INBOX_PAGE_SIZE', 200),
} }

View file

@ -101,7 +101,13 @@ STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
MEDIA_URL = '/media/' MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media' MEDIA_ROOT = BASE_DIR / 'media'
BG_MAX_BYTES = 5 * 1024 * 1024 # 5 MB BG_MAX_BYTES = 5 * 1024 * 1024 # 5 MB
HIGHLIGHTS_MAX_BYTES = 700 * 1024 # 700 KB
BOOKMARKS_MAX_BYTES = 100 * 1024 # 100 KB
VOLUME_DEFAULT = 204 # out of 255
ITUNES_TIMEOUT = 6 # seconds
PODCAST_INBOX_PAGE_SIZE = 200
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

View file

@ -145,7 +145,7 @@ def podcast_search(request):
try: try:
url = f'https://itunes.apple.com/search?term={urllib.parse.quote(q)}&media=podcast&limit=20' url = f'https://itunes.apple.com/search?term={urllib.parse.quote(q)}&media=podcast&limit=20'
resp = requests.get(url, timeout=6) resp = requests.get(url, timeout=getattr(settings, 'ITUNES_TIMEOUT', 6))
resp.raise_for_status() resp.raise_for_status()
raw = resp.json().get('results', []) raw = resp.json().get('results', [])
except Exception as e: except Exception as e:
@ -620,7 +620,7 @@ def inbox(request):
).values_list('episode_id', flat=True) ).values_list('episode_id', flat=True)
) )
limit = min(int(request.GET.get('limit', 200)), 1000) limit = min(int(request.GET.get('limit', getattr(settings, 'PODCAST_INBOX_PAGE_SIZE', 200))), 1000)
offset = max(int(request.GET.get('offset', 0)), 0) offset = max(int(request.GET.get('offset', 0)), 0)
episodes = list( episodes = list(

View file

@ -206,7 +206,7 @@ def affiliate_links(request):
f"https://itunes.apple.com/search" f"https://itunes.apple.com/search"
f"?term={urllib.parse.quote(track)}&media=music&limit=1" f"?term={urllib.parse.quote(track)}&media=music&limit=1"
) )
resp = requests.get(itunes_url, timeout=5) resp = requests.get(itunes_url, timeout=getattr(settings, 'ITUNES_TIMEOUT', 6))
resp.raise_for_status() resp.raise_for_status()
results = resp.json().get('results', []) results = resp.json().get('results', [])
if results: if results:
@ -584,9 +584,10 @@ def import_m3u(request):
def stream_player(request): def stream_player(request):
url = request.GET.get('url', '').strip() url = request.GET.get('url', '').strip()
name = request.GET.get('name', '').strip() name = request.GET.get('name', '').strip()
vol = request.GET.get('vol', '204').strip() _vol_default = getattr(settings, 'VOLUME_DEFAULT', 204)
vol = request.GET.get('vol', str(_vol_default)).strip()
try: try:
vol = max(0, min(255, int(vol))) vol = max(0, min(255, int(vol)))
except ValueError: except ValueError:
vol = 204 vol = _vol_default
return render(request, 'radio/stream_player.html', {'stream_url': url, 'stream_name': name, 'stream_vol': vol}) return render(request, 'radio/stream_player.html', {'stream_url': url, 'stream_name': name, 'stream_vol': vol})

View file

@ -1590,7 +1590,7 @@ async function savePodcastProgress() {
} }
let _inboxOffset = 0; let _inboxOffset = 0;
const _inboxPageSize = 200; const _inboxPageSize = DIORA_CONFIG.podcastInboxPageSize;
async function loadAndRenderInbox(append = false) { async function loadAndRenderInbox(append = false) {
const listEl = $('podcast-inbox-list'); const listEl = $('podcast-inbox-list');

View file

@ -13,7 +13,7 @@
<link rel="apple-touch-icon" href="/static/icon-192.png"> <link rel="apple-touch-icon" href="/static/icon-192.png">
<link rel="stylesheet" href="/static/css/app.css"> <link rel="stylesheet" href="/static/css/app.css">
<title>{% block title %}diora{% endblock %}</title> <title>{% block title %}diora{% endblock %}</title>
<script>const DIORA_CONFIG = { ebookMaxBytes: {{ EBOOK_MAX_BYTES }}, bgMaxBytes: {{ BG_MAX_BYTES }} };</script> <script>const DIORA_CONFIG = { ebookMaxBytes: {{ EBOOK_MAX_BYTES }}, bgMaxBytes: {{ BG_MAX_BYTES }}, podcastInboxPageSize: {{ PODCAST_INBOX_PAGE_SIZE }} };</script>
{% if encrypted_bg_json %} {% if encrypted_bg_json %}
<script>const ENCRYPTED_BG = {{ encrypted_bg_json|safe }};</script> <script>const ENCRYPTED_BG = {{ encrypted_bg_json|safe }};</script>
{% endif %} {% endif %}