mirror of
https://github.com/RYGhub/royalnet.git
synced 2024-11-23 11:34:18 +00:00
small tiny progress
This commit is contained in:
parent
fdddc70469
commit
18eeb6d487
14 changed files with 126 additions and 825 deletions
159
poetry.lock
generated
159
poetry.lock
generated
|
@ -143,7 +143,7 @@ humanfriendly = ">=4.7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cryptography"
|
name = "cryptography"
|
||||||
version = "3.1"
|
version = "3.1.1"
|
||||||
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."
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = true
|
optional = true
|
||||||
|
@ -184,7 +184,7 @@ python-versions = ">=2.6, !=3.0.*, !=3.1.*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "discord.py"
|
name = "discord.py"
|
||||||
version = "1.4.1"
|
version = "1.5.0"
|
||||||
description = "A Python wrapper for the Discord API"
|
description = "A Python wrapper for the Discord API"
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = true
|
optional = true
|
||||||
|
@ -344,7 +344,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pygments"
|
name = "pygments"
|
||||||
version = "2.7.0"
|
version = "2.7.1"
|
||||||
description = "Pygments is a syntax highlighting package written in Python."
|
description = "Pygments is a syntax highlighting package written in Python."
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
|
@ -453,9 +453,20 @@ category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redis"
|
||||||
|
version = "3.5.3"
|
||||||
|
description = "Python client for Redis key-value store"
|
||||||
|
category = "main"
|
||||||
|
optional = true
|
||||||
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
hiredis = ["hiredis (>=0.1.3)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "2020.7.14"
|
version = "2020.9.27"
|
||||||
description = "Alternative regular expression module, to replace re."
|
description = "Alternative regular expression module, to replace re."
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
|
@ -747,7 +758,7 @@ python-versions = ">=3.6.1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "yarl"
|
name = "yarl"
|
||||||
version = "1.5.1"
|
version = "1.6.0"
|
||||||
description = "Yet another URL library"
|
description = "Yet another URL library"
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = true
|
optional = true
|
||||||
|
@ -758,19 +769,19 @@ idna = ">=2.0"
|
||||||
multidict = ">=4.0"
|
multidict = ">=4.0"
|
||||||
|
|
||||||
[extras]
|
[extras]
|
||||||
telegram = ["python_telegram_bot"]
|
telegram = ["python_telegram_bot", "urllib3"]
|
||||||
discord = ["discord.py", "pynacl"]
|
discord = ["discord.py", "pynacl"]
|
||||||
alchemy_easy = ["sqlalchemy", "psycopg2_binary", "bcrypt"]
|
alchemy_easy = ["sqlalchemy", "psycopg2_binary", "bcrypt"]
|
||||||
alchemy_hard = ["sqlalchemy", "psycopg2", "bcrypt"]
|
alchemy_hard = ["sqlalchemy", "psycopg2", "bcrypt"]
|
||||||
constellation = ["starlette", "uvicorn", "python-multipart"]
|
constellation = ["starlette", "uvicorn", "python-multipart"]
|
||||||
sentry = ["sentry_sdk"]
|
sentry = ["sentry_sdk"]
|
||||||
herald = ["websockets"]
|
|
||||||
coloredlogs = ["coloredlogs"]
|
coloredlogs = ["coloredlogs"]
|
||||||
|
baron = ["redis"]
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "1.0"
|
lock-version = "1.0"
|
||||||
python-versions = "^3.8"
|
python-versions = "^3.8"
|
||||||
content-hash = "88bf2cfd1fc7d44eadf8222999146e8ba8846200bcc37899bb0ce268d441a313"
|
content-hash = "9151cde5dbb6b2f35316ed0b3674b37b9ac7ab919216f56646bb023b502c01f4"
|
||||||
|
|
||||||
[metadata.files]
|
[metadata.files]
|
||||||
aiohttp = [
|
aiohttp = [
|
||||||
|
@ -875,28 +886,28 @@ coloredlogs = [
|
||||||
{file = "coloredlogs-10.0.tar.gz", hash = "sha256:b869a2dda3fa88154b9dd850e27828d8755bfab5a838a1c97fbc850c6e377c36"},
|
{file = "coloredlogs-10.0.tar.gz", hash = "sha256:b869a2dda3fa88154b9dd850e27828d8755bfab5a838a1c97fbc850c6e377c36"},
|
||||||
]
|
]
|
||||||
cryptography = [
|
cryptography = [
|
||||||
{file = "cryptography-3.1-cp27-cp27m-macosx_10_10_x86_64.whl", hash = "sha256:969ae512a250f869c1738ca63be843488ff5cc031987d302c1f59c7dbe1b225f"},
|
{file = "cryptography-3.1.1-cp27-cp27m-macosx_10_10_x86_64.whl", hash = "sha256:65beb15e7f9c16e15934569d29fb4def74ea1469d8781f6b3507ab896d6d8719"},
|
||||||
{file = "cryptography-3.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:b45ab1c6ece7c471f01c56f5d19818ca797c34541f0b2351635a5c9fe09ac2e0"},
|
{file = "cryptography-3.1.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:983c0c3de4cb9fcba68fd3f45ed846eb86a2a8b8d8bc5bb18364c4d00b3c61fe"},
|
||||||
{file = "cryptography-3.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:247df238bc05c7d2e934a761243bfdc67db03f339948b1e2e80c75d41fc7cc36"},
|
{file = "cryptography-3.1.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:e97a3b627e3cb63c415a16245d6cef2139cca18bb1183d1b9375a1c14e83f3b3"},
|
||||||
{file = "cryptography-3.1-cp27-cp27m-win32.whl", hash = "sha256:10c9775a3f31610cf6b694d1fe598f2183441de81cedcf1814451ae53d71b13a"},
|
{file = "cryptography-3.1.1-cp27-cp27m-win32.whl", hash = "sha256:cb179acdd4ae1e4a5a160d80b87841b3d0e0be84af46c7bb2cd7ece57a39c4ba"},
|
||||||
{file = "cryptography-3.1-cp27-cp27m-win_amd64.whl", hash = "sha256:9f734423eb9c2ea85000aa2476e0d7a58e021bc34f0a373ac52a5454cd52f791"},
|
{file = "cryptography-3.1.1-cp27-cp27m-win_amd64.whl", hash = "sha256:b372026ebf32fe2523159f27d9f0e9f485092e43b00a5adacf732192a70ba118"},
|
||||||
{file = "cryptography-3.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:e7563eb7bc5c7e75a213281715155248cceba88b11cb4b22957ad45b85903761"},
|
{file = "cryptography-3.1.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:680da076cad81cdf5ffcac50c477b6790be81768d30f9da9e01960c4b18a66db"},
|
||||||
{file = "cryptography-3.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:94191501e4b4009642be21dde2a78bd3c2701a81ee57d3d3d02f1d99f8b64a9e"},
|
{file = "cryptography-3.1.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:5d52c72449bb02dd45a773a203196e6d4fae34e158769c896012401f33064396"},
|
||||||
{file = "cryptography-3.1-cp35-abi3-macosx_10_10_x86_64.whl", hash = "sha256:dc3f437ca6353979aace181f1b790f0fc79e446235b14306241633ab7d61b8f8"},
|
{file = "cryptography-3.1.1-cp35-abi3-macosx_10_10_x86_64.whl", hash = "sha256:f0e099fc4cc697450c3dd4031791559692dd941a95254cb9aeded66a7aa8b9bc"},
|
||||||
{file = "cryptography-3.1-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:725875681afe50b41aee7fdd629cedbc4720bab350142b12c55c0a4d17c7416c"},
|
{file = "cryptography-3.1.1-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:a7597ffc67987b37b12e09c029bd1dc43965f75d328076ae85721b84046e9ca7"},
|
||||||
{file = "cryptography-3.1-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:321761d55fb7cb256b771ee4ed78e69486a7336be9143b90c52be59d7657f50f"},
|
{file = "cryptography-3.1.1-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:4549b137d8cbe3c2eadfa56c0c858b78acbeff956bd461e40000b2164d9167c6"},
|
||||||
{file = "cryptography-3.1-cp35-abi3-manylinux2014_aarch64.whl", hash = "sha256:2a27615c965173c4c88f2961cf18115c08fedfb8bdc121347f26e8458dc6d237"},
|
{file = "cryptography-3.1.1-cp35-abi3-manylinux2014_aarch64.whl", hash = "sha256:89aceb31cd5f9fc2449fe8cf3810797ca52b65f1489002d58fe190bfb265c536"},
|
||||||
{file = "cryptography-3.1-cp35-cp35m-win32.whl", hash = "sha256:e7dad66a9e5684a40f270bd4aee1906878193ae50a4831922e454a2a457f1716"},
|
{file = "cryptography-3.1.1-cp35-cp35m-win32.whl", hash = "sha256:559d622aef2a2dff98a892eef321433ba5bc55b2485220a8ca289c1ecc2bd54f"},
|
||||||
{file = "cryptography-3.1-cp35-cp35m-win_amd64.whl", hash = "sha256:4005b38cd86fc51c955db40b0f0e52ff65340874495af72efabb1bb8ca881695"},
|
{file = "cryptography-3.1.1-cp35-cp35m-win_amd64.whl", hash = "sha256:451cdf60be4dafb6a3b78802006a020e6cd709c22d240f94f7a0696240a17154"},
|
||||||
{file = "cryptography-3.1-cp36-abi3-win32.whl", hash = "sha256:cc6096c86ec0de26e2263c228fb25ee01c3ff1346d3cfc219d67d49f303585af"},
|
{file = "cryptography-3.1.1-cp36-abi3-win32.whl", hash = "sha256:762bc5a0df03c51ee3f09c621e1cee64e3a079a2b5020de82f1613873d79ee70"},
|
||||||
{file = "cryptography-3.1-cp36-abi3-win_amd64.whl", hash = "sha256:2e26223ac636ca216e855748e7d435a1bf846809ed12ed898179587d0cf74618"},
|
{file = "cryptography-3.1.1-cp36-abi3-win_amd64.whl", hash = "sha256:b12e715c10a13ca1bd27fbceed9adc8c5ff640f8e1f7ea76416352de703523c8"},
|
||||||
{file = "cryptography-3.1-cp36-cp36m-win32.whl", hash = "sha256:7a63e97355f3cd77c94bd98c59cb85fe0efd76ea7ef904c9b0316b5bbfde6ed1"},
|
{file = "cryptography-3.1.1-cp36-cp36m-win32.whl", hash = "sha256:21b47c59fcb1c36f1113f3709d37935368e34815ea1d7073862e92f810dc7499"},
|
||||||
{file = "cryptography-3.1-cp36-cp36m-win_amd64.whl", hash = "sha256:4b9e96543d0784acebb70991ebc2dbd99aa287f6217546bb993df22dd361d41c"},
|
{file = "cryptography-3.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:48ee615a779ffa749d7d50c291761dc921d93d7cf203dca2db663b4f193f0e49"},
|
||||||
{file = "cryptography-3.1-cp37-cp37m-win32.whl", hash = "sha256:eb80a288e3cfc08f679f95da72d2ef90cb74f6d8a8ba69d2f215c5e110b2ca32"},
|
{file = "cryptography-3.1.1-cp37-cp37m-win32.whl", hash = "sha256:b2bded09c578d19e08bd2c5bb8fed7f103e089752c9cf7ca7ca7de522326e921"},
|
||||||
{file = "cryptography-3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:180c9f855a8ea280e72a5d61cf05681b230c2dce804c48e9b2983f491ecc44ed"},
|
{file = "cryptography-3.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:f99317a0fa2e49917689b8cf977510addcfaaab769b3f899b9c481bbd76730c2"},
|
||||||
{file = "cryptography-3.1-cp38-cp38-win32.whl", hash = "sha256:fa7fbcc40e2210aca26c7ac8a39467eae444d90a2c346cbcffd9133a166bcc67"},
|
{file = "cryptography-3.1.1-cp38-cp38-win32.whl", hash = "sha256:ab010e461bb6b444eaf7f8c813bb716be2d78ab786103f9608ffd37a4bd7d490"},
|
||||||
{file = "cryptography-3.1-cp38-cp38-win_amd64.whl", hash = "sha256:548b0818e88792318dc137d8b1ec82a0ab0af96c7f0603a00bb94f896fbf5e10"},
|
{file = "cryptography-3.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:99d4984aabd4c7182050bca76176ce2dbc9fa9748afe583a7865c12954d714ba"},
|
||||||
{file = "cryptography-3.1.tar.gz", hash = "sha256:26409a473cc6278e4c90f782cd5968ebad04d3911ed1c402fc86908c17633e08"},
|
{file = "cryptography-3.1.1.tar.gz", hash = "sha256:9d9fc6a16357965d282dd4ab6531013935425d0dc4950df2e0cf2a1b1ac1017d"},
|
||||||
]
|
]
|
||||||
dateparser = [
|
dateparser = [
|
||||||
{file = "dateparser-0.7.6-py2.py3-none-any.whl", hash = "sha256:7552c994f893b5cb8fcf103b4cd2ff7f57aab9bfd2619fdf0cf571c0740fd90b"},
|
{file = "dateparser-0.7.6-py2.py3-none-any.whl", hash = "sha256:7552c994f893b5cb8fcf103b4cd2ff7f57aab9bfd2619fdf0cf571c0740fd90b"},
|
||||||
|
@ -907,8 +918,8 @@ decorator = [
|
||||||
{file = "decorator-4.4.2.tar.gz", hash = "sha256:e3a62f0520172440ca0dcc823749319382e377f37f140a0b99ef45fecb84bfe7"},
|
{file = "decorator-4.4.2.tar.gz", hash = "sha256:e3a62f0520172440ca0dcc823749319382e377f37f140a0b99ef45fecb84bfe7"},
|
||||||
]
|
]
|
||||||
"discord.py" = [
|
"discord.py" = [
|
||||||
{file = "discord.py-1.4.1-py3-none-any.whl", hash = "sha256:98ea3096a3585c9c379209926f530808f5fcf4930928d8cfb579d2562d119570"},
|
{file = "discord.py-1.5.0-py3-none-any.whl", hash = "sha256:3acb61fde0d862ed346a191d69c46021e6063673f63963bc984ae09a685ab211"},
|
||||||
{file = "discord.py-1.4.1.tar.gz", hash = "sha256:f9decb3bfa94613d922376288617e6a6f969260923643e2897f4540c34793442"},
|
{file = "discord.py-1.5.0.tar.gz", hash = "sha256:e71089886aa157341644bdecad63a72ff56b44406b1a6467b66db31c8e5a5a15"},
|
||||||
]
|
]
|
||||||
docutils = [
|
docutils = [
|
||||||
{file = "docutils-0.16-py2.py3-none-any.whl", hash = "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af"},
|
{file = "docutils-0.16-py2.py3-none-any.whl", hash = "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af"},
|
||||||
|
@ -1061,8 +1072,8 @@ pycparser = [
|
||||||
{file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"},
|
{file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"},
|
||||||
]
|
]
|
||||||
pygments = [
|
pygments = [
|
||||||
{file = "Pygments-2.7.0-py3-none-any.whl", hash = "sha256:2df50d16b45b977217e02cba6c8422aaddb859f3d0570a88e09b00eafae89c6e"},
|
{file = "Pygments-2.7.1-py3-none-any.whl", hash = "sha256:307543fe65c0947b126e83dd5a61bd8acbd84abec11f43caebaf5534cbc17998"},
|
||||||
{file = "Pygments-2.7.0.tar.gz", hash = "sha256:2594e8fdb06fef91552f86f4fd3a244d148ab24b66042036e64f29a291515048"},
|
{file = "Pygments-2.7.1.tar.gz", hash = "sha256:926c3f319eda178d1bd90851e4317e6d8cdb5e292a3386aac9bd75eca29cf9c7"},
|
||||||
]
|
]
|
||||||
pynacl = [
|
pynacl = [
|
||||||
{file = "PyNaCl-1.4.0-cp27-cp27m-macosx_10_10_x86_64.whl", hash = "sha256:ea6841bc3a76fa4942ce00f3bda7d436fda21e2d91602b9e21b7ca9ecab8f3ff"},
|
{file = "PyNaCl-1.4.0-cp27-cp27m-macosx_10_10_x86_64.whl", hash = "sha256:ea6841bc3a76fa4942ce00f3bda7d436fda21e2d91602b9e21b7ca9ecab8f3ff"},
|
||||||
|
@ -1112,28 +1123,32 @@ pytz = [
|
||||||
{file = "pytz-2020.1-py2.py3-none-any.whl", hash = "sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed"},
|
{file = "pytz-2020.1-py2.py3-none-any.whl", hash = "sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed"},
|
||||||
{file = "pytz-2020.1.tar.gz", hash = "sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048"},
|
{file = "pytz-2020.1.tar.gz", hash = "sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048"},
|
||||||
]
|
]
|
||||||
|
redis = [
|
||||||
|
{file = "redis-3.5.3-py2.py3-none-any.whl", hash = "sha256:432b788c4530cfe16d8d943a09d40ca6c16149727e4afe8c2c9d5580c59d9f24"},
|
||||||
|
{file = "redis-3.5.3.tar.gz", hash = "sha256:0e7e0cfca8660dea8b7d5cd8c4f6c5e29e11f31158c0b0ae91a397f00e5a05a2"},
|
||||||
|
]
|
||||||
regex = [
|
regex = [
|
||||||
{file = "regex-2020.7.14-cp27-cp27m-win32.whl", hash = "sha256:e46d13f38cfcbb79bfdb2964b0fe12561fe633caf964a77a5f8d4e45fe5d2ef7"},
|
{file = "regex-2020.9.27-cp27-cp27m-win32.whl", hash = "sha256:d23a18037313714fb3bb5a94434d3151ee4300bae631894b1ac08111abeaa4a3"},
|
||||||
{file = "regex-2020.7.14-cp27-cp27m-win_amd64.whl", hash = "sha256:6961548bba529cac7c07af2fd4d527c5b91bb8fe18995fed6044ac22b3d14644"},
|
{file = "regex-2020.9.27-cp27-cp27m-win_amd64.whl", hash = "sha256:84e9407db1b2eb368b7ecc283121b5e592c9aaedbe8c78b1a2f1102eb2e21d19"},
|
||||||
{file = "regex-2020.7.14-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:c50a724d136ec10d920661f1442e4a8b010a4fe5aebd65e0c2241ea41dbe93dc"},
|
{file = "regex-2020.9.27-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:5f18875ac23d9aa2f060838e8b79093e8bb2313dbaaa9f54c6d8e52a5df097be"},
|
||||||
{file = "regex-2020.7.14-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:8a51f2c6d1f884e98846a0a9021ff6861bdb98457879f412fdc2b42d14494067"},
|
{file = "regex-2020.9.27-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:ae91972f8ac958039920ef6e8769277c084971a142ce2b660691793ae44aae6b"},
|
||||||
{file = "regex-2020.7.14-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:9c568495e35599625f7b999774e29e8d6b01a6fb684d77dee1f56d41b11b40cd"},
|
{file = "regex-2020.9.27-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:9a02d0ae31d35e1ec12a4ea4d4cca990800f66a917d0fb997b20fbc13f5321fc"},
|
||||||
{file = "regex-2020.7.14-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:51178c738d559a2d1071ce0b0f56e57eb315bcf8f7d4cf127674b533e3101f88"},
|
{file = "regex-2020.9.27-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:ebbe29186a3d9b0c591e71b7393f1ae08c83cb2d8e517d2a822b8f7ec99dfd8b"},
|
||||||
{file = "regex-2020.7.14-cp36-cp36m-win32.whl", hash = "sha256:9eddaafb3c48e0900690c1727fba226c4804b8e6127ea409689c3bb492d06de4"},
|
{file = "regex-2020.9.27-cp36-cp36m-win32.whl", hash = "sha256:4707f3695b34335afdfb09be3802c87fa0bc27030471dbc082f815f23688bc63"},
|
||||||
{file = "regex-2020.7.14-cp36-cp36m-win_amd64.whl", hash = "sha256:14a53646369157baa0499513f96091eb70382eb50b2c82393d17d7ec81b7b85f"},
|
{file = "regex-2020.9.27-cp36-cp36m-win_amd64.whl", hash = "sha256:9bc13e0d20b97ffb07821aa3e113f9998e84994fe4d159ffa3d3a9d1b805043b"},
|
||||||
{file = "regex-2020.7.14-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:1269fef3167bb52631ad4fa7dd27bf635d5a0790b8e6222065d42e91bede4162"},
|
{file = "regex-2020.9.27-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:f1b3afc574a3db3b25c89161059d857bd4909a1269b0b3cb3c904677c8c4a3f7"},
|
||||||
{file = "regex-2020.7.14-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:d0a5095d52b90ff38592bbdc2644f17c6d495762edf47d876049cfd2968fbccf"},
|
{file = "regex-2020.9.27-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5533a959a1748a5c042a6da71fe9267a908e21eded7a4f373efd23a2cbdb0ecc"},
|
||||||
{file = "regex-2020.7.14-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:4c037fd14c5f4e308b8370b447b469ca10e69427966527edcab07f52d88388f7"},
|
{file = "regex-2020.9.27-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:1fe0a41437bbd06063aa184c34804efa886bcc128222e9916310c92cd54c3b4c"},
|
||||||
{file = "regex-2020.7.14-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:bc3d98f621898b4a9bc7fecc00513eec8f40b5b83913d74ccb445f037d58cd89"},
|
{file = "regex-2020.9.27-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:c570f6fa14b9c4c8a4924aaad354652366577b4f98213cf76305067144f7b100"},
|
||||||
{file = "regex-2020.7.14-cp37-cp37m-win32.whl", hash = "sha256:46bac5ca10fb748d6c55843a931855e2727a7a22584f302dd9bb1506e69f83f6"},
|
{file = "regex-2020.9.27-cp37-cp37m-win32.whl", hash = "sha256:eda4771e0ace7f67f58bc5b560e27fb20f32a148cbc993b0c3835970935c2707"},
|
||||||
{file = "regex-2020.7.14-cp37-cp37m-win_amd64.whl", hash = "sha256:0dc64ee3f33cd7899f79a8d788abfbec168410be356ed9bd30bbd3f0a23a7204"},
|
{file = "regex-2020.9.27-cp37-cp37m-win_amd64.whl", hash = "sha256:60b0e9e6dc45683e569ec37c55ac20c582973841927a85f2d8a7d20ee80216ab"},
|
||||||
{file = "regex-2020.7.14-cp38-cp38-manylinux1_i686.whl", hash = "sha256:5ea81ea3dbd6767873c611687141ec7b06ed8bab43f68fad5b7be184a920dc99"},
|
{file = "regex-2020.9.27-cp38-cp38-manylinux1_i686.whl", hash = "sha256:088afc8c63e7bd187a3c70a94b9e50ab3f17e1d3f52a32750b5b77dbe99ef5ef"},
|
||||||
{file = "regex-2020.7.14-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:bbb332d45b32df41200380fff14712cb6093b61bd142272a10b16778c418e98e"},
|
{file = "regex-2020.9.27-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:eaf548d117b6737df379fdd53bdde4f08870e66d7ea653e230477f071f861121"},
|
||||||
{file = "regex-2020.7.14-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:c11d6033115dc4887c456565303f540c44197f4fc1a2bfb192224a301534888e"},
|
{file = "regex-2020.9.27-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:41bb65f54bba392643557e617316d0d899ed5b4946dccee1cb6696152b29844b"},
|
||||||
{file = "regex-2020.7.14-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:75aaa27aa521a182824d89e5ab0a1d16ca207318a6b65042b046053cfc8ed07a"},
|
{file = "regex-2020.9.27-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:8d69cef61fa50c8133382e61fd97439de1ae623fe943578e477e76a9d9471637"},
|
||||||
{file = "regex-2020.7.14-cp38-cp38-win32.whl", hash = "sha256:d6cff2276e502b86a25fd10c2a96973fdb45c7a977dca2138d661417f3728341"},
|
{file = "regex-2020.9.27-cp38-cp38-win32.whl", hash = "sha256:f2388013e68e750eaa16ccbea62d4130180c26abb1d8e5d584b9baf69672b30f"},
|
||||||
{file = "regex-2020.7.14-cp38-cp38-win_amd64.whl", hash = "sha256:7a2dd66d2d4df34fa82c9dc85657c5e019b87932019947faece7983f2089a840"},
|
{file = "regex-2020.9.27-cp38-cp38-win_amd64.whl", hash = "sha256:4318d56bccfe7d43e5addb272406ade7a2274da4b70eb15922a071c58ab0108c"},
|
||||||
{file = "regex-2020.7.14.tar.gz", hash = "sha256:3a3af27a8d23143c49a3420efe5b3f8cf1a48c6fc8bc6856b03f638abc1833bb"},
|
{file = "regex-2020.9.27.tar.gz", hash = "sha256:a6f32aea4260dfe0e55dc9733ea162ea38f0ea86aa7d0f77b15beac5bf7b369d"},
|
||||||
]
|
]
|
||||||
requests = [
|
requests = [
|
||||||
{file = "requests-2.24.0-py2.py3-none-any.whl", hash = "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"},
|
{file = "requests-2.24.0-py2.py3-none-any.whl", hash = "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"},
|
||||||
|
@ -1287,21 +1302,21 @@ websockets = [
|
||||||
{file = "websockets-8.1.tar.gz", hash = "sha256:5c65d2da8c6bce0fca2528f69f44b2f977e06954c8512a952222cea50dad430f"},
|
{file = "websockets-8.1.tar.gz", hash = "sha256:5c65d2da8c6bce0fca2528f69f44b2f977e06954c8512a952222cea50dad430f"},
|
||||||
]
|
]
|
||||||
yarl = [
|
yarl = [
|
||||||
{file = "yarl-1.5.1-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:db6db0f45d2c63ddb1a9d18d1b9b22f308e52c83638c26b422d520a815c4b3fb"},
|
{file = "yarl-1.6.0-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:db9eb8307219d7e09b33bcb43287222ef35cbcf1586ba9472b0a4b833666ada1"},
|
||||||
{file = "yarl-1.5.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:17668ec6722b1b7a3a05cc0167659f6c95b436d25a36c2d52db0eca7d3f72593"},
|
{file = "yarl-1.6.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:e31fef4e7b68184545c3d68baec7074532e077bd1906b040ecfba659737df188"},
|
||||||
{file = "yarl-1.5.1-cp35-cp35m-win32.whl", hash = "sha256:040b237f58ff7d800e6e0fd89c8439b841f777dd99b4a9cca04d6935564b9409"},
|
{file = "yarl-1.6.0-cp35-cp35m-win32.whl", hash = "sha256:5d84cc36981eb5a8533be79d6c43454c8e6a39ee3118ceaadbd3c029ab2ee580"},
|
||||||
{file = "yarl-1.5.1-cp35-cp35m-win_amd64.whl", hash = "sha256:f18d68f2be6bf0e89f1521af2b1bb46e66ab0018faafa81d70f358153170a317"},
|
{file = "yarl-1.6.0-cp35-cp35m-win_amd64.whl", hash = "sha256:5e447e7f3780f44f890360ea973418025e8c0cdcd7d6a1b221d952600fd945dc"},
|
||||||
{file = "yarl-1.5.1-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:c52ce2883dc193824989a9b97a76ca86ecd1fa7955b14f87bf367a61b6232511"},
|
{file = "yarl-1.6.0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:6f6898429ec3c4cfbef12907047136fd7b9e81a6ee9f105b45505e633427330a"},
|
||||||
{file = "yarl-1.5.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:ce584af5de8830d8701b8979b18fcf450cef9a382b1a3c8ef189bedc408faf1e"},
|
{file = "yarl-1.6.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:d088ea9319e49273f25b1c96a3763bf19a882cff774d1792ae6fba34bd40550a"},
|
||||||
{file = "yarl-1.5.1-cp36-cp36m-win32.whl", hash = "sha256:df89642981b94e7db5596818499c4b2219028f2a528c9c37cc1de45bf2fd3a3f"},
|
{file = "yarl-1.6.0-cp36-cp36m-win32.whl", hash = "sha256:b7c199d2cbaf892ba0f91ed36d12ff41ecd0dde46cbf64ff4bfe997a3ebc925e"},
|
||||||
{file = "yarl-1.5.1-cp36-cp36m-win_amd64.whl", hash = "sha256:3a584b28086bc93c888a6c2aa5c92ed1ae20932f078c46509a66dce9ea5533f2"},
|
{file = "yarl-1.6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:67c5ea0970da882eaf9efcf65b66792557c526f8e55f752194eff8ec722c75c2"},
|
||||||
{file = "yarl-1.5.1-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:da456eeec17fa8aa4594d9a9f27c0b1060b6a75f2419fe0c00609587b2695f4a"},
|
{file = "yarl-1.6.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:04a54f126a0732af75e5edc9addeaa2113e2ca7c6fce8974a63549a70a25e50e"},
|
||||||
{file = "yarl-1.5.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:bc2f976c0e918659f723401c4f834deb8a8e7798a71be4382e024bcc3f7e23a8"},
|
{file = "yarl-1.6.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:fcbe419805c9b20db9a51d33b942feddbf6e7fb468cb20686fd7089d4164c12a"},
|
||||||
{file = "yarl-1.5.1-cp37-cp37m-win32.whl", hash = "sha256:4439be27e4eee76c7632c2427ca5e73703151b22cae23e64adb243a9c2f565d8"},
|
{file = "yarl-1.6.0-cp37-cp37m-win32.whl", hash = "sha256:c604998ab8115db802cc55cb1b91619b2831a6128a62ca7eea577fc8ea4d3131"},
|
||||||
{file = "yarl-1.5.1-cp37-cp37m-win_amd64.whl", hash = "sha256:48e918b05850fffb070a496d2b5f97fc31d15d94ca33d3d08a4f86e26d4e7c5d"},
|
{file = "yarl-1.6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c22607421f49c0cb6ff3ed593a49b6a99c6ffdeaaa6c944cdda83c2393c8864d"},
|
||||||
{file = "yarl-1.5.1-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:9b930776c0ae0c691776f4d2891ebc5362af86f152dd0da463a6614074cb1b02"},
|
{file = "yarl-1.6.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:7ce35944e8e61927a8f4eb78f5bc5d1e6da6d40eadd77e3f79d4e9399e263921"},
|
||||||
{file = "yarl-1.5.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:b3b9ad80f8b68519cc3372a6ca85ae02cc5a8807723ac366b53c0f089db19e4a"},
|
{file = "yarl-1.6.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:c15d71a640fb1f8e98a1423f9c64d7f1f6a3a168f803042eaf3a5b5022fde0c1"},
|
||||||
{file = "yarl-1.5.1-cp38-cp38-win32.whl", hash = "sha256:f379b7f83f23fe12823085cd6b906edc49df969eb99757f58ff382349a3303c6"},
|
{file = "yarl-1.6.0-cp38-cp38-win32.whl", hash = "sha256:3cc860d72ed989f3b1f3abbd6ecf38e412de722fb38b8f1b1a086315cf0d69c5"},
|
||||||
{file = "yarl-1.5.1-cp38-cp38-win_amd64.whl", hash = "sha256:9102b59e8337f9874638fcfc9ac3734a0cfadb100e47d55c20d0dc6087fb4692"},
|
{file = "yarl-1.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:e32f0fb443afcfe7f01f95172b66f279938fbc6bdaebe294b0ff6747fb6db020"},
|
||||||
{file = "yarl-1.5.1.tar.gz", hash = "sha256:c22c75b5f394f3d47105045ea551e08a3e804dc7e01b37800ca35b58f856c3d6"},
|
{file = "yarl-1.6.0.tar.gz", hash = "sha256:61d3ea3c175fe45f1498af868879c6ffeb989d4143ac542163c45538ba5ec21b"},
|
||||||
]
|
]
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "royalnet"
|
name = "royalnet"
|
||||||
version = "5.11.13"
|
version = "6.0.0a1"
|
||||||
description = "A multipurpose bot and web framework"
|
description = "A multipurpose bot and web framework"
|
||||||
authors = ["Stefano Pigozzi <ste.pigozzi@gmail.com>"]
|
authors = ["Stefano Pigozzi <ste.pigozzi@gmail.com>"]
|
||||||
license = "AGPL-3.0+"
|
license = "AGPL-3.0+"
|
||||||
|
@ -48,12 +48,12 @@ python-multipart = { version = "^0.0.5", optional = true }
|
||||||
# sentry
|
# sentry
|
||||||
sentry_sdk = { version = "~0.13.2", optional = true }
|
sentry_sdk = { version = "~0.13.2", optional = true }
|
||||||
|
|
||||||
# herald
|
|
||||||
websockets = { version = "^8.1", optional = true }
|
|
||||||
|
|
||||||
# logging
|
# logging
|
||||||
coloredlogs = { version = "^10.0", optional = true }
|
coloredlogs = { version = "^10.0", optional = true }
|
||||||
|
|
||||||
|
# baron
|
||||||
|
redis = { version = "^3.5.3", optional = true }
|
||||||
|
|
||||||
# Development dependencies
|
# Development dependencies
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
pytest = "^5.2.1"
|
pytest = "^5.2.1"
|
||||||
|
@ -69,8 +69,8 @@ alchemy_easy = ["sqlalchemy", "psycopg2_binary", "bcrypt"]
|
||||||
alchemy_hard = ["sqlalchemy", "psycopg2", "bcrypt"]
|
alchemy_hard = ["sqlalchemy", "psycopg2", "bcrypt"]
|
||||||
constellation = ["starlette", "uvicorn", "python-multipart"]
|
constellation = ["starlette", "uvicorn", "python-multipart"]
|
||||||
sentry = ["sentry_sdk"]
|
sentry = ["sentry_sdk"]
|
||||||
herald = ["websockets"]
|
|
||||||
coloredlogs = ["coloredlogs"]
|
coloredlogs = ["coloredlogs"]
|
||||||
|
baron = ["redis"]
|
||||||
|
|
||||||
|
|
||||||
# Executable aliases
|
# Executable aliases
|
||||||
|
|
30
royalnet/baron/__init__.py
Normal file
30
royalnet/baron/__init__.py
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
from typing import *
|
||||||
|
import redis
|
||||||
|
import redis.client
|
||||||
|
import threading
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"Baron"
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class Baron:
|
||||||
|
def __init__(self, baron_cfg):
|
||||||
|
self.publisher: redis.Redis = redis.Redis(
|
||||||
|
host=baron_cfg["host"],
|
||||||
|
port=baron_cfg["port"],
|
||||||
|
db=baron_cfg["db"],
|
||||||
|
password=baron_cfg["password"]
|
||||||
|
)
|
||||||
|
self.listener: redis.client.PubSub = self.publisher.pubsub()
|
||||||
|
|
||||||
|
def publish(self, channel: str, message):
|
||||||
|
self.publisher.publish(channel=channel, message=message)
|
||||||
|
|
||||||
|
def subscribe(self, channel: str, callback: Callable):
|
||||||
|
self.listener.subscribe({
|
||||||
|
channel: callback
|
||||||
|
})
|
||||||
|
|
||||||
|
def listen(self):
|
||||||
|
self.listener.listen()
|
|
@ -1,12 +0,0 @@
|
||||||
# `royalnet.herald`
|
|
||||||
|
|
||||||
The subpackage providing all functions and classes to handle communication between process (even over the Internet).
|
|
||||||
|
|
||||||
It is based on [`websockets`](https://github.com/websockets).
|
|
||||||
|
|
||||||
It requires the `herald` extra to be installed.
|
|
||||||
|
|
||||||
You can install it with:
|
|
||||||
```
|
|
||||||
pip install royalnet[herald]
|
|
||||||
```
|
|
|
@ -1,37 +0,0 @@
|
||||||
"""The subpackage providing all functions and classes to handle communication between process (even over the Internet).
|
|
||||||
|
|
||||||
It is based on :mod:`websockets`.
|
|
||||||
|
|
||||||
It requires the ``herald`` extra to be installed.
|
|
||||||
|
|
||||||
You can install it with: ::
|
|
||||||
|
|
||||||
pip install royalnet[herald]
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
from .broadcast import Broadcast
|
|
||||||
from .config import Config
|
|
||||||
from .errors import *
|
|
||||||
from .link import Link
|
|
||||||
from .package import Package
|
|
||||||
from .request import Request
|
|
||||||
from .response import Response, ResponseSuccess, ResponseFailure
|
|
||||||
from .server import Server
|
|
||||||
|
|
||||||
__all__ = [
|
|
||||||
"Config",
|
|
||||||
"HeraldError",
|
|
||||||
"ConnectionClosedError",
|
|
||||||
"LinkError",
|
|
||||||
"InvalidServerResponseError",
|
|
||||||
"ServerError",
|
|
||||||
"Link",
|
|
||||||
"Package",
|
|
||||||
"Request",
|
|
||||||
"Response",
|
|
||||||
"ResponseSuccess",
|
|
||||||
"ResponseFailure",
|
|
||||||
"Server",
|
|
||||||
"Broadcast",
|
|
||||||
]
|
|
|
@ -1,26 +0,0 @@
|
||||||
from typing import *
|
|
||||||
|
|
||||||
|
|
||||||
class Broadcast:
|
|
||||||
def __init__(self, handler: str, data: dict, msg_type: Optional[str] = None):
|
|
||||||
super().__init__()
|
|
||||||
if msg_type is not None:
|
|
||||||
assert msg_type == self.__class__.__name__
|
|
||||||
self.msg_type = self.__class__.__name__
|
|
||||||
self.handler: str = handler
|
|
||||||
self.data: dict = data
|
|
||||||
|
|
||||||
def to_dict(self):
|
|
||||||
return self.__dict__
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_dict(cls, d: dict):
|
|
||||||
return cls(**d)
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
|
||||||
if isinstance(other, self.__class__):
|
|
||||||
return self.handler == other.handler and self.data == other.data
|
|
||||||
return False
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return f"{self.__class__.__qualname__}(handler={self.handler}, data={self.data})"
|
|
|
@ -1,73 +0,0 @@
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
|
|
||||||
class Config:
|
|
||||||
def __init__(self,
|
|
||||||
name: str,
|
|
||||||
address: str,
|
|
||||||
port: int,
|
|
||||||
secret: str,
|
|
||||||
secure: bool = False,
|
|
||||||
path: str = "/"
|
|
||||||
):
|
|
||||||
if ":" in name:
|
|
||||||
raise ValueError("Herald names cannot contain colons (:)")
|
|
||||||
self.name = name
|
|
||||||
|
|
||||||
self.address = address
|
|
||||||
|
|
||||||
if port < 0 or port > 65535:
|
|
||||||
raise ValueError("No such port")
|
|
||||||
self.port = port
|
|
||||||
|
|
||||||
self.secure = secure
|
|
||||||
|
|
||||||
if ":" in secret:
|
|
||||||
raise ValueError("Herald secrets cannot contain colons (:)")
|
|
||||||
self.secret = secret
|
|
||||||
|
|
||||||
if not path.startswith("/"):
|
|
||||||
raise ValueError("Herald paths must start with a slash (/)")
|
|
||||||
self.path = path
|
|
||||||
|
|
||||||
@property
|
|
||||||
def url(self):
|
|
||||||
return f"ws{'s' if self.secure else ''}://{self.address}:{self.port}{self.path}"
|
|
||||||
|
|
||||||
def copy(self,
|
|
||||||
name: Optional[str] = None,
|
|
||||||
address: Optional[str] = None,
|
|
||||||
port: Optional[int] = None,
|
|
||||||
secret: Optional[str] = None,
|
|
||||||
secure: Optional[bool] = None,
|
|
||||||
path: Optional[str] = None):
|
|
||||||
"""Create an exact copy of this configuration, but with different parameters."""
|
|
||||||
return self.__class__(name=name if name else self.name,
|
|
||||||
address=address if address else self.address,
|
|
||||||
port=port if port else self.port,
|
|
||||||
secret=secret if secret else self.secret,
|
|
||||||
secure=secure if secure else self.secure,
|
|
||||||
path=path if path else self.path)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return f"<HeraldConfig for {self.url}>"
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_config(
|
|
||||||
cls, *,
|
|
||||||
name: str,
|
|
||||||
address: str,
|
|
||||||
port: int,
|
|
||||||
secret: str,
|
|
||||||
secure: bool = False,
|
|
||||||
path: str = "/",
|
|
||||||
**_,
|
|
||||||
):
|
|
||||||
return cls(
|
|
||||||
name=name,
|
|
||||||
address=address,
|
|
||||||
port=port,
|
|
||||||
secret=secret,
|
|
||||||
secure=secure,
|
|
||||||
path=path
|
|
||||||
)
|
|
|
@ -1,18 +0,0 @@
|
||||||
class HeraldError(Exception):
|
|
||||||
"""A generic :mod:`royalnet.herald` error."""
|
|
||||||
|
|
||||||
|
|
||||||
class LinkError(HeraldError):
|
|
||||||
"""An error for something that happened in a :class:`Link`."""
|
|
||||||
|
|
||||||
|
|
||||||
class ServerError(HeraldError):
|
|
||||||
"""An error for something that happened in a :class:`Server`."""
|
|
||||||
|
|
||||||
|
|
||||||
class ConnectionClosedError(LinkError):
|
|
||||||
"""The :py:class:`Link`'s connection was closed unexpectedly. The link can't be used anymore."""
|
|
||||||
|
|
||||||
|
|
||||||
class InvalidServerResponseError(LinkError):
|
|
||||||
"""The :py:class:`Server` sent invalid data to the :class:`Link`."""
|
|
|
@ -1,189 +0,0 @@
|
||||||
import asyncio as aio
|
|
||||||
import functools
|
|
||||||
import logging
|
|
||||||
import uuid
|
|
||||||
from typing import *
|
|
||||||
|
|
||||||
import websockets
|
|
||||||
|
|
||||||
from .broadcast import Broadcast
|
|
||||||
from .config import Config
|
|
||||||
from .errors import ConnectionClosedError, InvalidServerResponseError
|
|
||||||
from .package import Package
|
|
||||||
from .request import Request
|
|
||||||
from .response import Response, ResponseSuccess, ResponseFailure
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class PendingRequest:
|
|
||||||
def __init__(self, *, loop: aio.AbstractEventLoop = None):
|
|
||||||
if loop is None:
|
|
||||||
self.loop = aio.get_event_loop()
|
|
||||||
else:
|
|
||||||
self.loop = loop
|
|
||||||
self.event: aio.Event = aio.Event(loop=loop)
|
|
||||||
self.data: Optional[dict] = None
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
if self.event.is_set():
|
|
||||||
return f"<{self.__class__.__qualname__}: {self.data.__class__.__name__}>"
|
|
||||||
return f"<{self.__class__.__qualname__}>"
|
|
||||||
|
|
||||||
def set(self, data):
|
|
||||||
self.data = data
|
|
||||||
self.event.set()
|
|
||||||
|
|
||||||
|
|
||||||
def requires_connection(func):
|
|
||||||
@functools.wraps(func)
|
|
||||||
async def new_func(self, *args, **kwargs):
|
|
||||||
await self.connect_event.wait()
|
|
||||||
return await func(self, *args, **kwargs)
|
|
||||||
|
|
||||||
return new_func
|
|
||||||
|
|
||||||
|
|
||||||
def requires_identification(func):
|
|
||||||
@functools.wraps(func)
|
|
||||||
async def new_func(self, *args, **kwargs):
|
|
||||||
await self.identify_event.wait()
|
|
||||||
return await func(self, *args, **kwargs)
|
|
||||||
|
|
||||||
return new_func
|
|
||||||
|
|
||||||
|
|
||||||
class Link:
|
|
||||||
def __init__(self, config: Config, request_handler, *,
|
|
||||||
loop: aio.AbstractEventLoop = None):
|
|
||||||
self.config: Config = config
|
|
||||||
self.nid: str = str(uuid.uuid4())
|
|
||||||
self.websocket: Optional["websockets.WebSocketClientProtocol"] = None
|
|
||||||
self.request_handler: Callable[[Union[Request, Broadcast]],
|
|
||||||
Awaitable[Response]] = request_handler
|
|
||||||
self._pending_requests: Dict[str, PendingRequest] = {}
|
|
||||||
if loop is None:
|
|
||||||
self._loop = aio.get_event_loop()
|
|
||||||
else:
|
|
||||||
self._loop = loop
|
|
||||||
self.error_event: aio.Event = aio.Event(loop=self._loop)
|
|
||||||
self.connect_event: aio.Event = aio.Event(loop=self._loop)
|
|
||||||
self.identify_event: aio.Event = aio.Event(loop=self._loop)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
if self.identify_event.is_set():
|
|
||||||
return f"<{self.__class__.__qualname__} (identified)>"
|
|
||||||
elif self.connect_event.is_set():
|
|
||||||
return f"<{self.__class__.__qualname__} (connected)>"
|
|
||||||
elif self.error_event.is_set():
|
|
||||||
return f"<{self.__class__.__qualname__} (error)>"
|
|
||||||
else:
|
|
||||||
return f"<{self.__class__.__qualname__} (disconnected)>"
|
|
||||||
|
|
||||||
async def connect(self):
|
|
||||||
"""Connect to the :class:`Server` at :attr:`.config.url`."""
|
|
||||||
log.debug(f"Connecting to Herald Server at {self.config.url}...")
|
|
||||||
self.websocket = await websockets.connect(self.config.url, loop=self._loop)
|
|
||||||
self.connect_event.set()
|
|
||||||
log.debug(f"Connected!")
|
|
||||||
|
|
||||||
@requires_connection
|
|
||||||
async def receive(self) -> Package:
|
|
||||||
"""Recieve a :py:class:`Package` from the :py:class:`Server`.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
:exc:`ConnectionClosedError` if the connection is closed."""
|
|
||||||
try:
|
|
||||||
jbytes: bytes = await self.websocket.recv()
|
|
||||||
package: Package = Package.from_json_bytes(jbytes)
|
|
||||||
except websockets.ConnectionClosed:
|
|
||||||
self.error_event.set()
|
|
||||||
self.connect_event.clear()
|
|
||||||
self.identify_event.clear()
|
|
||||||
log.warning(f"Herald Server connection closed: {self.config.url}")
|
|
||||||
# What to do now? Let's just reraise.
|
|
||||||
raise ConnectionClosedError()
|
|
||||||
if self.identify_event.is_set() and package.destination != self.nid:
|
|
||||||
raise InvalidServerResponseError("Package is not addressed to this NetworkLink.")
|
|
||||||
log.debug(f"Received package: {package}")
|
|
||||||
return package
|
|
||||||
|
|
||||||
@requires_connection
|
|
||||||
async def identify(self) -> None:
|
|
||||||
log.debug(f"Identifying...")
|
|
||||||
await self.websocket.send(f"Identify {self.nid}:{self.config.name}:{self.config.secret}")
|
|
||||||
response: Package = await self.receive()
|
|
||||||
if not response.source == "<server>":
|
|
||||||
raise InvalidServerResponseError("Received a non-service package before identification.")
|
|
||||||
if "type" not in response.data:
|
|
||||||
raise InvalidServerResponseError("Missing 'type' in response data")
|
|
||||||
if response.data["type"] == "error":
|
|
||||||
raise ConnectionClosedError(f"Identification error: {response.data['type']}")
|
|
||||||
assert response.data["type"] == "success"
|
|
||||||
self.identify_event.set()
|
|
||||||
log.debug(f"Identified successfully!")
|
|
||||||
|
|
||||||
@requires_identification
|
|
||||||
async def send(self, package: Package):
|
|
||||||
"""Send a package to the :class:`Server`."""
|
|
||||||
log.debug(f"Trying to send package: {package}")
|
|
||||||
try:
|
|
||||||
jbytes = package.to_json_bytes()
|
|
||||||
except TypeError as e:
|
|
||||||
log.fatal(f"Could not send package: {' '.join(e.args)}")
|
|
||||||
raise
|
|
||||||
await self.websocket.send(jbytes)
|
|
||||||
log.debug(f"Sent package: {package}")
|
|
||||||
|
|
||||||
@requires_identification
|
|
||||||
async def broadcast(self, destination: str, broadcast: Broadcast) -> None:
|
|
||||||
package = Package(broadcast.to_dict(), source=self.nid, destination=destination)
|
|
||||||
await self.send(package)
|
|
||||||
log.debug(f"Sent broadcast to {destination}: {broadcast}")
|
|
||||||
|
|
||||||
@requires_identification
|
|
||||||
async def request(self, destination: str, request: Request) -> Response:
|
|
||||||
if destination.startswith("*"):
|
|
||||||
raise ValueError("requests cannot have multiple destinations")
|
|
||||||
package = Package(request.to_dict(), source=self.nid, destination=destination)
|
|
||||||
request = PendingRequest(loop=self._loop)
|
|
||||||
self._pending_requests[package.source_conv_id] = request
|
|
||||||
await self.send(package)
|
|
||||||
log.debug(f"Sent request to {destination}: {request}")
|
|
||||||
await request.event.wait()
|
|
||||||
if request.data["type"] == "ResponseSuccess":
|
|
||||||
response: Response = ResponseSuccess.from_dict(request.data)
|
|
||||||
elif request.data["type"] == "ResponseFailure":
|
|
||||||
response: Response = ResponseFailure.from_dict(request.data)
|
|
||||||
else:
|
|
||||||
raise TypeError("Unknown response type")
|
|
||||||
log.debug(f"Received from {destination}: {request} -> {response}")
|
|
||||||
return response
|
|
||||||
|
|
||||||
async def run(self):
|
|
||||||
"""Blockingly run the Link."""
|
|
||||||
log.debug(f"Running link: {self.config.name}")
|
|
||||||
if self.error_event.is_set():
|
|
||||||
raise ConnectionClosedError("RoyalnetLinks can't be rerun after an error.")
|
|
||||||
while True:
|
|
||||||
if not self.connect_event.is_set():
|
|
||||||
await self.connect()
|
|
||||||
if not self.identify_event.is_set():
|
|
||||||
await self.identify()
|
|
||||||
package: Package = await self.receive()
|
|
||||||
# Package is a response
|
|
||||||
if package.destination_conv_id in self._pending_requests:
|
|
||||||
request = self._pending_requests[package.destination_conv_id]
|
|
||||||
request.set(package.data)
|
|
||||||
continue
|
|
||||||
# Package is a request
|
|
||||||
elif package.data["msg_type"] == "Request":
|
|
||||||
log.debug(f"Received request {package.source_conv_id}: {package}")
|
|
||||||
response: Response = await self.request_handler(Request.from_dict(package.data))
|
|
||||||
response_package: Package = package.reply(response.to_dict())
|
|
||||||
await self.send(response_package)
|
|
||||||
log.debug(f"Replied to request {response_package.source_conv_id}: {response_package}")
|
|
||||||
# Package is a broadcast
|
|
||||||
elif package.data["msg_type"] == "Broadcast":
|
|
||||||
log.debug(f"Received broadcast {package.source_conv_id}: {package}")
|
|
||||||
await self.request_handler(Broadcast.from_dict(package.data))
|
|
|
@ -1,114 +0,0 @@
|
||||||
import json
|
|
||||||
import uuid
|
|
||||||
from typing import *
|
|
||||||
|
|
||||||
|
|
||||||
class Package:
|
|
||||||
"""A data type with which a :py:class:`Link` communicates with a :py:class:`Server` or
|
|
||||||
another Link.
|
|
||||||
|
|
||||||
Contains info about the source and the destination."""
|
|
||||||
|
|
||||||
def __init__(self,
|
|
||||||
data: dict,
|
|
||||||
*,
|
|
||||||
source: str,
|
|
||||||
destination: str,
|
|
||||||
source_conv_id: Optional[str] = None,
|
|
||||||
destination_conv_id: Optional[str] = None):
|
|
||||||
"""Create a Package.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
data: The data that should be sent.
|
|
||||||
source: The ``nid`` of the node that created this Package.
|
|
||||||
destination: The ``link_type`` of the destination node, or alternatively, the ``nid`` of the node.
|
|
||||||
Can also be the ``NULL`` value to send the message to nobody.
|
|
||||||
source_conv_id: The conversation id of the node that created this package.
|
|
||||||
Akin to the sequence number on IP packets.
|
|
||||||
destination_conv_id: The conversation id of the node that this Package is a reply to."""
|
|
||||||
self.data: dict = data
|
|
||||||
self.source: str = source
|
|
||||||
self.source_conv_id: str = source_conv_id or str(uuid.uuid4())
|
|
||||||
self.destination: str = destination
|
|
||||||
self.destination_conv_id: Optional[str] = destination_conv_id
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return f"<{self.__class__.__qualname__} {self.source} » {self.destination}>"
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
|
||||||
if isinstance(other, Package):
|
|
||||||
return (self.data == other.data) and \
|
|
||||||
(self.source == other.source) and \
|
|
||||||
(self.destination == other.destination) and \
|
|
||||||
(self.source_conv_id == other.source_conv_id) and \
|
|
||||||
(self.destination_conv_id == other.destination_conv_id)
|
|
||||||
return False
|
|
||||||
|
|
||||||
def reply(self, data) -> "Package":
|
|
||||||
"""Reply to this :class:`Package` with another :class:`Package`.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
data: The data that should be sent. Usually a :class:`Request`.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The reply :class:`Package`."""
|
|
||||||
return Package(data,
|
|
||||||
source=self.destination,
|
|
||||||
destination=self.source,
|
|
||||||
source_conv_id=self.destination_conv_id or str(uuid.uuid4()),
|
|
||||||
destination_conv_id=self.source_conv_id)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def from_dict(d) -> "Package":
|
|
||||||
"""Create a :class:`Package` from a dictionary."""
|
|
||||||
if "source" not in d:
|
|
||||||
raise ValueError("Missing source field")
|
|
||||||
if "nid" not in d["source"]:
|
|
||||||
raise ValueError("Missing source.nid field")
|
|
||||||
if "conv_id" not in d["source"]:
|
|
||||||
raise ValueError("Missing source.conv_id field")
|
|
||||||
if "destination" not in d:
|
|
||||||
raise ValueError("Missing destination field")
|
|
||||||
if "nid" not in d["destination"]:
|
|
||||||
raise ValueError("Missing destination.nid field")
|
|
||||||
if "conv_id" not in d["destination"]:
|
|
||||||
raise ValueError("Missing destination.conv_id field")
|
|
||||||
if "data" not in d:
|
|
||||||
raise ValueError("Missing data field")
|
|
||||||
return Package(d["data"],
|
|
||||||
source=d["source"]["nid"],
|
|
||||||
destination=d["destination"]["nid"],
|
|
||||||
source_conv_id=d["source"]["conv_id"],
|
|
||||||
destination_conv_id=d["destination"]["conv_id"])
|
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
|
||||||
"""Convert the :class:`Package` into a dictionary."""
|
|
||||||
return {
|
|
||||||
"source": {
|
|
||||||
"nid": self.source,
|
|
||||||
"conv_id": self.source_conv_id
|
|
||||||
},
|
|
||||||
"destination": {
|
|
||||||
"nid": self.destination,
|
|
||||||
"conv_id": self.destination_conv_id
|
|
||||||
},
|
|
||||||
"data": self.data
|
|
||||||
}
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def from_json_string(string: str) -> "Package":
|
|
||||||
"""Create a :class:`Package` from a JSON string."""
|
|
||||||
return Package.from_dict(json.loads(string))
|
|
||||||
|
|
||||||
def to_json_string(self) -> str:
|
|
||||||
"""Convert the :class:`Package` into a JSON string."""
|
|
||||||
return json.dumps(self.to_dict())
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def from_json_bytes(b: bytes) -> "Package":
|
|
||||||
"""Create a :class:`Package` from UTF-8-encoded JSON bytes."""
|
|
||||||
return Package.from_json_string(str(b, encoding="utf8"))
|
|
||||||
|
|
||||||
def to_json_bytes(self) -> bytes:
|
|
||||||
"""Convert the :class:`Package` into UTF-8-encoded JSON bytes."""
|
|
||||||
return bytes(self.to_json_string(), encoding="utf8")
|
|
|
@ -1,30 +0,0 @@
|
||||||
from typing import *
|
|
||||||
|
|
||||||
|
|
||||||
class Request:
|
|
||||||
"""A request sent from a :class:`Link` to another.
|
|
||||||
|
|
||||||
It contains the name of the requested handler, in addition to the data."""
|
|
||||||
|
|
||||||
def __init__(self, handler: str, data: dict, msg_type: Optional[str] = None):
|
|
||||||
super().__init__()
|
|
||||||
if msg_type is not None:
|
|
||||||
assert msg_type == self.__class__.__name__
|
|
||||||
self.msg_type = self.__class__.__name__
|
|
||||||
self.handler: str = handler
|
|
||||||
self.data: dict = data
|
|
||||||
|
|
||||||
def to_dict(self):
|
|
||||||
return self.__dict__
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_dict(cls, d: dict):
|
|
||||||
return cls(**d)
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
|
||||||
if isinstance(other, self.__class__):
|
|
||||||
return self.handler == other.handler and self.data == other.data
|
|
||||||
return False
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return f"{self.__class__.__qualname__}(handler={self.handler}, data={self.data})"
|
|
|
@ -1,54 +0,0 @@
|
||||||
from typing import *
|
|
||||||
|
|
||||||
|
|
||||||
class Response:
|
|
||||||
"""A base class to be inherited by all other response types."""
|
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
|
||||||
"""Prepare the Response to be sent by converting it to a JSONable :py:class:`dict`."""
|
|
||||||
return {
|
|
||||||
"type": self.__class__.__name__,
|
|
||||||
**self.__dict__
|
|
||||||
}
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
|
||||||
if isinstance(other, Response):
|
|
||||||
return self.to_dict() == other.to_dict()
|
|
||||||
return False
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_dict(cls, d: dict) -> "Response":
|
|
||||||
"""Recreate the response from a received :py:class:`dict`."""
|
|
||||||
# Ignore type in dict
|
|
||||||
del d["type"]
|
|
||||||
# noinspection PyArgumentList
|
|
||||||
return cls(**d)
|
|
||||||
|
|
||||||
|
|
||||||
class ResponseSuccess(Response):
|
|
||||||
"""A response to a successful :py:class:`Request`."""
|
|
||||||
|
|
||||||
def __init__(self, data: Optional[dict] = None):
|
|
||||||
if data is None:
|
|
||||||
self.data = {}
|
|
||||||
else:
|
|
||||||
self.data = data
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return f"{self.__class__.__qualname__}(data={self.data})"
|
|
||||||
|
|
||||||
|
|
||||||
class ResponseFailure(Response):
|
|
||||||
"""A response to a invalid :py:class:`Request`."""
|
|
||||||
|
|
||||||
def __init__(self, name: str, description: str, extra_info: Optional[dict] = None):
|
|
||||||
self.name: str = name
|
|
||||||
self.description: str = description
|
|
||||||
self.extra_info: Optional[dict] = extra_info
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return f"{self.__class__.__qualname__}(" \
|
|
||||||
f"name={self.name}, " \
|
|
||||||
f"description={self.description}, " \
|
|
||||||
f"extra_info={self.extra_info}" \
|
|
||||||
f")"
|
|
|
@ -1,163 +0,0 @@
|
||||||
import asyncio as aio
|
|
||||||
import datetime
|
|
||||||
import logging
|
|
||||||
import re
|
|
||||||
import uuid
|
|
||||||
from typing import *
|
|
||||||
|
|
||||||
import websockets
|
|
||||||
|
|
||||||
import royalnet.utils as ru
|
|
||||||
from .config import Config
|
|
||||||
from .package import Package
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class ConnectedClient:
|
|
||||||
"""The :py:class:`Server`-side representation of a connected :py:class:`Link`."""
|
|
||||||
|
|
||||||
def __init__(self, socket: "websockets.WebSocketServerProtocol"):
|
|
||||||
self.socket: "websockets.WebSocketServerProtocol" = socket
|
|
||||||
self.nid: Optional[str] = None
|
|
||||||
self.link_type: Optional[str] = None
|
|
||||||
self.connection_datetime: datetime.datetime = datetime.datetime.now()
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return f"<{self.__class__.__qualname__} {self.nid}>"
|
|
||||||
|
|
||||||
@property
|
|
||||||
def is_identified(self) -> bool:
|
|
||||||
"""Has the client sent a valid identification package?"""
|
|
||||||
return bool(self.nid)
|
|
||||||
|
|
||||||
async def send_service(self, msg_type: str, message: str):
|
|
||||||
await self.send(Package({"type": msg_type, "service": message},
|
|
||||||
source="<server>",
|
|
||||||
destination=self.nid))
|
|
||||||
|
|
||||||
async def send(self, package: Package):
|
|
||||||
"""Send a :py:class:`Package` to the :py:class:`Link`."""
|
|
||||||
await self.socket.send(package.to_json_bytes())
|
|
||||||
|
|
||||||
|
|
||||||
class Server:
|
|
||||||
def __init__(self, config: Config, *, loop: aio.AbstractEventLoop = None):
|
|
||||||
self.config: Config = config
|
|
||||||
self.identified_clients: List[ConnectedClient] = []
|
|
||||||
self.loop = loop
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return f"<{self.__class__.__qualname__}>"
|
|
||||||
|
|
||||||
def find_client(self, *, nid: str = None, link_type: str = None) -> List[ConnectedClient]:
|
|
||||||
assert not (nid and link_type)
|
|
||||||
if nid:
|
|
||||||
matching = [client for client in self.identified_clients if client.nid == nid]
|
|
||||||
assert len(matching) <= 1
|
|
||||||
return matching
|
|
||||||
if link_type:
|
|
||||||
matching = [client for client in self.identified_clients if client.link_type == link_type]
|
|
||||||
return matching or []
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal
|
|
||||||
async def listener(self, websocket: "websockets.server.WebSocketServerProtocol", path):
|
|
||||||
connected_client = ConnectedClient(websocket)
|
|
||||||
# Wait for identification
|
|
||||||
identify_msg = await websocket.recv()
|
|
||||||
log.debug(f"{websocket.remote_address} identified itself with: {identify_msg}.")
|
|
||||||
if not isinstance(identify_msg, str):
|
|
||||||
log.warning(f"Failed Herald identification: {websocket.remote_address[0]}:{websocket.remote_address[1]}")
|
|
||||||
await connected_client.send_service("error", "Invalid identification message (not a str)")
|
|
||||||
return
|
|
||||||
identification = re.match(r"Identify ([^:\s]+):([^:\s]+):([^:\s]+)", identify_msg)
|
|
||||||
if identification is None:
|
|
||||||
log.warning(f"Failed Herald identification: {websocket.remote_address[0]}:{websocket.remote_address[1]}")
|
|
||||||
await connected_client.send_service("error", "Invalid identification message (regex failed)")
|
|
||||||
return
|
|
||||||
secret = identification.group(3)
|
|
||||||
if secret != self.config.secret:
|
|
||||||
log.warning(f"Invalid Herald secret: {websocket.remote_address[0]}:{websocket.remote_address[1]}")
|
|
||||||
await connected_client.send_service("error", "Invalid secret")
|
|
||||||
return
|
|
||||||
# Identification successful
|
|
||||||
connected_client.nid = identification.group(1)
|
|
||||||
connected_client.link_type = identification.group(2)
|
|
||||||
log.info(f"Joined the Herald: {websocket.remote_address[0]}:{websocket.remote_address[1]}"
|
|
||||||
f" ({connected_client.link_type})")
|
|
||||||
self.identified_clients.append(connected_client)
|
|
||||||
await connected_client.send_service("success", "Identification successful!")
|
|
||||||
log.debug(f"{connected_client.nid}'s identification confirmed.")
|
|
||||||
# Main loop
|
|
||||||
while True:
|
|
||||||
# Receive packages
|
|
||||||
raw_bytes = await websocket.recv()
|
|
||||||
package: Package = Package.from_json_bytes(raw_bytes)
|
|
||||||
log.debug(f"Received package: {package}")
|
|
||||||
# Check if the package destination is the server itself.
|
|
||||||
if package.destination == "<server>":
|
|
||||||
# Do... nothing for now?
|
|
||||||
pass
|
|
||||||
# Otherwise, route the package to its destination
|
|
||||||
# noinspection PyAsyncCall
|
|
||||||
self.loop.create_task(self.route_package(package))
|
|
||||||
|
|
||||||
def find_destination(self, package: Package) -> List[ConnectedClient]:
|
|
||||||
"""Find a list of destinations for the package.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
package: The package to find the destination of.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
A :class:`list` of :class:`ConnectedClient` to send the package to."""
|
|
||||||
# Parse destination
|
|
||||||
# Is it nothing?
|
|
||||||
if package.destination == "<none>":
|
|
||||||
return []
|
|
||||||
# Is it all possible destinations?
|
|
||||||
if package.destination == "*":
|
|
||||||
return self.identified_clients
|
|
||||||
# Is it a valid nid?
|
|
||||||
try:
|
|
||||||
destination = str(uuid.UUID(package.destination))
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
return self.find_client(nid=destination)
|
|
||||||
# Is it a link_type?
|
|
||||||
return self.find_client(link_type=package.destination)
|
|
||||||
|
|
||||||
async def route_package(self, package: Package) -> None:
|
|
||||||
"""Executed every time a :class:`Package` is received and must be routed somewhere."""
|
|
||||||
destinations = self.find_destination(package)
|
|
||||||
log.debug(f"Routing package: {package} -> {destinations}")
|
|
||||||
for destination in destinations:
|
|
||||||
# This may have some consequences
|
|
||||||
specific_package = Package(package.data,
|
|
||||||
source=package.source,
|
|
||||||
destination=destination.nid,
|
|
||||||
source_conv_id=package.source_conv_id,
|
|
||||||
destination_conv_id=package.destination_conv_id)
|
|
||||||
await destination.send(specific_package)
|
|
||||||
|
|
||||||
def serve(self):
|
|
||||||
if self.config.secure:
|
|
||||||
raise Exception("Secure servers aren't supported yet")
|
|
||||||
log.debug(f"Serving on {self.config.url}")
|
|
||||||
try:
|
|
||||||
self.loop.run_until_complete(self.run())
|
|
||||||
except OSError as e:
|
|
||||||
log.fatal(f"OSError: {e}")
|
|
||||||
self.loop.run_forever()
|
|
||||||
|
|
||||||
async def run(self):
|
|
||||||
await websockets.serve(self.listener,
|
|
||||||
host=self.config.address,
|
|
||||||
port=self.config.port,
|
|
||||||
loop=self.loop)
|
|
||||||
|
|
||||||
def run_blocking(self, logging_cfg: Dict[str, Any]):
|
|
||||||
ru.init_logging(logging_cfg)
|
|
||||||
if self.loop is None:
|
|
||||||
self.loop = aio.get_event_loop()
|
|
||||||
self.serve()
|
|
|
@ -1,31 +1,8 @@
|
||||||
# ROYALNET CONFIGURATION FILE
|
# ROYALNET CONFIGURATION FILE
|
||||||
|
|
||||||
[Herald]
|
[Baron]
|
||||||
# Enable the herald module, allowing different parts of Royalnet to talk to each other
|
host = "combo.steffo.eu"
|
||||||
# Requires the `herald` extra to be installed
|
port =
|
||||||
enabled = true
|
|
||||||
# Herald can run locally or connect to a remote instance
|
|
||||||
# "local" = run a local server
|
|
||||||
# "remote" = connect to a remote
|
|
||||||
mode = "local"
|
|
||||||
# The address of the network interface on which the Herald server should listen for connections
|
|
||||||
# If 0.0.0.0, listen for connections on all interfaces
|
|
||||||
# If 127.0.0.1, listen only for connections coming from the local machine
|
|
||||||
# OR
|
|
||||||
# The address of the remote Herald server
|
|
||||||
address = "127.0.0.1"
|
|
||||||
# The port on which the Herald server should run
|
|
||||||
# OR
|
|
||||||
# The port of the remote Herald server
|
|
||||||
port = 44444
|
|
||||||
# A password required to connect to the local Herald server
|
|
||||||
# OR
|
|
||||||
# The password required to connect to the remote Herald server
|
|
||||||
secret = "p4ssw0rd"
|
|
||||||
# Use HTTPS instead of HTTP for Herald connections
|
|
||||||
secure = false # Not supported yet!
|
|
||||||
# Use a different HTTP path for Herald connections
|
|
||||||
path = "/" # Different values aren't supported yet
|
|
||||||
|
|
||||||
|
|
||||||
[Alchemy]
|
[Alchemy]
|
||||||
|
@ -106,10 +83,5 @@ active = [
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# Configuration settings for specific packs
|
# Add packs config here!
|
||||||
[Packs."royalnet.backpack"]
|
|
||||||
# Enable exception debug commands and stars
|
|
||||||
exc_debug = false
|
|
||||||
|
|
||||||
# Add your packs config here!
|
|
||||||
# [Packs."yourpack"]
|
# [Packs."yourpack"]
|
||||||
|
|
Loading…
Reference in a new issue