Compare commits
2 Commits
190bb0742e
...
deae9af4c6
| Author | SHA1 | Date | |
|---|---|---|---|
| deae9af4c6 | |||
| 00b2f54381 |
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "rsbbs"
|
name = "rsbbs"
|
||||||
version = "0.1.0"
|
dynamic = ["version"]
|
||||||
authors = [
|
authors = [
|
||||||
{ name="John Burwell", email="john@atatdotdot.com" },
|
{ name="John Burwell", email="john@atatdotdot.com" },
|
||||||
]
|
]
|
||||||
@ -31,3 +31,6 @@ repository = "https://git.b-wells.us/jmbwell/rsbbs"
|
|||||||
|
|
||||||
[tool.setuptools.package-data]
|
[tool.setuptools.package-data]
|
||||||
rsbbs = ["config_default.yaml"]
|
rsbbs = ["config_default.yaml"]
|
||||||
|
|
||||||
|
[tool.setuptools.dynamic]
|
||||||
|
version = {attr = "rsbbs.__version__"}
|
||||||
@ -29,10 +29,9 @@ class Commands():
|
|||||||
# aliases,
|
# aliases,
|
||||||
# helpmsg,
|
# helpmsg,
|
||||||
# function,
|
# function,
|
||||||
# callback,
|
# arg:
|
||||||
# {arg:
|
# arg attributes...,
|
||||||
# {arg attributes},
|
# )
|
||||||
# ...})
|
|
||||||
('bye',
|
('bye',
|
||||||
['b', 'q'],
|
['b', 'q'],
|
||||||
'Sign off and disconnect',
|
'Sign off and disconnect',
|
||||||
@ -94,7 +93,7 @@ class Commands():
|
|||||||
'Send a new message to a user',
|
'Send a new message to a user',
|
||||||
self.responder.send,
|
self.responder.send,
|
||||||
{
|
{
|
||||||
'callsign': {'help': 'Message recipient callsign'},
|
'--callsign': {'help': 'Message recipient callsign'},
|
||||||
'--subject': {'help': 'Message subject'},
|
'--subject': {'help': 'Message subject'},
|
||||||
'--message': {'help': 'Message'},
|
'--message': {'help': 'Message'},
|
||||||
},),
|
},),
|
||||||
@ -104,7 +103,7 @@ class Commands():
|
|||||||
'Send a private message to a user',
|
'Send a private message to a user',
|
||||||
self.responder.send_private,
|
self.responder.send_private,
|
||||||
{
|
{
|
||||||
'callsign': {'help': 'Message recipient callsign'},
|
'--callsign': {'help': 'Message recipient callsign'},
|
||||||
'--subject': {'help': 'Message subject'},
|
'--subject': {'help': 'Message subject'},
|
||||||
'--message': {'help': 'Message'},
|
'--message': {'help': 'Message'},
|
||||||
},),]
|
},),]
|
||||||
|
|||||||
@ -25,45 +25,52 @@ import yaml
|
|||||||
class Config():
|
class Config():
|
||||||
|
|
||||||
def __init__(self, app_name, args):
|
def __init__(self, app_name, args):
|
||||||
self._app_name = app_name
|
self.app_name = app_name
|
||||||
self._config_file_path = args.config_file
|
self._argv_config_file = args.config_file
|
||||||
|
|
||||||
self._load_config()
|
self._load_config()
|
||||||
|
|
||||||
|
# Put the messages db file in the system's user data directory
|
||||||
self.config['db_path'] = os.path.join(
|
self.config['db_path'] = os.path.join(
|
||||||
platformdirs.user_data_dir(appname=app_name, ensure_exists=True),
|
platformdirs.user_data_dir(
|
||||||
|
appname=self.app_name,
|
||||||
|
ensure_exists=True),
|
||||||
'messages.db')
|
'messages.db')
|
||||||
|
|
||||||
self.config['debug'] = args.debug
|
# Grab some config from the command line for convenience
|
||||||
self.config['args'] = args
|
self.config['args'] = args
|
||||||
self.config['calling_station'] = args.calling_station.upper() or None
|
self.config['calling_station'] = args.calling_station.upper() or None
|
||||||
|
self.config['debug'] = args.debug
|
||||||
|
|
||||||
|
# The main thing people want from Config is config values, so let's pretend
|
||||||
|
# everything anyone asks of Config that isn't otherwise defined is probably
|
||||||
|
# a config value they want
|
||||||
def __getattr__(self, __name: str):
|
def __getattr__(self, __name: str):
|
||||||
return self.config[__name]
|
return self.config[__name]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def config_path(self):
|
def config_file(self):
|
||||||
# Use either the specified file or a file in a system config location
|
# Use either the specified file or a file in a system config location
|
||||||
config_path = self._config_file_path or os.path.join(
|
config_file = self._argv_config_file or os.path.join(
|
||||||
platformdirs.user_config_dir(
|
platformdirs.user_config_dir(
|
||||||
appname=self._app_name,
|
appname=self.app_name,
|
||||||
ensure_exists=True),
|
ensure_exists=True),
|
||||||
'config.yaml'
|
'config.yaml'
|
||||||
)
|
)
|
||||||
return config_path
|
return config_file
|
||||||
|
|
||||||
def _init_config_file(self):
|
def _init_config_file(self):
|
||||||
# If the file doesn't exist there, create it from the default file
|
# If the file doesn't exist there, create it from the default file
|
||||||
# included in the package
|
# included in the package
|
||||||
if not os.path.exists(self.config_path):
|
if not os.path.exists(self.config_file):
|
||||||
config_default_file_path = pkg_resources.resource_filename(
|
config_default_file = pkg_resources.resource_filename(
|
||||||
__name__,
|
__name__,
|
||||||
'config_default.yaml')
|
'config_default.yaml')
|
||||||
try:
|
try:
|
||||||
with open(config_default_file_path, 'r') as f:
|
with open(config_default_file, 'r') as f:
|
||||||
config_template = yaml.load(f, Loader=yaml.FullLoader)
|
config_default = yaml.load(f, Loader=yaml.FullLoader)
|
||||||
with open(self.config_path, 'w') as f:
|
with open(self.config_file, 'w') as f:
|
||||||
yaml.dump(config_template, f)
|
yaml.dump(config_default, f)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error creating configuration file: {e}")
|
print(f"Error creating configuration file: {e}")
|
||||||
exit(1)
|
exit(1)
|
||||||
@ -77,7 +84,7 @@ class Config():
|
|||||||
"""
|
"""
|
||||||
# Load it
|
# Load it
|
||||||
try:
|
try:
|
||||||
with open(self.config_path, 'r') as f:
|
with open(self.config_file, 'r') as f:
|
||||||
self.config = yaml.load(f, Loader=yaml.FullLoader)
|
self.config = yaml.load(f, Loader=yaml.FullLoader)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error loading configuration file: {e}")
|
print(f"Error loading configuration file: {e}")
|
||||||
|
|||||||
@ -174,7 +174,7 @@ class Console():
|
|||||||
self._write_output(f"Heard stations not available.")
|
self._write_output(f"Heard stations not available.")
|
||||||
|
|
||||||
def help(self, args):
|
def help(self, args):
|
||||||
self.parser.parser.print_help()
|
self.parser.print_help()
|
||||||
|
|
||||||
def list(self, args):
|
def list(self, args):
|
||||||
"""List all public messages and private messages to the caller."""
|
"""List all public messages and private messages to the caller."""
|
||||||
@ -267,7 +267,7 @@ class Console():
|
|||||||
# 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:
|
||||||
try:
|
try:
|
||||||
args = self.parser.parser.parse_args(line.split())
|
args = self.parser.parse_args(line.split())
|
||||||
args.func(args)
|
args.func(args)
|
||||||
except Exception:
|
except Exception:
|
||||||
if self.config.debug:
|
if self.config.debug:
|
||||||
|
|||||||
@ -21,15 +21,12 @@ import argparse
|
|||||||
from rsbbs.commands import Commands
|
from rsbbs.commands import Commands
|
||||||
|
|
||||||
|
|
||||||
# We want to override the error and exit methods of ArgumentParser
|
|
||||||
# to prevent it exiting unexpectedly or spewing error data over the air
|
|
||||||
|
|
||||||
class BBSArgumentParser(argparse.ArgumentParser):
|
class BBSArgumentParser(argparse.ArgumentParser):
|
||||||
# Override the error handler to prevent exiting on error
|
# Override the error handler to prevent spewing error cruft over the air
|
||||||
# def error(self, message):
|
# def error(self, message):
|
||||||
# print(message)
|
# print(message)
|
||||||
# raise
|
|
||||||
|
|
||||||
|
# Override the exit handler to prevent disconnecting unexpectedly
|
||||||
def exit(self, arg1, arg2):
|
def exit(self, arg1, arg2):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -37,9 +34,17 @@ class BBSArgumentParser(argparse.ArgumentParser):
|
|||||||
class Parser(BBSArgumentParser):
|
class Parser(BBSArgumentParser):
|
||||||
|
|
||||||
def __init__(self, commands: Commands):
|
def __init__(self, commands: Commands):
|
||||||
self.init_parser(commands)
|
self._init_parser(commands)
|
||||||
|
|
||||||
def init_parser(self, commands):
|
# The only thing anyone should ever access from Parser is its parser
|
||||||
|
# attribute, so let's save everyone a step.
|
||||||
|
def __getattribute__(self, attr):
|
||||||
|
try:
|
||||||
|
return object.__getattribute__(self, attr)
|
||||||
|
except AttributeError:
|
||||||
|
return getattr(self.parser, attr)
|
||||||
|
|
||||||
|
def _init_parser(self, commands):
|
||||||
# Root parser for BBS commands
|
# Root parser for BBS commands
|
||||||
self.parser = BBSArgumentParser(
|
self.parser = BBSArgumentParser(
|
||||||
description='BBS Main Menu',
|
description='BBS Main Menu',
|
||||||
@ -55,11 +60,14 @@ class Parser(BBSArgumentParser):
|
|||||||
|
|
||||||
# Loop through the commands and add each as a subparser
|
# Loop through the commands and add each as a subparser
|
||||||
for name, aliases, help_msg, func, arguments in commands.commands:
|
for name, aliases, help_msg, func, arguments in commands.commands:
|
||||||
|
# Add the command attributes
|
||||||
subparser = subparsers.add_parser(
|
subparser = subparsers.add_parser(
|
||||||
name,
|
name,
|
||||||
aliases=aliases,
|
aliases=aliases,
|
||||||
help=help_msg,
|
help=help_msg,
|
||||||
)
|
)
|
||||||
|
# Add the command parameters
|
||||||
for arg_name, options in arguments.items():
|
for arg_name, options in arguments.items():
|
||||||
subparser.add_argument(arg_name, **options)
|
subparser.add_argument(arg_name, **options)
|
||||||
|
# Trick to pass a function to call when the command is entered
|
||||||
subparser.set_defaults(func=func)
|
subparser.set_defaults(func=func)
|
||||||
|
|||||||
@ -30,7 +30,7 @@ from rsbbs.parser import Parser
|
|||||||
def main():
|
def main():
|
||||||
|
|
||||||
# Parse and handle the system invocation arguments
|
# Parse and handle the system invocation arguments
|
||||||
sysv_parser = argparse.ArgumentParser(
|
argv_parser = argparse.ArgumentParser(
|
||||||
description=("The BBS for ax.25 and packet radio "
|
description=("The BBS for ax.25 and packet radio "
|
||||||
"that is really simple."))
|
"that is really simple."))
|
||||||
|
|
||||||
@ -45,23 +45,23 @@ def main():
|
|||||||
'Path to config.yaml file', False],
|
'Path to config.yaml file', False],
|
||||||
]
|
]
|
||||||
for arg in args_list:
|
for arg in args_list:
|
||||||
sysv_parser.add_argument(
|
argv_parser.add_argument(
|
||||||
arg[0], arg[1], action=arg[2], default=arg[3], dest=arg[4],
|
arg[0], arg[1], action=arg[2], default=arg[3], dest=arg[4],
|
||||||
help=arg[5], required=arg[6])
|
help=arg[5], required=arg[6])
|
||||||
|
|
||||||
# Version arg is special:
|
# Version arg is special:
|
||||||
sysv_parser.add_argument(
|
argv_parser.add_argument(
|
||||||
'-v', '--version',
|
'-v', '--version',
|
||||||
action='version',
|
action='version',
|
||||||
version=f"{sysv_parser.prog} version {__version__}")
|
version=f"{argv_parser.prog} version {__version__}")
|
||||||
|
|
||||||
# Parse the args from the system
|
# Parse the args from the system
|
||||||
sysv_args = sysv_parser.parse_args(sys.argv[1:])
|
argv_args = argv_parser.parse_args(sys.argv[1:])
|
||||||
|
|
||||||
# Load configuration
|
# Load configuration
|
||||||
config = Config(
|
config = Config(
|
||||||
app_name='rsbbs',
|
app_name='rsbbs',
|
||||||
args=sysv_args)
|
args=argv_args)
|
||||||
|
|
||||||
# Init the contoller
|
# Init the contoller
|
||||||
controller = Controller(config)
|
controller = Controller(config)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user