front log and related datetime stuff

This commit is contained in:
cube
2026-03-30 22:20:16 +01:00
parent db4a7cc46e
commit 1ee6a96d58
13 changed files with 117 additions and 47 deletions

1
.gitignore vendored
View File

@@ -1,4 +1,5 @@
.venv/ .venv/
.vscode/
*.pyc *.pyc
__pycache__/ __pycache__/

View File

@@ -1,6 +1,8 @@
import os import os, datetime
from flask import Flask from flask import Flask
from myriad.utilities import server_time, get_datetime_str
from myriad.db import get_db
def create_app(test_config=None): def create_app(test_config=None):
@@ -33,6 +35,16 @@ def create_app(test_config=None):
def get_themes(): def get_themes():
themes = os.listdir(app.config["THEMES_FOLDER"]) themes = os.listdir(app.config["THEMES_FOLDER"])
return themes return themes
return dict(get_themes=get_themes) def w_server_time():
return server_time()
def w_get_datetime_str(dt_obj):
return get_datetime_str(dt_obj)
def get_member(mid):
db = get_db()
member = db.execute("SELECT * FROM member WHERE id=(?)",(mid,)).fetchone()
return member
return dict(get_themes=get_themes, server_time=w_server_time, get_datetime_str=w_get_datetime_str, get_member=get_member)
return app return app

View File

@@ -14,9 +14,7 @@ def login_required(view):
def wrapped_view(**kwargs): def wrapped_view(**kwargs):
if g.user is None: if g.user is None:
return redirect(url_for('auth.login')) return redirect(url_for('auth.login'))
return view(**kwargs) return view(**kwargs)
return wrapped_view return wrapped_view
@@ -27,9 +25,7 @@ def load_logged_in_user():
if user_id is None: if user_id is None:
g.user = None g.user = None
else: else:
g.user = get_db().execute( g.user = get_db().execute('SELECT * FROM user WHERE id = ?', (user_id,)).fetchone()
'SELECT * FROM user WHERE id = ?', (user_id,)
).fetchone()
@@ -50,10 +46,7 @@ def register():
if error is None: if error is None:
try: try:
db.execute( db.execute("INSERT INTO user (username, password) VALUES (?, ?)",(username, generate_password_hash(password)),)
"INSERT INTO user (username, password) VALUES (?, ?)",
(username, generate_password_hash(password)),
)
db.commit() db.commit()
except db.IntegrityError: except db.IntegrityError:
error = f"User {username} is already registered." error = f"User {username} is already registered."
@@ -71,9 +64,7 @@ def login():
password = request.form['password'] password = request.form['password']
db = get_db() db = get_db()
error = None error = None
user = db.execute( user = db.execute('SELECT * FROM user WHERE username = ?', (username,)).fetchone()
'SELECT * FROM user WHERE username = ?', (username,)
).fetchone()
if user is None: if user is None:
error = 'Incorrect username.' error = 'Incorrect username.'

View File

@@ -3,6 +3,7 @@ from flask import (
) )
from werkzeug.utils import secure_filename from werkzeug.utils import secure_filename
import os, uuid import os, uuid
from myriad.utilities import server_time, get_datetime_obj, get_datetime_str
from myriad.auth import login_required from myriad.auth import login_required
from myriad.db import get_db from myriad.db import get_db
@@ -36,8 +37,9 @@ def new():
content = request.form['content'] content = request.form['content']
mid = request.form["mid"] mid = request.form["mid"]
privacy = request.form["privacy"] privacy = request.form["privacy"]
created = get_datetime_obj(server_time())
db.execute("INSERT INTO blog (member_id, title, content, public) VALUES (?, ?, ?, ?)",(mid, title, content, privacy)) db.execute("INSERT INTO blog (member_id, title, content, public, created) VALUES (?, ?, ?, ?, ?)",(mid, title, content, privacy, created))
db.commit() db.commit()
return redirect(url_for('blog.blog')) return redirect(url_for('blog.blog'))

View File

@@ -14,6 +14,18 @@ def index():
fronters = db.execute("SELECT * FROM member WHERE front=(?) ORDER BY member_name",(1,)).fetchall() fronters = db.execute("SELECT * FROM member WHERE front=(?) ORDER BY member_name",(1,)).fetchall()
homepage = db.execute("SELECT * FROM member WHERE homepage=(?) ORDER BY member_name",(1,)).fetchall() homepage = db.execute("SELECT * FROM member WHERE homepage=(?) ORDER BY member_name",(1,)).fetchall()
latest_start = db.execute("SELECT start_time FROM front_log ORDER BY start_time DESC").fetchone()
latest_end = db.execute("SELECT end_time FROM front_log ORDER BY end_time DESC").fetchone()
latest = None
if latest_end[0]:
if latest_start[0] < latest_end[0]:
latest = latest_end[0]
else:
latest = latest_start[0]
else:
latest = latest_start[0]
icons={} icons={}
for member in homepage: for member in homepage:
icon_id = member[6] icon_id = member[6]
@@ -24,7 +36,7 @@ def index():
else: else:
icons[member[0]] = None icons[member[0]] = None
return render_template('index.html', front_list=fronters, home_pins=homepage, icons=icons) return render_template('index.html', front_list=fronters, home_pins=homepage, icons=icons, last_updated=latest)
@bp.route('/full') @bp.route('/full')
def full_list(): def full_list():

View File

@@ -2,6 +2,7 @@ from flask import Blueprint, flash, g, redirect, render_template, request, sessi
from werkzeug.utils import secure_filename from werkzeug.utils import secure_filename
import os, uuid, json, zipfile, datetime import os, uuid, json, zipfile, datetime
from myriad.utilities import server_time, get_datetime_obj, server_time_obj
from myriad.auth import login_required from myriad.auth import login_required
from myriad.db import get_db from myriad.db import get_db
@@ -16,9 +17,11 @@ def new():
subtitle = request.form["subtitle"] subtitle = request.form["subtitle"]
bio = request.form['bio'] bio = request.form['bio']
user_id = g.user[0] user_id = g.user[0]
date_created = get_datetime_obj(server_time())
db = get_db() db = get_db()
db.execute("INSERT INTO member (user_id, member_name, bio, subtitle) VALUES (?, ?, ?, ?)",(user_id, name, bio, subtitle)) db.execute("INSERT INTO member (user_id, member_name, bio, subtitle, created) VALUES (?, ?, ?, ?, ?)",(user_id, name, bio, subtitle, date_created))
db.commit() db.commit()
return redirect(url_for('home.full_list')) return redirect(url_for('home.full_list'))
@@ -193,6 +196,9 @@ def add_to_front(mid,location):
db.execute("UPDATE member SET front=(?) WHERE id=(?)",(1, mid)) db.execute("UPDATE member SET front=(?) WHERE id=(?)",(1, mid))
db.commit() db.commit()
db.execute("INSERT INTO front_log (member_id, start_time) VALUES (?, ?)",(mid, server_time_obj()))
db.commit()
if location == "home": if location == "home":
return redirect(url_for('index')) return redirect(url_for('index'))
else: else:
@@ -205,10 +211,24 @@ def remove_front(mid, location):
db.execute("UPDATE member SET front=(?) WHERE id=(?)",(0, mid)) db.execute("UPDATE member SET front=(?) WHERE id=(?)",(0, mid))
db.commit() db.commit()
current_entry = db.execute("SELECT id FROM front_log WHERE member_id=(?) AND end_time IS NULL",(mid,)).fetchone()
current_entry_id = current_entry[0]
db.execute("UPDATE front_log SET end_time=(?) WHERE id=(?)",(server_time_obj(), current_entry_id))
db.commit()
if location == "home": if location == "home":
return redirect(url_for('index')) return redirect(url_for('index'))
else: else:
return redirect(url_for('home.full_list')) return redirect(url_for('home.full_list'))
@bp.route("/delete_front_log/<fid>")
@login_required
def delete_front_log(fid):
db = get_db()
db.execute("DELETE FROM front_log WHERE id=(?)",(fid,))
db.commit()
return redirect(url_for('manage.admin'))
@bp.route("/add_to_home/<mid>/<location>") @bp.route("/add_to_home/<mid>/<location>")
@@ -255,13 +275,9 @@ def import_member(member):
db = get_db() db = get_db()
mid = member["id"] mid = member["id"]
date_raw = member["date-created"].split(",")
date = date_raw[0]
day,month,year = date.split("/")
time = date_raw[1]
hour,minute,second = time.split(":")
date_created = datetime.datetime(int(year), int(month), int(day), int(hour), int(minute), int(second))
date_created_obj = get_datetime_obj(member["date-created"])
name = member["name"] name = member["name"]
subtitle = member["subtitle"] subtitle = member["subtitle"]
description = member["description"] description = member["description"]
@@ -284,12 +300,7 @@ def import_member(member):
blog = member["blog"] blog = member["blog"]
for post in blog: for post in blog:
date_raw = post["date-created"].split(",") post_date_created = get_datetime_obj(post["date-created"])
date = date_raw[0]
day,month,year = date.split("/")
time = date_raw[1]
hour,minute,second = time.split(":")
date_created = datetime.datetime(int(year), int(month), int(day), int(hour), int(minute), int(second))
title = post["title"] title = post["title"]
content = post["content"] content = post["content"]
@@ -299,7 +310,7 @@ def import_member(member):
else: else:
privacy = 0 privacy = 0
db.execute("INSERT INTO blog (member_id, created, title, content, public) VALUES (?, ?, ?, ?, ?)",(mid, date_created, title, content, privacy)) db.execute("INSERT INTO blog (member_id, created, title, content, public) VALUES (?, ?, ?, ?, ?)",(mid, post_date_created, title, content, privacy))
db.commit() db.commit()
icons = member["icons"] icons = member["icons"]
@@ -320,7 +331,7 @@ def import_member(member):
db.execute("INSERT INTO stamps (member_id, stamp_location) VALUES (?, ?)",(mid, stamp)) db.execute("INSERT INTO stamps (member_id, stamp_location) VALUES (?, ?)",(mid, stamp))
db.commit() db.commit()
db.execute("INSERT INTO member (id,created,user_id, member_name,subtitle, bio,public,theme,homepage,main_icon) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",(mid, date_created, user_id, name, subtitle, description,privacy, theme, homepage, main_icon_id)) db.execute("INSERT INTO member (id,created,user_id, member_name,subtitle, bio,public,theme,homepage,main_icon) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",(mid, date_created_obj, user_id, name, subtitle, description,privacy, theme, homepage, main_icon_id))
db.commit() db.commit()
@@ -369,8 +380,9 @@ def admin():
return "<a href='/'>go home</a>" return "<a href='/'>go home</a>"
users = db.execute("SELECT * FROM user").fetchall() users = db.execute("SELECT * FROM user").fetchall()
front_log = db.execute("SELECT * FROM front_log ORDER BY start_time DESC").fetchall()
return render_template("manage/admin.html", users=users) return render_template("manage/admin.html", users=users, front_log=front_log)
@@ -394,7 +406,7 @@ def generate_json(mid):
else: else:
privacy = "private" privacy = "private"
date_created = member[2].strftime("%d/%m/%Y, %H:%M:%S") date_created = member[2]
homepage = member[7] homepage = member[7]
@@ -403,7 +415,7 @@ def generate_json(mid):
groups.append(group[0]) groups.append(group[0])
blog = [] blog = []
for post in blog_r: for post in blog_r:
d_c = post[2].strftime("%d/%m/%Y, %H:%M:%S") d_c = post[2]
if post[5] == 1: if post[5] == 1:
priv = "public" priv = "public"

View File

@@ -7,6 +7,7 @@ DROP TABLE IF EXISTS blog;
DROP TABLE IF EXISTS blinkies; DROP TABLE IF EXISTS blinkies;
DROP TABLE IF EXISTS stamps; DROP TABLE IF EXISTS stamps;
DROP TABLE IF EXISTS sections; DROP TABLE IF EXISTS sections;
DROP TABLE IF EXISTS front_log;
CREATE TABLE user ( CREATE TABLE user (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -17,7 +18,7 @@ CREATE TABLE user (
CREATE TABLE member ( CREATE TABLE member (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL, user_id INTEGER NOT NULL,
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, created TIMESTAMP,
member_name TEXT NOT NULL, member_name TEXT NOT NULL,
subtitle TEXT DEFAULT "", subtitle TEXT DEFAULT "",
bio TEXT, bio TEXT,
@@ -55,7 +56,7 @@ CREATE TABLE group_members (
CREATE TABLE blog ( CREATE TABLE blog (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
member_id INTEGER NOT NULL, member_id INTEGER NOT NULL,
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, created TIMESTAMP,
title TEXT, title TEXT,
content TEXT, content TEXT,
public BOOLEAN NOT NULL DEFAULT 1, public BOOLEAN NOT NULL DEFAULT 1,
@@ -82,4 +83,12 @@ CREATE TABLE sections (
title TEXT, title TEXT,
content TEXT, content TEXT,
FOREIGN KEY (member_id) REFERENCES member (id) FOREIGN KEY (member_id) REFERENCES member (id)
);
CREATE TABLE front_log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
member_id INTEGER NOT NULL,
start_time TIMESTAMP,
end_time TIMESTAMP,
FOREIGN KEY (member_id) REFERENCES member (id)
); );

View File

@@ -225,6 +225,11 @@ form textarea{
font-size:10px; font-size:10px;
} }
.log{
max-height:300px;
overflow-y:scroll;
}

View File

@@ -12,6 +12,7 @@
<div id="main"> <div id="main">
<div class="container" id="nav"> <div class="container" id="nav">
<div class="navitem">{{ server_time() }}</div>
<div class="heading">Myriad</div> <div class="heading">Myriad</div>
<div class="navitem">> <a href="{{ url_for('home.index') }}">Home</a></div> <div class="navitem">> <a href="{{ url_for('home.index') }}">Home</a></div>
<div class="navitem">> <a href="{{ url_for('home.full_list') }}">Full List</a></div> <div class="navitem">> <a href="{{ url_for('home.full_list') }}">Full List</a></div>

View File

@@ -19,7 +19,7 @@
<img src="{{ url_for('static', filename='any.jpg') }}" class="icon"> <img src="{{ url_for('static', filename='any.jpg') }}" class="icon">
{% endif %} {% endif %}
<div class="title">{{post[3]|safe}}</div> <div class="title">{{post[3]|safe}}</div>
<div class="timestamp">{{post[2]}} - <a href="{{ url_for('home.page', mid=post[1]) }}">{{op[3]}}</a> {% if g.user %}{% if op[9]==0 %}(Private){% else %}(Public)</b>{% endif %}{% endif %}</div> <div class="timestamp">{{ get_datetime_str(post[2]) }} - <a href="{{ url_for('home.page', mid=post[1]) }}">{{op[3]}}</a> {% if g.user %}{% if op[9]==0 %}(Private){% else %}(Public)</b>{% endif %}{% endif %}</div>
<div class="content"> <div class="content">
{{post[4]|safe}} {{post[4]|safe}}
</div> </div>

View File

@@ -4,13 +4,14 @@
{% block content %} {% block content %}
<div class="container"> <div class="container">
{% if front_list|length > 0 %}
<div id="frontbanner" class="heading"> <div id="frontbanner" class="heading">
{% if front_list|length > 0 %}
<b>currently fronting: </b> {% for member in front_list %}{% if not g.user and member[9]==0 %}{% else %}<a href="{{ url_for('home.page', mid=member[0]) }}">{{ member[3] }}</a> {% if front_list.index(member) != front_list|length -1 %}&{% endif %}{% endif %} {% endfor %} <b>currently fronting: </b> {% for member in front_list %}{% if not g.user and member[9]==0 %}{% else %}<a href="{{ url_for('home.page', mid=member[0]) }}">{{ member[3] }}</a> {% if front_list.index(member) != front_list|length -1 %}&{% endif %}{% endif %} {% endfor %}
</div>
{% else %} {% else %}
<p>There are currently no members listed as fronting</p> <i><sub>There are currently no members listed as fronting</sub></i>
{% endif %} {% endif %}
<br><i><sub>last updated: {{ get_datetime_str(last_updated) }}</sub></i>
</div>
{% for member in home_pins %} {% for member in home_pins %}

View File

@@ -6,6 +6,16 @@
{% block content %} {% block content %}
<div class="container"> <div class="container">
<div class="heading">Front Log</div>
<div class="maintext">Front change history</div>
<div class="log">
{% for front in front_log %}
<p><b>{{ get_datetime_str(front[2]) }}</b> - {{ get_member(front[1])[3] }}{% if front[3] %} <i>(ended: {{ get_datetime_str(front[3]) }})</i> | <a class="danger" href="{{ url_for('manage.delete_front_log', fid=front[0]) }}">delete</a>{% endif %}</p>
{% endfor %}
</div>
<div class="heading">Backup</div> <div class="heading">Backup</div>
<a href="{{ url_for('manage.export_system') }}">Export entire system as JSON</a> (without images)<br> <a href="{{ url_for('manage.export_system') }}">Export entire system as JSON</a> (without images)<br>
<a href="{{ url_for('manage.export_system_full') }}">Export entire system as ZIP</a> (with images) <a href="{{ url_for('manage.export_system_full') }}">Export entire system as ZIP</a> (with images)
@@ -30,10 +40,6 @@
<hr> <hr>
<a class="danger">Clear database</a> WARNING: this action is permanent and irreversible<br>
<br><br>
<div class="heading big pink">WIP ZONE</div> <div class="heading big pink">WIP ZONE</div>
<div class="heading">Site Users</div> <div class="heading">Site Users</div>
<div class="maintext">These are the usernames that can log in to the site</div> <div class="maintext">These are the usernames that can log in to the site</div>
@@ -44,9 +50,6 @@
<div class="heading">Admin Log</div> <div class="heading">Admin Log</div>
<div class="maintext">Actions taken by registered users</div> <div class="maintext">Actions taken by registered users</div>
<div class="heading">Front Log</div>
<div class="maintext">Front change history</div>
<div class="heading">Site Theme</div> <div class="heading">Site Theme</div>
<div class="maintext">Choose the overall theme for the site here</div> <div class="maintext">Choose the overall theme for the site here</div>

21
myriad/utilities.py Normal file
View File

@@ -0,0 +1,21 @@
import datetime
def server_time():
raw = datetime.datetime.now()
real = raw.strftime("%d/%m/%Y, %H:%M:%S")
return real
def server_time_obj():
return datetime.datetime.now()
def get_datetime_obj(dt_string):
date_raw = dt_string.split(",")
date = date_raw[0]
day,month,year = date.split("/")
time = date_raw[1]
hour,minute,second = time.split(":")
dt_obj = datetime.datetime(int(year), int(month), int(day), int(hour), int(minute), int(second))
return dt_obj
def get_datetime_str(dt_obj):
return dt_obj.strftime("%d/%m/%Y, %H:%M:%S")