Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 42d578da76 | |||
| d729d69ea3 | |||
| 498defc003 | |||
| c67179cdba | |||
| 1bef879dac | |||
| ea71dec87d | |||
| f813aa2656 | |||
| 6a8188f873 | |||
| db940aa983 | |||
| 46632fbef0 | |||
| e28756efa2 |
@ -29,6 +29,8 @@ user calls your station, `ax25d` answers the call and routes the connection to
|
|||||||
you have configured your axports, and that ax25d can answer calls.
|
you have configured your axports, and that ax25d can answer calls.
|
||||||
- **Python 3:** As this is a python 3 application, you will need python 3 and
|
- **Python 3:** As this is a python 3 application, you will need python 3 and
|
||||||
pip.
|
pip.
|
||||||
|
- Note on compiling Python3: If you build Python3 from source on
|
||||||
|
debian/raspbian, you will need libssl-dev, libffi-dev, and libsqlite3-dev
|
||||||
- **Hardware:** A system capable of running Direwolf and ax25d should be more
|
- **Hardware:** A system capable of running Direwolf and ax25d should be more
|
||||||
than sufficient.
|
than sufficient.
|
||||||
|
|
||||||
|
|||||||
@ -30,7 +30,7 @@ rsbbs = "rsbbs.rsbbs:main"
|
|||||||
repository = "https://git.b-wells.us/jmbwell/rsbbs"
|
repository = "https://git.b-wells.us/jmbwell/rsbbs"
|
||||||
|
|
||||||
[tool.setuptools.package-data]
|
[tool.setuptools.package-data]
|
||||||
rsbbs = ["config_default.yaml"]
|
rsbbs = ["config_default.yaml","plugins/info/info_default.txt"]
|
||||||
|
|
||||||
[tool.setuptools.dynamic]
|
[tool.setuptools.dynamic]
|
||||||
version = {attr = "rsbbs.__version__"}
|
version = {attr = "rsbbs.__version__"}
|
||||||
@ -20,11 +20,3 @@ __all__ = ['config', 'console', 'controller',
|
|||||||
'logger', 'models', 'parser', 'pluginloader']
|
'logger', 'models', 'parser', 'pluginloader']
|
||||||
|
|
||||||
__version__ = "0.4.0"
|
__version__ = "0.4.0"
|
||||||
|
|
||||||
from .config import Config
|
|
||||||
from .console import Console
|
|
||||||
from .controller import Controller
|
|
||||||
from .logger import Logger
|
|
||||||
from .parser import Parser
|
|
||||||
from .pluginloader import PluginLoader
|
|
||||||
from .user import User
|
|
||||||
|
|||||||
@ -28,13 +28,15 @@ class Config():
|
|||||||
self.app_name = app_name
|
self.app_name = app_name
|
||||||
self._argv_config_file = args.config_file
|
self._argv_config_file = args.config_file
|
||||||
|
|
||||||
|
self._init_config_file()
|
||||||
self._load_config()
|
self._load_config()
|
||||||
|
|
||||||
# Put the messages db file in the system's user data directory
|
# Put the messages db file in the system's user data directory
|
||||||
|
db_dir = platformdirs.user_data_dir(appname=self.app_name)
|
||||||
|
if not os.path.exists(db_dir):
|
||||||
|
os.makedirs(db_dir)
|
||||||
self._config['db_path'] = os.path.join(
|
self._config['db_path'] = os.path.join(
|
||||||
platformdirs.user_data_dir(
|
db_dir,
|
||||||
appname=self.app_name,
|
|
||||||
ensure_exists=True),
|
|
||||||
'messages.db')
|
'messages.db')
|
||||||
|
|
||||||
# Grab some config from the command line for convenience
|
# Grab some config from the command line for convenience
|
||||||
@ -63,10 +65,11 @@ class Config():
|
|||||||
@property
|
@property
|
||||||
def config_file(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_dir = platformdirs.user_config_dir(appname=self.app_name)
|
||||||
|
if not os.path.exists(config_dir):
|
||||||
|
os.makedirs(config_dir)
|
||||||
config_file = self._argv_config_file or os.path.join(
|
config_file = self._argv_config_file or os.path.join(
|
||||||
platformdirs.user_config_dir(
|
config_dir,
|
||||||
appname=self.app_name,
|
|
||||||
ensure_exists=True),
|
|
||||||
'config.yaml'
|
'config.yaml'
|
||||||
)
|
)
|
||||||
return config_file
|
return config_file
|
||||||
|
|||||||
@ -16,11 +16,15 @@
|
|||||||
# 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 io
|
||||||
import logging
|
import logging
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import rsbbs
|
import rsbbs
|
||||||
from rsbbs import Config, Controller
|
from rsbbs.config import Config
|
||||||
|
from rsbbs.controller import Controller
|
||||||
|
from rsbbs.parser import Parser
|
||||||
|
from rsbbs.pluginloader import PluginLoader
|
||||||
from rsbbs.models import User
|
from rsbbs.models import User
|
||||||
|
|
||||||
|
|
||||||
@ -34,11 +38,20 @@ class Console():
|
|||||||
self.controller = controller
|
self.controller = controller
|
||||||
self.user = user
|
self.user = user
|
||||||
|
|
||||||
self.parser = rsbbs.Parser()
|
self.parser = Parser()
|
||||||
|
|
||||||
self.pluginloader = rsbbs.PluginLoader(self)
|
self.pluginloader = PluginLoader(self)
|
||||||
self.pluginloader.load_plugins()
|
self.pluginloader.load_plugins()
|
||||||
|
|
||||||
|
# Configure stdin and stdout newlines and encoding
|
||||||
|
# when invoked by ax25:
|
||||||
|
if not sys.stdin.isatty():
|
||||||
|
sys.stdout = io.TextIOWrapper(sys.stdout.detach(),
|
||||||
|
newline=None)
|
||||||
|
|
||||||
|
sys.stdin = io.TextIOWrapper(sys.stdin.detach(),
|
||||||
|
newline=None)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Input and output
|
# Input and output
|
||||||
#
|
#
|
||||||
@ -87,18 +100,31 @@ class Console():
|
|||||||
self.write_output(prompt)
|
self.write_output(prompt)
|
||||||
while True:
|
while True:
|
||||||
input_line = sys.stdin.readline()
|
input_line = sys.stdin.readline()
|
||||||
if input_line.lower().strip() != "/ex":
|
if input_line.lower().strip() == "/ex":
|
||||||
break
|
break
|
||||||
input_lines.append(input_line)
|
input_lines.append(input_line)
|
||||||
return ''.join(input_lines)
|
return ''.join(input_lines)
|
||||||
|
|
||||||
|
def write_chunk(self, chunk: str) -> None:
|
||||||
|
"""Write a chunk of data to stdout.
|
||||||
|
|
||||||
|
:param output: the chunk to write to stdout
|
||||||
|
|
||||||
|
"""
|
||||||
|
sys.stdout.write(chunk + '\r\n')
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
def write_output(self, output: str) -> None:
|
def write_output(self, output: str) -> None:
|
||||||
"""Write something to stdout.
|
"""Write something to stdout.
|
||||||
|
|
||||||
:param output: the string to write to stdout
|
:param output: the string to write to stdout
|
||||||
|
|
||||||
"""
|
"""
|
||||||
sys.stdout.write(output + '\r\n')
|
chunk_size = 256 # Adjust the chunk size as needed
|
||||||
|
|
||||||
|
for i in range(0, len(output), chunk_size):
|
||||||
|
chunk = output[i:i + chunk_size]
|
||||||
|
self.write_chunk(chunk)
|
||||||
|
|
||||||
def print_configuration(self) -> None:
|
def print_configuration(self) -> None:
|
||||||
"""Print the current running configuration.
|
"""Print the current running configuration.
|
||||||
|
|||||||
@ -19,7 +19,7 @@
|
|||||||
from sqlalchemy import create_engine
|
from sqlalchemy import create_engine
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from rsbbs import Config
|
from rsbbs.config import Config
|
||||||
from rsbbs.models import Base
|
from rsbbs.models import Base
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -48,10 +48,12 @@ class Logger(logging.Logger):
|
|||||||
logger.removeHandler(handler)
|
logger.removeHandler(handler)
|
||||||
|
|
||||||
# Log to a file in the system user log directory
|
# Log to a file in the system user log directory
|
||||||
log_dir = platformdirs.user_log_dir(appname=self.name,
|
log_dir = platformdirs.user_log_dir(appname=self.name)
|
||||||
ensure_exists=True)
|
|
||||||
log_filepath = os.path.join(log_dir, 'activity.log')
|
log_filepath = os.path.join(log_dir, 'activity.log')
|
||||||
|
|
||||||
|
if not os.path.exists(log_dir):
|
||||||
|
os.makedirs(log_dir)
|
||||||
|
|
||||||
handler = logging.FileHandler(filename=log_filepath)
|
handler = logging.FileHandler(filename=log_filepath)
|
||||||
|
|
||||||
# Add the calling station to the log messages
|
# Add the calling station to the log messages
|
||||||
@ -60,7 +62,6 @@ class Logger(logging.Logger):
|
|||||||
# Add the handler!
|
# Add the handler!
|
||||||
logger.addHandler(handler)
|
logger.addHandler(handler)
|
||||||
|
|
||||||
|
|
||||||
class Formatter(logging.Formatter):
|
class Formatter(logging.Formatter):
|
||||||
def __init__(self, var):
|
def __init__(self, var):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|||||||
@ -18,7 +18,8 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from rsbbs import Console, Parser
|
from rsbbs.console import Console
|
||||||
|
from rsbbs.parser import Parser
|
||||||
|
|
||||||
|
|
||||||
class Plugin():
|
class Plugin():
|
||||||
|
|||||||
@ -21,7 +21,8 @@ import logging
|
|||||||
import sqlalchemy
|
import sqlalchemy
|
||||||
import sqlalchemy.exc
|
import sqlalchemy.exc
|
||||||
|
|
||||||
from rsbbs import Console, Parser
|
from rsbbs.console import Console
|
||||||
|
from rsbbs.parser import Parser
|
||||||
from rsbbs.models import Message
|
from rsbbs.models import Message
|
||||||
|
|
||||||
|
|
||||||
@ -48,13 +49,12 @@ class Plugin():
|
|||||||
sqlalchemy.and_(
|
sqlalchemy.and_(
|
||||||
Message.recipient == self.api.config.calling_station,
|
Message.recipient == self.api.config.calling_station,
|
||||||
Message.id == number,
|
Message.id == number,
|
||||||
)).returning(Message)
|
))
|
||||||
result = session.execute(
|
result = session.execute(
|
||||||
statement,
|
statement,
|
||||||
execution_options={"prebuffer_rows": True})
|
execution_options={"prebuffer_rows": True})
|
||||||
|
count = result.rowcount
|
||||||
session.commit()
|
session.commit()
|
||||||
results = result.all()
|
|
||||||
count = len(results)
|
|
||||||
if count > 0:
|
if count > 0:
|
||||||
self.api.write_output(f"Deleted message #{number}")
|
self.api.write_output(f"Deleted message #{number}")
|
||||||
logging.info(f"deleted message {number}")
|
logging.info(f"deleted message {number}")
|
||||||
|
|||||||
@ -19,7 +19,8 @@
|
|||||||
import logging
|
import logging
|
||||||
import sqlalchemy
|
import sqlalchemy
|
||||||
|
|
||||||
from rsbbs import Console, Parser
|
from rsbbs.console import Console
|
||||||
|
from rsbbs.parser import Parser
|
||||||
from rsbbs.models import Message
|
from rsbbs.models import Message
|
||||||
|
|
||||||
|
|
||||||
@ -42,13 +43,12 @@ class Plugin():
|
|||||||
try:
|
try:
|
||||||
statement = sqlalchemy.delete(Message).where(
|
statement = sqlalchemy.delete(Message).where(
|
||||||
Message.recipient == self.api.config.calling_station
|
Message.recipient == self.api.config.calling_station
|
||||||
).returning(Message)
|
)
|
||||||
result = session.execute(
|
result = session.execute(
|
||||||
statement,
|
statement,
|
||||||
execution_options={"prebuffer_rows": True})
|
execution_options={"prebuffer_rows": True})
|
||||||
|
count = result.rowcount
|
||||||
session.commit()
|
session.commit()
|
||||||
messages = result.all()
|
|
||||||
count = len(messages)
|
|
||||||
if count > 0:
|
if count > 0:
|
||||||
self.api.write_output(f"Deleted {count} messages")
|
self.api.write_output(f"Deleted {count} messages")
|
||||||
logging.info(f"deleted {count} messages")
|
logging.info(f"deleted {count} messages")
|
||||||
|
|||||||
@ -19,7 +19,8 @@
|
|||||||
import logging
|
import logging
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from rsbbs import Console, Parser
|
from rsbbs.console import Console
|
||||||
|
from rsbbs.parser import Parser
|
||||||
|
|
||||||
|
|
||||||
class Plugin():
|
class Plugin():
|
||||||
|
|||||||
@ -16,7 +16,8 @@
|
|||||||
# 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/>.
|
||||||
|
|
||||||
from rsbbs import Console, Parser
|
from rsbbs.console import Console
|
||||||
|
from rsbbs.parser import Parser
|
||||||
|
|
||||||
|
|
||||||
class Plugin():
|
class Plugin():
|
||||||
|
|||||||
@ -17,12 +17,14 @@
|
|||||||
# 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 logging
|
import logging
|
||||||
|
import os
|
||||||
import pkg_resources
|
import pkg_resources
|
||||||
import platformdirs
|
import platformdirs
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from rsbbs import Console, Parser
|
from rsbbs.console import Console
|
||||||
|
from rsbbs.parser import Parser
|
||||||
|
|
||||||
|
|
||||||
class Plugin():
|
class Plugin():
|
||||||
@ -42,10 +44,12 @@ class Plugin():
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def file(self) -> Path:
|
def file(self) -> Path:
|
||||||
|
file_dir = platformdirs.user_config_dir(
|
||||||
|
appname=self.api.config.app_name)
|
||||||
|
if not os.path.exists(file_dir):
|
||||||
|
os.makedirs(file_dir)
|
||||||
self._file = Path().joinpath(
|
self._file = Path().joinpath(
|
||||||
platformdirs.user_config_dir(
|
file_dir,
|
||||||
appname=self.api.config.app_name,
|
|
||||||
ensure_exists=True),
|
|
||||||
'info.txt'
|
'info.txt'
|
||||||
)
|
)
|
||||||
return self._file
|
return self._file
|
||||||
|
|||||||
@ -19,7 +19,8 @@
|
|||||||
import logging
|
import logging
|
||||||
import sqlalchemy
|
import sqlalchemy
|
||||||
|
|
||||||
from rsbbs import Console, Parser
|
from rsbbs.console import Console
|
||||||
|
from rsbbs.parser import Parser
|
||||||
from rsbbs.models import Message
|
from rsbbs.models import Message
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -19,7 +19,8 @@
|
|||||||
import logging
|
import logging
|
||||||
import sqlalchemy
|
import sqlalchemy
|
||||||
|
|
||||||
from rsbbs import Console, Parser
|
from rsbbs.console import Console
|
||||||
|
from rsbbs.parser import Parser
|
||||||
from rsbbs.models import Message
|
from rsbbs.models import Message
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -19,7 +19,8 @@
|
|||||||
import logging
|
import logging
|
||||||
import sqlalchemy
|
import sqlalchemy
|
||||||
|
|
||||||
from rsbbs import Console, Parser
|
from rsbbs.console import Console
|
||||||
|
from rsbbs.parser import Parser
|
||||||
from rsbbs.models import Message, User
|
from rsbbs.models import Message, User
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -20,7 +20,8 @@ import logging
|
|||||||
import sqlalchemy
|
import sqlalchemy
|
||||||
import sqlalchemy.exc
|
import sqlalchemy.exc
|
||||||
|
|
||||||
from rsbbs import Console, Parser
|
from rsbbs.console import Console
|
||||||
|
from rsbbs.parser import Parser
|
||||||
from rsbbs.models import Message, User
|
from rsbbs.models import Message, User
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -19,7 +19,8 @@
|
|||||||
import logging
|
import logging
|
||||||
import sqlalchemy
|
import sqlalchemy
|
||||||
|
|
||||||
from rsbbs import Console, Parser
|
from rsbbs.console import Console
|
||||||
|
from rsbbs.parser import Parser
|
||||||
from rsbbs.models import Message, User
|
from rsbbs.models import Message, User
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -19,7 +19,8 @@
|
|||||||
import logging
|
import logging
|
||||||
import sqlalchemy
|
import sqlalchemy
|
||||||
|
|
||||||
from rsbbs import Console, Parser
|
from rsbbs.console import Console
|
||||||
|
from rsbbs.parser import Parser
|
||||||
from rsbbs.models import Message, User
|
from rsbbs.models import Message, User
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,8 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from rsbbs import Console, Parser
|
from rsbbs.console import Console
|
||||||
|
from rsbbs.parser import Parser
|
||||||
from rsbbs.models import Message
|
from rsbbs.models import Message
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,8 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from rsbbs import Console, Parser
|
from rsbbs.console import Console
|
||||||
|
from rsbbs.parser import Parser
|
||||||
from rsbbs.models import Message
|
from rsbbs.models import Message
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -23,7 +23,8 @@ import sqlalchemy.orm
|
|||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from rsbbs import __version__
|
from rsbbs import __version__
|
||||||
from rsbbs import Console, Parser
|
from rsbbs.console import Console
|
||||||
|
from rsbbs.parser import Parser
|
||||||
from rsbbs.models import Message, User
|
from rsbbs.models import Message, User
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,10 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from rsbbs import Config, Console, Controller, Logger
|
from rsbbs.config import Config
|
||||||
|
from rsbbs.console import Console
|
||||||
|
from rsbbs.controller import Controller
|
||||||
|
from rsbbs.logger import Logger
|
||||||
|
|
||||||
from rsbbs.args import parse_args
|
from rsbbs.args import parse_args
|
||||||
|
|
||||||
@ -26,6 +29,10 @@ from rsbbs.user import User
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
"""RSBBS - The BBS for packet radio that is really simple.
|
||||||
|
|
||||||
|
main function.
|
||||||
|
"""
|
||||||
|
|
||||||
# Grab the invocation arguments
|
# Grab the invocation arguments
|
||||||
args = parse_args()
|
args = parse_args()
|
||||||
|
|||||||
@ -23,7 +23,8 @@ from typing import Any
|
|||||||
|
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
|
|
||||||
from rsbbs import Config, Controller
|
from rsbbs.config import Config
|
||||||
|
from rsbbs.controller import Controller
|
||||||
from rsbbs.models import User as SAUser
|
from rsbbs.models import User as SAUser
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user