1
Fork 0
mirror of https://github.com/RYGhub/royalnet.git synced 2024-11-27 13:34:28 +00:00

Some progress on config stuff

This commit is contained in:
Steffo 2019-11-24 21:09:45 +01:00
parent ba4058039b
commit f63520f385
10 changed files with 105 additions and 225 deletions

1
.gitignore vendored
View file

@ -3,3 +3,4 @@
.idea/royalnet.iml .idea/royalnet.iml
dist/ dist/
**/__pycache__/ **/__pycache__/
config.toml

2
.idea/.gitignore vendored
View file

@ -1,2 +1,4 @@
# Default ignored files # Default ignored files
/workspace.xml /workspace.xml
# Datasource local storage ignored files
/dataSources/

11
.idea/dataSources.xml Normal file
View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="scaleway.steffo.eu" uuid="baf4fe99-dd30-4b68-ab8a-67fe235e6724">
<driver-ref>postgresql</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
<jdbc-url>jdbc:postgresql://scaleway.steffo.eu:5432/royalnet</jdbc-url>
</data-source>
</component>
</project>

100
poetry.lock generated
View file

@ -78,7 +78,7 @@ version = "2019.9.11"
category = "main" category = "main"
description = "Foreign Function Interface for Python calling C code." description = "Foreign Function Interface for Python calling C code."
name = "cffi" name = "cffi"
optional = false optional = true
python-versions = "*" python-versions = "*"
version = "1.13.2" version = "1.13.2"
@ -129,7 +129,7 @@ cron = ["capturer (>=2.4)"]
category = "main" category = "main"
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
name = "cryptography" name = "cryptography"
optional = false optional = true
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
version = "2.8" version = "2.8"
@ -186,14 +186,6 @@ optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
version = "0.15.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]] [[package]]
category = "main" category = "main"
description = "Python bindings for FFmpeg - with complex filtering support" 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.*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "1.1.0" 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]] [[package]]
category = "dev" category = "dev"
description = "A very fast and expressive template engine." description = "A very fast and expressive template engine."
@ -286,23 +266,6 @@ MarkupSafe = ">=0.23"
[package.extras] [package.extras]
i18n = ["Babel (>=0.8)"] 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]] [[package]]
category = "dev" category = "dev"
description = "Safely add untrusted strings to HTML/XML markup." description = "Safely add untrusted strings to HTML/XML markup."
@ -378,7 +341,7 @@ version = "1.8.0"
category = "main" category = "main"
description = "C parser in Python" description = "C parser in Python"
name = "pycparser" name = "pycparser"
optional = false optional = true
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "2.19" version = "2.19"
@ -481,15 +444,6 @@ optional = false
python-versions = "*" python-versions = "*"
version = "2019.3" version = "2019.3"
[[package]]
category = "main"
description = ""
marker = "sys_platform == \"win32\""
name = "pywin32-ctypes"
optional = false
python-versions = "*"
version = "0.2.0"
[[package]] [[package]]
category = "main" category = "main"
description = "Alternative regular expression module, to replace re." 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)"] 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"] 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]] [[package]]
category = "main" category = "main"
description = "Python client for Sentry (https://getsentry.com)" description = "Python client for Sentry (https://getsentry.com)"
@ -701,6 +642,14 @@ version = "0.12.13"
[package.extras] [package.extras]
full = ["aiofiles", "graphene", "itsdangerous", "jinja2", "python-multipart", "pyyaml", "requests", "ujson"] 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]] [[package]]
category = "main" category = "main"
description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." 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"] telegram = ["python_telegram_bot"]
[metadata] [metadata]
content-hash = "ab3c90d2eb5ce9e8bfad099502bb183959ee406192d2ee159f902c2a52658614" content-hash = "b159275a7b57094bc7fd801ba47883be1c6d1be395780dca0d2c018fc98009b7"
python-versions = "^3.8" python-versions = "^3.8"
[metadata.files] [metadata.files]
@ -941,10 +890,6 @@ docutils = [
{file = "docutils-0.15.2-py3-none-any.whl", hash = "sha256:6c4f696463b79f1fb8ba0c594b63840ebd41f059e92b31957c46b74a4599b6d0"}, {file = "docutils-0.15.2-py3-none-any.whl", hash = "sha256:6c4f696463b79f1fb8ba0c594b63840ebd41f059e92b31957c46b74a4599b6d0"},
{file = "docutils-0.15.2.tar.gz", hash = "sha256:a2aeea129088da402665e92e0b25b04b073c04b2dce4ab65caaa38b7ce2e1a99"}, {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 = [ ffmpeg-python = [
{file = "ffmpeg-python-0.2.0.tar.gz", hash = "sha256:65225db34627c578ef0e11c8b1eb528bb35e024752f6f10b78c011f6f64c4127"}, {file = "ffmpeg-python-0.2.0.tar.gz", hash = "sha256:65225db34627c578ef0e11c8b1eb528bb35e024752f6f10b78c011f6f64c4127"},
{file = "ffmpeg_python-0.2.0-py3-none-any.whl", hash = "sha256:ac441a0404e053f8b6a1113a77c0f452f1cfc62f6344a769475ffdc0f56c23c5"}, {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-py2.py3-none-any.whl", hash = "sha256:3f349de3eb99145973fefb7dbe38554414e5c30abd0c8e4b970a7c9d09f3a1d8"},
{file = "imagesize-1.1.0.tar.gz", hash = "sha256:f3832918bc3c66617f92e35f5d70729187676313caa60c187eb0f28b8fe5e3b5"}, {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 = [ jinja2 = [
{file = "Jinja2-2.10.3-py2.py3-none-any.whl", hash = "sha256:74320bb91f31270f9551d46522e33af46a80c3d619f4a4bf42b3164d30b5911f"}, {file = "Jinja2-2.10.3-py2.py3-none-any.whl", hash = "sha256:74320bb91f31270f9551d46522e33af46a80c3d619f4a4bf42b3164d30b5911f"},
{file = "Jinja2-2.10.3.tar.gz", hash = "sha256:9fe95f19286cfefaa917656583d020be14e7859c6b0252588391e47db34527de"}, {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 = [ markupsafe = [
{file = "MarkupSafe-1.1.1-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161"}, {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"}, {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-py2.py3-none-any.whl", hash = "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d"},
{file = "pytz-2019.3.tar.gz", hash = "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be"}, {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 = [ regex = [
{file = "regex-2019.11.1-cp27-none-win32.whl", hash = "sha256:604dc563a02a74d70ae1f55208ddc9bfb6d9f470f6d1a5054c4bd5ae58744ab1"}, {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"}, {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-py2.py3-none-any.whl", hash = "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31"},
{file = "requests-2.22.0.tar.gz", hash = "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4"}, {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 = [ sentry-sdk = [
{file = "sentry-sdk-0.13.2.tar.gz", hash = "sha256:ff1fa7fb85703ae9414c8b427ee73f8363232767c9cd19158f08f6e4f0b58fc7"}, {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"}, {file = "sentry_sdk-0.13.2-py2.py3-none-any.whl", hash = "sha256:09e1e8f00f22ea580348f83bbbd880adf40b29f1dec494a8e4b33e22f77184fb"},
@ -1229,6 +1158,11 @@ sqlalchemy = [
starlette = [ starlette = [
{file = "starlette-0.12.13.tar.gz", hash = "sha256:9597bc28e3c4659107c1c4a45ec32dc45e947d78fe56230222be673b2c36454a"}, {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 = [ tornado = [
{file = "tornado-6.0.3-cp35-cp35m-win32.whl", hash = "sha256:c9399267c926a4e7c418baa5cbe91c7d1cf362d505a1ef898fde44a07c9dd8a5"}, {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"}, {file = "tornado-6.0.3-cp35-cp35m-win_amd64.whl", hash = "sha256:398e0d35e086ba38a0427c3b37f4337327231942e731edaa6e9fd1865bbd6f60"},

View file

@ -20,7 +20,7 @@
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = "^3.8" python = "^3.8"
dateparser = "^0.7.2" dateparser = "^0.7.2"
keyring = "^19.2.0" # TODO: Maybe remove this when possible? toml = "^0.10.0"
# telegram # telegram
python_telegram_bot = {version="^12.2.0", optional=true} python_telegram_bot = {version="^12.2.0", optional=true}

View file

@ -3,7 +3,7 @@ import typing
import importlib import importlib
import royalnet as r import royalnet as r
import multiprocessing import multiprocessing
import keyring import toml
from logging import Formatter, StreamHandler, getLogger, Logger from logging import Formatter, StreamHandler, getLogger, Logger
try: try:
@ -13,44 +13,16 @@ except ImportError:
@click.command() @click.command()
@click.option("--telegram/--no-telegram", default=None, @click.option("-c", "--config-filename", default="./config.toml", type=str,
help="Enable/disable the Telegram bot.") help="The filename of the Royalnet configuration file.")
@click.option("--discord/--no-discord", default=None, def run(config_filename: str):
help="Enable/disable the Discord bot.") # Read the configuration file
@click.option("--constellation/--no-constellation", default=None, with open(config_filename, "r") as t:
help="Enable/disable the Constellation web server.") config: dict = toml.load(t)
@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):
# Initialize logging # Initialize logging
royalnet_log: Logger = getLogger("royalnet") royalnet_log: Logger = getLogger("royalnet")
royalnet_log.setLevel(log_level) royalnet_log.setLevel(config["Logging"]["log_level"])
stream_handler = StreamHandler() stream_handler = StreamHandler()
if coloredlogs is not None: if coloredlogs is not None:
stream_handler.formatter = coloredlogs.ColoredFormatter("{asctime}\t| {processName}\t| {name}\t| {message}", 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}", stream_handler.formatter = Formatter("{asctime}\t| {processName}\t| {name}\t| {message}",
style="{") style="{")
royalnet_log.addHandler(stream_handler) royalnet_log.addHandler(stream_handler)
royalnet_log.debug("Logging: ready") royalnet_log.info("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
herald_process: typing.Optional[multiprocessing.Process] = None herald_process: typing.Optional[multiprocessing.Process] = None
# Start the Herald server
if interfaces["herald"]:
herald_config = r.herald.Config(name="<server>", herald_config = r.herald.Config(name="<server>",
address="127.0.0.1", address=config["Herald"]["Local"]["address"],
port=herald_port, port=config["Herald"]["Local"]["port"],
secret=get_secret("herald"), secret=config["Herald"]["Local"]["secret"],
secure=False, secure=config["Herald"]["Local"]["secure"],
path="/") path=config["Herald"]["Local"]["path"])
herald_kwargs = { # Start the Herald server
"log_level": log_level if config["Herald"]["Local"]["enabled"]:
}
herald_process = multiprocessing.Process(name="Herald Server", herald_process = multiprocessing.Process(name="Herald Server",
target=r.herald.Server(config=herald_config).run_blocking, target=r.herald.Server(config=herald_config).run_blocking,
kwargs=herald_kwargs,
daemon=True) daemon=True)
herald_process.start() herald_process.start()
elif config["Herald"]["Remote"]["enabled"]:
# Other processes will connect to the remote Herald independently
pass
else: else:
herald_config = r.herald.Config(name=..., royalnet_log.fatal("No Heralds are enabled, Royalnet can't function!")
address=remote_herald_address, exit(1)
port=herald_port,
secret=get_secret("herald"),
secure=False,
path="/")
# Import command and star packs # Import command and star packs
packs: typing.List[str] = list(pack) packs: typing.List[str] = config["Packs"]["active"]
packs.append("royalnet.backpack") # backpack is always imported
enabled_commands = [] enabled_commands = []
enabled_page_stars = [] enabled_page_stars = []
enabled_exception_stars = [] enabled_exception_stars = []
@ -124,40 +64,45 @@ def run(telegram: typing.Optional[bool],
try: try:
imported_commands = imported.available_commands imported_commands = imported.available_commands
except AttributeError: 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: try:
imported_page_stars = imported.available_page_stars imported_page_stars = imported.available_page_stars
except AttributeError: 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: try:
imported_exception_stars = imported.available_exception_stars imported_exception_stars = imported.available_exception_stars
except AttributeError: 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: try:
imported_events = imported.available_events imported_events = imported.available_events
except AttributeError: 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_commands = [*enabled_commands, *imported_commands]
enabled_page_stars = [*enabled_page_stars, *imported_page_stars] enabled_page_stars = [*enabled_page_stars, *imported_page_stars]
enabled_exception_stars = [*enabled_exception_stars, *imported_exception_stars] enabled_exception_stars = [*enabled_exception_stars, *imported_exception_stars]
enabled_events = [*enabled_events, *imported_events] enabled_events = [*enabled_events, *imported_events]
telegram_process: typing.Optional[multiprocessing.Process] = None telegram_process: typing.Optional[multiprocessing.Process] = None
if interfaces["telegram"]: if config["Serf"]["Telegram"]["enabled"]:
if alchemy_url is not None: if config["Alchemy"]["enabled"] is not None:
telegram_db_config = r.serf.AlchemyConfig(database_url=alchemy_url, telegram_db_config = r.serf.AlchemyConfig(database_url=config["Alchemy"]["database_url"],
master_table=r.backpack.tables.User, master_table=r.backpack.tables.User,
identity_table=r.backpack.tables.Telegram, identity_table=r.backpack.tables.Telegram,
identity_column="tg_id") identity_column="tg_id")
else: else:
telegram_db_config = None telegram_db_config = None
telegram_serf_kwargs = { telegram_serf_kwargs = {
'token': config["Serf"]["Telegram"]["token"],
'alchemy_config': telegram_db_config, 'alchemy_config': telegram_db_config,
'commands': enabled_commands, 'commands': enabled_commands,
'events': enabled_events, 'events': enabled_events,
'herald_config': herald_config.copy(name="telegram"), 'herald_config': herald_config.copy(name="telegram"),
'secrets_name': secrets_name, 'log_level': config["Logging"]["log_level"],
'log_level': log_level, 'sentry_dsn': config["Sentry"]["dsn"],
} }
telegram_process = multiprocessing.Process(name="Telegram Serf", telegram_process = multiprocessing.Process(name="Telegram Serf",
target=r.serf.telegram.TelegramSerf.run_process, target=r.serf.telegram.TelegramSerf.run_process,
@ -166,21 +111,22 @@ def run(telegram: typing.Optional[bool],
telegram_process.start() telegram_process.start()
discord_process: typing.Optional[multiprocessing.Process] = None discord_process: typing.Optional[multiprocessing.Process] = None
if interfaces["discord"]: if config["Serf"]["Discord"]["enabled"]:
if alchemy_url is not None: if config["Alchemy"]["enabled"] is not None:
discord_db_config = r.serf.AlchemyConfig(database_url=alchemy_url, discord_db_config = r.serf.AlchemyConfig(database_url=config["Alchemy"]["database_url"],
master_table=r.backpack.tables.User, master_table=r.backpack.tables.User,
identity_table=r.backpack.tables.Discord, identity_table=r.backpack.tables.Discord,
identity_column="discord_id") identity_column="discord_id")
else: else:
discord_db_config = None discord_db_config = None
discord_serf_kwargs = { discord_serf_kwargs = {
'token': config["Serf"]["Discord"]["token"],
'alchemy_config': discord_db_config, 'alchemy_config': discord_db_config,
'commands': enabled_commands, 'commands': enabled_commands,
'events': enabled_events, 'events': enabled_events,
'herald_config': herald_config.copy(name="discord"), 'herald_config': herald_config.copy(name="discord"),
'secrets_name': secrets_name, 'log_level': config["Logging"]["log_level"],
'log_level': log_level, 'sentry_dsn': config["Sentry"]["dsn"],
} }
discord_process = multiprocessing.Process(name="Discord Serf", discord_process = multiprocessing.Process(name="Discord Serf",
target=r.serf.discord.DiscordSerf.run_process, target=r.serf.discord.DiscordSerf.run_process,
@ -189,16 +135,15 @@ def run(telegram: typing.Optional[bool],
discord_process.start() discord_process.start()
constellation_process: typing.Optional[multiprocessing.Process] = None constellation_process: typing.Optional[multiprocessing.Process] = None
if interfaces["constellation"]: if config["Constellation"]["enabled"]:
# Create the Constellation # Create the Constellation
constellation_kwargs = { constellation_kwargs = {
'address': "127.0.0.1", 'address': config["Constellation"]["address"],
'port': constellation_port, 'port': config["Constellation"]["port"],
'secrets_name': secrets_name, 'database_uri': config["Alchemy"]["database_url"] if config["Alchemy"]["enabled"] else None,
'database_uri': alchemy_url,
'page_stars': enabled_page_stars, 'page_stars': enabled_page_stars,
'exc_stars': enabled_exception_stars, 'exc_stars': enabled_exception_stars,
'log_level': log_level, 'log_level': config["Logging"]["log_level"],
} }
constellation_process = multiprocessing.Process(name="Constellation", constellation_process = multiprocessing.Process(name="Constellation",
target=r.constellation.Constellation.run_process, target=r.constellation.Constellation.run_process,

View file

@ -6,12 +6,6 @@ from .excevent import ExceventCommand
# Enter the commands of your Pack here! # Enter the commands of your Pack here!
available_commands = [ available_commands = [
VersionCommand, VersionCommand,
]
# noinspection PyUnreachableCode
if __debug__:
available_commands = [
*available_commands,
ExceptionCommand, ExceptionCommand,
ExceventCommand, ExceventCommand,
] ]

View file

@ -34,19 +34,21 @@ class DiscordSerf(Serf):
interface_name = "discord" interface_name = "discord"
def __init__(self, *, def __init__(self, *,
token: str,
alchemy_config: Optional[AlchemyConfig] = None, alchemy_config: Optional[AlchemyConfig] = None,
commands: List[Type[Command]] = None, commands: List[Type[Command]] = None,
events: List[Type[Event]] = None, events: List[Type[Event]] = None,
herald_config: Optional[HeraldConfig] = None, herald_config: Optional[HeraldConfig] = None):
secrets_name: str = "__default__"):
if discord is None: if discord is None:
raise ImportError("'discord' extra is not installed") raise ImportError("'discord' extra is not installed")
super().__init__(alchemy_config=alchemy_config, super().__init__(alchemy_config=alchemy_config,
commands=commands, commands=commands,
events=events, events=events,
herald_config=herald_config, herald_config=herald_config)
secrets_name=secrets_name)
self.token = token
"""The Discord bot token."""
self.Client = self.client_factory() self.Client = self.client_factory()
"""The custom :class:`discord.Client` class that will be instantiated later.""" """The custom :class:`discord.Client` class that will be instantiated later."""
@ -154,10 +156,7 @@ class DiscordSerf(Serf):
async def run(self): async def run(self):
await super().run() await super().run()
token = self.get_secret("discord") await self.client.login(self.token)
if token is None:
raise ValueError("Missing discord token")
await self.client.login(token)
await self.client.connect() await self.client.connect()
def find_channel(self, def find_channel(self,
@ -230,4 +229,3 @@ class DiscordSerf(Serf):
channels.sort(key=people_count, reverse=True) channels.sort(key=people_count, reverse=True)
return channels[0] return channels[0]

View file

@ -3,7 +3,6 @@ import sys
import traceback import traceback
from asyncio import Task, AbstractEventLoop, get_event_loop from asyncio import Task, AbstractEventLoop, get_event_loop
from typing import Type, Optional, Awaitable, Dict, List, Any, Callable, Union, Set from typing import Type, Optional, Awaitable, Dict, List, Any, Callable, Union, Set
from keyring import get_password
from sqlalchemy.schema import Table from sqlalchemy.schema import Table
from royalnet import __version__ as version from royalnet import __version__ as version
from royalnet.commands import * from royalnet.commands import *
@ -56,9 +55,7 @@ class Serf:
commands: List[Type[Command]] = None, commands: List[Type[Command]] = None,
events: List[Type[Event]] = None, events: List[Type[Event]] = None,
herald_config: Optional[HeraldConfig] = None, herald_config: Optional[HeraldConfig] = None,
secrets_name: str = "__default__"): sentry_dsn: Optional[str] = None):
self.secrets_name = secrets_name
self.alchemy: Optional[Alchemy] = None self.alchemy: Optional[Alchemy] = None
"""The :class:`Alchemy` object connecting this Serf to the database.""" """The :class:`Alchemy` object connecting this Serf to the database."""
@ -115,6 +112,9 @@ class Serf:
self.loop: Optional[AbstractEventLoop] = None self.loop: Optional[AbstractEventLoop] = None
"""The event loop this Serf is running on.""" """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 @staticmethod
def find_tables(alchemy_config: AlchemyConfig, commands: List[Type[Command]]) -> Set[type]: def find_tables(alchemy_config: AlchemyConfig, commands: List[Type[Command]]) -> Set[type]:
"""Find the :class:`Table`s required by the Serf. """Find the :class:`Table`s required by the Serf.
@ -268,16 +268,16 @@ class Serf:
def init_sentry(dsn): def init_sentry(dsn):
# noinspection PyUnreachableCode # noinspection PyUnreachableCode
if __debug__: if __debug__:
release = f"Dev" release = f"royalnet"
else: else:
release = f"{version}" release = f"royalnet=={version}"
log.debug("Initializing Sentry...") log.debug("Initializing Sentry...")
sentry_sdk.init(dsn, sentry_sdk.init(dsn,
integrations=[AioHttpIntegration(), integrations=[AioHttpIntegration(),
SqlalchemyIntegration(), SqlalchemyIntegration(),
LoggingIntegration(event_level=None)], LoggingIntegration(event_level=None)],
release=release) release=release)
log.info(f"Sentry: enabled (Royalnet {release})") log.info(f"Sentry: enabled (release {release})")
# noinspection PyUnreachableCode # noinspection PyUnreachableCode
@staticmethod @staticmethod
@ -293,13 +293,6 @@ class Serf:
exc_type, exc_value, exc_traceback = sys.exc_info() exc_type, exc_value, exc_traceback = sys.exc_info()
traceback.print_exception(exc_type, exc_value, exc_traceback) 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]): async def call(self, command: Command, data: CommandData, parameters: List[str]):
log.info(f"Calling command: {command.name}") log.info(f"Calling command: {command.name}")
try: try:
@ -351,11 +344,10 @@ class Serf:
if sentry_sdk is None: if sentry_sdk is None:
log.info("Sentry: not installed") log.info("Sentry: not installed")
else: else:
sentry_dsn = serf.get_secret("sentry") if serf.sentry_dsn is None:
if sentry_dsn is None:
log.info("Sentry: disabled") log.info("Sentry: disabled")
else: else:
serf.init_sentry(sentry_dsn) serf.init_sentry(serf.sentry_dsn)
serf.loop = get_event_loop() serf.loop = get_event_loop()
try: try:

View file

@ -35,11 +35,14 @@ class TelegramSerf(Serf):
interface_name = "telegram" interface_name = "telegram"
def __init__(self, *, def __init__(self, *,
token: str,
pool_size: int = 8,
read_timeout: int = 60,
alchemy_config: Optional[AlchemyConfig] = None, alchemy_config: Optional[AlchemyConfig] = None,
commands: List[Type[Command]] = None, commands: List[Type[Command]] = None,
events: List[Type[Event]] = None, events: List[Type[Event]] = None,
herald_config: Optional[HeraldConfig] = None, herald_config: Optional[HeraldConfig] = None,
secrets_name: str = "__default__"): sentry_dsn: Optional[str] = None):
if telegram is None: if telegram is None:
raise ImportError("'telegram' extra is not installed") raise ImportError("'telegram' extra is not installed")
@ -47,9 +50,9 @@ class TelegramSerf(Serf):
commands=commands, commands=commands,
events=events, events=events,
herald_config=herald_config, 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.""" """The :class:`telegram.Bot` instance that will be used from the Serf."""
self.update_offset: int = -100 self.update_offset: int = -100