Merge remote-tracking branch 'origin/master' into development
This commit is contained in:
commit
f1ff833d89
8
app.py
8
app.py
@ -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':
|
||||||
@ -284,14 +286,12 @@ def api_browse(subpath):
|
|||||||
foldernames = []
|
foldernames = []
|
||||||
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])
|
||||||
|
|||||||
@ -1,57 +1,74 @@
|
|||||||
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 1–4 digits
|
|
||||||
m = re.search(r'(\d{1,4}\.\d{1,2}\.\d{1,4})', string_with_date)
|
|
||||||
if not m:
|
|
||||||
return None
|
|
||||||
|
|
||||||
date_str = m.group(1)
|
|
||||||
parts = date_str.split('.')
|
|
||||||
|
|
||||||
# 1) Unambiguous “last group = YYYY”
|
|
||||||
if len(parts) == 3 and len(parts[2]) == 4:
|
|
||||||
fmt = '%d.%m.%Y'
|
|
||||||
|
|
||||||
# 2) Unambiguous “first group = YYYY”
|
# Precompiled regex to find date-like patterns: either dotted X.Y.Z or ISO dashed YYYY-MM-DD
|
||||||
elif len(parts) == 3 and len(parts[0]) == 4:
|
_DATE_REGEX = re.compile(
|
||||||
fmt = '%Y.%m.%d'
|
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 1–4 digits (year may be 1–4)
|
||||||
|
r")"
|
||||||
|
)
|
||||||
|
|
||||||
# 3) Ambiguous “XX.XX.XX” → prefer DD.MM.YY, fallback to YY.MM.DD
|
|
||||||
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:
|
def _try_parse(date_str: str, fmt: str) -> Optional[datetime]:
|
||||||
# optional: handle ISO with dashes
|
"""Try to parse date_str with fmt, return datetime or None."""
|
||||||
if '-' in date_str:
|
|
||||||
try:
|
|
||||||
dt = datetime.strptime(date_str, '%Y-%m-%d')
|
|
||||||
return dt.strftime('%Y-%m-%d')
|
|
||||||
except ValueError:
|
|
||||||
return None
|
|
||||||
return None
|
|
||||||
|
|
||||||
# parse with whichever fmt we settled on
|
|
||||||
try:
|
try:
|
||||||
dt = datetime.strptime(date_str, fmt)
|
return datetime.strptime(date_str, fmt)
|
||||||
return dt.strftime('%Y-%m-%d')
|
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def extract_date_from_string(text: str) -> Optional[str]:
|
||||||
|
"""
|
||||||
|
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
|
||||||
|
|
||||||
|
date_str = match.group(1)
|
||||||
|
|
||||||
|
# 1) ISO dashed format takes priority
|
||||||
|
if '-' in date_str:
|
||||||
|
dt = _try_parse(date_str, '%Y-%m-%d')
|
||||||
|
return dt.strftime('%Y-%m-%d') if dt else None
|
||||||
|
|
||||||
|
# 2) Dotted formats
|
||||||
|
parts = date_str.split('.')
|
||||||
|
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')
|
||||||
|
|
||||||
|
# no valid parse
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def extract_structure_from_string(input_string):
|
def extract_structure_from_string(input_string):
|
||||||
# extract category and titel from filename
|
# extract category and titel from filename
|
||||||
filepathname_ext = os.path.splitext(input_string)[0] # remove file extension
|
filepathname_ext = os.path.splitext(input_string)[0] # remove file extension
|
||||||
@ -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 = None
|
||||||
category = 'Gedicht'
|
text = left_side.lower()
|
||||||
elif 'vortrag' in left_side.lower() or 'erzä' in left_side.lower() or 'program' in left_side.lower():
|
for cat, keywords in CATEGORY_KEYWORDS.items():
|
||||||
category = 'Erzählung'
|
if any(kw in text for kw in keywords):
|
||||||
elif 'instrumental' in input_string.lower() or 'musikstück' in left_side.lower() or 'harfenstück' in left_side.lower():
|
category = cat
|
||||||
category = 'Instrumental'
|
break
|
||||||
else:
|
|
||||||
category = None
|
|
||||||
|
|
||||||
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)
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user