add today function
This commit is contained in:
parent
a0f972f38a
commit
83bb62ad32
65
analytics.py
65
analytics.py
@ -7,8 +7,10 @@ from collections import defaultdict
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import auth
|
import auth
|
||||||
|
import helperfunctions as hf
|
||||||
|
|
||||||
file_access_temp = []
|
file_access_temp = []
|
||||||
|
folder_today = []
|
||||||
|
|
||||||
app_config = auth.return_app_config()
|
app_config = auth.return_app_config()
|
||||||
|
|
||||||
@ -98,11 +100,13 @@ def parse_timestamp(ts_str):
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
def log_file_access(rel_path, filesize, mime, ip_address, user_agent, device_id, cached):
|
def log_file_access(rel_path, filesize, mime, ip_address, user_agent, device_id, cached):
|
||||||
"""Insert a file access record into the database and prune entries older than 10 minutes."""
|
"""Insert a file access record into the database and prune entries older than 10 minutes,
|
||||||
global file_access_temp
|
and track today’s files separately in folder_today."""
|
||||||
# Create a timezone-aware timestamp (local time with offset)
|
global file_access_temp, folder_today
|
||||||
timestamp = datetime.now(timezone.utc).astimezone()
|
|
||||||
iso_ts = timestamp.isoformat()
|
# Create a timezone-aware timestamp
|
||||||
|
now = datetime.now(timezone.utc).astimezone()
|
||||||
|
iso_ts = now.isoformat()
|
||||||
|
|
||||||
# Convert the IP address to a location
|
# Convert the IP address to a location
|
||||||
city, country = lookup_location(ip_address)
|
city, country = lookup_location(ip_address)
|
||||||
@ -113,18 +117,47 @@ def log_file_access(rel_path, filesize, mime, ip_address, user_agent, device_id,
|
|||||||
(timestamp, rel_path, filesize, mime, city, country, user_agent, device_id, cached)
|
(timestamp, rel_path, filesize, mime, city, country, user_agent, device_id, cached)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
''', (iso_ts, rel_path, filesize, mime, city, country, user_agent, device_id, cached))
|
''', (iso_ts, rel_path, filesize, mime, city, country, user_agent, device_id, cached))
|
||||||
|
|
||||||
# Remove entries older than 10 minutes using our robust parser.
|
# Prune temp entries older than 10 minutes
|
||||||
cutoff_time = datetime.now(timezone.utc).astimezone() - timedelta(minutes=10)
|
cutoff = now - timedelta(minutes=10)
|
||||||
file_access_temp[:] = [
|
file_access_temp[:] = [
|
||||||
entry for entry in file_access_temp
|
entry for entry in file_access_temp
|
||||||
if parse_timestamp(entry[0]) >= cutoff_time
|
if parse_timestamp(entry[0]) >= cutoff
|
||||||
]
|
]
|
||||||
|
|
||||||
# Add the new entry at the beginning of the list
|
# Keep only today's entries in folder_today
|
||||||
file_access_temp.insert(0, [iso_ts, rel_path, filesize, mime, f"{city}, {country}", user_agent, device_id, cached])
|
date_str = iso_ts.split('T', 1)[0]
|
||||||
|
folder_today[:] = [
|
||||||
|
entry for entry in folder_today
|
||||||
|
if entry['date_str'] == date_str
|
||||||
|
]
|
||||||
|
|
||||||
|
# If this new access is from today, record it
|
||||||
|
# Compare the helper’s YYYY-MM-DD string to today’s ISO date string
|
||||||
|
date_from_path = hf.extract_date_from_string(rel_path)
|
||||||
|
|
||||||
|
if date_from_path == date_str:
|
||||||
|
# get just the folder part (everything before the final '/')
|
||||||
|
folder_path = rel_path.rsplit('/', 1)[0] if '/' in rel_path else rel_path
|
||||||
|
# only append if that folder isn't already in folder_today
|
||||||
|
if not any(entry['rel_path'] == folder_path for entry in folder_today):
|
||||||
|
folder_today.append({'date_str': date_str, 'rel_path': folder_path})
|
||||||
|
|
||||||
|
# Finally, insert the new access at the top of the temp log
|
||||||
|
file_access_temp.insert(0, [
|
||||||
|
iso_ts,
|
||||||
|
rel_path,
|
||||||
|
filesize,
|
||||||
|
mime,
|
||||||
|
f"{city}, {country}",
|
||||||
|
user_agent,
|
||||||
|
device_id,
|
||||||
|
cached
|
||||||
|
])
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def return_file_access():
|
def return_file_access():
|
||||||
"""Return recent file access logs from memory (the last 10 minutes)."""
|
"""Return recent file access logs from memory (the last 10 minutes)."""
|
||||||
global file_access_temp
|
global file_access_temp
|
||||||
@ -140,6 +173,14 @@ def return_file_access():
|
|||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
def return_folder_today():
|
||||||
|
global folder_today
|
||||||
|
if folder_today:
|
||||||
|
return folder_today
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
|
||||||
def songs_dashboard():
|
def songs_dashboard():
|
||||||
# — SESSION & PARAM HANDLING (unchanged) —
|
# — SESSION & PARAM HANDLING (unchanged) —
|
||||||
if 'songs_dashboard_timeframe' not in session:
|
if 'songs_dashboard_timeframe' not in session:
|
||||||
|
|||||||
20
app.py
20
app.py
@ -23,6 +23,7 @@ import search
|
|||||||
import auth
|
import auth
|
||||||
import analytics as a
|
import analytics as a
|
||||||
import folder_secret_config_editor as fsce
|
import folder_secret_config_editor as fsce
|
||||||
|
import helperfunctions as hf
|
||||||
|
|
||||||
app_config = auth.return_app_config()
|
app_config = auth.return_app_config()
|
||||||
BASE_DIR = os.path.realpath(app_config['BASE_DIR'])
|
BASE_DIR = os.path.realpath(app_config['BASE_DIR'])
|
||||||
@ -243,6 +244,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):
|
||||||
|
|
||||||
if subpath == '': # root directory
|
if subpath == '': # root directory
|
||||||
foldernames = []
|
foldernames = []
|
||||||
for foldername, _ in session['folders'].items():
|
for foldername, _ in session['folders'].items():
|
||||||
@ -251,7 +253,20 @@ def api_browse(subpath):
|
|||||||
return jsonify({
|
return jsonify({
|
||||||
'breadcrumbs': generate_breadcrumbs(),
|
'breadcrumbs': generate_breadcrumbs(),
|
||||||
'directories': foldernames,
|
'directories': foldernames,
|
||||||
'files': []
|
'files': [],
|
||||||
|
'folder_today': a.return_folder_today()
|
||||||
|
})
|
||||||
|
|
||||||
|
if subpath == 'today':
|
||||||
|
foldernames = []
|
||||||
|
for item in a.return_folder_today():
|
||||||
|
foldernames.append({'name': item['rel_path'], 'path': item['rel_path']})
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
'breadcrumbs': generate_breadcrumbs(),
|
||||||
|
'directories': foldernames,
|
||||||
|
'files': [],
|
||||||
|
'folder_today': []
|
||||||
})
|
})
|
||||||
|
|
||||||
root, *relative_parts = subpath.split('/')
|
root, *relative_parts = subpath.split('/')
|
||||||
@ -283,7 +298,8 @@ def api_browse(subpath):
|
|||||||
response = {
|
response = {
|
||||||
'breadcrumbs': breadcrumbs,
|
'breadcrumbs': breadcrumbs,
|
||||||
'directories': directories,
|
'directories': directories,
|
||||||
'files': files
|
'files': files,
|
||||||
|
'folder_today': a.return_folder_today()
|
||||||
}
|
}
|
||||||
|
|
||||||
# If a filename was selected include it.
|
# If a filename was selected include it.
|
||||||
|
|||||||
46
helperfunctions.py
Normal file
46
helperfunctions.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
import re
|
||||||
|
|
||||||
|
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”
|
||||||
|
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
|
||||||
|
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:
|
||||||
|
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:
|
||||||
|
dt = datetime.strptime(date_str, fmt)
|
||||||
|
return dt.strftime('%Y-%m-%d')
|
||||||
|
except ValueError:
|
||||||
|
return None
|
||||||
@ -111,6 +111,9 @@ function renderContent(data) {
|
|||||||
contentHTML += '</div>';
|
contentHTML += '</div>';
|
||||||
} else {
|
} else {
|
||||||
contentHTML += '<ul>';
|
contentHTML += '<ul>';
|
||||||
|
if (data.breadcrumbs.length === 1 && Array.isArray(data.folder_today) && data.folder_today.length > 0) {
|
||||||
|
contentHTML += `<li class="directory-item"><a href="#" class="directory-link" data-path="today">📅 Heute</a></li>`;
|
||||||
|
}
|
||||||
data.directories.forEach(dir => {
|
data.directories.forEach(dir => {
|
||||||
if (admin_enabled && data.breadcrumbs.length != 1 && dir.share) {
|
if (admin_enabled && data.breadcrumbs.length != 1 && dir.share) {
|
||||||
share_link = `<a href="#" class="create-share" data-url="${dir.path}">⚙️</a>`;
|
share_link = `<a href="#" class="create-share" data-url="${dir.path}">⚙️</a>`;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user