reset the requirements.txt file. Added some fixes to messages and attachments hopefully.

This commit is contained in:
Michael Woods
2025-02-04 20:23:12 -05:00
parent d48cbc67c0
commit 2bfa42f6da
3 changed files with 96 additions and 1 deletions

Binary file not shown.

View File

@@ -1,4 +1,5 @@
import re import re
import datetime
def email_valid(email: str) -> bool: def email_valid(email: str) -> bool:
"""Taken from https://www.geeksforgeeks.org/check-if-email-address-valid-or-not-in-python/""" """Taken from https://www.geeksforgeeks.org/check-if-email-address-valid-or-not-in-python/"""
@@ -7,3 +8,35 @@ def email_valid(email: str) -> bool:
return True return True
else: else:
return False return False
def to_date_digits(index: datetime.datetime) -> str:
return f"{str(index.year).zfill(4)}{str(index.month).zfill(2)}{str(index.day).zfill(2)}{str(index.hour).zfill(2)}{str(index.minute).zfill(2)}{str(index.second).zfill(2)}"
def from_date_digits(index: str) -> datetime:
ind = str(index)
if not ind.isdigit():
raise ValueError("Received invalid date digit string, containing non-digit chars.")
if len(ind) < 4:
raise ValueError("Received invalid date digit string, needs to at least by four digits for a year")
year = int(ind[:4])
month = 1
day = 1
hour = 0
minute = 0
second = 0
if len(ind) >= 6:
month = int(ind[4:6])
if len(ind) >= 8:
day = int(ind[6:8])
if len(ind) >= 10:
hour = int(ind[8:10])
if len(ind) >= 12:
minute = int(ind[10:12])
if len(ind) >= 14:
second = int(ind[12:14])
return datetime.datetime(year, month, day ,hour, minute, second)

View File

@@ -8,6 +8,7 @@ from typing import Self,Union,Optional,Iterable,Sequence
from packetserver.common import PacketServerConnection, Request, Response, send_response, send_blank_response from packetserver.common import PacketServerConnection, Request, Response, send_response, send_blank_response
from packetserver.common import Message as PacketMessage from packetserver.common import Message as PacketMessage
from packetserver.common.constants import yes_values, no_values from packetserver.common.constants import yes_values, no_values
from packetserver.common.util import from_date_digits, to_date_digits
import ZODB import ZODB
import logging import logging
import uuid import uuid
@@ -18,7 +19,9 @@ from BTrees.OOBTree import TreeSet
from packetserver.server.users import User, user_authorized from packetserver.server.users import User, user_authorized
from traceback import format_exc from traceback import format_exc
from collections import namedtuple from collections import namedtuple
import re
since_regex = '''^message\/since\/(\d+)$'''
def mailbox_create(username: str, db_root: PersistentMapping): def mailbox_create(username: str, db_root: PersistentMapping):
un = username.upper().strip() un = username.upper().strip()
@@ -83,6 +86,12 @@ class Attachment:
def copy(self): def copy(self):
return Attachment(self.name, self.data) return Attachment(self.name, self.data)
@classmethod
def from_dict(cls, attachment: dict):
name = attachment.get("name")
data = attachment.get("data")
return Attachment(name, data)
def to_dict(self, include_data: bool = True): def to_dict(self, include_data: bool = True):
d = { d = {
"name": self.name, "name": self.name,
@@ -150,7 +159,11 @@ class Message(persistent.Persistent):
if attachments: if attachments:
attch = [] attch = []
for i in attachments: for i in attachments:
if not isinstance(i,Attachment): if type(i) is Attachment:
attch.append(i)
elif type(i) is dict:
attch.append(Attachment.from_dict(i))
elif not isinstance(i,Attachment):
attch.append(Attachment("",str(i))) attch.append(Attachment("",str(i)))
else: else:
attch.append(i) attch.append(i)
@@ -286,8 +299,57 @@ def parse_display_options(req: Request) -> DisplayOptions:
return DisplayOptions(get_text, limit, sort_by, reverse, search, get_attachments, sent_received_all) return DisplayOptions(get_text, limit, sort_by, reverse, search, get_attachments, sent_received_all)
def handle_messages_since(req: Request, conn: PacketServerConnection, db: ZODB.DB):
if req.method is not Request.Method.GET:
send_blank_response(conn, req, 400, "method not implemented")
logging.warning(f"Received req with wrong message for path {req.path}.")
return
try:
since_date = from_date_digits(req.path.split("/")[2])
except ValueError as v:
send_blank_response(conn, req, 400, "invalid date string")
return
except:
send_blank_response(conn, req, 500, "unknown error")
logging.error(f"Unhandled exception: {format_exc()}")
return
opts = parse_display_options(req)
username = ax25.Address(conn.remote_callsign).call.upper().strip()
msg_return = []
with db.transaction() as db:
mailbox_create(username, db.root())
mb = db.root.messages[username]
new_mb = [msg for msg in mb if msg.sent_at >= since_date]
if opts.search:
messages = [msg for msg in new_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:
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))
response = Response.blank()
response.status_code = 200
response.payload = msg_return
send_response(conn, response, req)
def handle_message_get(req: Request, conn: PacketServerConnection, db: ZODB.DB): def handle_message_get(req: Request, conn: PacketServerConnection, db: ZODB.DB):
if re.match(since_regex,req.path):
return handle_messages_since(req, conn, db)
opts = parse_display_options(req) opts = parse_display_options(req)
username = ax25.Address(conn.remote_callsign).call.upper().strip() username = ax25.Address(conn.remote_callsign).call.upper().strip()
msg_return = [] msg_return = []