mirror of https://github.com/craigerl/aprsd.git
196 lines
5.5 KiB
Python
196 lines
5.5 KiB
Python
import datetime
|
|
import json
|
|
import logging
|
|
from logging import NullHandler
|
|
from logging.handlers import RotatingFileHandler
|
|
import sys
|
|
|
|
import flask
|
|
import flask_classful
|
|
from flask_httpauth import HTTPBasicAuth
|
|
from werkzeug.security import check_password_hash, generate_password_hash
|
|
|
|
import aprsd
|
|
from aprsd import messaging, packets, plugin, stats, utils
|
|
|
|
|
|
LOG = logging.getLogger("APRSD")
|
|
|
|
auth = HTTPBasicAuth()
|
|
users = None
|
|
|
|
|
|
# HTTPBasicAuth doesn't work on a class method.
|
|
# This has to be out here. Rely on the APRSDFlask
|
|
# class to initialize the users from the config
|
|
@auth.verify_password
|
|
def verify_password(username, password):
|
|
global users
|
|
|
|
if username in users and check_password_hash(users.get(username), password):
|
|
return username
|
|
|
|
|
|
class APRSDFlask(flask_classful.FlaskView):
|
|
config = None
|
|
|
|
def set_config(self, config):
|
|
global users
|
|
self.config = config
|
|
self.users = {}
|
|
for user in self.config["aprsd"]["web"]["users"]:
|
|
self.users[user] = generate_password_hash(
|
|
self.config["aprsd"]["web"]["users"][user],
|
|
)
|
|
|
|
users = self.users
|
|
|
|
@auth.login_required
|
|
def index(self):
|
|
stats = self._stats()
|
|
LOG.debug(
|
|
"watch list? {}".format(
|
|
self.config["aprsd"]["watch_list"],
|
|
),
|
|
)
|
|
wl = packets.WatchList()
|
|
if wl.is_enabled():
|
|
watch_count = len(wl.callsigns)
|
|
watch_age = wl.max_delta()
|
|
else:
|
|
watch_count = 0
|
|
watch_age = 0
|
|
|
|
return flask.render_template(
|
|
"index.html",
|
|
initial_stats=stats,
|
|
callsign=self.config["aprs"]["login"],
|
|
version=aprsd.__version__,
|
|
config_json=json.dumps(self.config),
|
|
watch_count=watch_count,
|
|
watch_age=watch_age,
|
|
)
|
|
|
|
@auth.login_required
|
|
def messages(self):
|
|
track = messaging.MsgTrack()
|
|
msgs = []
|
|
for id in track:
|
|
LOG.info(track[id].dict())
|
|
msgs.append(track[id].dict())
|
|
|
|
return flask.render_template("messages.html", messages=json.dumps(msgs))
|
|
|
|
@auth.login_required
|
|
def packets(self):
|
|
packet_list = packets.PacketList().get()
|
|
return json.dumps(packet_list)
|
|
|
|
@auth.login_required
|
|
def plugins(self):
|
|
pm = plugin.PluginManager()
|
|
pm.reload_plugins()
|
|
|
|
return "reloaded"
|
|
|
|
@auth.login_required
|
|
def save(self):
|
|
"""Save the existing queue to disk."""
|
|
track = messaging.MsgTrack()
|
|
track.save()
|
|
return json.dumps({"messages": "saved"})
|
|
|
|
def _stats(self):
|
|
stats_obj = stats.APRSDStats()
|
|
track = messaging.MsgTrack()
|
|
now = datetime.datetime.now()
|
|
|
|
time_format = "%m-%d-%Y %H:%M:%S"
|
|
|
|
stats_dict = stats_obj.stats()
|
|
|
|
# Convert the watch_list entries to age
|
|
wl = packets.WatchList()
|
|
new_list = {}
|
|
for call in wl.callsigns:
|
|
# call_date = datetime.datetime.strptime(
|
|
# str(wl.last_seen(call)),
|
|
# "%Y-%m-%d %H:%M:%S.%f",
|
|
# )
|
|
new_list[call] = {
|
|
"last": wl.age(call),
|
|
"packets": wl.callsigns[call]["packets"].get(),
|
|
}
|
|
|
|
stats_dict["aprsd"]["watch_list"] = new_list
|
|
packet_list = packets.PacketList()
|
|
rx = packet_list.total_received()
|
|
tx = packet_list.total_sent()
|
|
stats_dict["packets"] = {
|
|
"sent": tx,
|
|
"received": rx,
|
|
}
|
|
|
|
result = {
|
|
"time": now.strftime(time_format),
|
|
"size_tracker": len(track),
|
|
"stats": stats_dict,
|
|
}
|
|
|
|
return result
|
|
|
|
def stats(self):
|
|
return json.dumps(self._stats())
|
|
|
|
|
|
def setup_logging(config, flask_app, loglevel, quiet):
|
|
flask_log = logging.getLogger("werkzeug")
|
|
|
|
if not config["aprsd"]["web"].get("logging_enabled", False):
|
|
# disable web logging
|
|
flask_log.disabled = True
|
|
flask_app.logger.disabled = True
|
|
return
|
|
|
|
log_level = utils.LOG_LEVELS[loglevel]
|
|
LOG.setLevel(log_level)
|
|
log_format = config["aprsd"].get("logformat", utils.DEFAULT_LOG_FORMAT)
|
|
date_format = config["aprsd"].get("dateformat", utils.DEFAULT_DATE_FORMAT)
|
|
log_formatter = logging.Formatter(fmt=log_format, datefmt=date_format)
|
|
log_file = config["aprsd"].get("logfile", None)
|
|
if log_file:
|
|
fh = RotatingFileHandler(log_file, maxBytes=(10248576 * 5), backupCount=4)
|
|
else:
|
|
fh = NullHandler()
|
|
|
|
fh.setFormatter(log_formatter)
|
|
for handler in flask_app.logger.handlers:
|
|
handler.setFormatter(log_formatter)
|
|
print(handler)
|
|
|
|
flask_log.addHandler(fh)
|
|
|
|
if not quiet:
|
|
sh = logging.StreamHandler(sys.stdout)
|
|
sh.setFormatter(log_formatter)
|
|
flask_log.addHandler(sh)
|
|
|
|
|
|
def init_flask(config, loglevel, quiet):
|
|
flask_app = flask.Flask(
|
|
"aprsd",
|
|
static_url_path="/static",
|
|
static_folder="web/static",
|
|
template_folder="web/templates",
|
|
)
|
|
setup_logging(config, flask_app, loglevel, quiet)
|
|
server = APRSDFlask()
|
|
server.set_config(config)
|
|
flask_app.route("/", methods=["GET"])(server.index)
|
|
flask_app.route("/stats", methods=["GET"])(server.stats)
|
|
flask_app.route("/messages", methods=["GET"])(server.messages)
|
|
flask_app.route("/packets", methods=["GET"])(server.packets)
|
|
flask_app.route("/save", methods=["GET"])(server.save)
|
|
flask_app.route("/plugins", methods=["GET"])(server.plugins)
|
|
return flask_app
|