mirror of
https://github.com/craigerl/aprsd.git
synced 2024-11-10 10:33:31 -05:00
Upgraded the send-message POC to use websockets
This patch updates the send message Admi page to use websockets. It makes updates to the messages list instant.
This commit is contained in:
parent
23cbf32814
commit
c941379a5c
@ -123,6 +123,11 @@ class Aprsdis(aprslib.IS):
|
|||||||
self.select_timeout,
|
self.select_timeout,
|
||||||
)
|
)
|
||||||
if not readable:
|
if not readable:
|
||||||
|
if not blocking:
|
||||||
|
#self.logger.warning("not fucking readable, not blocking, break!")
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
#self.logger.warning("not fucking readable, continue")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -224,7 +229,7 @@ class Aprsdis(aprslib.IS):
|
|||||||
|
|
||||||
line = b""
|
line = b""
|
||||||
|
|
||||||
while True:
|
while True and not self.thread_stop:
|
||||||
try:
|
try:
|
||||||
for line in self._socket_readlines(blocking):
|
for line in self._socket_readlines(blocking):
|
||||||
if line[0:1] != b"#":
|
if line[0:1] != b"#":
|
||||||
@ -270,7 +275,9 @@ class Aprsdis(aprslib.IS):
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
if not blocking:
|
if not blocking:
|
||||||
|
#self.logger.error("Not blocking, bail bitch")
|
||||||
break
|
break
|
||||||
|
#self.logger.error("Consumer exiting")
|
||||||
|
|
||||||
|
|
||||||
def get_client():
|
def get_client():
|
||||||
|
160
aprsd/flask.py
160
aprsd/flask.py
@ -13,6 +13,7 @@ import flask
|
|||||||
from flask import request
|
from flask import request
|
||||||
import flask_classful
|
import flask_classful
|
||||||
from flask_httpauth import HTTPBasicAuth
|
from flask_httpauth import HTTPBasicAuth
|
||||||
|
from flask_socketio import Namespace, SocketIO
|
||||||
from werkzeug.security import check_password_hash, generate_password_hash
|
from werkzeug.security import check_password_hash, generate_password_hash
|
||||||
|
|
||||||
import aprsd
|
import aprsd
|
||||||
@ -108,11 +109,14 @@ class SendMessageThread(threads.APRSDThread):
|
|||||||
aprsis_client = None
|
aprsis_client = None
|
||||||
request = None
|
request = None
|
||||||
got_ack = False
|
got_ack = False
|
||||||
|
got_reply = False
|
||||||
|
|
||||||
def __init__(self, config, info, msg):
|
def __init__(self, config, info, msg, namespace):
|
||||||
self.config = config
|
self.config = config
|
||||||
self.request = info
|
self.request = info
|
||||||
self.msg = msg
|
self.msg = msg
|
||||||
|
self.namespace = namespace
|
||||||
|
self.start_time = datetime.datetime.now()
|
||||||
msg = "({} -> {}) : {}".format(
|
msg = "({} -> {}) : {}".format(
|
||||||
info["from"],
|
info["from"],
|
||||||
info["to"],
|
info["to"],
|
||||||
@ -183,7 +187,7 @@ class SendMessageThread(threads.APRSDThread):
|
|||||||
LOG.debug("Exiting")
|
LOG.debug("Exiting")
|
||||||
|
|
||||||
def rx_packet(self, packet):
|
def rx_packet(self, packet):
|
||||||
global got_ack, got_response
|
global socketio
|
||||||
# LOG.debug("Got packet back {}".format(packet))
|
# LOG.debug("Got packet back {}".format(packet))
|
||||||
resp = packet.get("response", None)
|
resp = packet.get("response", None)
|
||||||
if resp == "ack":
|
if resp == "ack":
|
||||||
@ -191,10 +195,15 @@ class SendMessageThread(threads.APRSDThread):
|
|||||||
LOG.info(f"We got ack for our sent message {ack_num}")
|
LOG.info(f"We got ack for our sent message {ack_num}")
|
||||||
messaging.log_packet(packet)
|
messaging.log_packet(packet)
|
||||||
SentMessages().ack(self.msg.id)
|
SentMessages().ack(self.msg.id)
|
||||||
|
socketio.emit(
|
||||||
|
"ack", SentMessages().get(self.msg.id),
|
||||||
|
namespace="/ws",
|
||||||
|
)
|
||||||
stats.APRSDStats().ack_rx_inc()
|
stats.APRSDStats().ack_rx_inc()
|
||||||
self.got_ack = True
|
self.got_ack = True
|
||||||
if self.request["wait_reply"] == "0":
|
if self.request["wait_reply"] == "0" or self.got_reply:
|
||||||
# We aren't waiting for a reply, so we can bail
|
# We aren't waiting for a reply, so we can bail
|
||||||
|
self.stop()
|
||||||
self.thread_stop = self.aprs_client.thread_stop = True
|
self.thread_stop = self.aprs_client.thread_stop = True
|
||||||
else:
|
else:
|
||||||
packets.PacketList().add(packet)
|
packets.PacketList().add(packet)
|
||||||
@ -209,9 +218,12 @@ class SendMessageThread(threads.APRSDThread):
|
|||||||
fromcall=fromcall,
|
fromcall=fromcall,
|
||||||
ack=msg_number,
|
ack=msg_number,
|
||||||
)
|
)
|
||||||
got_response = True
|
|
||||||
SentMessages().reply(self.msg.id, packet)
|
SentMessages().reply(self.msg.id, packet)
|
||||||
SentMessages().set_status(self.msg.id, "Got Reply")
|
SentMessages().set_status(self.msg.id, "Got Reply")
|
||||||
|
socketio.emit(
|
||||||
|
"reply", SentMessages().get(self.msg.id),
|
||||||
|
namespace="/ws",
|
||||||
|
)
|
||||||
|
|
||||||
# Send the ack back?
|
# Send the ack back?
|
||||||
ack = messaging.AckMessage(
|
ack = messaging.AckMessage(
|
||||||
@ -223,37 +235,37 @@ class SendMessageThread(threads.APRSDThread):
|
|||||||
SentMessages().set_status(self.msg.id, "Ack Sent")
|
SentMessages().set_status(self.msg.id, "Ack Sent")
|
||||||
|
|
||||||
# Now we can exit, since we are done.
|
# Now we can exit, since we are done.
|
||||||
|
self.got_reply = True
|
||||||
if self.got_ack:
|
if self.got_ack:
|
||||||
|
self.stop()
|
||||||
self.thread_stop = self.aprs_client.thread_stop = True
|
self.thread_stop = self.aprs_client.thread_stop = True
|
||||||
|
|
||||||
def loop(self):
|
def loop(self):
|
||||||
LOG.debug("LOOP Start")
|
# we have a general time limit expecting results of
|
||||||
|
# around 120 seconds before we exit
|
||||||
|
now = datetime.datetime.now()
|
||||||
|
start_delta = str(now - self.start_time)
|
||||||
|
delta = utils.parse_delta_str(start_delta)
|
||||||
|
d = datetime.timedelta(**delta)
|
||||||
|
max_timeout = {"hours": 0.0, "minutes": 1, "seconds": 0}
|
||||||
|
max_delta = datetime.timedelta(**max_timeout)
|
||||||
|
if d > max_delta:
|
||||||
|
LOG.error("XXXXXX Haven't completed everything in 60 seconds. BAIL!")
|
||||||
|
return False
|
||||||
|
|
||||||
|
if self.got_ack and self.got_reply:
|
||||||
|
LOG.warning("We got everything already. BAIL")
|
||||||
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# This will register a packet consumer with aprslib
|
# This will register a packet consumer with aprslib
|
||||||
# When new packets come in the consumer will process
|
# When new packets come in the consumer will process
|
||||||
# the packet
|
# the packet
|
||||||
self.aprs_client.consumer(self.rx_packet, raw=False, blocking=False)
|
self.aprs_client.consumer(self.rx_packet, raw=False, blocking=False)
|
||||||
except aprslib.exceptions.ConnectionDrop:
|
except aprslib.exceptions.ConnectionDrop:
|
||||||
LOG.error("Connection dropped, reconnecting")
|
LOG.error("Connection dropped.")
|
||||||
time.sleep(5)
|
|
||||||
# Force the deletion of the client object connected to aprs
|
|
||||||
# This will cause a reconnect, next time client.get_client()
|
|
||||||
# is called
|
|
||||||
del self.aprs_client
|
|
||||||
connecting = True
|
|
||||||
counter = 0;
|
|
||||||
while connecting:
|
|
||||||
try:
|
|
||||||
self.aprs_client = self.setup_connection()
|
|
||||||
connecting = False
|
|
||||||
except Exception:
|
|
||||||
LOG.error("Couldn't connect")
|
|
||||||
counter += 1
|
|
||||||
if counter >= 3:
|
|
||||||
LOG.error("Reached reconnect limit.")
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
LOG.debug("LOOP END")
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@ -351,38 +363,7 @@ class APRSDFlask(flask_classful.FlaskView):
|
|||||||
@auth.login_required
|
@auth.login_required
|
||||||
def send_message(self):
|
def send_message(self):
|
||||||
LOG.debug(request)
|
LOG.debug(request)
|
||||||
if request.method == "POST":
|
if request.method == "GET":
|
||||||
info = {
|
|
||||||
"from": request.form["from_call"],
|
|
||||||
"to": request.form["to_call"],
|
|
||||||
"password": request.form["from_call_password"],
|
|
||||||
"message": request.form["message"],
|
|
||||||
"wait_reply": request.form["wait_reply"],
|
|
||||||
}
|
|
||||||
LOG.debug(info)
|
|
||||||
msg = messaging.TextMessage(
|
|
||||||
info["from"], info["to"],
|
|
||||||
info["message"],
|
|
||||||
)
|
|
||||||
msgs = SentMessages()
|
|
||||||
msgs.add(msg)
|
|
||||||
msgs.set_status(msg.id, "Sending")
|
|
||||||
|
|
||||||
send_message_t = SendMessageThread(self.config, info, msg)
|
|
||||||
send_message_t.start()
|
|
||||||
|
|
||||||
|
|
||||||
info["from"]
|
|
||||||
result = "sending"
|
|
||||||
msg_id = msg.id
|
|
||||||
result = {
|
|
||||||
"msg_id": msg_id,
|
|
||||||
"status": "sending",
|
|
||||||
}
|
|
||||||
return json.dumps(result)
|
|
||||||
else:
|
|
||||||
result = "fail"
|
|
||||||
|
|
||||||
return flask.render_template(
|
return flask.render_template(
|
||||||
"send-message.html",
|
"send-message.html",
|
||||||
callsign=self.config["aprs"]["login"],
|
callsign=self.config["aprs"]["login"],
|
||||||
@ -451,6 +432,60 @@ class APRSDFlask(flask_classful.FlaskView):
|
|||||||
return json.dumps(self._stats())
|
return json.dumps(self._stats())
|
||||||
|
|
||||||
|
|
||||||
|
class SendMessageNamespace(Namespace):
|
||||||
|
_config = None
|
||||||
|
got_ack = False
|
||||||
|
reply_sent = False
|
||||||
|
msg = None
|
||||||
|
request = None
|
||||||
|
|
||||||
|
def __init__(self, namespace=None, config=None):
|
||||||
|
self._config = config
|
||||||
|
super().__init__(namespace)
|
||||||
|
|
||||||
|
def on_connect(self):
|
||||||
|
global socketio
|
||||||
|
LOG.debug("Web socket connected")
|
||||||
|
socketio.emit(
|
||||||
|
"connected", {"data": "Lets dance"},
|
||||||
|
namespace="/ws",
|
||||||
|
)
|
||||||
|
|
||||||
|
def on_disconnect(self):
|
||||||
|
LOG.debug("WS Disconnected")
|
||||||
|
|
||||||
|
def on_send(self, data):
|
||||||
|
global socketio
|
||||||
|
LOG.debug(f"WS: on_send {data}")
|
||||||
|
self.request = data
|
||||||
|
msg = messaging.TextMessage(
|
||||||
|
data["from"], data["to"],
|
||||||
|
data["message"],
|
||||||
|
)
|
||||||
|
self.msg = msg
|
||||||
|
msgs = SentMessages()
|
||||||
|
msgs.add(msg)
|
||||||
|
msgs.set_status(msg.id, "Sending")
|
||||||
|
socketio.emit(
|
||||||
|
"sent", SentMessages().get(self.msg.id),
|
||||||
|
namespace="/ws",
|
||||||
|
)
|
||||||
|
|
||||||
|
socketio.start_background_task(self._start, self._config, data, msg, self)
|
||||||
|
LOG.warning("WS: on_send: exit")
|
||||||
|
|
||||||
|
def _start(self, config, data, msg, namespace):
|
||||||
|
msg_thread = SendMessageThread(self._config, data, msg, self)
|
||||||
|
msg_thread.start()
|
||||||
|
|
||||||
|
def handle_message(self, data):
|
||||||
|
LOG.debug(f"WS Data {data}")
|
||||||
|
|
||||||
|
def handle_json(self, data):
|
||||||
|
LOG.debug(f"WS json {data}")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def setup_logging(config, flask_app, loglevel, quiet):
|
def setup_logging(config, flask_app, loglevel, quiet):
|
||||||
flask_log = logging.getLogger("werkzeug")
|
flask_log = logging.getLogger("werkzeug")
|
||||||
|
|
||||||
@ -485,6 +520,8 @@ def setup_logging(config, flask_app, loglevel, quiet):
|
|||||||
|
|
||||||
|
|
||||||
def init_flask(config, loglevel, quiet):
|
def init_flask(config, loglevel, quiet):
|
||||||
|
global socketio
|
||||||
|
|
||||||
flask_app = flask.Flask(
|
flask_app = flask.Flask(
|
||||||
"aprsd",
|
"aprsd",
|
||||||
static_url_path="/static",
|
static_url_path="/static",
|
||||||
@ -498,8 +535,17 @@ def init_flask(config, loglevel, quiet):
|
|||||||
flask_app.route("/stats", methods=["GET"])(server.stats)
|
flask_app.route("/stats", methods=["GET"])(server.stats)
|
||||||
flask_app.route("/messages", methods=["GET"])(server.messages)
|
flask_app.route("/messages", methods=["GET"])(server.messages)
|
||||||
flask_app.route("/packets", methods=["GET"])(server.packets)
|
flask_app.route("/packets", methods=["GET"])(server.packets)
|
||||||
flask_app.route("/send-message", methods=["GET", "POST"])(server.send_message)
|
flask_app.route("/send-message", methods=["GET"])(server.send_message)
|
||||||
flask_app.route("/send-message-status", methods=["GET"])(server.send_message_status)
|
flask_app.route("/send-message-status", methods=["GET"])(server.send_message_status)
|
||||||
flask_app.route("/save", methods=["GET"])(server.save)
|
flask_app.route("/save", methods=["GET"])(server.save)
|
||||||
flask_app.route("/plugins", methods=["GET"])(server.plugins)
|
flask_app.route("/plugins", methods=["GET"])(server.plugins)
|
||||||
return flask_app
|
|
||||||
|
socketio = SocketIO(
|
||||||
|
flask_app, logger=False, engineio_logger=False,
|
||||||
|
async_mode="threading",
|
||||||
|
)
|
||||||
|
# import eventlet
|
||||||
|
# eventlet.monkey_patch()
|
||||||
|
|
||||||
|
socketio.on_namespace(SendMessageNamespace("/ws", config=config))
|
||||||
|
return socketio, flask_app
|
||||||
|
@ -513,8 +513,9 @@ def server(
|
|||||||
|
|
||||||
if web_enabled:
|
if web_enabled:
|
||||||
flask_enabled = True
|
flask_enabled = True
|
||||||
app = flask.init_flask(config, loglevel, quiet)
|
(socketio, app) = flask.init_flask(config, loglevel, quiet)
|
||||||
app.run(
|
socketio.run(
|
||||||
|
app,
|
||||||
host=config["aprsd"]["web"]["host"],
|
host=config["aprsd"]["web"]["host"],
|
||||||
port=config["aprsd"]["web"]["port"],
|
port=config["aprsd"]["web"]["port"],
|
||||||
)
|
)
|
||||||
|
@ -1,74 +1,145 @@
|
|||||||
msgs_list = {};
|
msgs_list = {};
|
||||||
|
var cleared = false;
|
||||||
|
|
||||||
function size_dict(d){c=0; for (i in d) ++c; return c}
|
function size_dict(d){c=0; for (i in d) ++c; return c}
|
||||||
|
|
||||||
function update_messages(data) {
|
function init_messages() {
|
||||||
msgs_cnt = size_dict(data);
|
const socket = io("/ws");
|
||||||
$('#msgs_count').html(msgs_cnt);
|
socket.on('connect', function () {
|
||||||
|
console.log("Connected to socketio");
|
||||||
|
});
|
||||||
|
socket.on('connected', function(msg) {
|
||||||
|
console.log("Connected!");
|
||||||
|
console.log(msg);
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on("sent", function(msg) {
|
||||||
|
if (cleared == false) {
|
||||||
var msgsdiv = $("#msgsDiv");
|
var msgsdiv = $("#msgsDiv");
|
||||||
//nuke the contents first, then add to it.
|
|
||||||
if (size_dict(msgs_list) == 0 && size_dict(data) > 0) {
|
|
||||||
msgsdiv.html('')
|
msgsdiv.html('')
|
||||||
|
cleared = true
|
||||||
|
}
|
||||||
|
add_msg(msg);
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on("ack", function(msg) {
|
||||||
|
update_msg(msg);
|
||||||
|
});
|
||||||
|
socket.on("reply", function(msg) {
|
||||||
|
update_msg(msg);
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#sendform").submit(function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
var $checkboxes = $(this).find('input[type=checkbox]');
|
||||||
|
|
||||||
|
//loop through the checkboxes and change to hidden fields
|
||||||
|
$checkboxes.each(function() {
|
||||||
|
if ($(this)[0].checked) {
|
||||||
|
$(this).attr('type', 'hidden');
|
||||||
|
$(this).val(1);
|
||||||
|
} else {
|
||||||
|
$(this).attr('type', 'hidden');
|
||||||
|
$(this).val(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
msg = {'from': $('#from').val(),
|
||||||
|
'password': $('#password').val(),
|
||||||
|
'to': $('#to').val(),
|
||||||
|
'message': $('#message').val(),
|
||||||
|
'wait_reply': $('#wait_reply').val(),
|
||||||
}
|
}
|
||||||
|
|
||||||
jQuery.each(data, function(i, val) {
|
socket.emit("send", msg);
|
||||||
if ( msgs_list.hasOwnProperty(val["ts"]) == false ) {
|
|
||||||
// Store the packet
|
//loop through the checkboxes and change to hidden fields
|
||||||
msgs_list[val["ts"]] = val;
|
$checkboxes.each(function() {
|
||||||
ts_str = val["ts"].toString();
|
$(this).attr('type', 'checkbox');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_msg(msg) {
|
||||||
|
var msgsdiv = $("#msgsDiv");
|
||||||
|
|
||||||
|
ts_str = msg["ts"].toString();
|
||||||
ts = ts_str.split(".")[0]*1000;
|
ts = ts_str.split(".")[0]*1000;
|
||||||
var d = new Date(ts).toLocaleDateString("en-US")
|
var d = new Date(ts).toLocaleDateString("en-US")
|
||||||
var t = new Date(ts).toLocaleTimeString("en-US")
|
var t = new Date(ts).toLocaleTimeString("en-US")
|
||||||
|
|
||||||
from = val['from']
|
from = msg['from']
|
||||||
title_id = 'title_tx'
|
title_id = 'title_tx'
|
||||||
var from_to = d + " " + t + " " + from + " > "
|
var from_to = d + " " + t + " " + from + " > "
|
||||||
|
|
||||||
if (val.hasOwnProperty('to')) {
|
if (msg.hasOwnProperty('to')) {
|
||||||
from_to = from_to + val['to']
|
from_to = from_to + msg['to']
|
||||||
}
|
}
|
||||||
from_to = from_to + " - " + val['raw']
|
from_to = from_to + " - " + msg['message']
|
||||||
|
|
||||||
id = ts_str.split('.')[0]
|
id = ts_str.split('.')[0]
|
||||||
pretty_id = "pretty_" + id
|
pretty_id = "pretty_" + id
|
||||||
loader_id = "loader_" + id
|
loader_id = "loader_" + id
|
||||||
|
ack_id = "ack_" + id
|
||||||
reply_id = "reply_" + id
|
reply_id = "reply_" + id
|
||||||
json_pretty = Prism.highlight(JSON.stringify(val, null, '\t'), Prism.languages.json, 'json');
|
span_id = "span_" + id
|
||||||
|
json_pretty = Prism.highlight(JSON.stringify(msg, null, '\t'), Prism.languages.json, 'json');
|
||||||
msg_html = '<div class="ui title" id="' + title_id + '"><i class="dropdown icon"></i>';
|
msg_html = '<div class="ui title" id="' + title_id + '"><i class="dropdown icon"></i>';
|
||||||
msg_html += '<div class="ui active inline loader" id="' + loader_id +'" data-content="Waiting for Ack"></div> ';
|
msg_html += '<div class="ui active inline loader" id="' + loader_id +'" data-content="Waiting for Ack"></div> ';
|
||||||
msg_html += '<i class="thumbs down outline icon" id="' + reply_id + '" data-content="Waiting for Reply"></i> ' + from_to + '</div>';
|
msg_html += '<i class="thumbs down outline icon" id="' + ack_id + '" data-content="Waiting for ACK"></i> ';
|
||||||
|
msg_html += '<i class="thumbs down outline icon" id="' + reply_id + '" data-content="Waiting for Reply"></i> ';
|
||||||
|
msg_html += '<span id="' + span_id + '">' + from_to +'</span></div>';
|
||||||
msg_html += '<div class="content"><p class="transition hidden"><pre id="' + pretty_id + '" class="language-json">' + json_pretty + '</p></p></div>'
|
msg_html += '<div class="content"><p class="transition hidden"><pre id="' + pretty_id + '" class="language-json">' + json_pretty + '</p></p></div>'
|
||||||
msgsdiv.prepend(msg_html);
|
msgsdiv.prepend(msg_html);
|
||||||
} else {
|
$('.ui.accordion').accordion('refresh');
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_msg(msg) {
|
||||||
|
var msgsdiv = $("#msgsDiv");
|
||||||
// We have an existing entry
|
// We have an existing entry
|
||||||
msgs_list[val["ts"]] = val;
|
ts_str = msg["ts"].toString();
|
||||||
ts_str = val["ts"].toString();
|
|
||||||
id = ts_str.split('.')[0]
|
id = ts_str.split('.')[0]
|
||||||
pretty_id = "pretty_" + id
|
pretty_id = "pretty_" + id
|
||||||
loader_id = "loader_" + id
|
loader_id = "loader_" + id
|
||||||
reply_id = "reply_" + id
|
reply_id = "reply_" + id
|
||||||
var pretty_pre = $("#" + pretty_id);
|
ack_id = "ack_" + id
|
||||||
if (val['ack'] == true) {
|
span_id = "span_" + id
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (msg['ack'] == true) {
|
||||||
var loader_div = $('#' + loader_id);
|
var loader_div = $('#' + loader_id);
|
||||||
|
var ack_div = $('#' + ack_id);
|
||||||
loader_div.removeClass('ui active inline loader');
|
loader_div.removeClass('ui active inline loader');
|
||||||
loader_div.addClass('ui disabled loader');
|
loader_div.addClass('ui disabled loader');
|
||||||
loader_div.attr('data-content', 'Got reply');
|
ack_div.removeClass('thumbs up outline icon');
|
||||||
|
ack_div.addClass('thumbs up outline icon');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (val['reply'] !== null) {
|
if (msg['reply'] !== null) {
|
||||||
var reply_div = $('#' + reply_id);
|
var reply_div = $('#' + reply_id);
|
||||||
reply_div.removeClass("thumbs down outline icon");
|
reply_div.removeClass("thumbs down outline icon");
|
||||||
reply_div.addClass('thumbs up outline icon');
|
reply_div.addClass('reply icon');
|
||||||
reply_div.attr('data-content', 'Got Reply');
|
reply_div.attr('data-content', 'Got Reply');
|
||||||
|
|
||||||
|
var d = new Date(ts).toLocaleDateString("en-US")
|
||||||
|
var t = new Date(ts).toLocaleTimeString("en-US")
|
||||||
|
var from_to = d + " " + t + " " + from + " > "
|
||||||
|
|
||||||
|
if (msg.hasOwnProperty('to')) {
|
||||||
|
from_to = from_to + msg['to']
|
||||||
|
}
|
||||||
|
from_to = from_to + " - " + msg['message']
|
||||||
|
from_to += " ===> " + msg["reply"]["message_text"]
|
||||||
|
|
||||||
|
var span_div = $('#' + span_id);
|
||||||
|
span_div.html(from_to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var pretty_pre = $("#" + pretty_id);
|
||||||
pretty_pre.html('');
|
pretty_pre.html('');
|
||||||
json_pretty = Prism.highlight(JSON.stringify(val, null, '\t'), Prism.languages.json, 'json');
|
json_pretty = Prism.highlight(JSON.stringify(msg, null, '\t'), Prism.languages.json, 'json');
|
||||||
pretty_pre.html(json_pretty);
|
pretty_pre.html(json_pretty);
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.ui.accordion').accordion('refresh');
|
$('.ui.accordion').accordion('refresh');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,9 @@
|
|||||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
|
||||||
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
|
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
|
||||||
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
|
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/jquery-simple-websocket@1.1.4/src/jquery.simple.websocket.min.js"></script>
|
||||||
|
<script src="https://cdn.socket.io/4.1.2/socket.io.min.js" integrity="sha384-toS6mmwu70G0fw54EGlWWeA4z3dyJ+dlXBtSURSKN4vyRFOcxd3Bzjj/AoOwY+Rg" crossorigin="anonymous"></script>
|
||||||
|
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.23.0/prism.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.23.0/prism.min.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.23.0/components/prism-json.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.23.0/components/prism-json.js"></script>
|
||||||
@ -17,51 +20,7 @@
|
|||||||
|
|
||||||
<script language="JavaScript">
|
<script language="JavaScript">
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
init_messages();
|
||||||
$("#sendform").submit(function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
var $checkboxes = $(this).find('input[type=checkbox]');
|
|
||||||
|
|
||||||
//loop through the checkboxes and change to hidden fields
|
|
||||||
$checkboxes.each(function() {
|
|
||||||
if ($(this)[0].checked) {
|
|
||||||
$(this).attr('type', 'hidden');
|
|
||||||
$(this).val(1);
|
|
||||||
} else {
|
|
||||||
$(this).attr('type', 'hidden');
|
|
||||||
$(this).val(0);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var posting = $.post("/send-message", $("#sendform").serialize());
|
|
||||||
|
|
||||||
posting.done(function(data, status){
|
|
||||||
console.log("Data: " + data + "\nStatus: " + status);
|
|
||||||
});
|
|
||||||
|
|
||||||
//loop through the checkboxes and change to hidden fields
|
|
||||||
$checkboxes.each(function() {
|
|
||||||
$(this).attr('type', 'checkbox');
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
(function sent_msg_worker() {
|
|
||||||
$.ajax({
|
|
||||||
url: "/send-message-status",
|
|
||||||
type: 'GET',
|
|
||||||
dataType: 'json',
|
|
||||||
success: function(data) {
|
|
||||||
update_messages(data);
|
|
||||||
},
|
|
||||||
complete: function() {
|
|
||||||
setTimeout(sent_msg_worker, 1000);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})();
|
|
||||||
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -87,12 +46,12 @@
|
|||||||
<h3 class="ui dividing header">Send Message Form</h3>
|
<h3 class="ui dividing header">Send Message Form</h3>
|
||||||
<form id="sendform" name="sendmsg" action="">
|
<form id="sendform" name="sendmsg" action="">
|
||||||
<p><label for="from_call">From Callsign:</label>
|
<p><label for="from_call">From Callsign:</label>
|
||||||
<input type="text" name="from_call" id="fcall" value="WB4BOR"></p>
|
<input type="text" name="from_call" id="from" value="WB4BOR"></p>
|
||||||
<p><label for="from_call_password">Password:</label>
|
<p><label for="from_call_password">Password:</label>
|
||||||
<input type="text" name="from_call_password" value="24496"></p>
|
<input type="password" name="from_call_password" id='password' value="24496"></p>
|
||||||
|
|
||||||
<p><label for="to_call">To Callsign:</label>
|
<p><label for="to_call">To Callsign:</label>
|
||||||
<input type="text" name="to_call" id="tcall" value="WB4BOR-11"></p>
|
<input type="text" name="to_call" id="to" value="WB4BOR-11"></p>
|
||||||
|
|
||||||
<p><label for="message">Message:</label>
|
<p><label for="message">Message:</label>
|
||||||
<input type="text" name="message" id="message" value="ping"></p>
|
<input type="text" name="message" id="message" value="ping"></p>
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
flake8
|
flake8
|
||||||
isort
|
isort
|
||||||
mypy
|
mypy
|
||||||
pytest
|
|
||||||
pytest-cov
|
|
||||||
pep8-naming
|
pep8-naming
|
||||||
Sphinx
|
Sphinx
|
||||||
tox
|
tox
|
||||||
twine
|
twine
|
||||||
pre-commit
|
pre-commit
|
||||||
pip-tools
|
pip-tools
|
||||||
|
#pytest
|
||||||
|
#pytest-cov
|
||||||
gray
|
gray
|
||||||
|
@ -9,28 +9,26 @@ add-trailing-comma==2.1.0
|
|||||||
alabaster==0.7.12
|
alabaster==0.7.12
|
||||||
# via sphinx
|
# via sphinx
|
||||||
appdirs==1.4.4
|
appdirs==1.4.4
|
||||||
# via
|
# via black
|
||||||
# black
|
attrs==21.2.0
|
||||||
# virtualenv
|
# via jsonschema
|
||||||
attrs==20.3.0
|
|
||||||
# via
|
|
||||||
# jsonschema
|
|
||||||
# pytest
|
|
||||||
autoflake==1.4
|
autoflake==1.4
|
||||||
# via gray
|
# via gray
|
||||||
babel==2.9.1
|
babel==2.9.1
|
||||||
# via sphinx
|
# via sphinx
|
||||||
|
backports.entry-points-selectable==1.1.0
|
||||||
|
# via virtualenv
|
||||||
black==21.7b0
|
black==21.7b0
|
||||||
# via gray
|
# via gray
|
||||||
bleach==3.3.0
|
bleach==4.1.0
|
||||||
# via readme-renderer
|
# via readme-renderer
|
||||||
certifi==2020.12.5
|
certifi==2021.5.30
|
||||||
# via requests
|
# via requests
|
||||||
cfgv==3.2.0
|
cfgv==3.3.1
|
||||||
# via pre-commit
|
# via pre-commit
|
||||||
chardet==4.0.0
|
charset-normalizer==2.0.4
|
||||||
# via requests
|
# via requests
|
||||||
click==7.1.2
|
click==8.0.1
|
||||||
# via
|
# via
|
||||||
# black
|
# black
|
||||||
# pip-tools
|
# pip-tools
|
||||||
@ -40,11 +38,9 @@ colorlog==6.4.1
|
|||||||
# via prettylog
|
# via prettylog
|
||||||
configargparse==1.5.2
|
configargparse==1.5.2
|
||||||
# via gray
|
# via gray
|
||||||
coverage==5.5
|
distlib==0.3.2
|
||||||
# via pytest-cov
|
|
||||||
distlib==0.3.1
|
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
docutils==0.16
|
docutils==0.17.1
|
||||||
# via
|
# via
|
||||||
# readme-renderer
|
# readme-renderer
|
||||||
# sphinx
|
# sphinx
|
||||||
@ -58,40 +54,39 @@ fixit==0.1.4
|
|||||||
# via gray
|
# via gray
|
||||||
flake8-polyfill==1.0.2
|
flake8-polyfill==1.0.2
|
||||||
# via pep8-naming
|
# via pep8-naming
|
||||||
flake8==3.9.1
|
flake8==3.9.2
|
||||||
# via
|
# via
|
||||||
# -r dev-requirements.in
|
# -r dev-requirements.in
|
||||||
# fixit
|
# fixit
|
||||||
# flake8-polyfill
|
# flake8-polyfill
|
||||||
|
# pep8-naming
|
||||||
gray==0.10.1
|
gray==0.10.1
|
||||||
# via -r dev-requirements.in
|
# via -r dev-requirements.in
|
||||||
identify==2.2.4
|
identify==2.2.13
|
||||||
# via pre-commit
|
# via pre-commit
|
||||||
idna==2.10
|
idna==3.2
|
||||||
# via requests
|
# via requests
|
||||||
imagesize==1.2.0
|
imagesize==1.2.0
|
||||||
# via sphinx
|
# via sphinx
|
||||||
importlib-metadata==4.0.1
|
importlib-metadata==4.7.1
|
||||||
# via
|
# via
|
||||||
# keyring
|
# keyring
|
||||||
# twine
|
# twine
|
||||||
importlib-resources==5.2.2
|
importlib-resources==5.2.2
|
||||||
# via fixit
|
# via fixit
|
||||||
iniconfig==1.1.1
|
isort==5.9.3
|
||||||
# via pytest
|
|
||||||
isort==5.8.0
|
|
||||||
# via
|
# via
|
||||||
# -r dev-requirements.in
|
# -r dev-requirements.in
|
||||||
# gray
|
# gray
|
||||||
jinja2==2.11.3
|
jinja2==3.0.1
|
||||||
# via sphinx
|
# via sphinx
|
||||||
jsonschema==3.2.0
|
jsonschema==3.2.0
|
||||||
# via fixit
|
# via fixit
|
||||||
keyring==23.0.1
|
keyring==23.1.0
|
||||||
# via twine
|
# via twine
|
||||||
libcst==0.3.20
|
libcst==0.3.20
|
||||||
# via fixit
|
# via fixit
|
||||||
markupsafe==1.1.1
|
markupsafe==2.0.1
|
||||||
# via jinja2
|
# via jinja2
|
||||||
mccabe==0.6.1
|
mccabe==0.6.1
|
||||||
# via flake8
|
# via flake8
|
||||||
@ -100,45 +95,42 @@ mypy-extensions==0.4.3
|
|||||||
# black
|
# black
|
||||||
# mypy
|
# mypy
|
||||||
# typing-inspect
|
# typing-inspect
|
||||||
mypy==0.812
|
mypy==0.910
|
||||||
# via -r dev-requirements.in
|
# via -r dev-requirements.in
|
||||||
nodeenv==1.6.0
|
nodeenv==1.6.0
|
||||||
# via pre-commit
|
# via pre-commit
|
||||||
packaging==20.9
|
packaging==21.0
|
||||||
# via
|
# via
|
||||||
# bleach
|
# bleach
|
||||||
# pytest
|
|
||||||
# sphinx
|
# sphinx
|
||||||
# tox
|
# tox
|
||||||
pathspec==0.8.1
|
pathspec==0.9.0
|
||||||
# via black
|
# via black
|
||||||
pep517==0.10.0
|
pep517==0.11.0
|
||||||
# via pip-tools
|
# via pip-tools
|
||||||
pep8-naming==0.11.1
|
pep8-naming==0.12.1
|
||||||
# via -r dev-requirements.in
|
# via -r dev-requirements.in
|
||||||
pip-tools==6.1.0
|
pip-tools==6.2.0
|
||||||
# via -r dev-requirements.in
|
# via -r dev-requirements.in
|
||||||
pkginfo==1.7.0
|
pkginfo==1.7.1
|
||||||
# via twine
|
# via twine
|
||||||
pluggy==0.13.1
|
platformdirs==2.2.0
|
||||||
# via
|
# via virtualenv
|
||||||
# pytest
|
pluggy==1.0.0
|
||||||
# tox
|
# via tox
|
||||||
pre-commit==2.12.1
|
pre-commit==2.14.0
|
||||||
# via -r dev-requirements.in
|
# via -r dev-requirements.in
|
||||||
prettylog==0.3.0
|
prettylog==0.3.0
|
||||||
# via gray
|
# via gray
|
||||||
py==1.10.0
|
py==1.10.0
|
||||||
# via
|
# via tox
|
||||||
# pytest
|
|
||||||
# tox
|
|
||||||
pycodestyle==2.7.0
|
pycodestyle==2.7.0
|
||||||
# via flake8
|
# via flake8
|
||||||
pyflakes==2.3.1
|
pyflakes==2.3.1
|
||||||
# via
|
# via
|
||||||
# autoflake
|
# autoflake
|
||||||
# flake8
|
# flake8
|
||||||
pygments==2.9.0
|
pygments==2.10.0
|
||||||
# via
|
# via
|
||||||
# readme-renderer
|
# readme-renderer
|
||||||
# sphinx
|
# sphinx
|
||||||
@ -146,12 +138,6 @@ pyparsing==2.4.7
|
|||||||
# via packaging
|
# via packaging
|
||||||
pyrsistent==0.18.0
|
pyrsistent==0.18.0
|
||||||
# via jsonschema
|
# via jsonschema
|
||||||
pytest-cov==2.11.1
|
|
||||||
# via -r dev-requirements.in
|
|
||||||
pytest==6.2.3
|
|
||||||
# via
|
|
||||||
# -r dev-requirements.in
|
|
||||||
# pytest-cov
|
|
||||||
pytz==2021.1
|
pytz==2021.1
|
||||||
# via babel
|
# via babel
|
||||||
pyupgrade==2.24.0
|
pyupgrade==2.24.0
|
||||||
@ -163,18 +149,18 @@ pyyaml==5.4.1
|
|||||||
# pre-commit
|
# pre-commit
|
||||||
readme-renderer==29.0
|
readme-renderer==29.0
|
||||||
# via twine
|
# via twine
|
||||||
regex==2021.4.4
|
regex==2021.8.27
|
||||||
# via black
|
# via black
|
||||||
requests-toolbelt==0.9.1
|
requests-toolbelt==0.9.1
|
||||||
# via twine
|
# via twine
|
||||||
requests==2.25.1
|
requests==2.26.0
|
||||||
# via
|
# via
|
||||||
# requests-toolbelt
|
# requests-toolbelt
|
||||||
# sphinx
|
# sphinx
|
||||||
# twine
|
# twine
|
||||||
rfc3986==1.4.0
|
rfc3986==1.5.0
|
||||||
# via twine
|
# via twine
|
||||||
six==1.15.0
|
six==1.16.0
|
||||||
# via
|
# via
|
||||||
# bleach
|
# bleach
|
||||||
# jsonschema
|
# jsonschema
|
||||||
@ -183,19 +169,19 @@ six==1.15.0
|
|||||||
# virtualenv
|
# virtualenv
|
||||||
snowballstemmer==2.1.0
|
snowballstemmer==2.1.0
|
||||||
# via sphinx
|
# via sphinx
|
||||||
sphinx==3.5.4
|
sphinx==4.1.2
|
||||||
# via -r dev-requirements.in
|
# via -r dev-requirements.in
|
||||||
sphinxcontrib-applehelp==1.0.2
|
sphinxcontrib-applehelp==1.0.2
|
||||||
# via sphinx
|
# via sphinx
|
||||||
sphinxcontrib-devhelp==1.0.2
|
sphinxcontrib-devhelp==1.0.2
|
||||||
# via sphinx
|
# via sphinx
|
||||||
sphinxcontrib-htmlhelp==1.0.3
|
sphinxcontrib-htmlhelp==2.0.0
|
||||||
# via sphinx
|
# via sphinx
|
||||||
sphinxcontrib-jsmath==1.0.1
|
sphinxcontrib-jsmath==1.0.1
|
||||||
# via sphinx
|
# via sphinx
|
||||||
sphinxcontrib-qthelp==1.0.3
|
sphinxcontrib-qthelp==1.0.3
|
||||||
# via sphinx
|
# via sphinx
|
||||||
sphinxcontrib-serializinghtml==1.1.4
|
sphinxcontrib-serializinghtml==1.1.5
|
||||||
# via sphinx
|
# via sphinx
|
||||||
tokenize-rt==4.1.0
|
tokenize-rt==4.1.0
|
||||||
# via
|
# via
|
||||||
@ -203,20 +189,19 @@ tokenize-rt==4.1.0
|
|||||||
# pyupgrade
|
# pyupgrade
|
||||||
toml==0.10.2
|
toml==0.10.2
|
||||||
# via
|
# via
|
||||||
# pep517
|
# mypy
|
||||||
# pre-commit
|
# pre-commit
|
||||||
# pytest
|
|
||||||
# tox
|
# tox
|
||||||
tomli==1.2.1
|
tomli==1.2.1
|
||||||
# via black
|
# via
|
||||||
tox==3.23.0
|
# black
|
||||||
|
# pep517
|
||||||
|
tox==3.24.3
|
||||||
# via -r dev-requirements.in
|
# via -r dev-requirements.in
|
||||||
tqdm==4.60.0
|
tqdm==4.62.2
|
||||||
# via twine
|
# via twine
|
||||||
twine==3.4.1
|
twine==3.4.2
|
||||||
# via -r dev-requirements.in
|
# via -r dev-requirements.in
|
||||||
typed-ast==1.4.3
|
|
||||||
# via mypy
|
|
||||||
typing-extensions==3.10.0.0
|
typing-extensions==3.10.0.0
|
||||||
# via
|
# via
|
||||||
# libcst
|
# libcst
|
||||||
@ -230,15 +215,17 @@ unify==0.5
|
|||||||
# via gray
|
# via gray
|
||||||
untokenize==0.1.1
|
untokenize==0.1.1
|
||||||
# via unify
|
# via unify
|
||||||
urllib3==1.26.5
|
urllib3==1.26.6
|
||||||
# via requests
|
# via requests
|
||||||
virtualenv==20.4.4
|
virtualenv==20.7.2
|
||||||
# via
|
# via
|
||||||
# pre-commit
|
# pre-commit
|
||||||
# tox
|
# tox
|
||||||
webencodings==0.5.1
|
webencodings==0.5.1
|
||||||
# via bleach
|
# via bleach
|
||||||
zipp==3.4.1
|
wheel==0.37.0
|
||||||
|
# via pip-tools
|
||||||
|
zipp==3.5.0
|
||||||
# via
|
# via
|
||||||
# importlib-metadata
|
# importlib-metadata
|
||||||
# importlib-resources
|
# importlib-resources
|
||||||
|
@ -12,10 +12,12 @@ pbr
|
|||||||
pyyaml
|
pyyaml
|
||||||
# Allowing a newer version can lead to a conflict with
|
# Allowing a newer version can lead to a conflict with
|
||||||
# requests.
|
# requests.
|
||||||
py3-validate-email==0.2.16
|
# py3-validate-email
|
||||||
pytz
|
pytz
|
||||||
requests
|
requests
|
||||||
six
|
six
|
||||||
thesmuggler
|
thesmuggler
|
||||||
yfinance
|
yfinance
|
||||||
update_checker
|
update_checker
|
||||||
|
flask-socketio
|
||||||
|
eventlet
|
||||||
|
@ -8,17 +8,19 @@ aioax25==0.0.10
|
|||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
aprslib==0.6.47
|
aprslib==0.6.47
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
backoff==1.10.0
|
backoff==1.11.1
|
||||||
# via opencage
|
# via opencage
|
||||||
certifi==2020.12.5
|
bidict==0.21.2
|
||||||
|
# via python-socketio
|
||||||
|
certifi==2021.5.30
|
||||||
# via requests
|
# via requests
|
||||||
cffi==1.14.5
|
cffi==1.14.6
|
||||||
# via cryptography
|
# via cryptography
|
||||||
chardet==4.0.0
|
charset-normalizer==2.0.4
|
||||||
# via requests
|
# via requests
|
||||||
click-completion==0.5.2
|
click-completion==0.5.2
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
click==7.1.2
|
click==8.0.1
|
||||||
# via
|
# via
|
||||||
# -r requirements.in
|
# -r requirements.in
|
||||||
# click-completion
|
# click-completion
|
||||||
@ -27,50 +29,51 @@ contexter==0.1.4
|
|||||||
# via signalslot
|
# via signalslot
|
||||||
cryptography==3.4.7
|
cryptography==3.4.7
|
||||||
# via pyopenssl
|
# via pyopenssl
|
||||||
dnspython==2.1.0
|
dnspython==1.16.0
|
||||||
# via py3-validate-email
|
# via eventlet
|
||||||
filelock==3.0.12
|
eventlet==0.31.1
|
||||||
# via py3-validate-email
|
# via -r requirements.in
|
||||||
flask-classful==0.14.2
|
flask-classful==0.14.2
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
flask-httpauth==4.3.0
|
flask-httpauth==4.4.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
flask==1.1.2
|
flask-socketio==5.1.1
|
||||||
|
# via -r requirements.in
|
||||||
|
flask==2.0.1
|
||||||
# via
|
# via
|
||||||
# -r requirements.in
|
# -r requirements.in
|
||||||
# flask-classful
|
# flask-classful
|
||||||
# flask-httpauth
|
# flask-httpauth
|
||||||
idna==2.10
|
# flask-socketio
|
||||||
# via
|
greenlet==1.1.1
|
||||||
# py3-validate-email
|
# via eventlet
|
||||||
# requests
|
idna==3.2
|
||||||
|
# via requests
|
||||||
imapclient==2.2.0
|
imapclient==2.2.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
itsdangerous==1.1.0
|
itsdangerous==2.0.1
|
||||||
# via flask
|
# via flask
|
||||||
jinja2==2.11.3
|
jinja2==3.0.1
|
||||||
# via
|
# via
|
||||||
# click-completion
|
# click-completion
|
||||||
# flask
|
# flask
|
||||||
lxml==4.6.3
|
lxml==4.6.3
|
||||||
# via yfinance
|
# via yfinance
|
||||||
markupsafe==1.1.1
|
markupsafe==2.0.1
|
||||||
# via jinja2
|
# via jinja2
|
||||||
multitasking==0.0.9
|
multitasking==0.0.9
|
||||||
# via yfinance
|
# via yfinance
|
||||||
numpy==1.20.2
|
numpy==1.21.2
|
||||||
# via
|
# via
|
||||||
# pandas
|
# pandas
|
||||||
# yfinance
|
# yfinance
|
||||||
opencage==1.2.2
|
opencage==2.0.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
pandas==1.2.4
|
pandas==1.3.2
|
||||||
# via yfinance
|
# via yfinance
|
||||||
pbr==5.6.0
|
pbr==5.6.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
pluggy==0.13.1
|
pluggy==1.0.0
|
||||||
# via -r requirements.in
|
|
||||||
py3-validate-email==0.2.16
|
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
pycparser==2.20
|
pycparser==2.20
|
||||||
# via cffi
|
# via cffi
|
||||||
@ -80,13 +83,17 @@ pyserial==3.5
|
|||||||
# via aioax25
|
# via aioax25
|
||||||
python-dateutil==2.8.1
|
python-dateutil==2.8.1
|
||||||
# via pandas
|
# via pandas
|
||||||
|
python-engineio==4.2.1
|
||||||
|
# via python-socketio
|
||||||
|
python-socketio==5.4.0
|
||||||
|
# via flask-socketio
|
||||||
pytz==2021.1
|
pytz==2021.1
|
||||||
# via
|
# via
|
||||||
# -r requirements.in
|
# -r requirements.in
|
||||||
# pandas
|
# pandas
|
||||||
pyyaml==5.4.1
|
pyyaml==5.4.1
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
requests==2.25.1
|
requests==2.26.0
|
||||||
# via
|
# via
|
||||||
# -r requirements.in
|
# -r requirements.in
|
||||||
# opencage
|
# opencage
|
||||||
@ -100,8 +107,8 @@ six==1.15.0
|
|||||||
# via
|
# via
|
||||||
# -r requirements.in
|
# -r requirements.in
|
||||||
# click-completion
|
# click-completion
|
||||||
|
# eventlet
|
||||||
# imapclient
|
# imapclient
|
||||||
# opencage
|
|
||||||
# pyopenssl
|
# pyopenssl
|
||||||
# python-dateutil
|
# python-dateutil
|
||||||
# signalslot
|
# signalslot
|
||||||
@ -109,11 +116,11 @@ thesmuggler==1.0.1
|
|||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
update-checker==0.18.0
|
update-checker==0.18.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
urllib3==1.26.5
|
urllib3==1.26.6
|
||||||
# via requests
|
# via requests
|
||||||
weakrefmethod==1.0.3
|
weakrefmethod==1.0.3
|
||||||
# via signalslot
|
# via signalslot
|
||||||
werkzeug==1.0.1
|
werkzeug==1.0.1
|
||||||
# via flask
|
# via flask
|
||||||
yfinance==0.1.59
|
yfinance==0.1.63
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
|
Loading…
Reference in New Issue
Block a user