Message sending and receiving appears provisionally working. Job system next... :D
This commit is contained in:
@@ -165,7 +165,7 @@ class Message:
|
||||
def payload(self):
|
||||
if 'd' in self.data:
|
||||
pl = self.data['d']
|
||||
if type(pl) in (dict, str, bytes):
|
||||
if type(pl) in (dict, str, bytes, list):
|
||||
return pl
|
||||
else:
|
||||
return str(pl)
|
||||
@@ -173,11 +173,15 @@ class Message:
|
||||
return ""
|
||||
|
||||
@payload.setter
|
||||
def payload(self, payload: Union[str, bytes, dict]):
|
||||
if type(payload) in (str, bytes, dict):
|
||||
def payload(self, payload: Union[str, bytes, dict, list]):
|
||||
logging.debug(f"Setting a message payload: {type(payload)}: {payload}")
|
||||
if type(payload) in (str, bytes, dict, list):
|
||||
logging.debug(f"Payload type is {type(payload)}, conversion to string unnecessary")
|
||||
self.data['d'] = payload
|
||||
else:
|
||||
logging.debug("payload type is not in (str, bytes, dict, list); converting to string")
|
||||
self.data['d'] = str(payload)
|
||||
logging.debug(f"Final payload is: {type(payload)}: {payload}")
|
||||
|
||||
@classmethod
|
||||
def partial_unpack(cls, msg: dict) -> Self:
|
||||
|
||||
@@ -36,6 +36,7 @@ class Server:
|
||||
self.zeo_addr = None
|
||||
self.zeo_stop = None
|
||||
self.zeo = zeo
|
||||
self.started = False
|
||||
if data_dir:
|
||||
data_path = Path(data_dir)
|
||||
else:
|
||||
@@ -170,6 +171,13 @@ class Server:
|
||||
def register_path_handler(self, path_root: str, fn: Callable):
|
||||
self.handlers[path_root.strip().lower()] = fn
|
||||
|
||||
def server_worker(self):
|
||||
"""When called, do things. Should get called every so often."""
|
||||
if not self.started:
|
||||
return
|
||||
# Add things to do here:
|
||||
pass
|
||||
|
||||
def start_db(self):
|
||||
if not self.zeo:
|
||||
self.storage = ZODB.FileStorage.FileStorage(self.data_file)
|
||||
@@ -192,6 +200,11 @@ class Server:
|
||||
self.start_db()
|
||||
self.app.start(self.pe_server, self.pe_port)
|
||||
self.app.register_callsigns(self.callsign)
|
||||
self.started = True
|
||||
while self.started:
|
||||
self.server_worker()
|
||||
time.sleep(5)
|
||||
|
||||
|
||||
def exit_gracefully(self, signum, frame):
|
||||
self.stop()
|
||||
|
||||
@@ -120,7 +120,7 @@ class MessageAlreadySentError(Exception):
|
||||
pass
|
||||
|
||||
class Message(persistent.Persistent):
|
||||
def __init__(self, text: str, msg_to: Optional[Iterable[str],str]= None, msg_from: Optional[str] = None,
|
||||
def __init__(self, text: str, msg_to: Optional[Iterable[str]]= None, msg_from: Optional[str] = None,
|
||||
attachments: Optional[Iterable[Attachment]] = None):
|
||||
self.retrieved = False
|
||||
self.sent_at = datetime.datetime.now(datetime.UTC)
|
||||
@@ -166,7 +166,7 @@ class Message(persistent.Persistent):
|
||||
"attachments": attachments,
|
||||
"to": self.msg_to,
|
||||
"from": self.msg_from,
|
||||
"id": self.msg_id,
|
||||
"id": str(self.msg_id),
|
||||
"sent_at": self.sent_at.isoformat(),
|
||||
"text": ""
|
||||
}
|
||||
@@ -175,6 +175,10 @@ class Message(persistent.Persistent):
|
||||
|
||||
return d
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: dict) -> Self:
|
||||
return Message(data['text'],msg_to=data.get('to'), attachments=data.get("attachments"))
|
||||
|
||||
def send(self, db: ZODB.DB) -> tuple:
|
||||
if self.msg_delivered:
|
||||
raise MessageAlreadySentError("Cannot send a private message that has already been sent.")
|
||||
@@ -221,6 +225,7 @@ DisplayOptions = namedtuple('DisplayOptions', ['get_text', 'limit', 'sort_by', '
|
||||
'get_attachments', 'sent_received_all'])
|
||||
|
||||
def parse_display_options(req: Request) -> DisplayOptions:
|
||||
logging.debug(f"Parsing request vars for message get: {req.vars}")
|
||||
sent_received_all = "received"
|
||||
d = req.vars.get("source")
|
||||
if type(d) is str:
|
||||
@@ -234,7 +239,7 @@ def parse_display_options(req: Request) -> DisplayOptions:
|
||||
try:
|
||||
limit = int(limit)
|
||||
except:
|
||||
limit = 10
|
||||
limit = None
|
||||
|
||||
d = req.vars.get('fetch_text')
|
||||
if type(d) is str:
|
||||
@@ -245,12 +250,15 @@ def parse_display_options(req: Request) -> DisplayOptions:
|
||||
get_text = True
|
||||
|
||||
d = req.vars.get('fetch_attachments')
|
||||
logging.debug(f"Parsing fetch_attachment var: {d}")
|
||||
if type(d) is str:
|
||||
d.lower().strip()
|
||||
if d in yes_values:
|
||||
logging.debug("fetch_attachment is yes")
|
||||
get_attachments = True
|
||||
else:
|
||||
get_attachments = False
|
||||
logging.debug("fetch_attachment is no")
|
||||
|
||||
r = req.vars.get('reverse')
|
||||
if type(r) is str:
|
||||
@@ -274,9 +282,9 @@ def parse_display_options(req: Request) -> DisplayOptions:
|
||||
if type(s) is str:
|
||||
s = s.lower()
|
||||
if s:
|
||||
search = str(s)
|
||||
search = str(s).lower()
|
||||
|
||||
return DisplayOptions(get_text, limit, sort_by, reverse, search, get_attachments, sent_receive_all)
|
||||
return DisplayOptions(get_text, limit, sort_by, reverse, search, get_attachments, sent_received_all)
|
||||
|
||||
|
||||
def handle_message_get(req: Request, conn: PacketServerConnection, db: ZODB.DB):
|
||||
@@ -285,21 +293,52 @@ def handle_message_get(req: Request, conn: PacketServerConnection, db: ZODB.DB):
|
||||
msg_return = []
|
||||
with db.transaction() as db:
|
||||
mailbox_create(username, db.root())
|
||||
mb = db.root.messages['username']
|
||||
messages = []
|
||||
if opts.reverse:
|
||||
for i in range(1,len(mb)+1):
|
||||
messages.append(mb[len(mb) - 1])
|
||||
mb = db.root.messages[username]
|
||||
if opts.search:
|
||||
messages = [msg for msg in mb if (opts.search in msg.text.lower()) or (opts.search in msg.msg_to[0].lower())
|
||||
or (opts.search in msg.msg_from.lower())]
|
||||
else:
|
||||
for i in range(0,len(mb)):
|
||||
messages.append(mb[i])
|
||||
for msg in messages:
|
||||
# do other filtering.
|
||||
messages = [msg for msg in mb]
|
||||
|
||||
if opts.sort_by == "from":
|
||||
messages.sort(key=lambda x: x.msg_from, reverse=opts.reverse)
|
||||
elif opts.sort_by == "to":
|
||||
messages.sort(key=lambda x: x.msg_to, reverse=opts.reverse)
|
||||
else:
|
||||
messages.sort(key=lambda x: x.sent_at, reverse=opts.reverse)
|
||||
|
||||
for i in range(0, len(messages)):
|
||||
if opts.limit and (len(msg_return) >= opts.limit):
|
||||
break
|
||||
|
||||
msg = messages[i]
|
||||
msg.retrieved = True
|
||||
msg_return.append(msg.to_dict(get_text=opts.get_text, get_attachments=opts.get_attachments))
|
||||
|
||||
def object_root_handler(req: Request, conn: PacketServerConnection, db: ZODB.DB):
|
||||
response = Response.blank()
|
||||
response.status_code = 200
|
||||
response.payload = msg_return
|
||||
send_response(conn, response, req)
|
||||
|
||||
def handle_message_post(req: Request, conn: PacketServerConnection, db: ZODB.DB):
|
||||
username = ax25.Address(conn.remote_callsign).call.upper().strip()
|
||||
try:
|
||||
msg = Message.from_dict(req.payload)
|
||||
except:
|
||||
send_blank_response(conn, req, status_code=400)
|
||||
logging.warning(f"User '{username}' attempted to post message with invalid payload: {req.payload}")
|
||||
return
|
||||
msg.msg_from = username
|
||||
try:
|
||||
send_counter, failed = msg.send(db)
|
||||
except:
|
||||
send_blank_response(conn, req, status_code=500)
|
||||
logging.error(f"Error while attempting to send message:\n{format_exc()}")
|
||||
return
|
||||
|
||||
send_blank_response(conn, req, status_code=201, payload={"successes": send_counter, "failed": failed})
|
||||
|
||||
def message_root_handler(req: Request, conn: PacketServerConnection, db: ZODB.DB):
|
||||
logging.debug(f"{req} being processed by user_root_handler")
|
||||
if not user_authorized(conn, db):
|
||||
logging.debug(f"user {conn.remote_callsign} not authorized")
|
||||
@@ -308,6 +347,8 @@ def object_root_handler(req: Request, conn: PacketServerConnection, db: ZODB.DB)
|
||||
logging.debug("user is authorized")
|
||||
if req.method is Request.Method.GET:
|
||||
handle_message_get(req, conn, db)
|
||||
if req.method is Request.Method.POST:
|
||||
handle_message_post(req, conn, db)
|
||||
else:
|
||||
send_blank_response(conn, req, status_code=404)
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ from packetserver.common import Message, Request, Response, PacketServerConnecti
|
||||
from .bulletin import bulletin_root_handler
|
||||
from .users import user_root_handler, user_authorized
|
||||
from .objects import object_root_handler
|
||||
from .messages import message_root_handler
|
||||
import logging
|
||||
from typing import Union
|
||||
import ZODB
|
||||
@@ -50,7 +51,8 @@ standard_handlers = {
|
||||
"": root_root_handler,
|
||||
"bulletin": bulletin_root_handler,
|
||||
"user": user_root_handler,
|
||||
"object": object_root_handler
|
||||
"object": object_root_handler,
|
||||
"message": message_root_handler
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user