cli client can now send messages.

This commit is contained in:
Michael Woods
2025-03-17 23:48:29 -04:00
parent 6d25551847
commit ec983c4613
6 changed files with 102 additions and 8 deletions

View File

@@ -7,6 +7,7 @@ from packetserver.common import Request, Response
from packetserver.client.cli.util import format_list_dicts, exit_client
from packetserver.client.cli.job import job
from packetserver.client.cli.object import objects
from packetserver.client.cli.message import message
import ZODB
import ZODB.FileStorage
import ax25
@@ -184,6 +185,7 @@ cli.add_command(query_server)
cli.add_command(job, name='job')
cli.add_command(objects, name='object')
cli.add_command(set_user, name='set')
cli.add_command(message)
if __name__ == '__main__':
cli()

View File

@@ -0,0 +1,87 @@
import os
import sys
import os.path
from email.policy import default
import click
from packetserver.client.cli.util import exit_client, format_list_dicts
from copy import deepcopy
from uuid import UUID
from packetserver.client.messages import *
@click.group()
@click.pass_context
def message(ctx):
"""Send, search, and filter messages to and from other users on the BBS system."""
pass
@click.command()
@click.argument("recipients", type=str)
@click.argument("body", type=str)
@click.option("--body-filename", '-f', is_flag=True, default=False, help="Treat body argument as a filename to read body text from. '-' to read from stdin.")
@click.option("--attachment", "-A", multiple=True, default=[],
help="Files to attach to message in form '[<t|b>:]<filename>' use 't' for text (default), 'b' to interpret file as binary data.")
@click.pass_context
def send(ctx, recipients, body, body_filename, attachment):
"""Send a message to one or more recipients.
<recipients> should be a comma-separated list of recipients to send the message to
<body> should be either body text, or a filename (or '-' for stdin) to read body text from
"""
client = ctx.obj['client']
bbs = ctx.obj['bbs']
recips = [x.strip() for x in recipients.split(",") if x.strip() != ""]
if len(recips) == 0:
click.echo("You must specify at least one recipient.", err=True)
exit_client(ctx.obj, 89)
attachments = []
for a in attachment:
is_text = True
filename = a
if len(a) > 1:
if a[1] == ":":
filename = a[2:]
if a[0].lower() == "b":
is_text = False
try:
attachments.append(attachment_from_file(filename, binary=not is_text))
except Exception as e:
click.echo(str(e), err=True)
exit_client(ctx.obj, 89)
if len(attachments) == 0:
attachments = None
if body_filename:
if body == "-":
body_text = sys.stdin.read()
else:
if not os.path.isfile(body):
click.echo(f"{body} is not a file that can be read for body text.", err=True)
exit_client(ctx.obj, 92)
sys.exit(92)
try:
body_text = open(body, "r").read()
except:
click.echo(f"{body} is not a file that can be read for body text.", err=True)
exit_client(ctx.obj, 92)
sys.exit(92)
else:
body_text = body
try:
resp = send_message(client, bbs, body_text, recips, attachments=attachments)
click.echo(f"Message received by server: {resp}")
exit_client(ctx.obj, 0)
except Exception as e:
click.echo(f"Error sending message: {str(e)}", err=True)
exit_client(ctx.obj, 53)
message.add_command(send)

View File

@@ -100,8 +100,9 @@ def send_message(client: Client, bbs_callsign: str, text: str, to: list[str],
"to": to,
"attachments": []
}
for a in attachments:
payload["attachments"].append(a.to_dict())
if attachments is not None:
for a in attachments:
payload["attachments"].append(a.to_dict())
req = Request.blank()
req.path = "message"

View File

@@ -118,5 +118,5 @@ def update_self(client: Client, bbs_callsign: str, email: str = None, bio: str =
req.payload = payload
response = client.send_receive_callsign(req, bbs_callsign)
if response.status_code != 200:
raise RuntimeError(f"GET user {username} failed: {response.status_code}: {response.payload}")
raise RuntimeError(f"Updating profile failed: {response.status_code}: {response.payload}")
return True

View File

@@ -234,6 +234,7 @@ class Message(persistent.Persistent):
send_counter = send_counter + 1
for recipient in recipients:
msg = Message(self.text, recipient, self.msg_from, attachments=[x.copy() for x in new_attachments])
msg.msg_id = self.msg_id
try:
mailbox_create(recipient, db.root())
msg.msg_delivered = True
@@ -245,9 +246,11 @@ class Message(persistent.Persistent):
except:
logging.error(f"Error sending message to {recipient}:\n{format_exc()}")
failed.append(recipient)
self.msg_delivered = True
self.attachments = [x.copy() for x in new_attachments]
db.root.messages[self.msg_from.upper().strip()].append(msg)
self.msg_delivered = True
msg = Message(self.text, recipient, self.msg_from, attachments=[x.copy() for x in new_attachments])
msg.msg_id = self.msg_id
msg.msg_to = self.msg_to
db.root.messages[self.msg_from.upper().strip()].append(msg)
return send_counter, failed, self.msg_id
DisplayOptions = namedtuple('DisplayOptions', ['get_text', 'limit', 'sort_by', 'reverse', 'search',
@@ -451,7 +454,7 @@ def handle_message_post(req: Request, conn: PacketServerConnection, db: ZODB.DB)
send_blank_response(conn, req, status_code=201, payload={
"successes": send_counter,
"failed": failed,
'msg_id': msg_id})
'msg_id': str(msg_id)})
def message_root_handler(req: Request, conn: PacketServerConnection, db: ZODB.DB):
logging.debug(f"{req} being processed by message_root_handler")