You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
95 lines
3.1 KiB
95 lines
3.1 KiB
2 years ago
|
"""Flask app to display a table with the result of a postgreSQL query"""
|
||
|
|
||
|
from flask import Flask, render_template
|
||
|
import pandas as pd
|
||
|
from dotenv import load_dotenv
|
||
|
import os
|
||
|
import psycopg2
|
||
|
import logging
|
||
|
import sys
|
||
|
import datetime
|
||
|
import warnings
|
||
|
|
||
|
warnings.filterwarnings("ignore")
|
||
|
|
||
|
load_dotenv()
|
||
|
|
||
|
app = Flask(__name__)
|
||
|
|
||
|
def connect_to_database(args):
|
||
|
|
||
|
try:
|
||
|
conn = psycopg2.connect(
|
||
|
host=args.dbhost,
|
||
|
database=args.dbname,
|
||
|
user=args.dbuser,
|
||
|
password=args.dbpass,
|
||
|
sslmode='require',
|
||
|
options=f'project={args.project}'
|
||
|
)
|
||
|
cur = conn.cursor()
|
||
|
except Exception as e:
|
||
|
logging.error('Failed to connect to database: %s', e)
|
||
|
sys.exit(1)
|
||
|
|
||
|
table_name = vars(args).get('table', 'minecraft')
|
||
|
# if args.clean doesn't exist, it will be False
|
||
|
if vars(args).get('clean', False):
|
||
|
# remove table if it exists
|
||
|
try:
|
||
|
cur.execute(f'DROP TABLE IF EXISTS {table_name}')
|
||
|
conn.commit()
|
||
|
except Exception as e:
|
||
|
logging.error('Failed to drop table: %s', e)
|
||
|
sys.exit(1)
|
||
|
|
||
|
# Create table if it doesn't exist
|
||
|
try:
|
||
|
cur.execute(f'CREATE TABLE IF NOT EXISTS {table_name} (timestamp TIMESTAMP, server_name TEXT, version TEXT, protocol INT, players INT, max_players INT, latency INT)')
|
||
|
conn.commit()
|
||
|
except Exception as e:
|
||
|
logging.error('Failed to create table: %s', e)
|
||
|
sys.exit(1)
|
||
|
|
||
|
return conn
|
||
|
|
||
|
|
||
|
@app.route("/")
|
||
|
def index():
|
||
|
# make a fake args object that acts the same way as argparse.Namespace
|
||
|
class Args:
|
||
|
def __init__(self, **kwargs):
|
||
|
self.__dict__.update(kwargs)
|
||
|
|
||
|
args = Args(
|
||
|
dbhost=os.environ.get("DB_HOST", "localhost"),
|
||
|
dbname=os.environ.get("DB_NAME", "minecraft"),
|
||
|
dbuser=os.environ.get("DB_USER", "postgres"),
|
||
|
dbpass=os.environ.get("DB_PASS", ""),
|
||
|
project=os.environ.get("DB_PROJ", "default"),
|
||
|
table=os.environ.get("DB_TABLE", "minecraft"),
|
||
|
)
|
||
|
|
||
|
conn = connect_to_database(args)
|
||
|
table_name = vars(args).get("table", "minecraft")
|
||
|
df = pd.read_sql(
|
||
|
f"SELECT * FROM {table_name} ORDER BY timestamp DESC LIMIT 100;", conn
|
||
|
)
|
||
|
online = df["players"].tolist()[0]
|
||
|
df = df[['timestamp', 'players', 'latency']]
|
||
|
# format timestamp
|
||
|
df['timestamp'] = df['timestamp'].dt.strftime('%Y-%m-%d %H:%M:%S')
|
||
|
# if the timestamp is more than 5 minutes old, the server is offline
|
||
|
latest_timestamp = datetime.datetime.strptime(df['timestamp'].tolist()[0], '%Y-%m-%d %H:%M:%S')
|
||
|
if (datetime.datetime.now() - latest_timestamp) > datetime.timedelta(minutes=5):
|
||
|
status = "The server is currently offline. Please try again later."
|
||
|
else:
|
||
|
if online > 0:
|
||
|
status = f"There are currently <b>{ online }</b> players online."
|
||
|
else:
|
||
|
status = "There are currently no players online."
|
||
|
return render_template("index.html", data=df.to_html(justify="center"), status=status)
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
app.run(debug=True, host="0.0.0.0", port=9993)
|