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