move all commands to plugins
This commit is contained in:
parent
d6e3f02ca1
commit
acc6061c62
@ -16,5 +16,13 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
__all__ = ["rsbbs", "bbs", "message", "parser"]
|
__all__ = ['config', 'console',
|
||||||
|
'controller', 'parser', 'pluginloader']
|
||||||
|
|
||||||
__version__ = "0.2.0"
|
__version__ = "0.2.0"
|
||||||
|
|
||||||
|
# from .config import Config
|
||||||
|
# from .console import Console
|
||||||
|
# from .controller import Controller
|
||||||
|
# from .parser import Parser
|
||||||
|
# from .pluginloader import PluginLoader
|
||||||
|
|||||||
@ -1,111 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
#
|
|
||||||
# Really Simple BBS - a really simple BBS for ax.25 packet radio.
|
|
||||||
# Copyright (C) 2023 John Burwell <john@atatdotdot.com>
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
|
|
||||||
class Commands():
|
|
||||||
|
|
||||||
def __init__(self, responder):
|
|
||||||
self.responder = responder
|
|
||||||
|
|
||||||
@property
|
|
||||||
def commands(self):
|
|
||||||
commands = [
|
|
||||||
# (name,
|
|
||||||
# aliases,
|
|
||||||
# helpmsg,
|
|
||||||
# function,
|
|
||||||
# arg:
|
|
||||||
# arg attributes...,
|
|
||||||
# )
|
|
||||||
('bye',
|
|
||||||
['b', 'q'],
|
|
||||||
'Sign off and disconnect',
|
|
||||||
self.responder.bye,
|
|
||||||
{}),
|
|
||||||
|
|
||||||
('delete',
|
|
||||||
['d', 'k'],
|
|
||||||
'Delete a message',
|
|
||||||
self.responder.delete,
|
|
||||||
{'number':
|
|
||||||
{'help':
|
|
||||||
'The numeric index of the message to delete'}},),
|
|
||||||
|
|
||||||
('deletem',
|
|
||||||
['dm', 'km'],
|
|
||||||
'Delete all your messages',
|
|
||||||
self.responder.delete_mine,
|
|
||||||
{}),
|
|
||||||
|
|
||||||
('help',
|
|
||||||
['h', '?'],
|
|
||||||
'Show help',
|
|
||||||
self.responder.help,
|
|
||||||
{}),
|
|
||||||
|
|
||||||
('heard',
|
|
||||||
['j'],
|
|
||||||
'Show heard stations log',
|
|
||||||
self.responder.heard,
|
|
||||||
{}),
|
|
||||||
|
|
||||||
('list',
|
|
||||||
['l'],
|
|
||||||
'List all messages',
|
|
||||||
self.responder.list,
|
|
||||||
{}),
|
|
||||||
|
|
||||||
('listm',
|
|
||||||
['lm'],
|
|
||||||
'List only messages addressed to you',
|
|
||||||
self.responder.list_mine,
|
|
||||||
{}),
|
|
||||||
|
|
||||||
('read',
|
|
||||||
['r'],
|
|
||||||
'Read messages',
|
|
||||||
self.responder.read,
|
|
||||||
{'number': {'help': 'Message number to read'}}),
|
|
||||||
|
|
||||||
('readm',
|
|
||||||
['rm'],
|
|
||||||
'Read only messages addressed to you',
|
|
||||||
self.responder.read_mine,
|
|
||||||
{}),
|
|
||||||
|
|
||||||
('send',
|
|
||||||
['s'],
|
|
||||||
'Send a new message to a user',
|
|
||||||
self.responder.send,
|
|
||||||
{
|
|
||||||
'--callsign': {'help': 'Message recipient callsign'},
|
|
||||||
'--subject': {'help': 'Message subject'},
|
|
||||||
'--message': {'help': 'Message'},
|
|
||||||
},),
|
|
||||||
|
|
||||||
('sendp',
|
|
||||||
['sp'],
|
|
||||||
'Send a private message to a user',
|
|
||||||
self.responder.send_private,
|
|
||||||
{
|
|
||||||
'--callsign': {'help': 'Message recipient callsign'},
|
|
||||||
'--subject': {'help': 'Message subject'},
|
|
||||||
'--message': {'help': 'Message'},
|
|
||||||
},),]
|
|
||||||
|
|
||||||
return commands
|
|
||||||
175
rsbbs/console.py
175
rsbbs/console.py
@ -16,15 +16,16 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import sqlalchemy.exc
|
import sqlalchemy.exc
|
||||||
|
|
||||||
import rsbbs
|
import rsbbs
|
||||||
from rsbbs.commands import Commands
|
|
||||||
from rsbbs.config import Config
|
from rsbbs.config import Config
|
||||||
from rsbbs.controller import Controller
|
from rsbbs.controller import Controller
|
||||||
from rsbbs.parser import Parser
|
from rsbbs.parser import Parser
|
||||||
|
from rsbbs.pluginloader import PluginLoader
|
||||||
|
|
||||||
|
|
||||||
# Main UI console class
|
# Main UI console class
|
||||||
@ -35,33 +36,42 @@ class Console():
|
|||||||
self.config = config
|
self.config = config
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
|
|
||||||
self.commands = Commands(self)
|
self.parser = Parser()
|
||||||
self.parser = Parser(self.commands)
|
|
||||||
|
self.pluginloader = PluginLoader(self)
|
||||||
|
self.pluginloader.load_plugins()
|
||||||
|
|
||||||
#
|
#
|
||||||
# Input and output
|
# Input and output
|
||||||
#
|
#
|
||||||
|
|
||||||
def _read_line(self, prompt):
|
def read_enter(self, prompt) -> None:
|
||||||
|
"""Wait for the user to press enter.
|
||||||
|
"""
|
||||||
|
if prompt:
|
||||||
|
self.write_output(prompt)
|
||||||
|
sys.stdin.readline().strip()
|
||||||
|
|
||||||
|
def read_line(self, prompt) -> str:
|
||||||
"""Read a single line of input, with an optional prompt,
|
"""Read a single line of input, with an optional prompt,
|
||||||
until we get something.
|
until we get something.
|
||||||
"""
|
"""
|
||||||
output = None
|
output = None
|
||||||
while not output:
|
while not output:
|
||||||
if prompt:
|
if prompt:
|
||||||
self._write_output(prompt)
|
self.write_output(prompt)
|
||||||
input = sys.stdin.readline().strip()
|
input = sys.stdin.readline().strip()
|
||||||
if input != "":
|
if input != "":
|
||||||
output = input
|
output = input
|
||||||
return output
|
return output
|
||||||
|
|
||||||
def _read_multiline(self, prompt):
|
def read_multiline(self, prompt) -> str:
|
||||||
"""Read multiple lines of input, with an optional prompt,
|
"""Read multiple lines of input, with an optional prompt,
|
||||||
until the user enters '/ex' by itself on a line.
|
until the user enters '/ex' by itself on a line.
|
||||||
"""
|
"""
|
||||||
output = []
|
output = []
|
||||||
if prompt:
|
if prompt:
|
||||||
self._write_output(prompt)
|
self.write_output(prompt)
|
||||||
while True:
|
while True:
|
||||||
line = sys.stdin.readline()
|
line = sys.stdin.readline()
|
||||||
if line.lower().strip() == "/ex":
|
if line.lower().strip() == "/ex":
|
||||||
@ -70,14 +80,14 @@ class Console():
|
|||||||
output.append(line)
|
output.append(line)
|
||||||
return ''.join(output)
|
return ''.join(output)
|
||||||
|
|
||||||
def _write_output(self, output):
|
def write_output(self, output) -> None:
|
||||||
"""Write something to stdout."""
|
"""Write something to stdout."""
|
||||||
sys.stdout.write(output + '\r\n')
|
sys.stdout.write(output + '\r\n')
|
||||||
|
|
||||||
def print_configuration(self):
|
def print_configuration(self) -> None:
|
||||||
self._write_output(repr(self.config))
|
self.write_output(repr(self.config))
|
||||||
|
|
||||||
def print_greeting(self):
|
def print_greeting(self) -> None:
|
||||||
# Show greeting
|
# Show greeting
|
||||||
greeting = []
|
greeting = []
|
||||||
greeting.append(f"[RSBBS-{rsbbs.__version__}] listening on "
|
greeting.append(f"[RSBBS-{rsbbs.__version__}] listening on "
|
||||||
@ -90,7 +100,7 @@ class Console():
|
|||||||
|
|
||||||
greeting.append("For help, enter 'h'")
|
greeting.append("For help, enter 'h'")
|
||||||
|
|
||||||
self._write_output('\r\n'.join(greeting))
|
self.write_output('\r\n'.join(greeting))
|
||||||
|
|
||||||
def print_message(self, message):
|
def print_message(self, message):
|
||||||
"""Print an individual message."""
|
"""Print an individual message."""
|
||||||
@ -98,19 +108,19 @@ class Console():
|
|||||||
datetime = message.Message.datetime.strftime(
|
datetime = message.Message.datetime.strftime(
|
||||||
'%A, %B %-d, %Y at %-H:%M %p UTC')
|
'%A, %B %-d, %Y at %-H:%M %p UTC')
|
||||||
# Print the message
|
# Print the message
|
||||||
self._write_output(f"")
|
self.write_output(f"")
|
||||||
self._write_output(f"Message: {message.Message.id}")
|
self.write_output(f"Message: {message.Message.id}")
|
||||||
self._write_output(f"Date: {datetime}")
|
self.write_output(f"Date: {datetime}")
|
||||||
self._write_output(f"From: {message.Message.sender}")
|
self.write_output(f"From: {message.Message.sender}")
|
||||||
self._write_output(f"To: {message.Message.recipient}")
|
self.write_output(f"To: {message.Message.recipient}")
|
||||||
self._write_output(f"Subject: {message.Message.subject}")
|
self.write_output(f"Subject: {message.Message.subject}")
|
||||||
self._write_output(f"")
|
self.write_output(f"")
|
||||||
self._write_output(f"{message.Message.message}")
|
self.write_output(f"{message.Message.message}")
|
||||||
|
|
||||||
def print_message_list(self, messages):
|
def print_message_list(self, messages) -> None:
|
||||||
"""Print a list of messages."""
|
"""Print a list of messages."""
|
||||||
# Print the column headers
|
# Print the column headers
|
||||||
self._write_output(f"{'MSG#': <{5}} "
|
self.write_output(f"{'MSG#': <{5}} "
|
||||||
f"{'TO': <{9}} "
|
f"{'TO': <{9}} "
|
||||||
f"{'FROM': <{9}} "
|
f"{'FROM': <{9}} "
|
||||||
f"{'DATE': <{11}} "
|
f"{'DATE': <{11}} "
|
||||||
@ -118,7 +128,7 @@ class Console():
|
|||||||
# Print the messages
|
# Print the messages
|
||||||
for message in messages:
|
for message in messages:
|
||||||
datetime_ = message.Message.datetime.strftime('%Y-%m-%d')
|
datetime_ = message.Message.datetime.strftime('%Y-%m-%d')
|
||||||
self._write_output(f"{message.Message.id: <{5}} "
|
self.write_output(f"{message.Message.id: <{5}} "
|
||||||
f"{message.Message.recipient: <{9}} "
|
f"{message.Message.recipient: <{9}} "
|
||||||
f"{message.Message.sender: <{9}} "
|
f"{message.Message.sender: <{9}} "
|
||||||
f"{datetime_: <{11}} "
|
f"{datetime_: <{11}} "
|
||||||
@ -128,121 +138,6 @@ class Console():
|
|||||||
# Command functions
|
# Command functions
|
||||||
#
|
#
|
||||||
|
|
||||||
def bye(self, args):
|
|
||||||
"""Disconnect and exit."""
|
|
||||||
self._write_output("Bye!")
|
|
||||||
exit(0)
|
|
||||||
|
|
||||||
def delete(self, args):
|
|
||||||
"""Delete a message specified by ID number."""
|
|
||||||
if args.number:
|
|
||||||
try:
|
|
||||||
self.controller.delete(args)
|
|
||||||
self._write_output(f"Deleted message #{args.number}")
|
|
||||||
except Exception as e:
|
|
||||||
self._write_output(f"Message not found.")
|
|
||||||
|
|
||||||
def delete_mine(self, args):
|
|
||||||
"""Delete all messages addressed to the calling station's callsign."""
|
|
||||||
self._write_output("Delete all messages addressed to you? Y/N:")
|
|
||||||
response = sys.stdin.readline().strip()
|
|
||||||
if response.lower() != "y":
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
result = self.controller.delete_mine(args)
|
|
||||||
messages = result.all()
|
|
||||||
count = len(messages)
|
|
||||||
if count > 0:
|
|
||||||
self._write_output(f"Deleted {count} messages")
|
|
||||||
else:
|
|
||||||
self._write_output(f"No messages to delete.")
|
|
||||||
except Exception as e:
|
|
||||||
self._write_output(f"Unable to delete messages: {e}")
|
|
||||||
|
|
||||||
def heard(self, args):
|
|
||||||
"""Show a log of stations that have been heard by this station,
|
|
||||||
also known as the 'mheard' (linux) or 'jheard' (KPC, etc.) log.
|
|
||||||
"""
|
|
||||||
self._write_output(f"Heard stations:")
|
|
||||||
try:
|
|
||||||
result = self.controller.heard(args)
|
|
||||||
self._write_output(result.stdout)
|
|
||||||
except FileNotFoundError:
|
|
||||||
self._write_output(f"mheard utility not found.")
|
|
||||||
except Exception as e:
|
|
||||||
if self.config.debug:
|
|
||||||
raise
|
|
||||||
else:
|
|
||||||
self._write_output(f"Heard stations not available.")
|
|
||||||
|
|
||||||
def help(self, args):
|
|
||||||
self.parser.print_help()
|
|
||||||
|
|
||||||
def list(self, args):
|
|
||||||
"""List all public messages and private messages to the caller."""
|
|
||||||
result = self.controller.list(args)
|
|
||||||
self.print_message_list(result)
|
|
||||||
|
|
||||||
def list_mine(self, args):
|
|
||||||
"""List only messages addressed to the calling station's callsign,
|
|
||||||
including public and private messages.
|
|
||||||
"""
|
|
||||||
result = self.controller.list_mine(args)
|
|
||||||
self.print_message_list(result)
|
|
||||||
|
|
||||||
def read(self, args):
|
|
||||||
"""Read a message.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
number -- the message number to read
|
|
||||||
"""
|
|
||||||
if args.number:
|
|
||||||
try:
|
|
||||||
result = self.controller.read(args)
|
|
||||||
self.print_message(result)
|
|
||||||
except sqlalchemy.exc.NoResultFound:
|
|
||||||
self._write_output(f"Message not found.")
|
|
||||||
except Exception as e:
|
|
||||||
print(e)
|
|
||||||
|
|
||||||
def read_mine(self, args):
|
|
||||||
"""Read all messages addressed to the calling station's callsign,
|
|
||||||
in sequence."""
|
|
||||||
result = self.controller.list_mine(args)
|
|
||||||
messages = result.all()
|
|
||||||
count = len(messages)
|
|
||||||
if count > 0:
|
|
||||||
self._write_output(f"Reading {count} messages:")
|
|
||||||
for message in messages:
|
|
||||||
self.print_message(message)
|
|
||||||
self._write_output("Enter to continue...")
|
|
||||||
sys.stdin.readline()
|
|
||||||
else:
|
|
||||||
self._write_output(f"No messages to read.")
|
|
||||||
|
|
||||||
def send(self, args, is_private=False):
|
|
||||||
"""Create a new message addressed to another callsign.
|
|
||||||
|
|
||||||
Required arguments:
|
|
||||||
callsign -- the recipient's callsign
|
|
||||||
|
|
||||||
Optional arguments:
|
|
||||||
subject -- message subject
|
|
||||||
message -- the message itself
|
|
||||||
"""
|
|
||||||
if not args.callsign:
|
|
||||||
args.callsign = self._read_line("Callsign:")
|
|
||||||
if not args.subject:
|
|
||||||
args.subject = self._read_line("Subject:")
|
|
||||||
if not args.message:
|
|
||||||
args.message = self._read_multiline(
|
|
||||||
"Message - end with /ex on a single line:")
|
|
||||||
try:
|
|
||||||
self.controller.send(args, is_private=is_private)
|
|
||||||
except Exception as e:
|
|
||||||
print(e)
|
|
||||||
|
|
||||||
def send_private(self, args):
|
def send_private(self, args):
|
||||||
self.send(args, is_private=True)
|
self.send(args, is_private=True)
|
||||||
"""Send a message visible only to the recipient callsign.
|
"""Send a message visible only to the recipient callsign.
|
||||||
@ -270,7 +165,7 @@ class Console():
|
|||||||
self.print_greeting()
|
self.print_greeting()
|
||||||
|
|
||||||
# Show initial prompt to the calling user
|
# Show initial prompt to the calling user
|
||||||
self._write_output(self.config.command_prompt)
|
self.write_output(self.config.command_prompt)
|
||||||
|
|
||||||
# Parse the BBS interactive commands for the rest of time
|
# Parse the BBS interactive commands for the rest of time
|
||||||
for line in sys.stdin:
|
for line in sys.stdin:
|
||||||
@ -284,4 +179,4 @@ class Console():
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
# Show our prompt to the calling user again
|
# Show our prompt to the calling user again
|
||||||
self._write_output(self.config.command_prompt)
|
self.write_output(self.config.command_prompt)
|
||||||
|
|||||||
@ -93,17 +93,6 @@ class Controller():
|
|||||||
except Exception:
|
except Exception:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def heard(self, args):
|
|
||||||
"""Show a log of stations that have been heard by this station,
|
|
||||||
also known as the 'mheard' (linux) or 'jheard' (KPC, etc.) log.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
return subprocess.run(['mheard'], capture_output=True, text=True)
|
|
||||||
except FileNotFoundError:
|
|
||||||
raise
|
|
||||||
except Exception:
|
|
||||||
raise
|
|
||||||
|
|
||||||
def list(self, args):
|
def list(self, args):
|
||||||
"""List all messages."""
|
"""List all messages."""
|
||||||
with Session(self.engine) as session:
|
with Session(self.engine) as session:
|
||||||
|
|||||||
@ -18,8 +18,6 @@
|
|||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
from rsbbs.commands import Commands
|
|
||||||
|
|
||||||
|
|
||||||
class BBSArgumentParser(argparse.ArgumentParser):
|
class BBSArgumentParser(argparse.ArgumentParser):
|
||||||
# Override the error handler to prevent spewing error cruft over the air
|
# Override the error handler to prevent spewing error cruft over the air
|
||||||
@ -33,8 +31,8 @@ class BBSArgumentParser(argparse.ArgumentParser):
|
|||||||
|
|
||||||
class Parser(BBSArgumentParser):
|
class Parser(BBSArgumentParser):
|
||||||
|
|
||||||
def __init__(self, commands: Commands):
|
def __init__(self):
|
||||||
self._init_parser(commands)
|
self._init_parser()
|
||||||
|
|
||||||
# The only thing anyone should ever access from Parser is its parser
|
# The only thing anyone should ever access from Parser is its parser
|
||||||
# attribute, so let's save everyone a step.
|
# attribute, so let's save everyone a step.
|
||||||
@ -44,7 +42,7 @@ class Parser(BBSArgumentParser):
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
return getattr(self.parser, attr)
|
return getattr(self.parser, attr)
|
||||||
|
|
||||||
def _init_parser(self, commands):
|
def _init_parser(self):
|
||||||
# Root parser for BBS commands
|
# Root parser for BBS commands
|
||||||
self.parser = BBSArgumentParser(
|
self.parser = BBSArgumentParser(
|
||||||
description='BBS Main Menu',
|
description='BBS Main Menu',
|
||||||
@ -54,20 +52,9 @@ class Parser(BBSArgumentParser):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# We will create a subparser for each individual command
|
# We will create a subparser for each individual command
|
||||||
subparsers = self.parser.add_subparsers(
|
self.subparsers = self.parser.add_subparsers(
|
||||||
title='Commands',
|
title='Commands',
|
||||||
dest='command')
|
dest='command')
|
||||||
|
|
||||||
# Loop through the commands and add each as a subparser
|
# Plugins will then add a subparser for each command, so we're done
|
||||||
for name, aliases, help_msg, func, arguments in commands.commands:
|
# here
|
||||||
# Add the command attributes
|
|
||||||
subparser = subparsers.add_parser(
|
|
||||||
name,
|
|
||||||
aliases=aliases,
|
|
||||||
help=help_msg,
|
|
||||||
)
|
|
||||||
# Add the command parameters
|
|
||||||
for arg_name, options in arguments.items():
|
|
||||||
subparser.add_argument(arg_name, **options)
|
|
||||||
# Trick to pass a function to call when the command is entered
|
|
||||||
subparser.set_defaults(func=func)
|
|
||||||
|
|||||||
66
rsbbs/pluginloader.py
Normal file
66
rsbbs/pluginloader.py
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Really Simple BBS - a really simple BBS for ax.25 packet radio.
|
||||||
|
# Copyright (C) 2023 John Burwell <john@atatdotdot.com>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import importlib
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
class PluginLoader():
|
||||||
|
|
||||||
|
def __init__(self, api) -> None:
|
||||||
|
self.api = api
|
||||||
|
self.plugins = []
|
||||||
|
|
||||||
|
def load_plugins(self) -> None:
|
||||||
|
# Path to command plugin directory
|
||||||
|
plugins_dir = os.path.join(os.path.dirname(__file__), 'plugins')
|
||||||
|
|
||||||
|
# Discover all subdirectories in the plugins directory
|
||||||
|
plugin_dirs = [d
|
||||||
|
for d in os.listdir(plugins_dir)
|
||||||
|
if os.path.isdir(os.path.join(plugins_dir, d))
|
||||||
|
and not d.startswith('__')]
|
||||||
|
|
||||||
|
if self.api.config.debug:
|
||||||
|
print(f"Plugin dirs: {plugin_dirs}")
|
||||||
|
|
||||||
|
# Loop over each plugin directory
|
||||||
|
for plugin_dir in plugin_dirs:
|
||||||
|
try:
|
||||||
|
# Import the module containing the plugin class
|
||||||
|
if self.api.config.debug:
|
||||||
|
print(f"Import rsbbs.plugins.{plugin_dir}.plugin")
|
||||||
|
|
||||||
|
plugin_module = importlib.import_module(
|
||||||
|
f"rsbbs.plugins.{plugin_dir}.plugin")
|
||||||
|
|
||||||
|
# Get a reference to the plugin class
|
||||||
|
plugin_class = plugin_module.Plugin
|
||||||
|
|
||||||
|
# Initialize an instance of the plugin class, passing api as an
|
||||||
|
# argument
|
||||||
|
plugin = plugin_class(self.api)
|
||||||
|
|
||||||
|
# Add the loaded plugin to the list of plugins
|
||||||
|
self.plugins.append(plugin)
|
||||||
|
except Exception as e:
|
||||||
|
if self.api.config.debug:
|
||||||
|
print(f"{e}")
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
continue
|
||||||
41
rsbbs/plugins/bye/plugin.py
Normal file
41
rsbbs/plugins/bye/plugin.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Really Simple BBS - a really simple BBS for ax.25 packet radio.
|
||||||
|
# Copyright (C) 2023 John Burwell <john@atatdotdot.com>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from rsbbs.console import Console
|
||||||
|
from rsbbs.parser import Parser
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin():
|
||||||
|
|
||||||
|
def __init__(self, api: Console):
|
||||||
|
self.api = api
|
||||||
|
self.init_parser(api.parser)
|
||||||
|
if api.config.debug:
|
||||||
|
print(f"Plugin {__name__} loaded")
|
||||||
|
|
||||||
|
def init_parser(self, parser: Parser):
|
||||||
|
subparser = parser.subparsers.add_parser(
|
||||||
|
name='bye',
|
||||||
|
aliases=['b', 'q'],
|
||||||
|
help='Sign off and disconnect')
|
||||||
|
subparser.set_defaults(func=self.run)
|
||||||
|
|
||||||
|
def run(self, args):
|
||||||
|
"""Disconnect and exit."""
|
||||||
|
self.api.write_output("Bye!")
|
||||||
|
exit(0)
|
||||||
47
rsbbs/plugins/delete/plugin.py
Normal file
47
rsbbs/plugins/delete/plugin.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Really Simple BBS - a really simple BBS for ax.25 packet radio.
|
||||||
|
# Copyright (C) 2023 John Burwell <john@atatdotdot.com>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from rsbbs.console import Console
|
||||||
|
from rsbbs.parser import Parser
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin():
|
||||||
|
|
||||||
|
def __init__(self, api: Console):
|
||||||
|
self.api = api
|
||||||
|
self.init_parser(api.parser)
|
||||||
|
if api.config.debug:
|
||||||
|
print(f"Plugin {__name__} loaded")
|
||||||
|
|
||||||
|
def init_parser(self, parser: Parser):
|
||||||
|
subparser = parser.subparsers.add_parser(
|
||||||
|
name='delete',
|
||||||
|
aliases=['d', 'k'],
|
||||||
|
help='Delete a message')
|
||||||
|
subparser.add_argument('number',
|
||||||
|
help='The number of the message to delete')
|
||||||
|
subparser.set_defaults(func=self.run)
|
||||||
|
|
||||||
|
def run(self, args):
|
||||||
|
"""Delete a message specified by ID number."""
|
||||||
|
if args.number:
|
||||||
|
try:
|
||||||
|
self.api.controller.delete(args)
|
||||||
|
self.api.write_output(f"Deleted message #{args.number}")
|
||||||
|
except Exception as e:
|
||||||
|
self.api.write_output(f"Message not found.")
|
||||||
54
rsbbs/plugins/deletem/plugin.py
Normal file
54
rsbbs/plugins/deletem/plugin.py
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Really Simple BBS - a really simple BBS for ax.25 packet radio.
|
||||||
|
# Copyright (C) 2023 John Burwell <john@atatdotdot.com>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from rsbbs.console import Console
|
||||||
|
from rsbbs.parser import Parser
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin():
|
||||||
|
|
||||||
|
def __init__(self, api: Console):
|
||||||
|
self.api = api
|
||||||
|
self.init_parser(api.parser)
|
||||||
|
if api.config.debug:
|
||||||
|
print(f"Plugin {__name__} loaded")
|
||||||
|
|
||||||
|
def init_parser(self, parser: Parser):
|
||||||
|
subparser = parser.subparsers.add_parser(
|
||||||
|
name='deletem',
|
||||||
|
aliases=['dm', 'km'],
|
||||||
|
help='Delete all messages addressed to you')
|
||||||
|
subparser.set_defaults(func=self.run)
|
||||||
|
|
||||||
|
def run(self, args):
|
||||||
|
"""Delete all messages addressed to the calling station's callsign."""
|
||||||
|
response = self.api.read_line(
|
||||||
|
"Delete all messages addressed to you? Y/N:")
|
||||||
|
if response.lower() != "y":
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
result = self.api.controller.delete_mine(args)
|
||||||
|
messages = result.all()
|
||||||
|
count = len(messages)
|
||||||
|
if count > 0:
|
||||||
|
self.api.write_output(f"Deleted {count} messages")
|
||||||
|
else:
|
||||||
|
self.api.write_output(f"No messages to delete.")
|
||||||
|
except Exception as e:
|
||||||
|
self.api.write_output(f"Unable to delete messages: {e}")
|
||||||
54
rsbbs/plugins/heard/plugin.py
Normal file
54
rsbbs/plugins/heard/plugin.py
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Really Simple BBS - a really simple BBS for ax.25 packet radio.
|
||||||
|
# Copyright (C) 2023 John Burwell <john@atatdotdot.com>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
from rsbbs.console import Console
|
||||||
|
from rsbbs.parser import Parser
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin():
|
||||||
|
|
||||||
|
def __init__(self, api: Console):
|
||||||
|
self.api = api
|
||||||
|
self.init_parser(api.parser)
|
||||||
|
if api.config.debug:
|
||||||
|
print(f"Plugin {__name__} loaded")
|
||||||
|
|
||||||
|
def init_parser(self, parser: Parser):
|
||||||
|
subparser = parser.subparsers.add_parser(
|
||||||
|
name='heard',
|
||||||
|
aliases=['j'],
|
||||||
|
help='Show heard stations log')
|
||||||
|
subparser.set_defaults(func=self.run)
|
||||||
|
|
||||||
|
def run(self, args):
|
||||||
|
"""Show a log of stations that have been heard by this station,
|
||||||
|
also known as the 'mheard' (linux) or 'jheard' (KPC, etc.) log.
|
||||||
|
"""
|
||||||
|
self.api.write_output(f"Heard stations:")
|
||||||
|
try:
|
||||||
|
result = subprocess.run(['mheard'], capture_output=True, text=True)
|
||||||
|
self.api.write_output(result.stdout)
|
||||||
|
except FileNotFoundError:
|
||||||
|
self.api.write_output(f"mheard utility not found.")
|
||||||
|
except Exception as e:
|
||||||
|
if self.api.config.debug:
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
self.api.write_output(f"Heard stations not available.")
|
||||||
42
rsbbs/plugins/help/plugin.py
Normal file
42
rsbbs/plugins/help/plugin.py
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Really Simple BBS - a really simple BBS for ax.25 packet radio.
|
||||||
|
# Copyright (C) 2023 John Burwell <john@atatdotdot.com>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from rsbbs.console import Console
|
||||||
|
from rsbbs.parser import Parser
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin():
|
||||||
|
|
||||||
|
def __init__(self, api: Console):
|
||||||
|
self.api = api
|
||||||
|
self.init_parser(api.parser)
|
||||||
|
if api.config.debug:
|
||||||
|
print(f"Plugin {__name__} loaded")
|
||||||
|
|
||||||
|
def init_parser(self, parser: Parser):
|
||||||
|
subparser = parser.subparsers.add_parser(
|
||||||
|
name='help',
|
||||||
|
aliases=['h', '?'],
|
||||||
|
help='Show help')
|
||||||
|
subparser.set_defaults(func=self.run)
|
||||||
|
|
||||||
|
def run(self, args):
|
||||||
|
"""Show a log of stations that have been heard by this station,
|
||||||
|
also known as the 'mheard' (linux) or 'jheard' (KPC, etc.) log.
|
||||||
|
"""
|
||||||
|
self.api.parser.print_help()
|
||||||
41
rsbbs/plugins/list/plugin.py
Normal file
41
rsbbs/plugins/list/plugin.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Really Simple BBS - a really simple BBS for ax.25 packet radio.
|
||||||
|
# Copyright (C) 2023 John Burwell <john@atatdotdot.com>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from rsbbs.console import Console
|
||||||
|
from rsbbs.parser import Parser
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin():
|
||||||
|
|
||||||
|
def __init__(self, api: Console):
|
||||||
|
self.api = api
|
||||||
|
self.init_parser(api.parser)
|
||||||
|
if api.config.debug:
|
||||||
|
print(f"Plugin {__name__} loaded")
|
||||||
|
|
||||||
|
def init_parser(self, parser: Parser):
|
||||||
|
subparser = parser.subparsers.add_parser(
|
||||||
|
name='list',
|
||||||
|
aliases=['l'],
|
||||||
|
help='List all available messages')
|
||||||
|
subparser.set_defaults(func=self.run)
|
||||||
|
|
||||||
|
def run(self, args):
|
||||||
|
"""List all public messages and messages private to the caller."""
|
||||||
|
result = self.api.controller.list(args)
|
||||||
|
self.api.print_message_list(result)
|
||||||
43
rsbbs/plugins/listm/plugin.py
Normal file
43
rsbbs/plugins/listm/plugin.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Really Simple BBS - a really simple BBS for ax.25 packet radio.
|
||||||
|
# Copyright (C) 2023 John Burwell <john@atatdotdot.com>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from rsbbs.console import Console
|
||||||
|
from rsbbs.parser import Parser
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin():
|
||||||
|
|
||||||
|
def __init__(self, api: Console):
|
||||||
|
self.api = api
|
||||||
|
self.init_parser(api.parser)
|
||||||
|
if api.config.debug:
|
||||||
|
print(f"Plugin {__name__} loaded")
|
||||||
|
|
||||||
|
def init_parser(self, parser: Parser):
|
||||||
|
subparser = parser.subparsers.add_parser(
|
||||||
|
name='listm',
|
||||||
|
aliases=['lm'],
|
||||||
|
help='List only messages addressed to you')
|
||||||
|
subparser.set_defaults(func=self.run)
|
||||||
|
|
||||||
|
def run(self, args):
|
||||||
|
"""List only messages addressed to the calling station's callsign,
|
||||||
|
including public and private messages.
|
||||||
|
"""
|
||||||
|
result = self.api.controller.list_mine(args)
|
||||||
|
self.api.print_message_list(result)
|
||||||
54
rsbbs/plugins/read/plugin.py
Normal file
54
rsbbs/plugins/read/plugin.py
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Really Simple BBS - a really simple BBS for ax.25 packet radio.
|
||||||
|
# Copyright (C) 2023 John Burwell <john@atatdotdot.com>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import sqlalchemy
|
||||||
|
|
||||||
|
from rsbbs.console import Console
|
||||||
|
from rsbbs.parser import Parser
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin():
|
||||||
|
|
||||||
|
def __init__(self, api: Console):
|
||||||
|
self.api = api
|
||||||
|
self.init_parser(api.parser)
|
||||||
|
if api.config.debug:
|
||||||
|
print(f"Plugin {__name__} loaded")
|
||||||
|
|
||||||
|
def init_parser(self, parser: Parser):
|
||||||
|
subparser = parser.subparsers.add_parser(
|
||||||
|
name='read',
|
||||||
|
aliases=['r'],
|
||||||
|
help='Read a message')
|
||||||
|
subparser.add_argument('number', help='Message number to read')
|
||||||
|
subparser.set_defaults(func=self.run)
|
||||||
|
|
||||||
|
def run(self, args):
|
||||||
|
"""Read a message.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
number -- the message number to read
|
||||||
|
"""
|
||||||
|
if args.number:
|
||||||
|
try:
|
||||||
|
result = self.api.controller.read(args)
|
||||||
|
self.api.print_message(result)
|
||||||
|
except sqlalchemy.exc.NoResultFound:
|
||||||
|
self.api.write_output(f"Message not found.")
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
52
rsbbs/plugins/readm/plugin.py
Normal file
52
rsbbs/plugins/readm/plugin.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Really Simple BBS - a really simple BBS for ax.25 packet radio.
|
||||||
|
# Copyright (C) 2023 John Burwell <john@atatdotdot.com>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import sqlalchemy
|
||||||
|
|
||||||
|
from rsbbs.console import Console
|
||||||
|
from rsbbs.parser import Parser
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin():
|
||||||
|
|
||||||
|
def __init__(self, api: Console):
|
||||||
|
self.api = api
|
||||||
|
self.init_parser(api.parser)
|
||||||
|
if api.config.debug:
|
||||||
|
print(f"Plugin {__name__} loaded")
|
||||||
|
|
||||||
|
def init_parser(self, parser: Parser):
|
||||||
|
subparser = parser.subparsers.add_parser(
|
||||||
|
name='readm',
|
||||||
|
aliases=['rm'],
|
||||||
|
help='Read all messages addressed to you')
|
||||||
|
subparser.set_defaults(func=self.run)
|
||||||
|
|
||||||
|
def run(self, args):
|
||||||
|
"""Read all messages addressed to the calling station's callsign,
|
||||||
|
in sequence."""
|
||||||
|
result = self.api.controller.list_mine(args)
|
||||||
|
messages = result.all()
|
||||||
|
count = len(messages)
|
||||||
|
if count > 0:
|
||||||
|
self.api.write_output(f"Reading {count} messages:")
|
||||||
|
for message in messages:
|
||||||
|
self.api.print_message(message)
|
||||||
|
self.api.read_enter("Enter to continue...")
|
||||||
|
else:
|
||||||
|
self.api.write_output(f"No messages to read.")
|
||||||
63
rsbbs/plugins/send/plugin.py
Normal file
63
rsbbs/plugins/send/plugin.py
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Really Simple BBS - a really simple BBS for ax.25 packet radio.
|
||||||
|
# Copyright (C) 2023 John Burwell <john@atatdotdot.com>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import sqlalchemy
|
||||||
|
|
||||||
|
from rsbbs.console import Console
|
||||||
|
from rsbbs.parser import Parser
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin():
|
||||||
|
|
||||||
|
def __init__(self, api: Console):
|
||||||
|
self.api = api
|
||||||
|
self.init_parser(api.parser)
|
||||||
|
if api.config.debug:
|
||||||
|
print(f"Plugin {__name__} loaded")
|
||||||
|
|
||||||
|
def init_parser(self, parser: Parser):
|
||||||
|
subparser = parser.subparsers.add_parser(
|
||||||
|
name='send',
|
||||||
|
aliases=['s'],
|
||||||
|
help='Send a new message to a user')
|
||||||
|
subparser.add_argument('--callsign', help='Message recipient callsign')
|
||||||
|
subparser.add_argument('--subject', help='Message subject')
|
||||||
|
subparser.add_argument('--message', help='Message')
|
||||||
|
subparser.set_defaults(func=self.run)
|
||||||
|
|
||||||
|
def run(self, args):
|
||||||
|
"""Create a new message addressed to another callsign.
|
||||||
|
|
||||||
|
Required arguments:
|
||||||
|
callsign -- the recipient's callsign
|
||||||
|
|
||||||
|
Optional arguments:
|
||||||
|
subject -- message subject
|
||||||
|
message -- the message itself
|
||||||
|
"""
|
||||||
|
if not args.callsign:
|
||||||
|
args.callsign = self.api.read_line("Callsign:")
|
||||||
|
if not args.subject:
|
||||||
|
args.subject = self.api.read_line("Subject:")
|
||||||
|
if not args.message:
|
||||||
|
args.message = self.api.read_multiline(
|
||||||
|
"Message - end with /ex on a single line:")
|
||||||
|
try:
|
||||||
|
self.api.controller.send(args, is_private=False)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
63
rsbbs/plugins/sendp/plugin.py
Normal file
63
rsbbs/plugins/sendp/plugin.py
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Really Simple BBS - a really simple BBS for ax.25 packet radio.
|
||||||
|
# Copyright (C) 2023 John Burwell <john@atatdotdot.com>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import sqlalchemy
|
||||||
|
|
||||||
|
from rsbbs.console import Console
|
||||||
|
from rsbbs.parser import Parser
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin():
|
||||||
|
|
||||||
|
def __init__(self, api: Console):
|
||||||
|
self.api = api
|
||||||
|
self.init_parser(api.parser)
|
||||||
|
if api.config.debug:
|
||||||
|
print(f"Plugin {__name__} loaded")
|
||||||
|
|
||||||
|
def init_parser(self, parser: Parser):
|
||||||
|
subparser = parser.subparsers.add_parser(
|
||||||
|
name='sendp',
|
||||||
|
aliases=['sp'],
|
||||||
|
help='Send a private message to a user')
|
||||||
|
subparser.add_argument('--callsign', help='Message recipient callsign')
|
||||||
|
subparser.add_argument('--subject', help='Message subject')
|
||||||
|
subparser.add_argument('--message', help='Message')
|
||||||
|
subparser.set_defaults(func=self.run)
|
||||||
|
|
||||||
|
def run(self, args):
|
||||||
|
"""Create a new message addressed to another callsign.
|
||||||
|
|
||||||
|
Required arguments:
|
||||||
|
callsign -- the recipient's callsign
|
||||||
|
|
||||||
|
Optional arguments:
|
||||||
|
subject -- message subject
|
||||||
|
message -- the message itself
|
||||||
|
"""
|
||||||
|
if not args.callsign:
|
||||||
|
args.callsign = self.api.read_line("Callsign:")
|
||||||
|
if not args.subject:
|
||||||
|
args.subject = self.api.read_line("Subject:")
|
||||||
|
if not args.message:
|
||||||
|
args.message = self.api.read_multiline(
|
||||||
|
"Message - end with /ex on a single line:")
|
||||||
|
try:
|
||||||
|
self.api.controller.send(args, is_private=True)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
@ -20,7 +20,6 @@ import argparse
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
from rsbbs import __version__
|
from rsbbs import __version__
|
||||||
from rsbbs.commands import Commands
|
|
||||||
from rsbbs.config import Config
|
from rsbbs.config import Config
|
||||||
from rsbbs.console import Console
|
from rsbbs.console import Console
|
||||||
from rsbbs.controller import Controller
|
from rsbbs.controller import Controller
|
||||||
@ -82,7 +81,7 @@ def main():
|
|||||||
app_name='rsbbs',
|
app_name='rsbbs',
|
||||||
args=argv_args)
|
args=argv_args)
|
||||||
|
|
||||||
# Init the contoller
|
# Init the controller
|
||||||
controller = Controller(config)
|
controller = Controller(config)
|
||||||
|
|
||||||
# Init the UI console
|
# Init the UI console
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user