From f63520f38590f3f435bf718f26ac0df16ea98e6d Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sun, 24 Nov 2019 21:09:45 +0100 Subject: [PATCH] Some progress on config stuff --- .gitignore | 1 + .idea/.gitignore | 4 +- .idea/dataSources.xml | 11 ++ poetry.lock | 100 +++------------- pyproject.toml | 2 +- royalnet/__main__.py | 151 ++++++++----------------- royalnet/backpack/commands/__init__.py | 10 +- royalnet/serf/discord/discordserf.py | 16 ++- royalnet/serf/serf.py | 26 ++--- royalnet/serf/telegram/telegramserf.py | 9 +- 10 files changed, 105 insertions(+), 225 deletions(-) create mode 100644 .idea/dataSources.xml diff --git a/.gitignore b/.gitignore index dffa20b1..45ef1213 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ .idea/royalnet.iml dist/ **/__pycache__/ +config.toml diff --git a/.idea/.gitignore b/.idea/.gitignore index 5c98b428..1f1e8932 100644 --- a/.idea/.gitignore +++ b/.idea/.gitignore @@ -1,2 +1,4 @@ # Default ignored files -/workspace.xml \ No newline at end of file +/workspace.xml +# Datasource local storage ignored files +/dataSources/ \ No newline at end of file diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml new file mode 100644 index 00000000..bda80ca4 --- /dev/null +++ b/.idea/dataSources.xml @@ -0,0 +1,11 @@ + + + + + postgresql + true + org.postgresql.Driver + jdbc:postgresql://scaleway.steffo.eu:5432/royalnet + + + \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index e66aa4f4..ce9e234b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -78,7 +78,7 @@ version = "2019.9.11" category = "main" description = "Foreign Function Interface for Python calling C code." name = "cffi" -optional = false +optional = true python-versions = "*" version = "1.13.2" @@ -129,7 +129,7 @@ cron = ["capturer (>=2.4)"] category = "main" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." name = "cryptography" -optional = false +optional = true python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" version = "2.8" @@ -186,14 +186,6 @@ optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" version = "0.15.2" -[[package]] -category = "main" -description = "Discover and load entry points from installed packages." -name = "entrypoints" -optional = false -python-versions = ">=2.7" -version = "0.3" - [[package]] category = "main" description = "Python bindings for FFmpeg - with complex filtering support" @@ -260,18 +252,6 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" version = "1.1.0" -[[package]] -category = "main" -description = "Low-level, pure Python DBus protocol wrapper." -marker = "sys_platform == \"linux\"" -name = "jeepney" -optional = false -python-versions = ">=3.5" -version = "0.4.1" - -[package.extras] -dev = ["testpath"] - [[package]] category = "dev" description = "A very fast and expressive template engine." @@ -286,23 +266,6 @@ MarkupSafe = ">=0.23" [package.extras] i18n = ["Babel (>=0.8)"] -[[package]] -category = "main" -description = "Store and access your passwords safely." -name = "keyring" -optional = false -python-versions = ">=3.5" -version = "19.2.0" - -[package.dependencies] -entrypoints = "*" -pywin32-ctypes = "<0.1.0 || >0.1.0,<0.1.1 || >0.1.1" -secretstorage = "*" - -[package.extras] -docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"] -testing = ["pytest (>=3.5,<3.7.3 || >3.7.3)", "pytest-checkdocs", "pytest-flake8", "pytest-black-multipy"] - [[package]] category = "dev" description = "Safely add untrusted strings to HTML/XML markup." @@ -378,7 +341,7 @@ version = "1.8.0" category = "main" description = "C parser in Python" name = "pycparser" -optional = false +optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" version = "2.19" @@ -481,15 +444,6 @@ optional = false python-versions = "*" version = "2019.3" -[[package]] -category = "main" -description = "" -marker = "sys_platform == \"win32\"" -name = "pywin32-ctypes" -optional = false -python-versions = "*" -version = "0.2.0" - [[package]] category = "main" description = "Alternative regular expression module, to replace re." @@ -516,19 +470,6 @@ urllib3 = ">=1.21.1,<1.25.0 || >1.25.0,<1.25.1 || >1.25.1,<1.26" security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)"] socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"] -[[package]] -category = "main" -description = "Python bindings to FreeDesktop.org Secret Service API" -marker = "sys_platform == \"linux\"" -name = "secretstorage" -optional = false -python-versions = ">=3.5" -version = "3.1.1" - -[package.dependencies] -cryptography = "*" -jeepney = "*" - [[package]] category = "main" description = "Python client for Sentry (https://getsentry.com)" @@ -701,6 +642,14 @@ version = "0.12.13" [package.extras] full = ["aiofiles", "graphene", "itsdangerous", "jinja2", "python-multipart", "pyyaml", "requests", "ujson"] +[[package]] +category = "main" +description = "Python Library for Tom's Obvious, Minimal Language" +name = "toml" +optional = false +python-versions = "*" +version = "0.10.0" + [[package]] category = "main" description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." @@ -805,7 +754,7 @@ sentry = ["sentry_sdk"] telegram = ["python_telegram_bot"] [metadata] -content-hash = "ab3c90d2eb5ce9e8bfad099502bb183959ee406192d2ee159f902c2a52658614" +content-hash = "b159275a7b57094bc7fd801ba47883be1c6d1be395780dca0d2c018fc98009b7" python-versions = "^3.8" [metadata.files] @@ -941,10 +890,6 @@ docutils = [ {file = "docutils-0.15.2-py3-none-any.whl", hash = "sha256:6c4f696463b79f1fb8ba0c594b63840ebd41f059e92b31957c46b74a4599b6d0"}, {file = "docutils-0.15.2.tar.gz", hash = "sha256:a2aeea129088da402665e92e0b25b04b073c04b2dce4ab65caaa38b7ce2e1a99"}, ] -entrypoints = [ - {file = "entrypoints-0.3-py2.py3-none-any.whl", hash = "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19"}, - {file = "entrypoints-0.3.tar.gz", hash = "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451"}, -] ffmpeg-python = [ {file = "ffmpeg-python-0.2.0.tar.gz", hash = "sha256:65225db34627c578ef0e11c8b1eb528bb35e024752f6f10b78c011f6f64c4127"}, {file = "ffmpeg_python-0.2.0-py3-none-any.whl", hash = "sha256:ac441a0404e053f8b6a1113a77c0f452f1cfc62f6344a769475ffdc0f56c23c5"}, @@ -971,18 +916,10 @@ imagesize = [ {file = "imagesize-1.1.0-py2.py3-none-any.whl", hash = "sha256:3f349de3eb99145973fefb7dbe38554414e5c30abd0c8e4b970a7c9d09f3a1d8"}, {file = "imagesize-1.1.0.tar.gz", hash = "sha256:f3832918bc3c66617f92e35f5d70729187676313caa60c187eb0f28b8fe5e3b5"}, ] -jeepney = [ - {file = "jeepney-0.4.1-py3-none-any.whl", hash = "sha256:f6a3f93464a0cf052f4e87da3c8b3ed1e27696758fb9739c63d3a74d9a1b6774"}, - {file = "jeepney-0.4.1.tar.gz", hash = "sha256:13806f91a96e9b2623fd2a81b950d763ee471454aafd9eb6d75dbe7afce428fb"}, -] jinja2 = [ {file = "Jinja2-2.10.3-py2.py3-none-any.whl", hash = "sha256:74320bb91f31270f9551d46522e33af46a80c3d619f4a4bf42b3164d30b5911f"}, {file = "Jinja2-2.10.3.tar.gz", hash = "sha256:9fe95f19286cfefaa917656583d020be14e7859c6b0252588391e47db34527de"}, ] -keyring = [ - {file = "keyring-19.2.0-py2.py3-none-any.whl", hash = "sha256:f5bb20ea6c57c2360daf0c591931c9ea0d7660a8d9e32ca84d63273f131ea605"}, - {file = "keyring-19.2.0.tar.gz", hash = "sha256:91037ccaf0c9a112a76f7740e4a416b9457a69b66c2799421581bee710a974b3"}, -] markupsafe = [ {file = "MarkupSafe-1.1.1-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161"}, {file = "MarkupSafe-1.1.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"}, @@ -1152,10 +1089,6 @@ pytz = [ {file = "pytz-2019.3-py2.py3-none-any.whl", hash = "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d"}, {file = "pytz-2019.3.tar.gz", hash = "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be"}, ] -pywin32-ctypes = [ - {file = "pywin32-ctypes-0.2.0.tar.gz", hash = "sha256:24ffc3b341d457d48e8922352130cf2644024a4ff09762a2261fd34c36ee5942"}, - {file = "pywin32_ctypes-0.2.0-py2.py3-none-any.whl", hash = "sha256:9dc2d991b3479cc2df15930958b674a48a227d5361d413827a4cfd0b5876fc98"}, -] regex = [ {file = "regex-2019.11.1-cp27-none-win32.whl", hash = "sha256:604dc563a02a74d70ae1f55208ddc9bfb6d9f470f6d1a5054c4bd5ae58744ab1"}, {file = "regex-2019.11.1-cp27-none-win_amd64.whl", hash = "sha256:5e00f65cc507d13ab4dfa92c1232d004fa202c1d43a32a13940ab8a5afe2fb96"}, @@ -1175,10 +1108,6 @@ requests = [ {file = "requests-2.22.0-py2.py3-none-any.whl", hash = "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31"}, {file = "requests-2.22.0.tar.gz", hash = "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4"}, ] -secretstorage = [ - {file = "SecretStorage-3.1.1-py3-none-any.whl", hash = "sha256:7a119fb52a88e398dbb22a4b3eb39b779bfbace7e4153b7bc6e5954d86282a8a"}, - {file = "SecretStorage-3.1.1.tar.gz", hash = "sha256:20c797ae48a4419f66f8d28fc221623f11fc45b6828f96bdb1ad9990acb59f92"}, -] sentry-sdk = [ {file = "sentry-sdk-0.13.2.tar.gz", hash = "sha256:ff1fa7fb85703ae9414c8b427ee73f8363232767c9cd19158f08f6e4f0b58fc7"}, {file = "sentry_sdk-0.13.2-py2.py3-none-any.whl", hash = "sha256:09e1e8f00f22ea580348f83bbbd880adf40b29f1dec494a8e4b33e22f77184fb"}, @@ -1229,6 +1158,11 @@ sqlalchemy = [ starlette = [ {file = "starlette-0.12.13.tar.gz", hash = "sha256:9597bc28e3c4659107c1c4a45ec32dc45e947d78fe56230222be673b2c36454a"}, ] +toml = [ + {file = "toml-0.10.0-py2.7.egg", hash = "sha256:f1db651f9657708513243e61e6cc67d101a39bad662eaa9b5546f789338e07a3"}, + {file = "toml-0.10.0-py2.py3-none-any.whl", hash = "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e"}, + {file = "toml-0.10.0.tar.gz", hash = "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c"}, +] tornado = [ {file = "tornado-6.0.3-cp35-cp35m-win32.whl", hash = "sha256:c9399267c926a4e7c418baa5cbe91c7d1cf362d505a1ef898fde44a07c9dd8a5"}, {file = "tornado-6.0.3-cp35-cp35m-win_amd64.whl", hash = "sha256:398e0d35e086ba38a0427c3b37f4337327231942e731edaa6e9fd1865bbd6f60"}, diff --git a/pyproject.toml b/pyproject.toml index 53f7b4f4..7d039f5c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,7 +20,7 @@ [tool.poetry.dependencies] python = "^3.8" dateparser = "^0.7.2" - keyring = "^19.2.0" # TODO: Maybe remove this when possible? + toml = "^0.10.0" # telegram python_telegram_bot = {version="^12.2.0", optional=true} diff --git a/royalnet/__main__.py b/royalnet/__main__.py index f939050a..19a7bf3f 100644 --- a/royalnet/__main__.py +++ b/royalnet/__main__.py @@ -3,7 +3,7 @@ import typing import importlib import royalnet as r import multiprocessing -import keyring +import toml from logging import Formatter, StreamHandler, getLogger, Logger try: @@ -13,44 +13,16 @@ except ImportError: @click.command() -@click.option("--telegram/--no-telegram", default=None, - help="Enable/disable the Telegram bot.") -@click.option("--discord/--no-discord", default=None, - help="Enable/disable the Discord bot.") -@click.option("--constellation/--no-constellation", default=None, - help="Enable/disable the Constellation web server.") -@click.option("--herald/--no-herald", default=None, - help="Enable/disable the integrated Herald server." - " If turned off, Royalnet will try to connect to another server.") -@click.option("--remote-herald-address", type=str, default=None, - help="If --no-herald is specified, connect to the Herald server at this URL instead.") -@click.option("-c", "--constellation-port", default=44445, - help="The port on which the Constellation will serve webpages on.") -@click.option("-a", "--alchemy-url", type=str, default=None, - help="The Alchemy database path.") -@click.option("-h", "--herald-port", type=int, default=44444, - help="The port on which the Herald should be running.") -@click.option("-p", "--pack", type=str, multiple=True, default=tuple(), - help="Import the pack with the specified name and use it in the Royalnet instance.") -@click.option("-s", "--secrets-name", type=str, default="__default__", - help="The name in the keyring that the secrets are stored with.") -@click.option("-l", "--log-level", type=str, default="INFO", - help="Select how much information you want to be printed on the console." - " Valid log levels are: FATAL/ERROR/WARNING/INFO/DEBUG") -def run(telegram: typing.Optional[bool], - discord: typing.Optional[bool], - constellation: typing.Optional[bool], - herald: typing.Optional[bool], - remote_herald_address: typing.Optional[str], - constellation_port: int, - alchemy_url: typing.Optional[str], - herald_port: int, - pack: typing.Tuple[str], - secrets_name: str, - log_level: str): +@click.option("-c", "--config-filename", default="./config.toml", type=str, + help="The filename of the Royalnet configuration file.") +def run(config_filename: str): + # Read the configuration file + with open(config_filename, "r") as t: + config: dict = toml.load(t) + # Initialize logging royalnet_log: Logger = getLogger("royalnet") - royalnet_log.setLevel(log_level) + royalnet_log.setLevel(config["Logging"]["log_level"]) stream_handler = StreamHandler() if coloredlogs is not None: stream_handler.formatter = coloredlogs.ColoredFormatter("{asctime}\t| {processName}\t| {name}\t| {message}", @@ -59,62 +31,30 @@ def run(telegram: typing.Optional[bool], stream_handler.formatter = Formatter("{asctime}\t| {processName}\t| {name}\t| {message}", style="{") royalnet_log.addHandler(stream_handler) - royalnet_log.debug("Logging: ready") - - def get_secret(username: str): - return keyring.get_password(f"Royalnet/{secrets_name}", username) - - # Enable / Disable interfaces - interfaces = { - "telegram": telegram, - "discord": discord, - "herald": herald, - "constellation": constellation, - } - # If any interface is True, then the undefined ones should be False - if any(interfaces[name] is True for name in interfaces): - for name in interfaces: - if interfaces[name] is None: - interfaces[name] = False - # Likewise, if any interface is False, then the undefined ones should be True - elif any(interfaces[name] is False for name in interfaces): - for name in interfaces: - if interfaces[name] is None: - interfaces[name] = True - # Otherwise, if no interfaces are specified, all should be enabled - else: - assert all(interfaces[name] is None for name in interfaces) - for name in interfaces: - interfaces[name] = True + royalnet_log.info("Logging: ready") herald_process: typing.Optional[multiprocessing.Process] = None + herald_config = r.herald.Config(name="", + address=config["Herald"]["Local"]["address"], + port=config["Herald"]["Local"]["port"], + secret=config["Herald"]["Local"]["secret"], + secure=config["Herald"]["Local"]["secure"], + path=config["Herald"]["Local"]["path"]) # Start the Herald server - if interfaces["herald"]: - herald_config = r.herald.Config(name="", - address="127.0.0.1", - port=herald_port, - secret=get_secret("herald"), - secure=False, - path="/") - herald_kwargs = { - "log_level": log_level - } + if config["Herald"]["Local"]["enabled"]: herald_process = multiprocessing.Process(name="Herald Server", target=r.herald.Server(config=herald_config).run_blocking, - kwargs=herald_kwargs, daemon=True) herald_process.start() + elif config["Herald"]["Remote"]["enabled"]: + # Other processes will connect to the remote Herald independently + pass else: - herald_config = r.herald.Config(name=..., - address=remote_herald_address, - port=herald_port, - secret=get_secret("herald"), - secure=False, - path="/") + royalnet_log.fatal("No Heralds are enabled, Royalnet can't function!") + exit(1) # Import command and star packs - packs: typing.List[str] = list(pack) - packs.append("royalnet.backpack") # backpack is always imported + packs: typing.List[str] = config["Packs"]["active"] enabled_commands = [] enabled_page_stars = [] enabled_exception_stars = [] @@ -124,40 +64,45 @@ def run(telegram: typing.Optional[bool], try: imported_commands = imported.available_commands except AttributeError: - raise click.ClickException(f"{pack} isn't a Royalnet Pack as it is missing available_commands.") + royalnet_log.error(f"{pack} isn't a Royalnet Pack as it is missing available_commands.") + continue try: imported_page_stars = imported.available_page_stars except AttributeError: - raise click.ClickException(f"{pack} isn't a Royalnet Pack as it is missing available_page_stars.") + royalnet_log.error(f"{pack} isn't a Royalnet Pack as it is missing available_page_stars.") + continue try: imported_exception_stars = imported.available_exception_stars except AttributeError: - raise click.ClickException(f"{pack} isn't a Royalnet Pack as it is missing available_exception_stars.") + royalnet_log.error(f"{pack} isn't a Royalnet Pack as it is missing available_exception_stars.") + continue try: imported_events = imported.available_events except AttributeError: - raise click.ClickException(f"{pack} isn't a Royalnet Pack as it is missing available_events.") + royalnet_log.error(f"{pack} isn't a Royalnet Pack as it is missing available_events.") + continue enabled_commands = [*enabled_commands, *imported_commands] enabled_page_stars = [*enabled_page_stars, *imported_page_stars] enabled_exception_stars = [*enabled_exception_stars, *imported_exception_stars] enabled_events = [*enabled_events, *imported_events] telegram_process: typing.Optional[multiprocessing.Process] = None - if interfaces["telegram"]: - if alchemy_url is not None: - telegram_db_config = r.serf.AlchemyConfig(database_url=alchemy_url, + if config["Serf"]["Telegram"]["enabled"]: + if config["Alchemy"]["enabled"] is not None: + telegram_db_config = r.serf.AlchemyConfig(database_url=config["Alchemy"]["database_url"], master_table=r.backpack.tables.User, identity_table=r.backpack.tables.Telegram, identity_column="tg_id") else: telegram_db_config = None telegram_serf_kwargs = { + 'token': config["Serf"]["Telegram"]["token"], 'alchemy_config': telegram_db_config, 'commands': enabled_commands, 'events': enabled_events, 'herald_config': herald_config.copy(name="telegram"), - 'secrets_name': secrets_name, - 'log_level': log_level, + 'log_level': config["Logging"]["log_level"], + 'sentry_dsn': config["Sentry"]["dsn"], } telegram_process = multiprocessing.Process(name="Telegram Serf", target=r.serf.telegram.TelegramSerf.run_process, @@ -166,21 +111,22 @@ def run(telegram: typing.Optional[bool], telegram_process.start() discord_process: typing.Optional[multiprocessing.Process] = None - if interfaces["discord"]: - if alchemy_url is not None: - discord_db_config = r.serf.AlchemyConfig(database_url=alchemy_url, + if config["Serf"]["Discord"]["enabled"]: + if config["Alchemy"]["enabled"] is not None: + discord_db_config = r.serf.AlchemyConfig(database_url=config["Alchemy"]["database_url"], master_table=r.backpack.tables.User, identity_table=r.backpack.tables.Discord, identity_column="discord_id") else: discord_db_config = None discord_serf_kwargs = { + 'token': config["Serf"]["Discord"]["token"], 'alchemy_config': discord_db_config, 'commands': enabled_commands, 'events': enabled_events, 'herald_config': herald_config.copy(name="discord"), - 'secrets_name': secrets_name, - 'log_level': log_level, + 'log_level': config["Logging"]["log_level"], + 'sentry_dsn': config["Sentry"]["dsn"], } discord_process = multiprocessing.Process(name="Discord Serf", target=r.serf.discord.DiscordSerf.run_process, @@ -189,16 +135,15 @@ def run(telegram: typing.Optional[bool], discord_process.start() constellation_process: typing.Optional[multiprocessing.Process] = None - if interfaces["constellation"]: + if config["Constellation"]["enabled"]: # Create the Constellation constellation_kwargs = { - 'address': "127.0.0.1", - 'port': constellation_port, - 'secrets_name': secrets_name, - 'database_uri': alchemy_url, + 'address': config["Constellation"]["address"], + 'port': config["Constellation"]["port"], + 'database_uri': config["Alchemy"]["database_url"] if config["Alchemy"]["enabled"] else None, 'page_stars': enabled_page_stars, 'exc_stars': enabled_exception_stars, - 'log_level': log_level, + 'log_level': config["Logging"]["log_level"], } constellation_process = multiprocessing.Process(name="Constellation", target=r.constellation.Constellation.run_process, diff --git a/royalnet/backpack/commands/__init__.py b/royalnet/backpack/commands/__init__.py index 1ae94c97..1211e4eb 100644 --- a/royalnet/backpack/commands/__init__.py +++ b/royalnet/backpack/commands/__init__.py @@ -6,15 +6,9 @@ from .excevent import ExceventCommand # Enter the commands of your Pack here! available_commands = [ VersionCommand, + ExceptionCommand, + ExceventCommand, ] -# noinspection PyUnreachableCode -if __debug__: - available_commands = [ - *available_commands, - ExceptionCommand, - ExceventCommand, - ] - # Don't change this, it should automatically generate __all__ __all__ = [command.__name__ for command in available_commands] diff --git a/royalnet/serf/discord/discordserf.py b/royalnet/serf/discord/discordserf.py index 902f6660..232fc7d9 100644 --- a/royalnet/serf/discord/discordserf.py +++ b/royalnet/serf/discord/discordserf.py @@ -34,19 +34,21 @@ class DiscordSerf(Serf): interface_name = "discord" def __init__(self, *, + token: str, alchemy_config: Optional[AlchemyConfig] = None, commands: List[Type[Command]] = None, events: List[Type[Event]] = None, - herald_config: Optional[HeraldConfig] = None, - secrets_name: str = "__default__"): + herald_config: Optional[HeraldConfig] = None): if discord is None: raise ImportError("'discord' extra is not installed") super().__init__(alchemy_config=alchemy_config, commands=commands, events=events, - herald_config=herald_config, - secrets_name=secrets_name) + herald_config=herald_config) + + self.token = token + """The Discord bot token.""" self.Client = self.client_factory() """The custom :class:`discord.Client` class that will be instantiated later.""" @@ -154,10 +156,7 @@ class DiscordSerf(Serf): async def run(self): await super().run() - token = self.get_secret("discord") - if token is None: - raise ValueError("Missing discord token") - await self.client.login(token) + await self.client.login(self.token) await self.client.connect() def find_channel(self, @@ -230,4 +229,3 @@ class DiscordSerf(Serf): channels.sort(key=people_count, reverse=True) return channels[0] - diff --git a/royalnet/serf/serf.py b/royalnet/serf/serf.py index 6a906e43..e443ced5 100644 --- a/royalnet/serf/serf.py +++ b/royalnet/serf/serf.py @@ -3,7 +3,6 @@ import sys import traceback from asyncio import Task, AbstractEventLoop, get_event_loop from typing import Type, Optional, Awaitable, Dict, List, Any, Callable, Union, Set -from keyring import get_password from sqlalchemy.schema import Table from royalnet import __version__ as version from royalnet.commands import * @@ -56,9 +55,7 @@ class Serf: commands: List[Type[Command]] = None, events: List[Type[Event]] = None, herald_config: Optional[HeraldConfig] = None, - secrets_name: str = "__default__"): - self.secrets_name = secrets_name - + sentry_dsn: Optional[str] = None): self.alchemy: Optional[Alchemy] = None """The :class:`Alchemy` object connecting this Serf to the database.""" @@ -115,6 +112,9 @@ class Serf: self.loop: Optional[AbstractEventLoop] = None """The event loop this Serf is running on.""" + self.sentry_dsn: Optional[str] = sentry_dsn + """The Sentry DSN / Token. If :const:`None`, Sentry is disabled.""" + @staticmethod def find_tables(alchemy_config: AlchemyConfig, commands: List[Type[Command]]) -> Set[type]: """Find the :class:`Table`s required by the Serf. @@ -268,16 +268,16 @@ class Serf: def init_sentry(dsn): # noinspection PyUnreachableCode if __debug__: - release = f"Dev" + release = f"royalnet" else: - release = f"{version}" + release = f"royalnet=={version}" log.debug("Initializing Sentry...") sentry_sdk.init(dsn, integrations=[AioHttpIntegration(), SqlalchemyIntegration(), LoggingIntegration(event_level=None)], release=release) - log.info(f"Sentry: enabled (Royalnet {release})") + log.info(f"Sentry: enabled (release {release})") # noinspection PyUnreachableCode @staticmethod @@ -293,13 +293,6 @@ class Serf: exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback) - def get_secret(self, username: str): - """Get a Royalnet secret from the keyring. - - Args: - username: the name of the secret that should be retrieved.""" - return get_password(f"Royalnet/{self.secrets_name}", username) - async def call(self, command: Command, data: CommandData, parameters: List[str]): log.info(f"Calling command: {command.name}") try: @@ -351,11 +344,10 @@ class Serf: if sentry_sdk is None: log.info("Sentry: not installed") else: - sentry_dsn = serf.get_secret("sentry") - if sentry_dsn is None: + if serf.sentry_dsn is None: log.info("Sentry: disabled") else: - serf.init_sentry(sentry_dsn) + serf.init_sentry(serf.sentry_dsn) serf.loop = get_event_loop() try: diff --git a/royalnet/serf/telegram/telegramserf.py b/royalnet/serf/telegram/telegramserf.py index 682231a5..fdcbd43c 100644 --- a/royalnet/serf/telegram/telegramserf.py +++ b/royalnet/serf/telegram/telegramserf.py @@ -35,11 +35,14 @@ class TelegramSerf(Serf): interface_name = "telegram" def __init__(self, *, + token: str, + pool_size: int = 8, + read_timeout: int = 60, alchemy_config: Optional[AlchemyConfig] = None, commands: List[Type[Command]] = None, events: List[Type[Event]] = None, herald_config: Optional[HeraldConfig] = None, - secrets_name: str = "__default__"): + sentry_dsn: Optional[str] = None): if telegram is None: raise ImportError("'telegram' extra is not installed") @@ -47,9 +50,9 @@ class TelegramSerf(Serf): commands=commands, events=events, herald_config=herald_config, - secrets_name=secrets_name) + sentry_dsn=sentry_dsn) - self.client = telegram.Bot(self.get_secret("telegram"), request=TRequest(50, read_timeout=30)) + self.client = telegram.Bot(token, request=TRequest(pool_size, read_timeout=read_timeout)) """The :class:`telegram.Bot` instance that will be used from the Serf.""" self.update_offset: int = -100