* scan log files for timestamp as creating timestamp * increase test coverage * add an empty file for unit tests - the empty file is needed for unit tests to force an exception on the try to scan the first line for an timestamp * set timezone of scanned creation time
93 lines
2.5 KiB
Python
93 lines
2.5 KiB
Python
from quart import render_template
|
|
from quart_babel import format_datetime, format_decimal, _
|
|
from quart.helpers import send_from_directory
|
|
from werkzeug.utils import secure_filename
|
|
from cnf.config import Config
|
|
from datetime import datetime
|
|
from os import DirEntry
|
|
import os
|
|
from dateutil import tz
|
|
|
|
from . import web
|
|
|
|
|
|
def _get_birth_from_log(path: str) -> None | datetime:
|
|
'''read timestamp from the first line of a log file'''
|
|
dt = None
|
|
try:
|
|
with open(path) as f:
|
|
first_line = f.readline()
|
|
first_line = first_line.lstrip("'")
|
|
fmt = "%Y-%m-%d %H:%M:%S" if first_line[4] == '-' \
|
|
else "%d-%m-%Y %H:%M:%S"
|
|
dt = datetime.strptime(first_line[0:19], fmt). \
|
|
replace(tzinfo=tz.tzlocal())
|
|
except Exception:
|
|
pass
|
|
return dt
|
|
|
|
|
|
def _get_file(file: DirEntry) -> dict:
|
|
'''build one row for the connection table'''
|
|
entry = {}
|
|
entry['name'] = file.name
|
|
stat = file.stat()
|
|
entry['size'] = format_decimal(stat.st_size)
|
|
try:
|
|
dt = stat.st_birthtime
|
|
|
|
except Exception:
|
|
dt = _get_birth_from_log(file.path)
|
|
|
|
if dt:
|
|
entry['created'] = format_datetime(dt, format="short")
|
|
|
|
# sort by creating date, if available
|
|
entry['date'] = dt if isinstance(dt, float) else dt.timestamp()
|
|
else:
|
|
entry['created'] = _('n/a')
|
|
entry['date'] = stat.st_mtime
|
|
|
|
entry['modified'] = format_datetime(stat.st_mtime, format="short")
|
|
return entry
|
|
|
|
|
|
def get_list_data() -> list:
|
|
'''build the connection table'''
|
|
file_list = []
|
|
with os.scandir(Config.get_log_path()) as it:
|
|
for entry in it:
|
|
if entry.is_file():
|
|
file_list.append(_get_file(entry))
|
|
|
|
file_list.sort(key=lambda x: x['date'], reverse=True)
|
|
return file_list
|
|
|
|
|
|
@web.route('/file-fetch')
|
|
async def file_fetch():
|
|
data = {
|
|
"update-time": format_datetime(format="medium"),
|
|
}
|
|
data["file-list"] = await render_template('templ_log_files_list.html.j2',
|
|
dir_list=get_list_data())
|
|
|
|
return data
|
|
|
|
|
|
@web.route('/send-file/<file>')
|
|
async def send(file):
|
|
return await send_from_directory(
|
|
directory=Config.get_log_path(),
|
|
file_name=secure_filename(file),
|
|
as_attachment=True)
|
|
|
|
|
|
@web.route('/del-file/<file>', methods=['DELETE'])
|
|
async def delete(file):
|
|
try:
|
|
os.remove(Config.get_log_path() + secure_filename(file))
|
|
except OSError:
|
|
return 'File not found', 404
|
|
return '', 204
|