Merge remote-tracking branch 'origin/master' into development

This commit is contained in:
lelo 2025-06-14 18:39:37 +00:00
commit f1ff833d89
3 changed files with 81 additions and 66 deletions

8
app.py
View File

@ -249,6 +249,7 @@ def serve_sw():
@app.route('/api/path/<path:subpath>') @app.route('/api/path/<path:subpath>')
@auth.require_secret @auth.require_secret
def api_browse(subpath): def api_browse(subpath):
toplist_categories = app_config.get('toplist_categories', None)
if subpath == '': # root directory if subpath == '': # root directory
foldernames = [] foldernames = []
@ -260,7 +261,8 @@ def api_browse(subpath):
'directories': foldernames, 'directories': foldernames,
'files': [], 'files': [],
'folder_today': a.return_folder_today(), 'folder_today': a.return_folder_today(),
'folder_yesterday': a.return_folder_yesterday() 'folder_yesterday': a.return_folder_yesterday(),
'toplist_enabled': bool(toplist_categories)
}) })
if subpath == 'heute' or subpath == 'gestern': if subpath == 'heute' or subpath == 'gestern':
@ -285,13 +287,11 @@ def api_browse(subpath):
files = [] files = []
split_path = subpath.split('/') split_path = subpath.split('/')
valid_categories = ['Predigt', 'Erzählung', 'Gedicht', 'Gemeinsamer Gesang', 'Chor', 'Kinderchor', 'Jugendchor', 'Orchester', 'Instrumental', 'Gruppenlied']
if len(split_path) == 1 and split_path[0] == 'toplist': if len(split_path) == 1 and split_path[0] == 'toplist':
foldernames = [ foldernames = [
{ {
'name': categorie, 'path': 'toplist/' + categorie 'name': categorie, 'path': 'toplist/' + categorie
} for categorie in valid_categories } for categorie in toplist_categories
] ]
elif len(split_path) > 1 and split_path[0] == 'toplist': elif len(split_path) > 1 and split_path[0] == 'toplist':
files = hf.generate_top_list(split_path[1]) files = hf.generate_top_list(split_path[1])

View File

@ -1,54 +1,71 @@
from flask import session from flask import session
from datetime import datetime
import re import re
import os import os
import sqlite3 import sqlite3
from datetime import datetime, timedelta from datetime import datetime, timedelta
from typing import Optional
log_db = sqlite3.connect("access_log.db", check_same_thread=False) log_db = sqlite3.connect("access_log.db", check_same_thread=False)
def extract_date_from_string(string_with_date):
# grab X.Y.Z where X,Y,Z are 14 digits
m = re.search(r'(\d{1,4}\.\d{1,2}\.\d{1,4})', string_with_date) # Precompiled regex to find date-like patterns: either dotted X.Y.Z or ISO dashed YYYY-MM-DD
if not m: _DATE_REGEX = re.compile(
r"(" # start group
r"\d{4}-\d{1,2}-\d{1,2}" # ISO: YYYY-M-D or YYYY-MM-DD
r"|" # or
r"\d{1,4}\.\d{1,2}\.\d{1,4}" # dotted: X.Y.Z, where each is 14 digits (year may be 14)
r")"
)
def _try_parse(date_str: str, fmt: str) -> Optional[datetime]:
"""Try to parse date_str with fmt, return datetime or None."""
try:
return datetime.strptime(date_str, fmt)
except ValueError:
return None return None
date_str = m.group(1)
parts = date_str.split('.')
# 1) Unambiguous “last group = YYYY” def extract_date_from_string(text: str) -> Optional[str]:
if len(parts) == 3 and len(parts[2]) == 4: """
fmt = '%d.%m.%Y' Extract the first date-like substring from text and return it in ISO format (YYYY-MM-DD).
Supports:
- ISO-style dates with dashes (YYYY-M-D or YYYY-MM-DD)
- Dotted dates (DD.MM.YYYY, YYYY.MM.DD, DD.MM.YY, YY.MM.DD)
"""
match = _DATE_REGEX.search(text)
if not match:
return None
# 2) Unambiguous “first group = YYYY” date_str = match.group(1)
elif len(parts) == 3 and len(parts[0]) == 4:
fmt = '%Y.%m.%d'
# 3) Ambiguous “XX.XX.XX” → prefer DD.MM.YY, fallback to YY.MM.DD # 1) ISO dashed format takes priority
elif len(parts) == 3 and all(len(p) == 2 for p in parts):
# try last-group-as-year first
try:
dt = datetime.strptime(date_str, '%d.%m.%y')
return dt.strftime('%Y-%m-%d')
except ValueError:
# fallback to first-group-as-year
fmt = '%y.%m.%d'
else:
# optional: handle ISO with dashes
if '-' in date_str: if '-' in date_str:
try: dt = _try_parse(date_str, '%Y-%m-%d')
dt = datetime.strptime(date_str, '%Y-%m-%d') return dt.strftime('%Y-%m-%d') if dt else None
return dt.strftime('%Y-%m-%d')
except ValueError:
return None
return None
# parse with whichever fmt we settled on # 2) Dotted formats
try: parts = date_str.split('.')
dt = datetime.strptime(date_str, fmt) candidates = []
# Unambiguous: last part 4 digits → DD.MM.YYYY
if len(parts) == 3 and len(parts[2]) == 4:
candidates.append('%d.%m.%Y')
# Unambiguous: first part 4 digits → YYYY.MM.DD
if len(parts) == 3 and len(parts[0]) == 4:
candidates.append('%Y.%m.%d')
# Ambiguous two-digit groups: try DD.MM.YY, then YY.MM.DD
if len(parts) == 3 and all(len(p) == 2 for p in parts):
candidates.extend(['%d.%m.%y', '%y.%m.%d'])
# Try each candidate
for fmt in candidates:
dt = _try_parse(date_str, fmt)
if dt:
return dt.strftime('%Y-%m-%d') return dt.strftime('%Y-%m-%d')
except ValueError:
# no valid parse
return None return None
@ -67,30 +84,28 @@ def extract_structure_from_string(input_string):
# first part not a number # first part not a number
pass pass
if 'predig' in left_side.lower() or 'thema' in left_side.lower(): # define your mapping: category → list of trigger-words
category = 'Predigt' CATEGORY_KEYWORDS = {
elif 'wort' in left_side.lower() or 'einladung' in left_side.lower() or 'begrüßung' in left_side.lower() or 'ansprache' in left_side.lower() or 'einleitung' in left_side.lower() or 'aufruf zum' in left_side.lower() or 'zuruf zum' in left_side.lower(): 'Predigt': ['predig', 'thema'],
category = 'Vorwort' 'Vorwort': ['wort', 'einladung', 'begrüßung', 'ansprache', 'einleitung', 'aufruf zum', 'zuruf zum'],
elif 'kinderchor' in left_side.lower(): 'Kinderchor': ['kinderchor'],
category = 'Kinderchor' 'Jugendchor': ['jugendchor'],
elif 'jugendchor' in left_side.lower(): 'Orchester': ['orchester', 'sinfonie', 'symphonie'],
category = 'Jugendchor' 'Chor': ['chor'],
elif 'orchester' in input_string.lower() or 'sinfonie' in input_string.lower() or 'symphonie' in input_string.lower(): 'Gemeinsamer Gesang': ['gemeinsam', 'gemeindelied', 'gemeinsamer gesang'],
category = 'Orchester' 'Gruppenlied': ['gruppenlied', 'jugend', 'lied', 'musikgruppe'],
elif 'chor' in left_side.lower(): 'Gedicht': ['gedicht'],
category = 'Chor' 'Erzählung': ['vortrag', 'erzä', 'program'],
elif 'gemeinsam' in left_side.lower() or 'gemeindelied' in left_side.lower() or 'gemeinsamer gesang' in input_string.lower(): 'Instrumental': ['instrumental', 'musikstück', 'harfenstück'],
category = 'Gemeinsamer Gesang' }
elif 'gruppenlied' in left_side.lower() or 'jugend' in left_side.lower() or 'lied' in left_side.lower():
category = 'Gruppenlied' # walk the dict in your desired priority order
elif 'gedicht' in left_side.lower():
category = 'Gedicht'
elif 'vortrag' in left_side.lower() or 'erzä' in left_side.lower() or 'program' in left_side.lower():
category = 'Erzählung'
elif 'instrumental' in input_string.lower() or 'musikstück' in left_side.lower() or 'harfenstück' in left_side.lower():
category = 'Instrumental'
else:
category = None category = None
text = left_side.lower()
for cat, keywords in CATEGORY_KEYWORDS.items():
if any(kw in text for kw in keywords):
category = cat
break
if right_side: if right_side:
titel, name = right_side.split('-', 1) if '-' in right_side else (right_side, None) titel, name = right_side.split('-', 1) if '-' in right_side else (right_side, None)

View File

@ -113,7 +113,7 @@ function renderContent(data) {
} else if (data.breadcrumbs.length === 1 && Array.isArray(data.folder_yesterday) && data.folder_yesterday.length > 0) { } else if (data.breadcrumbs.length === 1 && Array.isArray(data.folder_yesterday) && data.folder_yesterday.length > 0) {
contentHTML += `<li class="directory-item"><a href="#" class="directory-link" data-path="gestern">📅 Gestern</a></li>`; contentHTML += `<li class="directory-item"><a href="#" class="directory-link" data-path="gestern">📅 Gestern</a></li>`;
} }
if (data.breadcrumbs.length === 1 ) { if (data.breadcrumbs.length === 1 && data.toplist_enabled) {
contentHTML += `<li class="directory-item"><a href="#" class="directory-link" data-path="toplist">🔥 oft angehört</a></li>`; contentHTML += `<li class="directory-item"><a href="#" class="directory-link" data-path="toplist">🔥 oft angehört</a></li>`;
} }
console.log(data.folder_today, data.folder_yesterday); console.log(data.folder_today, data.folder_yesterday);