diff --git a/rsbbs/__init__.py b/rsbbs/__init__.py index 555eef2..c705fc4 100644 --- a/rsbbs/__init__.py +++ b/rsbbs/__init__.py @@ -16,8 +16,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -__all__ = ['config', 'console', - 'controller', 'parser', 'pluginloader'] +__all__ = ['config', 'console', 'controller', + 'logger', 'parser', 'pluginloader'] __version__ = "0.3.0" diff --git a/rsbbs/console.py b/rsbbs/console.py index f7eb548..109d06c 100644 --- a/rsbbs/console.py +++ b/rsbbs/console.py @@ -16,6 +16,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import logging import sys import rsbbs @@ -42,6 +43,10 @@ class Console(): # Input and output # + def disconnect(self) -> None: + logging.info("caller disconnected") + exit(0) + def read_enter(self, prompt) -> None: """Wait for the user to press enter. """ diff --git a/rsbbs/logger.py b/rsbbs/logger.py new file mode 100644 index 0000000..e4bb318 --- /dev/null +++ b/rsbbs/logger.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python +# +# Really Simple BBS - a really simple BBS for ax.25 packet radio. +# Copyright (C) 2023 John Burwell +# +# 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 . + +import datetime +import logging +import logging.handlers +import os +import platformdirs + + +class RSLogger(logging.Logger): + def __init__(self, config): + super().__init__(name=config.app_name) + self.config = config + self.name = config.app_name + self.caller = config.calling_station + + if self.config.args.debug: + self.log_level = logging.DEBUG + else: + self.log_level = getattr(logging, + self.config.args.log_level.upper()) + + self.init_logger() + + def init_logger(self): + logger = logging.getLogger() + logger.setLevel(self.level) + + # Remove the default StreamHandler that logs to the console + for handler in logger.handlers: + if isinstance(handler, logging.StreamHandler): + logger.removeHandler(handler) + + # Log to a file in the system user log directory + log_dir = platformdirs.user_log_dir(appname=self.name, + ensure_exists=True) + log_filepath = os.path.join(log_dir, 'activity.log') + + handler = logging.FileHandler(filename=log_filepath) + + # Add the calling station to the log messages + handler.setFormatter(RSFormatter(self.caller)) + + # Add the handler! + logger.addHandler(handler) + + +class RSFormatter(logging.Formatter): + def __init__(self, var): + super().__init__() + self.var = var + + def format(self, record): + now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3] + record.msg = f"{now} {record.levelname} {self.var} {record.msg}" + return super().format(record) diff --git a/rsbbs/logging.py b/rsbbs/logging.py deleted file mode 100644 index 329dc53..0000000 --- a/rsbbs/logging.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env python -# -# Really Simple BBS - a really simple BBS for ax.25 packet radio. -# Copyright (C) 2023 John Burwell -# -# 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 . - -import datetime -import logging - - -class Formatter(logging.Formatter): - def __init__(self, var): - super().__init__() - self.var = var - - def format(self, record): - now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3] - record.msg = f"{now} {record.levelname} {self.var} {record.msg}" - return super().format(record) diff --git a/rsbbs/plugins/bye/plugin.py b/rsbbs/plugins/bye/plugin.py index 1465541..f58114d 100644 --- a/rsbbs/plugins/bye/plugin.py +++ b/rsbbs/plugins/bye/plugin.py @@ -40,4 +40,4 @@ class Plugin(): """Disconnect and exit.""" self.api.write_output("Bye!") logging.info(f"{__name__} exiting") - exit(0) + self.api.disconnect() diff --git a/rsbbs/plugins/heard/plugin.py b/rsbbs/plugins/heard/plugin.py index 16b7082..b7696e3 100644 --- a/rsbbs/plugins/heard/plugin.py +++ b/rsbbs/plugins/heard/plugin.py @@ -28,7 +28,7 @@ class Plugin(): def __init__(self, api: Console) -> None: self.api = api self.init_parser(api.parser) - logging.info("plugin {__name__} loaded") + logging.info(f"plugin {__name__} loaded") def init_parser(self, parser: Parser) -> None: subparser = parser.subparsers.add_parser( diff --git a/rsbbs/plugins/list/plugin.py b/rsbbs/plugins/list/plugin.py index 81d254e..1d723da 100644 --- a/rsbbs/plugins/list/plugin.py +++ b/rsbbs/plugins/list/plugin.py @@ -29,7 +29,7 @@ class Plugin(): def __init__(self, api: Console) -> None: self.api = api self.init_parser(api.parser) - logging.info("plugin {__name__} loaded") + logging.info(f"plugin {__name__} loaded") def init_parser(self, parser: Parser) -> None: subparser = parser.subparsers.add_parser( diff --git a/rsbbs/plugins/listm/plugin.py b/rsbbs/plugins/listm/plugin.py index d9b54b2..e7c963c 100644 --- a/rsbbs/plugins/listm/plugin.py +++ b/rsbbs/plugins/listm/plugin.py @@ -29,7 +29,7 @@ class Plugin(): def __init__(self, api: Console) -> None: self.api = api self.init_parser(api.parser) - logging.info("plugin {__name__} loaded") + logging.info(f"plugin {__name__} loaded") def init_parser(self, parser: Parser) -> None: subparser = parser.subparsers.add_parser( diff --git a/rsbbs/rsbbs.py b/rsbbs/rsbbs.py index ab7144e..62dd43f 100755 --- a/rsbbs/rsbbs.py +++ b/rsbbs/rsbbs.py @@ -24,7 +24,7 @@ from rsbbs import __version__ from rsbbs.config import Config from rsbbs.console import Console from rsbbs.controller import Controller -from rsbbs.logging import Formatter +from rsbbs.logger import RSLogger def parse_args(): @@ -51,10 +51,10 @@ def parse_args(): group = argv_parser.add_mutually_exclusive_group(required=True) # Log level: - group.add_argument( + argv_parser.add_argument( '--log-level', action='store', - default='ERROR', + default='INFO', dest='log_level', help="Logging level") @@ -90,28 +90,14 @@ def main(): # Grab the invocation arguments args = parse_args() - # Start logging - if args.debug: - log_level = logging.DEBUG - else: - log_level = getattr(logging, args.log_level.upper()) - - logging.basicConfig(format='%(asctime)s %(message)s', - level=log_level) - logging.info(f"{__name__} started") - # Load configuration config = Config( app_name='rsbbs', args=args) - # Add the calling station to the logs - logger = logging.getLogger() - handler = logging.StreamHandler() - handler.setFormatter(Formatter(config.calling_station)) - logger.addHandler(handler) - - logger.info("connected") + # Start logging + logger = RSLogger(config) + logging.info(f"caller connected") # Init the controller controller = Controller(config) @@ -122,8 +108,6 @@ def main(): # Start the app console.run() - logging.info(f"{__name__} exiting") - if __name__ == "__main__": main()