Logs minecraft status to postgres and creates webpage based on current server status using mcstatus.
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

"""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)