add analytics
This commit is contained in:
parent
8f5488faf3
commit
b17ed9b8c9
BIN
access_log.db
Normal file
BIN
access_log.db
Normal file
Binary file not shown.
74
app.py
74
app.py
@ -4,7 +4,8 @@ from PIL import Image
|
||||
import io
|
||||
from functools import wraps
|
||||
import mimetypes
|
||||
from datetime import datetime, date
|
||||
import sqlite3
|
||||
from datetime import datetime, date, timedelta
|
||||
from urllib.parse import unquote
|
||||
import diskcache
|
||||
import json
|
||||
@ -193,6 +194,75 @@ def api_browse(subpath):
|
||||
'files': files
|
||||
})
|
||||
|
||||
@app.route("/access-log")
|
||||
@require_secret
|
||||
def access_log():
|
||||
# Get timeframe filter from query parameter; default to "today"
|
||||
timeframe = request.args.get('timeframe', 'today')
|
||||
now = datetime.now()
|
||||
|
||||
# Determine the start time based on the requested timeframe
|
||||
if timeframe == 'today':
|
||||
# Beginning of today
|
||||
start = now.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
elif timeframe == '7days':
|
||||
start = now - timedelta(days=7)
|
||||
elif timeframe == '30days':
|
||||
start = now - timedelta(days=30)
|
||||
elif timeframe == '365days':
|
||||
start = now - timedelta(days=365)
|
||||
else:
|
||||
# Default to today if an unknown timeframe is passed
|
||||
start = now.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
|
||||
# Query the access log database for file access counts since the 'start' time
|
||||
conn = sqlite3.connect('access_log.db')
|
||||
cursor = conn.cursor()
|
||||
cursor.execute('''
|
||||
SELECT full_path, COUNT(*) as access_count
|
||||
FROM file_access_log
|
||||
WHERE timestamp >= ?
|
||||
GROUP BY full_path
|
||||
ORDER BY access_count DESC
|
||||
''', (start.isoformat(),))
|
||||
rows = cursor.fetchall()
|
||||
conn.close()
|
||||
|
||||
return render_template("access_log.html", rows=rows, timeframe=timeframe)
|
||||
|
||||
def log_file_access(full_path):
|
||||
"""
|
||||
Log file access details to a SQLite database.
|
||||
Records the timestamp, full file path, client IP, user agent, and referrer.
|
||||
"""
|
||||
# Connect to the database (this will create the file if it doesn't exist)
|
||||
conn = sqlite3.connect('access_log.db')
|
||||
cursor = conn.cursor()
|
||||
# Create the table if it doesn't exist
|
||||
cursor.execute('''
|
||||
CREATE TABLE IF NOT EXISTS file_access_log (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
timestamp TEXT,
|
||||
full_path TEXT,
|
||||
ip_address TEXT,
|
||||
user_agent TEXT,
|
||||
referrer TEXT
|
||||
)
|
||||
''')
|
||||
# Gather information from the request
|
||||
timestamp = datetime.now().isoformat()
|
||||
ip_address = request.remote_addr
|
||||
user_agent = request.headers.get('User-Agent')
|
||||
referrer = request.headers.get('Referer')
|
||||
|
||||
# Insert the access record into the database
|
||||
cursor.execute('''
|
||||
INSERT INTO file_access_log (timestamp, full_path, ip_address, user_agent, referrer)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
''', (timestamp, full_path, ip_address, user_agent, referrer))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
@app.route("/media/<path:filename>")
|
||||
@require_secret
|
||||
def serve_file(filename):
|
||||
@ -203,6 +273,8 @@ def serve_file(filename):
|
||||
app.logger.error(f"File not found: {full_path}")
|
||||
return "File not found", 404
|
||||
|
||||
log_file_access(full_path)
|
||||
|
||||
mime, _ = mimetypes.guess_type(full_path)
|
||||
mime = mime or 'application/octet-stream'
|
||||
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
flask-app:
|
||||
image: python:3.11-slim
|
||||
|
||||
46
templates/access_log.html
Normal file
46
templates/access_log.html
Normal file
@ -0,0 +1,46 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>File Access Log</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; margin: 20px; }
|
||||
table, th, td { border: 1px solid #ccc; border-collapse: collapse; padding: 8px; }
|
||||
th { background-color: #f2f2f2; }
|
||||
.btn { margin: 5px; padding: 8px 12px; text-decoration: none; background-color: #4CAF50; color: white; border-radius: 4px; }
|
||||
.btn:hover { background-color: #45a049; }
|
||||
.box { margin: 15px 0; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>File Access Log ({{ timeframe }})</h1>
|
||||
<div class="box">
|
||||
<a href="{{ url_for('access_log', timeframe='today') }}" class="btn">Today</a>
|
||||
<a href="{{ url_for('access_log', timeframe='7days') }}" class="btn">Last 7 Days</a>
|
||||
<a href="{{ url_for('access_log', timeframe='30days') }}" class="btn">Last 30 Days</a>
|
||||
<a href="{{ url_for('access_log', timeframe='365days') }}" class="btn">Last 365 Days</a>
|
||||
</div>
|
||||
<div class="box">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>File Path</th>
|
||||
<th>Access Count</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for row in rows %}
|
||||
<tr>
|
||||
<td>{{ row[0] }}</td>
|
||||
<td>{{ row[1] }}</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="2">No data available for the selected timeframe.</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
x
Reference in New Issue
Block a user