diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 8177a91..01e25c1 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,4 +1,4 @@
-image: python:3.9-alpine
+image: python:3.10-alpine
variables:
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
diff --git a/LICENSE b/LICENSE
index f1d5400..8bd7101 100644
--- a/LICENSE
+++ b/LICENSE
@@ -632,7 +632,7 @@ state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Litecord
- Copyright (C) 2018 Luna Mendes
+ Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -651,7 +651,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
- litecord Copyright (C) 2018 Luna Mendes
+ litecord Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
diff --git a/README.md b/README.md
index f3296f7..cbdf65e 100644
--- a/README.md
+++ b/README.md
@@ -53,7 +53,7 @@ are not implemented, for example:
- Threads
- Channel Categories
-- API v9 (Right now, Litecord, in generla, assumes v9 is
+- API v9 (Right now, Litecord, in general, assumes v9 is
just v6 to make clients work, new payload structure support is
scattered throughout the codebase)
diff --git a/__init__.py b/__init__.py
index 62dfb89..3878d03 100644
--- a/__init__.py
+++ b/__init__.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -16,4 +16,3 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-
diff --git a/config.ci.py b/config.ci.py
index 911085a..83290d3 100644
--- a/config.ci.py
+++ b/config.ci.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/config.example.py b/config.example.py
index 999add7..56d701b 100644
--- a/config.example.py
+++ b/config.example.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -48,6 +48,11 @@ class Config:
# e.g 'gateway.example.com' for reverse proxies.
WEBSOCKET_URL = "localhost:5001"
+ # Set these to file paths if you want to enable raw TLS support on
+ # the websocket (without NGINX)
+ WEBSOCKET_TLS_CERT_PATH = None
+ WEBSOCKET_TLS_KEY_PATH = None
+
#: Where to host the websocket?
# (a local address the server will bind to)
WS_HOST = "0.0.0.0"
@@ -60,6 +65,9 @@ class Config:
#: Postgres credentials
POSTGRES = {}
+
+ #: Shared secret for LVSP
+ LVSP_SECRET = ""
class Development(Config):
diff --git a/docs/lvsp.md b/docs/lvsp.md
index bbd31ba..2913769 100644
--- a/docs/lvsp.md
+++ b/docs/lvsp.md
@@ -8,7 +8,9 @@ LVSP runs over a *long-lived* websocket with TLS. The encoding is JSON.
## OP code table
-"client" is litecord. "server" is the voice server.
+"client" is litecord. "server" is the voice server.
+
+note: only the opcode is sent in a message, so the names are determined by the implementation of LVSP.
| opcode | name | sent by |
| --: | :-- | :-- |
@@ -119,15 +121,17 @@ are laid on.
### InfoType Enum
+note: this enum is only ever identified by its opcode, so the `name` field can differ from the values in this enum without error.
+
| value | name | description |
| --: | :-- | :-- |
| 0 | CHANNEL\_REQ | channel assignment request |
| 1 | CHANNEL\_ASSIGN | channel assignment reply |
| 2 | CHANNEL\_DESTROY | channel destroy |
-| 3 | VST\_CREATE | voice state create request |
-| 4 | VST\_DONE | voice state created |
-| 5 | VST\_UPDATE | voice state update |
-| 6 | VST\_LEAVE | voice state leave |
+| 3 | VOICE\_STATE\_CREATE | voice state create request |
+| 4 | VOICE\_STATE\_DONE | voice state created |
+| 5 | VOICE\_STATE\_DESTROY | voice state destroy |
+| 6 | VOICE\_STATE\_UPDATE | voice state update |
### CHANNEL\_REQ
@@ -158,7 +162,7 @@ a channel being deleted, or all members in it leaving.
Same data as CHANNEL\_ASSIGN, but without `token`.
-### VST\_CREATE
+### VOICE\_STATE\_CREATE
Sent by the client to create a voice state.
@@ -168,21 +172,25 @@ Sent by the client to create a voice state.
| channel\_id | snowflake | channel id |
| guild\_id | Optional[snowflake] | guild id. not provided if dm / group dm |
-### VST\_DONE
+### VOICE\_STATE\_DONE
-Sent by the server to indicate the success of a VST\_CREATE.
+Sent by the server to indicate the success of a VOICE\_STATE\_CREATE.
-Has the same fields as VST\_CREATE, but with extras:
+Has the same fields as VOICE\_STATE\_CREATE, but with extras:
| field | type | description |
| --: | :-- | :-- |
| session\_id | string | session id for the voice state |
-### VST\_DESTROY
+### VOICE\_STATE\_DESTROY
Sent by the client when a user is leaving a channel OR moving between channels
in a guild. More on state transitions later on.
+### VOICE\_STATE\_UPDATE
+
+Sent to update an existing voice state. Potentially unused.
+
| field | type | description |
| --: | :-- | :-- |
| session\_id | string | session id for the voice state |
@@ -195,11 +203,11 @@ Since the channel is unitialized, both logic on initialization AND
user join is here.
- Client will send a CHANNEL\_REQ.
- - Client MAY send a VST\_CREATE right after as well.
+ - Client MAY send a VOICE\_STATE\_CREATE right after as well.
- The Server MUST process CHANNEL\_REQ first, so the Server can keep
a lock on channel operations while it is initialized.
- Reply with CHANNEL\_ASSIGN once initialization is done.
- - Process VST\_CREATE
+ - Process VOICE\_STATE\_CREATE
### Updating a voice channel
@@ -214,15 +222,15 @@ user join is here.
### User joining an (initialized) voice channel
- - Client sends VST\_CREATE
- - Server sends VST\_DONE
+ - Client sends VOICE\_STATE\_CREATE
+ - Server sends VOICE\_STATE\_DONE
### User leaves a channel
- - Client sends VST\_DESTROY with the old fields
+ - Client sends VOICE\_STATE\_DESTROY with the old fields
### User moves a channel
- - Client sends VST\_DESTROY with the old fields
- - Client sends VST\_CREATE with the new fields
- - Server sends VST\_DONE
+ - Client sends VOICE\_STATE\_DESTROY with the old fields
+ - Client sends VOICE\_STATE\_CREATE with the new fields
+ - Server sends VOICE\_STATE\_DONE
diff --git a/litecord/__init__.py b/litecord/__init__.py
index d21f555..3878d03 100644
--- a/litecord/__init__.py
+++ b/litecord/__init__.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/admin_schemas.py b/litecord/admin_schemas.py
index 900f734..39cc244 100644
--- a/litecord/admin_schemas.py
+++ b/litecord/admin_schemas.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/auth.py b/litecord/auth.py
index 849a45a..841c49d 100644
--- a/litecord/auth.py
+++ b/litecord/auth.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/__init__.py b/litecord/blueprints/__init__.py
index e02db5b..0d8ad80 100644
--- a/litecord/blueprints/__init__.py
+++ b/litecord/blueprints/__init__.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/admin_api/__init__.py b/litecord/blueprints/admin_api/__init__.py
index ab0e1e8..633221b 100644
--- a/litecord/blueprints/admin_api/__init__.py
+++ b/litecord/blueprints/admin_api/__init__.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/admin_api/features.py b/litecord/blueprints/admin_api/features.py
index 2d9d655..6e4aeb6 100644
--- a/litecord/blueprints/admin_api/features.py
+++ b/litecord/blueprints/admin_api/features.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/admin_api/guilds.py b/litecord/blueprints/admin_api/guilds.py
index 153bdff..e1d98d3 100644
--- a/litecord/blueprints/admin_api/guilds.py
+++ b/litecord/blueprints/admin_api/guilds.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/admin_api/instance_invites.py b/litecord/blueprints/admin_api/instance_invites.py
index 2a9540d..d053dc9 100644
--- a/litecord/blueprints/admin_api/instance_invites.py
+++ b/litecord/blueprints/admin_api/instance_invites.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/admin_api/users.py b/litecord/blueprints/admin_api/users.py
index d18cb76..4c04fc7 100644
--- a/litecord/blueprints/admin_api/users.py
+++ b/litecord/blueprints/admin_api/users.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/admin_api/voice.py b/litecord/blueprints/admin_api/voice.py
index 6326003..83a33ba 100644
--- a/litecord/blueprints/admin_api/voice.py
+++ b/litecord/blueprints/admin_api/voice.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/applications.py b/litecord/blueprints/applications.py
index 5b789c2..67b39a7 100644
--- a/litecord/blueprints/applications.py
+++ b/litecord/blueprints/applications.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/attachments.py b/litecord/blueprints/attachments.py
index 49da21a..9c60082 100644
--- a/litecord/blueprints/attachments.py
+++ b/litecord/blueprints/attachments.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/auth.py b/litecord/blueprints/auth.py
index dda3e4f..c801bde 100644
--- a/litecord/blueprints/auth.py
+++ b/litecord/blueprints/auth.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/channel/__init__.py b/litecord/blueprints/channel/__init__.py
index fc08dd2..081f072 100644
--- a/litecord/blueprints/channel/__init__.py
+++ b/litecord/blueprints/channel/__init__.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/channel/messages.py b/litecord/blueprints/channel/messages.py
index 98f7e3b..c1a621b 100644
--- a/litecord/blueprints/channel/messages.py
+++ b/litecord/blueprints/channel/messages.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -29,7 +29,8 @@ from litecord.errors import MessageNotFound, Forbidden
from litecord.enums import MessageType, ChannelType, GUILD_CHANS
from litecord.schemas import validate, MESSAGE_CREATE
-from litecord.utils import pg_set_json, query_tuple_from_args, extract_limit
+from litecord.utils import query_tuple_from_args, extract_limit
+from litecord.json import pg_set_json
from litecord.permissions import get_permissions
from litecord.embed.sanitizer import fill_embed
diff --git a/litecord/blueprints/channel/pins.py b/litecord/blueprints/channel/pins.py
index 477d543..56db54e 100644
--- a/litecord/blueprints/channel/pins.py
+++ b/litecord/blueprints/channel/pins.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/channel/reactions.py b/litecord/blueprints/channel/reactions.py
index 3fa18a6..b42c47f 100644
--- a/litecord/blueprints/channel/reactions.py
+++ b/litecord/blueprints/channel/reactions.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/channels.py b/litecord/blueprints/channels.py
index d1caf94..21dcb55 100644
--- a/litecord/blueprints/channels.py
+++ b/litecord/blueprints/channels.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/checks.py b/litecord/blueprints/checks.py
index aa126b8..ddd345d 100644
--- a/litecord/blueprints/checks.py
+++ b/litecord/blueprints/checks.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/dm_channels.py b/litecord/blueprints/dm_channels.py
index 041c288..a126928 100644
--- a/litecord/blueprints/dm_channels.py
+++ b/litecord/blueprints/dm_channels.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/dms.py b/litecord/blueprints/dms.py
index 5c7ad31..de0d10d 100644
--- a/litecord/blueprints/dms.py
+++ b/litecord/blueprints/dms.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/gateway.py b/litecord/blueprints/gateway.py
index 5a4601b..e6e0d2f 100644
--- a/litecord/blueprints/gateway.py
+++ b/litecord/blueprints/gateway.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/guild/__init__.py b/litecord/blueprints/guild/__init__.py
index 31c2640..37be2f8 100644
--- a/litecord/blueprints/guild/__init__.py
+++ b/litecord/blueprints/guild/__init__.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/guild/channels.py b/litecord/blueprints/guild/channels.py
index 56a1d21..6cce8d0 100644
--- a/litecord/blueprints/guild/channels.py
+++ b/litecord/blueprints/guild/channels.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/guild/emoji.py b/litecord/blueprints/guild/emoji.py
index 1716af2..aa8d7e5 100644
--- a/litecord/blueprints/guild/emoji.py
+++ b/litecord/blueprints/guild/emoji.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/guild/members.py b/litecord/blueprints/guild/members.py
index 0f77dc8..e6aae5c 100644
--- a/litecord/blueprints/guild/members.py
+++ b/litecord/blueprints/guild/members.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/guild/mod.py b/litecord/blueprints/guild/mod.py
index 8084e72..913c3cc 100644
--- a/litecord/blueprints/guild/mod.py
+++ b/litecord/blueprints/guild/mod.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/guild/roles.py b/litecord/blueprints/guild/roles.py
index 265ccf8..dc7a122 100644
--- a/litecord/blueprints/guild/roles.py
+++ b/litecord/blueprints/guild/roles.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/guilds.py b/litecord/blueprints/guilds.py
index 4ada15f..0e064cd 100644
--- a/litecord/blueprints/guilds.py
+++ b/litecord/blueprints/guilds.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/icons.py b/litecord/blueprints/icons.py
index fc6eec3..2d455d9 100644
--- a/litecord/blueprints/icons.py
+++ b/litecord/blueprints/icons.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/invites.py b/litecord/blueprints/invites.py
index c31820a..c53b739 100644
--- a/litecord/blueprints/invites.py
+++ b/litecord/blueprints/invites.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/nodeinfo.py b/litecord/blueprints/nodeinfo.py
index 7afefb2..a15e84b 100644
--- a/litecord/blueprints/nodeinfo.py
+++ b/litecord/blueprints/nodeinfo.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/read_states.py b/litecord/blueprints/read_states.py
index 04053b5..827698a 100644
--- a/litecord/blueprints/read_states.py
+++ b/litecord/blueprints/read_states.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/relationships.py b/litecord/blueprints/relationships.py
index 7e88af2..50b7310 100644
--- a/litecord/blueprints/relationships.py
+++ b/litecord/blueprints/relationships.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/science.py b/litecord/blueprints/science.py
index 7a5273c..ba995b0 100644
--- a/litecord/blueprints/science.py
+++ b/litecord/blueprints/science.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/static.py b/litecord/blueprints/static.py
index 61f2148..c3416f4 100644
--- a/litecord/blueprints/static.py
+++ b/litecord/blueprints/static.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,7 +17,7 @@ along with this program. If not, see .
"""
-from quart import Blueprint, current_app as app, render_template_string
+from quart import Blueprint, current_app as app, render_template_string, send_file
from pathlib import Path
bp = Blueprint("static", __name__)
@@ -30,7 +30,10 @@ async def static_pages(path):
return "no", 404
static_path = Path.cwd() / Path("static") / path
- return await app.send_static_file(str(static_path))
+ if static_path.exists():
+ return await send_file(static_path)
+ else:
+ return "not found", 404
@bp.route("/")
diff --git a/litecord/blueprints/stickers.py b/litecord/blueprints/stickers.py
index afd8297..824f74a 100644
--- a/litecord/blueprints/stickers.py
+++ b/litecord/blueprints/stickers.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/store.py b/litecord/blueprints/store.py
index 27a22a7..46efc4a 100644
--- a/litecord/blueprints/store.py
+++ b/litecord/blueprints/store.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/user/__init__.py b/litecord/blueprints/user/__init__.py
index bd27fa4..a383443 100644
--- a/litecord/blueprints/user/__init__.py
+++ b/litecord/blueprints/user/__init__.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/user/billing.py b/litecord/blueprints/user/billing.py
index 30e27e3..8d159fa 100644
--- a/litecord/blueprints/user/billing.py
+++ b/litecord/blueprints/user/billing.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/user/billing_job.py b/litecord/blueprints/user/billing_job.py
index 0824f82..3676ef7 100644
--- a/litecord/blueprints/user/billing_job.py
+++ b/litecord/blueprints/user/billing_job.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/user/fake_store.py b/litecord/blueprints/user/fake_store.py
index 7f4fc3c..eaeef0e 100644
--- a/litecord/blueprints/user/fake_store.py
+++ b/litecord/blueprints/user/fake_store.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/user/settings.py b/litecord/blueprints/user/settings.py
index ae05b59..cc8c018 100644
--- a/litecord/blueprints/user/settings.py
+++ b/litecord/blueprints/user/settings.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/users.py b/litecord/blueprints/users.py
index af4e028..f50e583 100644
--- a/litecord/blueprints/users.py
+++ b/litecord/blueprints/users.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/voice.py b/litecord/blueprints/voice.py
index dd3cad5..cde0db8 100644
--- a/litecord/blueprints/voice.py
+++ b/litecord/blueprints/voice.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/blueprints/webhooks.py b/litecord/blueprints/webhooks.py
index fb5e7b7..cc5d4ab 100644
--- a/litecord/blueprints/webhooks.py
+++ b/litecord/blueprints/webhooks.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -52,7 +52,7 @@ from litecord.common.messages import (
from litecord.embed.sanitizer import fill_embed, fetch_mediaproxy_img
from litecord.embed.messages import process_url_embed, is_media_url
from litecord.embed.schemas import EmbedURL
-from litecord.utils import pg_set_json
+from litecord.json import pg_set_json
from litecord.enums import MessageType
from litecord.images import STATIC_IMAGE_MIMES
diff --git a/litecord/common/channels.py b/litecord/common/channels.py
index 08ff7f0..7245e20 100644
--- a/litecord/common/channels.py
+++ b/litecord/common/channels.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/common/guilds.py b/litecord/common/guilds.py
index 44ec3f4..476d9a1 100644
--- a/litecord/common/guilds.py
+++ b/litecord/common/guilds.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/common/users.py b/litecord/common/users.py
index 550218b..04428cc 100644
--- a/litecord/common/users.py
+++ b/litecord/common/users.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/dispatcher.py b/litecord/dispatcher.py
index 21e3dfe..67c27d5 100644
--- a/litecord/dispatcher.py
+++ b/litecord/dispatcher.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/embed/__init__.py b/litecord/embed/__init__.py
index c813d99..35a696e 100644
--- a/litecord/embed/__init__.py
+++ b/litecord/embed/__init__.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/embed/messages.py b/litecord/embed/messages.py
index 69b1576..72be730 100644
--- a/litecord/embed/messages.py
+++ b/litecord/embed/messages.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/embed/sanitizer.py b/litecord/embed/sanitizer.py
index 992522b..79416d9 100644
--- a/litecord/embed/sanitizer.py
+++ b/litecord/embed/sanitizer.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/embed/schemas.py b/litecord/embed/schemas.py
index 7df073c..b3521c2 100644
--- a/litecord/embed/schemas.py
+++ b/litecord/embed/schemas.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/enums.py b/litecord/enums.py
index 284204c..235b865 100644
--- a/litecord/enums.py
+++ b/litecord/enums.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -189,6 +189,8 @@ class StatusType(EasyEnum):
IDLE = "idle"
INVISIBLE = "invisible"
OFFLINE = "offline"
+ STREAMING = "streaming"
+ UNKNOWN = "unknown"
class ExplicitFilter(EasyEnum):
diff --git a/litecord/errors.py b/litecord/errors.py
index 89463be..23ffea4 100644
--- a/litecord/errors.py
+++ b/litecord/errors.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/gateway/encoding.py b/litecord/gateway/encoding.py
index 788d2b7..dc187b3 100644
--- a/litecord/gateway/encoding.py
+++ b/litecord/gateway/encoding.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,7 +20,7 @@ along with this program. If not, see .
import json
import earl
-from litecord.utils import LitecordJSONEncoder
+from litecord.json import LitecordJSONEncoder
def encode_json(payload) -> str:
diff --git a/litecord/gateway/errors.py b/litecord/gateway/errors.py
index 569bc88..0b89dc2 100644
--- a/litecord/gateway/errors.py
+++ b/litecord/gateway/errors.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/gateway/gateway.py b/litecord/gateway/gateway.py
index c7f0cf1..50c231a 100644
--- a/litecord/gateway/gateway.py
+++ b/litecord/gateway/gateway.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/gateway/opcodes.py b/litecord/gateway/opcodes.py
index 626d109..67c7463 100644
--- a/litecord/gateway/opcodes.py
+++ b/litecord/gateway/opcodes.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/gateway/schemas.py b/litecord/gateway/schemas.py
index 8335a37..af8d469 100644
--- a/litecord/gateway/schemas.py
+++ b/litecord/gateway/schemas.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -120,8 +120,12 @@ IDENTIFY_SCHEMA = {
"type": "number",
"required": False,
},
+ "user_settings_version": {"type": "number", "required": False},
},
},
+ "guild_subscriptions": {"type": "boolean", "required": False},
+ # this is just to make bot libraries happy
+ "v": {"type": "number", "required": False},
},
}
},
diff --git a/litecord/gateway/state.py b/litecord/gateway/state.py
index 3d97788..840af3e 100644
--- a/litecord/gateway/state.py
+++ b/litecord/gateway/state.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/gateway/state_manager.py b/litecord/gateway/state_manager.py
index bbfdc2c..c1b88bf 100644
--- a/litecord/gateway/state_manager.py
+++ b/litecord/gateway/state_manager.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/gateway/utils.py b/litecord/gateway/utils.py
index 8f158b3..81da248 100644
--- a/litecord/gateway/utils.py
+++ b/litecord/gateway/utils.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/gateway/websocket.py b/litecord/gateway/websocket.py
index c535c1a..3f12d06 100644
--- a/litecord/gateway/websocket.py
+++ b/litecord/gateway/websocket.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -91,7 +91,8 @@ def _complete_users_list(user_id: str, base_ready, user_ready, ws_properties) ->
for recipient in private_channel["recipients"]:
users_to_send[recipient["id"]] = recipient
- for relationship in user_ready["relationships"]:
+ user_relationships = user_ready.get("relationships", [])
+ for relationship in user_relationships:
relationship_user = relationship["user"]
users_to_send[relationship_user["id"]] = relationship_user
@@ -101,7 +102,7 @@ def _complete_users_list(user_id: str, base_ready, user_ready, ws_properties) ->
# relationship object structure changed in v9
if ws_properties.version == 9:
ready["relationships"] = []
- for relationship in user_ready["relationships"]:
+ for relationship in user_relationships:
ready["relationships"].append(
{
"user_id": relationship["user"]["id"],
@@ -138,7 +139,9 @@ async def _compute_supplemental(app, base_ready, user_ready, users_to_send: dict
"guilds": [],
}
- for relationship in user_ready["relationships"]:
+ user_relationships = user_ready.get("relationships", [])
+
+ for relationship in user_relationships:
if relationship["type"] != RelationshipType.FRIEND.value:
continue
@@ -265,16 +268,13 @@ class GatewayWebsocket:
"""Split data in chunk_size-big chunks and send them
over the websocket."""
log.debug(
- "zlib-stream: chunking {} bytes into {}-byte chunks", len(data), chunk_size
+ "zlib-stream: sending {} bytes into {}-byte chunks", len(data), chunk_size
)
- total_chunks = 0
- for chunk in yield_chunks(data, chunk_size):
- total_chunks += 1
- log.debug("zlib-stream: chunk {}", total_chunks)
- await self.ws.send(chunk)
-
- log.debug("zlib-stream: sent {} chunks", total_chunks)
+ # we send the entire iterator as per websockets documentation
+ # to pretent setting FIN when we don't want to
+ # see https://gitlab.com/litecord/litecord/-/issues/139
+ await self.ws.send(yield_chunks(data, chunk_size))
async def _zlib_stream_send(self, encoded):
"""Sending a single payload across multiple compressed
@@ -283,39 +283,19 @@ class GatewayWebsocket:
# compress and flush (for the rest of compressed data + ZLIB_SUFFIX)
data1 = self.ws_properties.zctx.compress(encoded)
data2 = self.ws_properties.zctx.flush(zlib.Z_FULL_FLUSH)
+ data = data1 + data2
log.debug(
- "zlib-stream: length {} -> compressed ({} + {})",
+ "zlib-stream: length {} -> compressed ({})",
len(encoded),
- len(data1),
- len(data2),
+ len(data),
)
- if not data1:
- # if data1 is nothing, that might cause problems
- # to clients, since they'll receive an empty message
- data1 = bytes([data2[0]])
- data2 = data2[1:]
-
- log.debug(
- "zlib-stream: len(data1) == 0, remaking as ({} + {})",
- len(data1),
- len(data2),
- )
-
- # NOTE: the old approach was ws.send(data1 + data2).
- # I changed this to a chunked send of data1 and data2
- # because that can bring some problems to the network
- # since we can be potentially sending a really big packet
- # as a single message.
-
- # clients should handle chunked sends (via detection
- # of the ZLIB_SUFFIX suffix appended to data2), so
- # this shouldn't being problems.
+ # since we always chunk the entire compressed message, we shouldn't
+ # worry about sending big frames to the clients
# TODO: the chunks are 1024 bytes, 1KB, is this good enough?
- await self._chunked_send(data1, 1024)
- await self._chunked_send(data2, 1024)
+ await self._chunked_send(data, 1024)
async def _zstd_stream_send(self, encoded):
compressor = self.ws_properties.zsctx.stream_writer(
@@ -730,7 +710,7 @@ class GatewayWebsocket:
presence.game = game
- if presence.status == "invisible":
+ if presence.status in ("invisible", "unknown"):
presence.status = "offline"
self.state.presence = presence
@@ -915,6 +895,9 @@ class GatewayWebsocket:
# they CAN NOT enter two channels in a single guild.
# this state id format takes care of that.
+ #
+ # TODO voice_key should have a type as a 0th element to prevent
+ # code from having to call get_guild(id2).
voice_key = (self.state.user_id, state_id2)
voice_state = await self.app.voice.get_state(voice_key)
@@ -932,6 +915,10 @@ class GatewayWebsocket:
if same_guild and not same_channel:
return await self.app.voice.move_state(voice_state, channel_id)
+ # TODO: this is an edge case. we're trying to move guilds in
+ # a single message, perhaps?
+ log.warning("vsu payload does not appear logical")
+
async def _handle_5(self, payload: Dict[str, Any]):
"""Handle OP 5 Voice Server Ping.
diff --git a/litecord/guild_memory_store.py b/litecord/guild_memory_store.py
index 223891c..b2541d0 100644
--- a/litecord/guild_memory_store.py
+++ b/litecord/guild_memory_store.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/images.py b/litecord/images.py
index d13f997..e14ab2d 100644
--- a/litecord/images.py
+++ b/litecord/images.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/jobs.py b/litecord/jobs.py
index 44342e1..46e3ad1 100644
--- a/litecord/jobs.py
+++ b/litecord/jobs.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/json.py b/litecord/json.py
new file mode 100644
index 0000000..e6fccbf
--- /dev/null
+++ b/litecord/json.py
@@ -0,0 +1,69 @@
+"""
+
+Litecord
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 3 of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+
+"""
+
+import json
+from typing import Any
+from decimal import Decimal
+from uuid import UUID
+from dataclasses import asdict, is_dataclass
+
+import quart.json.provider
+
+
+class LitecordJSONEncoder(json.JSONEncoder):
+ """Custom JSON encoder for Litecord. Useful for json.dumps"""
+
+ def default(self, value: Any):
+ if isinstance(value, (Decimal, UUID)):
+ return str(value)
+
+ if is_dataclass(value):
+ return asdict(value)
+
+ if hasattr(value, "to_json"):
+ return value.to_json
+
+ return super().default(self, value)
+
+
+class LitecordJSONProvider(quart.json.provider.DefaultJSONProvider):
+ """Custom JSON provider for Quart."""
+
+ def __init__(self, *args, **kwargs):
+ self.encoder = LitecordJSONEncoder(**kwargs)
+
+ def default(self, value: Any):
+ self.encoder.default(value)
+
+
+async def pg_set_json(con):
+ """Set JSON and JSONB codecs for an asyncpg connection."""
+ await con.set_type_codec(
+ "json",
+ encoder=lambda v: json.dumps(v, cls=LitecordJSONEncoder),
+ decoder=json.loads,
+ schema="pg_catalog",
+ )
+
+ await con.set_type_codec(
+ "jsonb",
+ encoder=lambda v: json.dumps(v, cls=LitecordJSONEncoder),
+ decoder=json.loads,
+ schema="pg_catalog",
+ )
diff --git a/litecord/permissions.py b/litecord/permissions.py
index 654e2be..3825fe3 100644
--- a/litecord/permissions.py
+++ b/litecord/permissions.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/presence.py b/litecord/presence.py
index 32600ae..398bbe0 100644
--- a/litecord/presence.py
+++ b/litecord/presence.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/pubsub/__init__.py b/litecord/pubsub/__init__.py
index a038822..b4e20f3 100644
--- a/litecord/pubsub/__init__.py
+++ b/litecord/pubsub/__init__.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/pubsub/channel.py b/litecord/pubsub/channel.py
index 4cdb9b2..67826d0 100644
--- a/litecord/pubsub/channel.py
+++ b/litecord/pubsub/channel.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/pubsub/dispatcher.py b/litecord/pubsub/dispatcher.py
index 50e3ead..b617dc0 100644
--- a/litecord/pubsub/dispatcher.py
+++ b/litecord/pubsub/dispatcher.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/pubsub/friend.py b/litecord/pubsub/friend.py
index c129ed3..aa9ba3d 100644
--- a/litecord/pubsub/friend.py
+++ b/litecord/pubsub/friend.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/pubsub/guild.py b/litecord/pubsub/guild.py
index 32a3e6d..ab9194a 100644
--- a/litecord/pubsub/guild.py
+++ b/litecord/pubsub/guild.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/pubsub/lazy_guild.py b/litecord/pubsub/lazy_guild.py
index 9b9dd0c..69f57a6 100644
--- a/litecord/pubsub/lazy_guild.py
+++ b/litecord/pubsub/lazy_guild.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/pubsub/member.py b/litecord/pubsub/member.py
index d026ef9..c7679da 100644
--- a/litecord/pubsub/member.py
+++ b/litecord/pubsub/member.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/pubsub/user.py b/litecord/pubsub/user.py
index 178d6b8..d3b4220 100644
--- a/litecord/pubsub/user.py
+++ b/litecord/pubsub/user.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/pubsub/utils.py b/litecord/pubsub/utils.py
index bb1981b..614553d 100644
--- a/litecord/pubsub/utils.py
+++ b/litecord/pubsub/utils.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/ratelimits/bucket.py b/litecord/ratelimits/bucket.py
index c79bca2..817ab24 100644
--- a/litecord/ratelimits/bucket.py
+++ b/litecord/ratelimits/bucket.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/ratelimits/handler.py b/litecord/ratelimits/handler.py
index 74b2270..708feb9 100644
--- a/litecord/ratelimits/handler.py
+++ b/litecord/ratelimits/handler.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/ratelimits/main.py b/litecord/ratelimits/main.py
index 88ec1a2..6ede010 100644
--- a/litecord/ratelimits/main.py
+++ b/litecord/ratelimits/main.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/schemas.py b/litecord/schemas.py
index 2d4fca1..eff44da 100644
--- a/litecord/schemas.py
+++ b/litecord/schemas.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -450,8 +450,8 @@ MESSAGE_CREATE = {
"required": False,
"nullable": True,
"schema": {
- "parse": {"type": "list", "required": True},
- "replied_user": {"type": "boolean", "required": True},
+ "parse": {"type": "list", "required": False},
+ "replied_user": {"type": "boolean", "required": False},
},
},
}
diff --git a/litecord/snowflake.py b/litecord/snowflake.py
index 24a83c8..dbf47b1 100644
--- a/litecord/snowflake.py
+++ b/litecord/snowflake.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/storage.py b/litecord/storage.py
index eca2481..3f9b77d 100644
--- a/litecord/storage.py
+++ b/litecord/storage.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -33,7 +33,7 @@ from litecord.blueprints.channel.reactions import (
from litecord.blueprints.user.billing import PLAN_ID_TO_TYPE
from litecord.types import timestamp_
-from litecord.utils import pg_set_json
+from litecord.json import pg_set_json
log = Logger(__name__)
diff --git a/litecord/system_messages.py b/litecord/system_messages.py
index b32168d..e1f18e0 100644
--- a/litecord/system_messages.py
+++ b/litecord/system_messages.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/types.py b/litecord/types.py
index da8b157..81ac165 100644
--- a/litecord/types.py
+++ b/litecord/types.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/user_storage.py b/litecord/user_storage.py
index 02979fd..1dadd8a 100644
--- a/litecord/user_storage.py
+++ b/litecord/user_storage.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/utils.py b/litecord/utils.py
index 355bebf..f153d85 100644
--- a/litecord/utils.py
+++ b/litecord/utils.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -18,14 +18,12 @@ along with this program. If not, see .
"""
import asyncio
-import json
import secrets
import datetime
import re
from typing import Any, Iterable, Optional, Sequence, List, Dict, Union
from logbook import Logger
-from quart.json import JSONEncoder
from quart import current_app as app
from litecord.common.messages import message_view
@@ -156,35 +154,6 @@ def mmh3(inp_str: str, seed: int = 0):
return _u(h1) >> 0
-class LitecordJSONEncoder(JSONEncoder):
- """Custom JSON encoder for Litecord."""
-
- def default(self, value: Any):
- """By default, this will try to get the to_json attribute of a given
- value being JSON encoded."""
- try:
- return value.to_json
- except AttributeError:
- return super().default(value)
-
-
-async def pg_set_json(con):
- """Set JSON and JSONB codecs for an asyncpg connection."""
- await con.set_type_codec(
- "json",
- encoder=lambda v: json.dumps(v, cls=LitecordJSONEncoder),
- decoder=json.loads,
- schema="pg_catalog",
- )
-
- await con.set_type_codec(
- "jsonb",
- encoder=lambda v: json.dumps(v, cls=LitecordJSONEncoder),
- decoder=json.loads,
- schema="pg_catalog",
- )
-
-
def yield_chunks(input_list: Sequence[Any], chunk_size: int):
"""Yield successive n-sized chunks from l.
diff --git a/litecord/voice/lvsp_conn.py b/litecord/voice/lvsp_conn.py
index 30a39da..73be635 100644
--- a/litecord/voice/lvsp_conn.py
+++ b/litecord/voice/lvsp_conn.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -24,6 +24,9 @@ from typing import Dict
import websockets
from logbook import Logger
+import hmac
+import hashlib
+
from litecord.voice.lvsp_opcodes import OPCodes as OP, InfoTable, InfoReverse
log = Logger(__name__)
@@ -59,7 +62,7 @@ class LVSPConnection:
"""Receive a payload."""
assert self.conn is not None
msg = await self.conn.recv()
- msg = json.dumps(msg)
+ msg = json.loads(msg)
return msg
async def send_op(self, opcode: int, data: dict):
@@ -100,10 +103,15 @@ class LVSPConnection:
"""Handle HELLO message."""
data = msg["d"]
- # nonce = data['nonce']
self._hb_interval = data["heartbeat_interval"]
- # TODO: send identify
+ token = hmac.new(
+ self.app.config.get("LVSP_SECRET").encode(),
+ data["nonce"].encode(),
+ hashlib.sha256,
+ ).hexdigest()
+
+ await self.send_op(OP.identify, {"token": token})
async def _update_health(self, new_health: float):
"""Update the health value of a given voice server."""
@@ -112,7 +120,7 @@ class LVSPConnection:
await self.app.db.execute(
"""
UPDATE voice_servers
- SET health = $1
+ SET last_health = $1
WHERE hostname = $2
""",
new_health,
@@ -124,13 +132,17 @@ class LVSPConnection:
We only start heartbeating after READY.
"""
- await self._update_health(msg["health"])
+ data = msg["d"]
+
+ await self._update_health(data["health"])
self._start_hb()
async def _handle_5(self, msg):
"""Handle HEARTBEAT_ACK."""
self._stop_hb()
- await self._update_health(msg["health"])
+ data = msg["d"]
+
+ await self._update_health(data["health"])
self._start_hb()
async def _handle_6(self, msg):
diff --git a/litecord/voice/lvsp_manager.py b/litecord/voice/lvsp_manager.py
index 178ab41..f3e1265 100644
--- a/litecord/voice/lvsp_manager.py
+++ b/litecord/voice/lvsp_manager.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/voice/lvsp_opcodes.py b/litecord/voice/lvsp_opcodes.py
index b617fae..9f27cc1 100644
--- a/litecord/voice/lvsp_opcodes.py
+++ b/litecord/voice/lvsp_opcodes.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/voice/manager.py b/litecord/voice/manager.py
index 5499363..09d43bc 100644
--- a/litecord/voice/manager.py
+++ b/litecord/voice/manager.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/litecord/voice/state.py b/litecord/voice/state.py
index b3d8d31..b993be7 100644
--- a/litecord/voice/state.py
+++ b/litecord/voice/state.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/manage.py b/manage.py
index 454f304..5a2a2de 100755
--- a/manage.py
+++ b/manage.py
@@ -2,7 +2,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/manage/__init__.py b/manage/__init__.py
index d21f555..3878d03 100644
--- a/manage/__init__.py
+++ b/manage/__init__.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/manage/cmd/invites.py b/manage/cmd/invites.py
index 05b3edc..7f354b0 100644
--- a/manage/cmd/invites.py
+++ b/manage/cmd/invites.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/manage/cmd/migration/__init__.py b/manage/cmd/migration/__init__.py
index 6ceffc6..5d1db64 100644
--- a/manage/cmd/migration/__init__.py
+++ b/manage/cmd/migration/__init__.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/manage/cmd/migration/command.py b/manage/cmd/migration/command.py
index 9151d51..87ebd0b 100644
--- a/manage/cmd/migration/command.py
+++ b/manage/cmd/migration/command.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/manage/cmd/users.py b/manage/cmd/users.py
index e54ee87..87d3fdd 100644
--- a/manage/cmd/users.py
+++ b/manage/cmd/users.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -130,6 +130,23 @@ async def set_max_concurrency(ctx, args):
print(f"OK: set max_concurrency={args.max_concurrency} for {args.user_id}")
+async def addbot(ctx, args):
+ uid, _ = await create_user(args.username, args.email, args.password)
+
+ await ctx.db.execute(
+ """
+ UPDATE users
+ SET bot=True
+ WHERE id = $1
+ """,
+ uid,
+ )
+
+ args.user_id = uid
+
+ return await generate_bot_token(ctx, args)
+
+
async def set_flag(ctx, args):
"""Setting a 'staff' flag gives the user access to the Admin API.
Beware of that.
@@ -174,7 +191,8 @@ async def generate_bot_token(ctx, args):
)
if not password_hash:
- return print("cannot find a bot with specified id")
+ print("cannot find a bot with specified id")
+ return 1
print(make_token(args.user_id, password_hash))
@@ -245,6 +263,14 @@ def setup(subparser):
)
set_max_concurrency_parser.set_defaults(func=set_max_concurrency)
+ addbot_parser = subparser.add_parser("addbot", help="create a bot")
+
+ addbot_parser.add_argument("username", help="username of the bot")
+ addbot_parser.add_argument("email", help="email of the bot")
+ addbot_parser.add_argument("password", help="password of the bot")
+
+ addbot_parser.set_defaults(func=addbot)
+
setflag_parser = subparser.add_parser(
"setflag", help="set a flag for a user", description=set_flag.__doc__
)
diff --git a/manage/main.py b/manage/main.py
index 2008237..457673f 100644
--- a/manage/main.py
+++ b/manage/main.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -93,7 +93,7 @@ def main(config):
async def _ctx_wrapper(fake_app, args):
app = fake_app.make_app()
async with app.app_context():
- await args.func(fake_app, args)
+ return await args.func(fake_app, args)
try:
if len(argv) < 2:
@@ -107,8 +107,9 @@ def main(config):
init_app_managers(app, init_voice=False)
args = parser.parse_args()
- loop.run_until_complete(_ctx_wrapper(app, args))
+ return loop.run_until_complete(_ctx_wrapper(app, args))
except Exception:
log.exception("error while running command")
+ return 1
finally:
loop.run_until_complete(app.db.close())
diff --git a/poetry.lock b/poetry.lock
index dac5df5..aa343ef 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,6 +1,6 @@
[[package]]
name = "aiofiles"
-version = "0.7.0"
+version = "0.8.0"
description = "File support for asyncio."
category = "main"
optional = false
@@ -8,61 +8,73 @@ python-versions = ">=3.6,<4.0"
[[package]]
name = "aiohttp"
-version = "3.7.4.post0"
+version = "3.8.1"
description = "Async http client/server framework (asyncio)"
category = "main"
optional = false
python-versions = ">=3.6"
[package.dependencies]
-async-timeout = ">=3.0,<4.0"
+aiosignal = ">=1.1.2"
+async-timeout = ">=4.0.0a3,<5.0"
attrs = ">=17.3.0"
-chardet = ">=2.0,<5.0"
+charset-normalizer = ">=2.0,<3.0"
+frozenlist = ">=1.1.1"
multidict = ">=4.5,<7.0"
-typing-extensions = ">=3.6.5"
yarl = ">=1.0,<2.0"
[package.extras]
-speedups = ["aiodns", "brotlipy", "cchardet"]
+speedups = ["cchardet", "brotli", "aiodns"]
+
+[[package]]
+name = "aiosignal"
+version = "1.2.0"
+description = "aiosignal: a list of registered asynchronous callbacks"
+category = "main"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+frozenlist = ">=1.1.0"
[[package]]
name = "async-timeout"
-version = "3.0.1"
+version = "4.0.2"
description = "Timeout context manager for asyncio programs"
category = "main"
optional = false
-python-versions = ">=3.5.3"
+python-versions = ">=3.6"
[[package]]
name = "asyncpg"
-version = "0.24.0"
+version = "0.26.0"
description = "An asyncio PostgreSQL driver"
category = "main"
optional = false
python-versions = ">=3.6.0"
[package.extras]
-dev = ["Cython (>=0.29.24,<0.30.0)", "pytest (>=6.0)", "Sphinx (>=4.1.2,<4.2.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "pycodestyle (>=2.7.0,<2.8.0)", "flake8 (>=3.9.2,<3.10.0)", "uvloop (>=0.15.3)"]
-docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)"]
-test = ["pycodestyle (>=2.7.0,<2.8.0)", "flake8 (>=3.9.2,<3.10.0)", "uvloop (>=0.15.3)"]
+test = ["uvloop (>=0.15.3)", "flake8 (>=3.9.2,<3.10.0)", "pycodestyle (>=2.7.0,<2.8.0)"]
+docs = ["sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)", "Sphinx (>=4.1.2,<4.2.0)"]
+dev = ["uvloop (>=0.15.3)", "flake8 (>=3.9.2,<3.10.0)", "pycodestyle (>=2.7.0,<2.8.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)", "Sphinx (>=4.1.2,<4.2.0)", "pytest (>=6.0)", "Cython (>=0.29.24,<0.30.0)"]
[[package]]
name = "attrs"
-version = "21.2.0"
+version = "22.1.0"
description = "Classes Without Boilerplate"
category = "main"
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+python-versions = ">=3.5"
[package.extras]
-dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit"]
-docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"]
-tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface"]
-tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins"]
+tests_no_zope = ["cloudpickle", "pytest-mypy-plugins", "mypy (>=0.900,!=0.940)", "pytest (>=4.3.0)", "pympler", "hypothesis", "coverage[toml] (>=5.0.2)"]
+tests = ["cloudpickle", "zope.interface", "pytest-mypy-plugins", "mypy (>=0.900,!=0.940)", "pytest (>=4.3.0)", "pympler", "hypothesis", "coverage[toml] (>=5.0.2)"]
+docs = ["sphinx-notfound-page", "zope.interface", "sphinx", "furo"]
+dev = ["cloudpickle", "pre-commit", "sphinx-notfound-page", "sphinx", "furo", "zope.interface", "pytest-mypy-plugins", "mypy (>=0.900,!=0.940)", "pytest (>=4.3.0)", "pympler", "hypothesis", "coverage[toml] (>=5.0.2)"]
[[package]]
name = "bcrypt"
-version = "3.2.0"
+version = "3.2.2"
description = "Modern password hashing for your software and your servers"
category = "main"
optional = false
@@ -70,7 +82,6 @@ python-versions = ">=3.6"
[package.dependencies]
cffi = ">=1.1"
-six = ">=1.4.1"
[package.extras]
tests = ["pytest (>=3.2.1,!=3.3.0)"]
@@ -78,11 +89,11 @@ typecheck = ["mypy"]
[[package]]
name = "blinker"
-version = "1.4"
+version = "1.5"
description = "Fast, simple object-to-object and broadcast signaling"
category = "main"
optional = false
-python-versions = "*"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
[[package]]
name = "cerberus"
@@ -94,7 +105,7 @@ python-versions = ">=2.7"
[[package]]
name = "cffi"
-version = "1.14.6"
+version = "1.15.1"
description = "Foreign Function Interface for Python calling C code."
category = "main"
optional = false
@@ -104,27 +115,30 @@ python-versions = "*"
pycparser = "*"
[[package]]
-name = "chardet"
-version = "4.0.0"
-description = "Universal encoding detector for Python 2 and 3"
+name = "charset-normalizer"
+version = "2.1.0"
+description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
category = "main"
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+python-versions = ">=3.6.0"
+
+[package.extras]
+unicode_backport = ["unicodedata2"]
[[package]]
name = "click"
-version = "8.0.1"
+version = "8.1.3"
description = "Composable command line interface toolkit"
category = "main"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.7"
[package.dependencies]
colorama = {version = "*", markers = "platform_system == \"Windows\""}
[[package]]
name = "colorama"
-version = "0.4.4"
+version = "0.4.5"
description = "Cross-platform colored terminal text."
category = "main"
optional = false
@@ -138,9 +152,17 @@ category = "main"
optional = false
python-versions = "*"
+[[package]]
+name = "frozenlist"
+version = "1.3.1"
+description = "A list-like structure which implements collections.abc.MutableSequence"
+category = "main"
+optional = false
+python-versions = ">=3.7"
+
[[package]]
name = "h11"
-version = "0.12.0"
+version = "0.13.0"
description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
category = "main"
optional = false
@@ -148,7 +170,7 @@ python-versions = ">=3.6"
[[package]]
name = "h2"
-version = "4.0.0"
+version = "4.1.0"
description = "HTTP/2 State-Machine based protocol implementation"
category = "main"
optional = false
@@ -168,8 +190,8 @@ python-versions = ">=3.6.1"
[[package]]
name = "hypercorn"
-version = "0.11.2"
-description = "A ASGI Server based on Hyper libraries and inspired by Gunicorn."
+version = "0.13.2"
+description = "A ASGI Server based on Hyper libraries and inspired by Gunicorn"
category = "main"
optional = false
python-versions = ">=3.7"
@@ -183,7 +205,6 @@ wsproto = ">=0.14.0"
[package.extras]
h3 = ["aioquic (>=0.9.0,<1.0)"]
-tests = ["hypothesis", "mock", "pytest", "pytest-asyncio", "pytest-cov", "pytest-trio", "trio"]
trio = ["trio (>=0.11.0)"]
uvloop = ["uvloop"]
@@ -197,27 +218,43 @@ python-versions = ">=3.6.1"
[[package]]
name = "idna"
-version = "3.2"
+version = "3.3"
description = "Internationalized Domain Names in Applications (IDNA)"
category = "main"
optional = false
python-versions = ">=3.5"
[[package]]
-name = "itsdangerous"
-version = "1.1.0"
-description = "Various helpers to pass data to untrusted environments and back."
+name = "importlib-metadata"
+version = "4.12.0"
+description = "Read metadata from Python packages"
category = "main"
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+python-versions = ">=3.7"
+
+[package.dependencies]
+zipp = ">=0.5"
+
+[package.extras]
+testing = ["importlib-resources (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-black (>=0.3.7)", "pytest-perf (>=0.9.2)", "flufl.flake8", "pyfakefs", "packaging", "pytest-enabler (>=1.3)", "pytest-cov", "pytest-flake8", "pytest-checkdocs (>=2.4)", "pytest (>=6)"]
+perf = ["ipython"]
+docs = ["rst.linker (>=1.9)", "jaraco.packaging (>=9)", "sphinx"]
+
+[[package]]
+name = "itsdangerous"
+version = "2.1.2"
+description = "Safely pass data to untrusted environments and back."
+category = "main"
+optional = false
+python-versions = ">=3.7"
[[package]]
name = "jinja2"
-version = "3.0.1"
+version = "3.1.2"
description = "A very fast and expressive template engine."
category = "main"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.7"
[package.dependencies]
MarkupSafe = ">=2.0"
@@ -246,27 +283,31 @@ zmq = ["pyzmq"]
[[package]]
name = "markupsafe"
-version = "2.0.1"
+version = "2.1.1"
description = "Safely add untrusted strings to HTML/XML markup."
category = "main"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.7"
[[package]]
name = "multidict"
-version = "5.1.0"
+version = "6.0.2"
description = "multidict implementation"
category = "main"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.7"
[[package]]
name = "pillow"
-version = "8.3.2"
+version = "9.2.0"
description = "Python Imaging Library (Fork)"
category = "main"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.7"
+
+[package.extras]
+tests = ["pytest-timeout", "pytest-cov", "pytest", "pyroma", "packaging", "olefile", "markdown2", "defusedxml", "coverage", "check-manifest"]
+docs = ["sphinxext-opengraph", "sphinx-removed-in", "sphinx-issues (>=3.0.1)", "sphinx-copybutton", "sphinx (>=2.4)", "olefile", "furo"]
[[package]]
name = "priority"
@@ -278,7 +319,7 @@ python-versions = ">=3.6.1"
[[package]]
name = "pycparser"
-version = "2.20"
+version = "2.21"
description = "C parser in Python"
category = "main"
optional = false
@@ -286,32 +327,26 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
[[package]]
name = "quart"
-version = "0.15.1"
+version = "0.18.0"
description = "A Python ASGI web microframework with the same API as Flask"
category = "main"
optional = false
-python-versions = ">=3.7.0"
+python-versions = ">=3.7"
[package.dependencies]
aiofiles = "*"
blinker = "*"
click = "*"
hypercorn = ">=0.11.2"
+importlib_metadata = {version = "*", markers = "python_version < \"3.10\""}
itsdangerous = "*"
jinja2 = "*"
-toml = "*"
-werkzeug = ">=2.0.0"
+markupsafe = "*"
+werkzeug = ">=2.2.0"
[package.extras]
dotenv = ["python-dotenv"]
-
-[[package]]
-name = "six"
-version = "1.16.0"
-description = "Python 2 and 3 compatibility utilities"
-category = "main"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
+docs = ["pydata-sphinx-theme"]
[[package]]
name = "toml"
@@ -321,17 +356,9 @@ category = "main"
optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
-[[package]]
-name = "typing-extensions"
-version = "3.10.0.2"
-description = "Backported and Experimental Type Hints for Python 3.5+"
-category = "main"
-optional = false
-python-versions = "*"
-
[[package]]
name = "websockets"
-version = "10.0"
+version = "10.3"
description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)"
category = "main"
optional = false
@@ -339,11 +366,14 @@ python-versions = ">=3.7"
[[package]]
name = "werkzeug"
-version = "2.0.1"
+version = "2.2.2"
description = "The comprehensive WSGI web application library."
category = "main"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.7"
+
+[package.dependencies]
+MarkupSafe = ">=2.1.1"
[package.extras]
watchdog = ["watchdog"]
@@ -365,34 +395,46 @@ resolved_reference = "7390e1747d9c6a1d1bf571b7a2b419b09728a654"
[[package]]
name = "wsproto"
-version = "1.0.0"
+version = "1.1.0"
description = "WebSockets state-machine based protocol implementation"
category = "main"
optional = false
-python-versions = ">=3.6.1"
+python-versions = ">=3.7.0"
[package.dependencies]
h11 = ">=0.9.0,<1"
[[package]]
name = "yarl"
-version = "1.6.3"
+version = "1.8.1"
description = "Yet another URL library"
category = "main"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.7"
[package.dependencies]
idna = ">=2.0"
multidict = ">=4.0"
+[[package]]
+name = "zipp"
+version = "3.8.1"
+description = "Backport of pathlib-compatible object wrapper for zip files"
+category = "main"
+optional = false
+python-versions = ">=3.7"
+
+[package.extras]
+testing = ["pytest-mypy (>=0.9.1)", "pytest-black (>=0.3.7)", "func-timeout", "jaraco.itertools", "pytest-enabler (>=1.3)", "pytest-cov", "pytest-flake8", "pytest-checkdocs (>=2.4)", "pytest (>=6)"]
+docs = ["jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "jaraco.packaging (>=9)", "sphinx"]
+
[[package]]
name = "zstandard"
-version = "0.15.2"
+version = "0.18.0"
description = "Zstandard bindings for Python"
category = "main"
optional = false
-python-versions = ">=3.5"
+python-versions = ">=3.6"
[package.dependencies]
cffi = {version = ">=1.11", markers = "platform_python_implementation == \"PyPy\""}
@@ -403,473 +445,128 @@ cffi = ["cffi (>=1.11)"]
[metadata]
lock-version = "1.1"
python-versions = "^3.9"
-content-hash = "e07bedf6968bdb2112e351624b975a2ea8ababdad1693ad6a40e664953f77c19"
+content-hash = "2ad3557d85930df2e93df80ce9381b1bd4e055f9adcaf17b14a3e33a08978cf5"
[metadata.files]
aiofiles = [
- {file = "aiofiles-0.7.0-py3-none-any.whl", hash = "sha256:c67a6823b5f23fcab0a2595a289cec7d8c863ffcb4322fb8cd6b90400aedfdbc"},
- {file = "aiofiles-0.7.0.tar.gz", hash = "sha256:a1c4fc9b2ff81568c83e21392a82f344ea9d23da906e4f6a52662764545e19d4"},
-]
-aiohttp = [
- {file = "aiohttp-3.7.4.post0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:3cf75f7cdc2397ed4442594b935a11ed5569961333d49b7539ea741be2cc79d5"},
- {file = "aiohttp-3.7.4.post0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:4b302b45040890cea949ad092479e01ba25911a15e648429c7c5aae9650c67a8"},
- {file = "aiohttp-3.7.4.post0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:fe60131d21b31fd1a14bd43e6bb88256f69dfc3188b3a89d736d6c71ed43ec95"},
- {file = "aiohttp-3.7.4.post0-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:393f389841e8f2dfc86f774ad22f00923fdee66d238af89b70ea314c4aefd290"},
- {file = "aiohttp-3.7.4.post0-cp36-cp36m-manylinux2014_ppc64le.whl", hash = "sha256:c6e9dcb4cb338d91a73f178d866d051efe7c62a7166653a91e7d9fb18274058f"},
- {file = "aiohttp-3.7.4.post0-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:5df68496d19f849921f05f14f31bd6ef53ad4b00245da3195048c69934521809"},
- {file = "aiohttp-3.7.4.post0-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:0563c1b3826945eecd62186f3f5c7d31abb7391fedc893b7e2b26303b5a9f3fe"},
- {file = "aiohttp-3.7.4.post0-cp36-cp36m-win32.whl", hash = "sha256:3d78619672183be860b96ed96f533046ec97ca067fd46ac1f6a09cd9b7484287"},
- {file = "aiohttp-3.7.4.post0-cp36-cp36m-win_amd64.whl", hash = "sha256:f705e12750171c0ab4ef2a3c76b9a4024a62c4103e3a55dd6f99265b9bc6fcfc"},
- {file = "aiohttp-3.7.4.post0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:230a8f7e24298dea47659251abc0fd8b3c4e38a664c59d4b89cca7f6c09c9e87"},
- {file = "aiohttp-3.7.4.post0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:2e19413bf84934d651344783c9f5e22dee452e251cfd220ebadbed2d9931dbf0"},
- {file = "aiohttp-3.7.4.post0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:e4b2b334e68b18ac9817d828ba44d8fcb391f6acb398bcc5062b14b2cbeac970"},
- {file = "aiohttp-3.7.4.post0-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:d012ad7911653a906425d8473a1465caa9f8dea7fcf07b6d870397b774ea7c0f"},
- {file = "aiohttp-3.7.4.post0-cp37-cp37m-manylinux2014_ppc64le.whl", hash = "sha256:40eced07f07a9e60e825554a31f923e8d3997cfc7fb31dbc1328c70826e04cde"},
- {file = "aiohttp-3.7.4.post0-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:209b4a8ee987eccc91e2bd3ac36adee0e53a5970b8ac52c273f7f8fd4872c94c"},
- {file = "aiohttp-3.7.4.post0-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:14762875b22d0055f05d12abc7f7d61d5fd4fe4642ce1a249abdf8c700bf1fd8"},
- {file = "aiohttp-3.7.4.post0-cp37-cp37m-win32.whl", hash = "sha256:7615dab56bb07bff74bc865307aeb89a8bfd9941d2ef9d817b9436da3a0ea54f"},
- {file = "aiohttp-3.7.4.post0-cp37-cp37m-win_amd64.whl", hash = "sha256:d9e13b33afd39ddeb377eff2c1c4f00544e191e1d1dee5b6c51ddee8ea6f0cf5"},
- {file = "aiohttp-3.7.4.post0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:547da6cacac20666422d4882cfcd51298d45f7ccb60a04ec27424d2f36ba3eaf"},
- {file = "aiohttp-3.7.4.post0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:af9aa9ef5ba1fd5b8c948bb11f44891968ab30356d65fd0cc6707d989cd521df"},
- {file = "aiohttp-3.7.4.post0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:64322071e046020e8797117b3658b9c2f80e3267daec409b350b6a7a05041213"},
- {file = "aiohttp-3.7.4.post0-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:bb437315738aa441251214dad17428cafda9cdc9729499f1d6001748e1d432f4"},
- {file = "aiohttp-3.7.4.post0-cp38-cp38-manylinux2014_ppc64le.whl", hash = "sha256:e54962802d4b8b18b6207d4a927032826af39395a3bd9196a5af43fc4e60b009"},
- {file = "aiohttp-3.7.4.post0-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:a00bb73540af068ca7390e636c01cbc4f644961896fa9363154ff43fd37af2f5"},
- {file = "aiohttp-3.7.4.post0-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:79ebfc238612123a713a457d92afb4096e2148be17df6c50fb9bf7a81c2f8013"},
- {file = "aiohttp-3.7.4.post0-cp38-cp38-win32.whl", hash = "sha256:515dfef7f869a0feb2afee66b957cc7bbe9ad0cdee45aec7fdc623f4ecd4fb16"},
- {file = "aiohttp-3.7.4.post0-cp38-cp38-win_amd64.whl", hash = "sha256:114b281e4d68302a324dd33abb04778e8557d88947875cbf4e842c2c01a030c5"},
- {file = "aiohttp-3.7.4.post0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:7b18b97cf8ee5452fa5f4e3af95d01d84d86d32c5e2bfa260cf041749d66360b"},
- {file = "aiohttp-3.7.4.post0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:15492a6368d985b76a2a5fdd2166cddfea5d24e69eefed4630cbaae5c81d89bd"},
- {file = "aiohttp-3.7.4.post0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:bdb230b4943891321e06fc7def63c7aace16095be7d9cf3b1e01be2f10fba439"},
- {file = "aiohttp-3.7.4.post0-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:cffe3ab27871bc3ea47df5d8f7013945712c46a3cc5a95b6bee15887f1675c22"},
- {file = "aiohttp-3.7.4.post0-cp39-cp39-manylinux2014_ppc64le.whl", hash = "sha256:f881853d2643a29e643609da57b96d5f9c9b93f62429dcc1cbb413c7d07f0e1a"},
- {file = "aiohttp-3.7.4.post0-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:a5ca29ee66f8343ed336816c553e82d6cade48a3ad702b9ffa6125d187e2dedb"},
- {file = "aiohttp-3.7.4.post0-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:17c073de315745a1510393a96e680d20af8e67e324f70b42accbd4cb3315c9fb"},
- {file = "aiohttp-3.7.4.post0-cp39-cp39-win32.whl", hash = "sha256:932bb1ea39a54e9ea27fc9232163059a0b8855256f4052e776357ad9add6f1c9"},
- {file = "aiohttp-3.7.4.post0-cp39-cp39-win_amd64.whl", hash = "sha256:02f46fc0e3c5ac58b80d4d56eb0a7c7d97fcef69ace9326289fb9f1955e65cfe"},
- {file = "aiohttp-3.7.4.post0.tar.gz", hash = "sha256:493d3299ebe5f5a7c66b9819eacdcfbbaaf1a8e84911ddffcdc48888497afecf"},
-]
-async-timeout = [
- {file = "async-timeout-3.0.1.tar.gz", hash = "sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f"},
- {file = "async_timeout-3.0.1-py3-none-any.whl", hash = "sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3"},
-]
-asyncpg = [
- {file = "asyncpg-0.24.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c4fc0205fe4ddd5aeb3dfdc0f7bafd43411181e1f5650189608e5971cceacff1"},
- {file = "asyncpg-0.24.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a7095890c96ba36f9f668eb552bb020dddb44f8e73e932f8573efc613ee83843"},
- {file = "asyncpg-0.24.0-cp310-cp310-win_amd64.whl", hash = "sha256:8ff5073d4b654e34bd5eaadc01dc4d68b8a9609084d835acd364cd934190a08d"},
- {file = "asyncpg-0.24.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e36c6806883786b19551bb70a4882561f31135dc8105a59662e0376cf5b2cbc5"},
- {file = "asyncpg-0.24.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ddffcb85227bf39cd1bedd4603e0082b243cf3b14ced64dce506a15b05232b83"},
- {file = "asyncpg-0.24.0-cp37-cp37m-win_amd64.whl", hash = "sha256:41704c561d354bef01353835a7846e5606faabbeb846214dfcf666cf53319f18"},
- {file = "asyncpg-0.24.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:29ef6ae0a617fc13cc2ac5dc8e9b367bb83cba220614b437af9b67766f4b6b20"},
- {file = "asyncpg-0.24.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:eed43abc6ccf1dc02e0d0efc06ce46a411362f3358847c6b0ec9a43426f91ece"},
- {file = "asyncpg-0.24.0-cp38-cp38-win_amd64.whl", hash = "sha256:129d501f3d30616afd51eb8d3142ef51ba05374256bd5834cec3ef4956a9b317"},
- {file = "asyncpg-0.24.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a458fc69051fbb67d995fdda46d75a012b5d6200f91e17d23d4751482640ed4c"},
- {file = "asyncpg-0.24.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:556b0e92e2b75dc028b3c4bc9bd5162ddf0053b856437cf1f04c97f9c6837d03"},
- {file = "asyncpg-0.24.0-cp39-cp39-win_amd64.whl", hash = "sha256:a738f4807c853623d3f93f0fea11f61be6b0e5ca16ea8aeb42c2c7ee742aa853"},
- {file = "asyncpg-0.24.0.tar.gz", hash = "sha256:dd2fa063c3344823487d9ddccb40802f02622ddf8bf8a6cc53885ee7a2c1c0c6"},
-]
-attrs = [
- {file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"},
- {file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"},
-]
-bcrypt = [
- {file = "bcrypt-3.2.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6"},
- {file = "bcrypt-3.2.0-cp36-abi3-manylinux1_x86_64.whl", hash = "sha256:63d4e3ff96188e5898779b6057878fecf3f11cfe6ec3b313ea09955d587ec7a7"},
- {file = "bcrypt-3.2.0-cp36-abi3-manylinux2010_x86_64.whl", hash = "sha256:cd1ea2ff3038509ea95f687256c46b79f5fc382ad0aa3664d200047546d511d1"},
- {file = "bcrypt-3.2.0-cp36-abi3-manylinux2014_aarch64.whl", hash = "sha256:cdcdcb3972027f83fe24a48b1e90ea4b584d35f1cc279d76de6fc4b13376239d"},
- {file = "bcrypt-3.2.0-cp36-abi3-win32.whl", hash = "sha256:a67fb841b35c28a59cebed05fbd3e80eea26e6d75851f0574a9273c80f3e9b55"},
- {file = "bcrypt-3.2.0-cp36-abi3-win_amd64.whl", hash = "sha256:81fec756feff5b6818ea7ab031205e1d323d8943d237303baca2c5f9c7846f34"},
- {file = "bcrypt-3.2.0.tar.gz", hash = "sha256:5b93c1726e50a93a033c36e5ca7fdcd29a5c7395af50a6892f5d9e7c6cfbfb29"},
-]
-blinker = [
- {file = "blinker-1.4.tar.gz", hash = "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"},
-]
-cerberus = [
- {file = "Cerberus-1.3.4.tar.gz", hash = "sha256:d1b21b3954b2498d9a79edf16b3170a3ac1021df88d197dc2ce5928ba519237c"},
-]
-cffi = [
- {file = "cffi-1.14.6-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:22b9c3c320171c108e903d61a3723b51e37aaa8c81255b5e7ce102775bd01e2c"},
- {file = "cffi-1.14.6-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:f0c5d1acbfca6ebdd6b1e3eded8d261affb6ddcf2186205518f1428b8569bb99"},
- {file = "cffi-1.14.6-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:99f27fefe34c37ba9875f224a8f36e31d744d8083e00f520f133cab79ad5e819"},
- {file = "cffi-1.14.6-cp27-cp27m-win32.whl", hash = "sha256:55af55e32ae468e9946f741a5d51f9896da6b9bf0bbdd326843fec05c730eb20"},
- {file = "cffi-1.14.6-cp27-cp27m-win_amd64.whl", hash = "sha256:7bcac9a2b4fdbed2c16fa5681356d7121ecabf041f18d97ed5b8e0dd38a80224"},
- {file = "cffi-1.14.6-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:ed38b924ce794e505647f7c331b22a693bee1538fdf46b0222c4717b42f744e7"},
- {file = "cffi-1.14.6-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:e22dcb48709fc51a7b58a927391b23ab37eb3737a98ac4338e2448bef8559b33"},
- {file = "cffi-1.14.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e8c6a99be100371dbb046880e7a282152aa5d6127ae01783e37662ef73850d8f"},
- {file = "cffi-1.14.6-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:19ca0dbdeda3b2615421d54bef8985f72af6e0c47082a8d26122adac81a95872"},
- {file = "cffi-1.14.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:d950695ae4381ecd856bcaf2b1e866720e4ab9a1498cba61c602e56630ca7195"},
- {file = "cffi-1.14.6-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9dc245e3ac69c92ee4c167fbdd7428ec1956d4e754223124991ef29eb57a09d"},
- {file = "cffi-1.14.6-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a8661b2ce9694ca01c529bfa204dbb144b275a31685a075ce123f12331be790b"},
- {file = "cffi-1.14.6-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b315d709717a99f4b27b59b021e6207c64620790ca3e0bde636a6c7f14618abb"},
- {file = "cffi-1.14.6-cp36-cp36m-win32.whl", hash = "sha256:80b06212075346b5546b0417b9f2bf467fea3bfe7352f781ffc05a8ab24ba14a"},
- {file = "cffi-1.14.6-cp36-cp36m-win_amd64.whl", hash = "sha256:a9da7010cec5a12193d1af9872a00888f396aba3dc79186604a09ea3ee7c029e"},
- {file = "cffi-1.14.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4373612d59c404baeb7cbd788a18b2b2a8331abcc84c3ba40051fcd18b17a4d5"},
- {file = "cffi-1.14.6-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:f10afb1004f102c7868ebfe91c28f4a712227fe4cb24974350ace1f90e1febbf"},
- {file = "cffi-1.14.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:fd4305f86f53dfd8cd3522269ed7fc34856a8ee3709a5e28b2836b2db9d4cd69"},
- {file = "cffi-1.14.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d6169cb3c6c2ad50db5b868db6491a790300ade1ed5d1da29289d73bbe40b56"},
- {file = "cffi-1.14.6-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d4b68e216fc65e9fe4f524c177b54964af043dde734807586cf5435af84045c"},
- {file = "cffi-1.14.6-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33791e8a2dc2953f28b8d8d300dde42dd929ac28f974c4b4c6272cb2955cb762"},
- {file = "cffi-1.14.6-cp37-cp37m-win32.whl", hash = "sha256:0c0591bee64e438883b0c92a7bed78f6290d40bf02e54c5bf0978eaf36061771"},
- {file = "cffi-1.14.6-cp37-cp37m-win_amd64.whl", hash = "sha256:8eb687582ed7cd8c4bdbff3df6c0da443eb89c3c72e6e5dcdd9c81729712791a"},
- {file = "cffi-1.14.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ba6f2b3f452e150945d58f4badd92310449876c4c954836cfb1803bdd7b422f0"},
- {file = "cffi-1.14.6-cp38-cp38-manylinux1_i686.whl", hash = "sha256:64fda793737bc4037521d4899be780534b9aea552eb673b9833b01f945904c2e"},
- {file = "cffi-1.14.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:9f3e33c28cd39d1b655ed1ba7247133b6f7fc16fa16887b120c0c670e35ce346"},
- {file = "cffi-1.14.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26bb2549b72708c833f5abe62b756176022a7b9a7f689b571e74c8478ead51dc"},
- {file = "cffi-1.14.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb687a11f0a7a1839719edd80f41e459cc5366857ecbed383ff376c4e3cc6afd"},
- {file = "cffi-1.14.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d2ad4d668a5c0645d281dcd17aff2be3212bc109b33814bbb15c4939f44181cc"},
- {file = "cffi-1.14.6-cp38-cp38-win32.whl", hash = "sha256:487d63e1454627c8e47dd230025780e91869cfba4c753a74fda196a1f6ad6548"},
- {file = "cffi-1.14.6-cp38-cp38-win_amd64.whl", hash = "sha256:c33d18eb6e6bc36f09d793c0dc58b0211fccc6ae5149b808da4a62660678b156"},
- {file = "cffi-1.14.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:06c54a68935738d206570b20da5ef2b6b6d92b38ef3ec45c5422c0ebaf338d4d"},
- {file = "cffi-1.14.6-cp39-cp39-manylinux1_i686.whl", hash = "sha256:f174135f5609428cc6e1b9090f9268f5c8935fddb1b25ccb8255a2d50de6789e"},
- {file = "cffi-1.14.6-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f3ebe6e73c319340830a9b2825d32eb6d8475c1dac020b4f0aa774ee3b898d1c"},
- {file = "cffi-1.14.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c8d896becff2fa653dc4438b54a5a25a971d1f4110b32bd3068db3722c80202"},
- {file = "cffi-1.14.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4922cd707b25e623b902c86188aca466d3620892db76c0bdd7b99a3d5e61d35f"},
- {file = "cffi-1.14.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c9e005e9bd57bc987764c32a1bee4364c44fdc11a3cc20a40b93b444984f2b87"},
- {file = "cffi-1.14.6-cp39-cp39-win32.whl", hash = "sha256:eb9e2a346c5238a30a746893f23a9535e700f8192a68c07c0258e7ece6ff3728"},
- {file = "cffi-1.14.6-cp39-cp39-win_amd64.whl", hash = "sha256:818014c754cd3dba7229c0f5884396264d51ffb87ec86e927ef0be140bfdb0d2"},
- {file = "cffi-1.14.6.tar.gz", hash = "sha256:c9a875ce9d7fe32887784274dd533c57909b7b1dcadcc128a2ac21331a9765dd"},
-]
-chardet = [
- {file = "chardet-4.0.0-py2.py3-none-any.whl", hash = "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5"},
- {file = "chardet-4.0.0.tar.gz", hash = "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa"},
+ {file = "aiofiles-0.8.0-py3-none-any.whl", hash = "sha256:7a973fc22b29e9962d0897805ace5856e6a566ab1f0c8e5c91ff6c866519c937"},
+ {file = "aiofiles-0.8.0.tar.gz", hash = "sha256:8334f23235248a3b2e83b2c3a78a22674f39969b96397126cc93664d9a901e59"},
]
+aiohttp = []
+aiosignal = []
+async-timeout = []
+asyncpg = []
+attrs = []
+bcrypt = []
+blinker = []
+cerberus = []
+cffi = []
+charset-normalizer = []
click = [
- {file = "click-8.0.1-py3-none-any.whl", hash = "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"},
- {file = "click-8.0.1.tar.gz", hash = "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a"},
+ {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
+ {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
]
colorama = [
- {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
- {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
-]
-earl-etf = [
- {file = "earl-etf-2.1.2.tar.gz", hash = "sha256:f43cffbcf754e45f6716d82bb885c5072f3f8b16c1f1e26b46cb63f27e838640"},
- {file = "earl_etf-2.1.2-cp34-cp34m-win32.whl", hash = "sha256:d6f3e3bdbe2b74571f57b2c23f68233b464785ddf0c41870c3d8ff88db06b40e"},
- {file = "earl_etf-2.1.2-cp34-cp34m-win_amd64.whl", hash = "sha256:870b40778ef6f644d6568a5afd481ce53bc87cb21fd92bfcf5b6072ede8e3078"},
- {file = "earl_etf-2.1.2-cp35-cp35m-win32.whl", hash = "sha256:f6a77049a21ed04095ef64f7e39ed26a2a88c17fffaf361119cd739683d25d55"},
- {file = "earl_etf-2.1.2-cp35-cp35m-win_amd64.whl", hash = "sha256:46bea44c3a3bf3914b01eb6a3bd42e3fb6dee6f45d68372b1237a153bf9fe4fc"},
- {file = "earl_etf-2.1.2-cp36-cp36m-win32.whl", hash = "sha256:6e3595ca9642d33cc5644c923826271f960c7df567fdaf62b5b439a0a6a9b619"},
- {file = "earl_etf-2.1.2-cp36-cp36m-win_amd64.whl", hash = "sha256:52155ec379ec96560938f295bfa1f055743dc8be275423bdfebef14b16acfdab"},
+ {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"},
+ {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"},
]
+earl-etf = []
+frozenlist = []
h11 = [
- {file = "h11-0.12.0-py3-none-any.whl", hash = "sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6"},
- {file = "h11-0.12.0.tar.gz", hash = "sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042"},
+ {file = "h11-0.13.0-py3-none-any.whl", hash = "sha256:8ddd78563b633ca55346c8cd41ec0af27d3c79931828beffb46ce70a379e7442"},
+ {file = "h11-0.13.0.tar.gz", hash = "sha256:70813c1135087a248a4d38cc0e1a0181ffab2188141a93eaf567940c3957ff06"},
]
h2 = [
- {file = "h2-4.0.0-py3-none-any.whl", hash = "sha256:ac9e293a1990b339d5d71b19c5fe630e3dd4d768c620d1730d355485323f1b25"},
- {file = "h2-4.0.0.tar.gz", hash = "sha256:bb7ac7099dd67a857ed52c815a6192b6b1f5ba6b516237fc24a085341340593d"},
+ {file = "h2-4.1.0-py3-none-any.whl", hash = "sha256:03a46bcf682256c95b5fd9e9a99c1323584c3eec6440d379b9903d709476bc6d"},
+ {file = "h2-4.1.0.tar.gz", hash = "sha256:a83aca08fbe7aacb79fec788c9c0bac936343560ed9ec18b82a13a12c28d2abb"},
]
hpack = [
{file = "hpack-4.0.0-py3-none-any.whl", hash = "sha256:84a076fad3dc9a9f8063ccb8041ef100867b1878b25ef0ee63847a5d53818a6c"},
{file = "hpack-4.0.0.tar.gz", hash = "sha256:fc41de0c63e687ebffde81187a948221294896f6bdc0ae2312708df339430095"},
]
hypercorn = [
- {file = "Hypercorn-0.11.2-py3-none-any.whl", hash = "sha256:8007c10f81566920f8ae12c0e26e146f94ca70506da964b5a727ad610aa1d821"},
- {file = "Hypercorn-0.11.2.tar.gz", hash = "sha256:5ba1e719c521080abd698ff5781a2331e34ef50fc1c89a50960538115a896a9a"},
+ {file = "Hypercorn-0.13.2-py3-none-any.whl", hash = "sha256:ca18f91ab3fa823cbe9e949738f9f2cc07027cd647c80d8f93e4b1a2a175f112"},
+ {file = "Hypercorn-0.13.2.tar.gz", hash = "sha256:6307be5cbdf6ba411967d4661202dc4f79bd511b5d318bc4eed88b09418427f8"},
]
hyperframe = [
{file = "hyperframe-6.0.1-py3-none-any.whl", hash = "sha256:0ec6bafd80d8ad2195c4f03aacba3a8265e57bc4cff261e802bf39970ed02a15"},
{file = "hyperframe-6.0.1.tar.gz", hash = "sha256:ae510046231dc8e9ecb1a6586f63d2347bf4c8905914aa84ba585ae85f28a914"},
]
idna = [
- {file = "idna-3.2-py3-none-any.whl", hash = "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a"},
- {file = "idna-3.2.tar.gz", hash = "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"},
+ {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"},
+ {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"},
]
+importlib-metadata = []
itsdangerous = [
- {file = "itsdangerous-1.1.0-py2.py3-none-any.whl", hash = "sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749"},
- {file = "itsdangerous-1.1.0.tar.gz", hash = "sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19"},
+ {file = "itsdangerous-2.1.2-py3-none-any.whl", hash = "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44"},
+ {file = "itsdangerous-2.1.2.tar.gz", hash = "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a"},
]
jinja2 = [
- {file = "Jinja2-3.0.1-py3-none-any.whl", hash = "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4"},
- {file = "Jinja2-3.0.1.tar.gz", hash = "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"},
-]
-logbook = [
- {file = "Logbook-1.5.3-cp27-cp27m-win32.whl", hash = "sha256:56ee54c11df3377314cedcd6507638f015b4b88c0238c2e01b5eb44fd3a6ad1b"},
- {file = "Logbook-1.5.3-cp27-cp27m-win_amd64.whl", hash = "sha256:2dc85f1510533fddb481e97677bb7bca913560862734c0b3b289bfed04f78c92"},
- {file = "Logbook-1.5.3-cp35-cp35m-win32.whl", hash = "sha256:94e2e11ff3c2304b0d09a36c6208e5ae756eb948b210e5cbd63cd8d27f911542"},
- {file = "Logbook-1.5.3-cp35-cp35m-win_amd64.whl", hash = "sha256:97fee1bd9605f76335b169430ed65e15e457a844b2121bd1d90a08cf7e30aba0"},
- {file = "Logbook-1.5.3-cp36-cp36m-win32.whl", hash = "sha256:7c533eb728b3d220b1b5414ba4635292d149d79f74f6973b4aa744c850ca944a"},
- {file = "Logbook-1.5.3-cp36-cp36m-win_amd64.whl", hash = "sha256:e18f7422214b1cf0240c56f884fd9c9b4ff9d0da2eabca9abccba56df7222f66"},
- {file = "Logbook-1.5.3-cp37-cp37m-win32.whl", hash = "sha256:8f76a2e7b1f72595f753228732f81ce342caf03babc3fed6bbdcf366f2f20f18"},
- {file = "Logbook-1.5.3-cp37-cp37m-win_amd64.whl", hash = "sha256:0cf2cdbfb65a03b5987d19109dacad13417809dcf697f66e1a7084fb21744ea9"},
- {file = "Logbook-1.5.3.tar.gz", hash = "sha256:66f454ada0f56eae43066f604a222b09893f98c1adc18df169710761b8f32fe8"},
+ {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"},
+ {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"},
]
+logbook = []
markupsafe = [
- {file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"},
- {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"},
- {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"},
- {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"},
- {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"},
- {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"},
- {file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"},
- {file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"},
- {file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"},
- {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18"},
- {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f"},
- {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"},
- {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"},
- {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"},
- {file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"},
- {file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"},
- {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"},
- {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"},
- {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"},
- {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"},
- {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"},
- {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"},
- {file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"},
- {file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"},
- {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"},
- {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7"},
- {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8"},
- {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5"},
- {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"},
- {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"},
- {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"},
- {file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"},
- {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"},
- {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"},
-]
-multidict = [
- {file = "multidict-5.1.0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:b7993704f1a4b204e71debe6095150d43b2ee6150fa4f44d6d966ec356a8d61f"},
- {file = "multidict-5.1.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:9dd6e9b1a913d096ac95d0399bd737e00f2af1e1594a787e00f7975778c8b2bf"},
- {file = "multidict-5.1.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:f21756997ad8ef815d8ef3d34edd98804ab5ea337feedcd62fb52d22bf531281"},
- {file = "multidict-5.1.0-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:1ab820665e67373de5802acae069a6a05567ae234ddb129f31d290fc3d1aa56d"},
- {file = "multidict-5.1.0-cp36-cp36m-manylinux2014_ppc64le.whl", hash = "sha256:9436dc58c123f07b230383083855593550c4d301d2532045a17ccf6eca505f6d"},
- {file = "multidict-5.1.0-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:830f57206cc96ed0ccf68304141fec9481a096c4d2e2831f311bde1c404401da"},
- {file = "multidict-5.1.0-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:2e68965192c4ea61fff1b81c14ff712fc7dc15d2bd120602e4a3494ea6584224"},
- {file = "multidict-5.1.0-cp36-cp36m-win32.whl", hash = "sha256:2f1a132f1c88724674271d636e6b7351477c27722f2ed789f719f9e3545a3d26"},
- {file = "multidict-5.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:3a4f32116f8f72ecf2a29dabfb27b23ab7cdc0ba807e8459e59a93a9be9506f6"},
- {file = "multidict-5.1.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:46c73e09ad374a6d876c599f2328161bcd95e280f84d2060cf57991dec5cfe76"},
- {file = "multidict-5.1.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:018132dbd8688c7a69ad89c4a3f39ea2f9f33302ebe567a879da8f4ca73f0d0a"},
- {file = "multidict-5.1.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:4b186eb7d6ae7c06eb4392411189469e6a820da81447f46c0072a41c748ab73f"},
- {file = "multidict-5.1.0-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:3a041b76d13706b7fff23b9fc83117c7b8fe8d5fe9e6be45eee72b9baa75f348"},
- {file = "multidict-5.1.0-cp37-cp37m-manylinux2014_ppc64le.whl", hash = "sha256:051012ccee979b2b06be928a6150d237aec75dd6bf2d1eeeb190baf2b05abc93"},
- {file = "multidict-5.1.0-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:6a4d5ce640e37b0efcc8441caeea8f43a06addace2335bd11151bc02d2ee31f9"},
- {file = "multidict-5.1.0-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:5cf3443199b83ed9e955f511b5b241fd3ae004e3cb81c58ec10f4fe47c7dce37"},
- {file = "multidict-5.1.0-cp37-cp37m-win32.whl", hash = "sha256:f200755768dc19c6f4e2b672421e0ebb3dd54c38d5a4f262b872d8cfcc9e93b5"},
- {file = "multidict-5.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:05c20b68e512166fddba59a918773ba002fdd77800cad9f55b59790030bab632"},
- {file = "multidict-5.1.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:54fd1e83a184e19c598d5e70ba508196fd0bbdd676ce159feb412a4a6664f952"},
- {file = "multidict-5.1.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:0e3c84e6c67eba89c2dbcee08504ba8644ab4284863452450520dad8f1e89b79"},
- {file = "multidict-5.1.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:dc862056f76443a0db4509116c5cd480fe1b6a2d45512a653f9a855cc0517456"},
- {file = "multidict-5.1.0-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:0e929169f9c090dae0646a011c8b058e5e5fb391466016b39d21745b48817fd7"},
- {file = "multidict-5.1.0-cp38-cp38-manylinux2014_ppc64le.whl", hash = "sha256:d81eddcb12d608cc08081fa88d046c78afb1bf8107e6feab5d43503fea74a635"},
- {file = "multidict-5.1.0-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:585fd452dd7782130d112f7ddf3473ffdd521414674c33876187e101b588738a"},
- {file = "multidict-5.1.0-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:37e5438e1c78931df5d3c0c78ae049092877e5e9c02dd1ff5abb9cf27a5914ea"},
- {file = "multidict-5.1.0-cp38-cp38-win32.whl", hash = "sha256:07b42215124aedecc6083f1ce6b7e5ec5b50047afa701f3442054373a6deb656"},
- {file = "multidict-5.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:929006d3c2d923788ba153ad0de8ed2e5ed39fdbe8e7be21e2f22ed06c6783d3"},
- {file = "multidict-5.1.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:b797515be8743b771aa868f83563f789bbd4b236659ba52243b735d80b29ed93"},
- {file = "multidict-5.1.0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:d5c65bdf4484872c4af3150aeebe101ba560dcfb34488d9a8ff8dbcd21079647"},
- {file = "multidict-5.1.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:b47a43177a5e65b771b80db71e7be76c0ba23cc8aa73eeeb089ed5219cdbe27d"},
- {file = "multidict-5.1.0-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:806068d4f86cb06af37cd65821554f98240a19ce646d3cd24e1c33587f313eb8"},
- {file = "multidict-5.1.0-cp39-cp39-manylinux2014_ppc64le.whl", hash = "sha256:46dd362c2f045095c920162e9307de5ffd0a1bfbba0a6e990b344366f55a30c1"},
- {file = "multidict-5.1.0-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:ace010325c787c378afd7f7c1ac66b26313b3344628652eacd149bdd23c68841"},
- {file = "multidict-5.1.0-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:ecc771ab628ea281517e24fd2c52e8f31c41e66652d07599ad8818abaad38cda"},
- {file = "multidict-5.1.0-cp39-cp39-win32.whl", hash = "sha256:fc13a9524bc18b6fb6e0dbec3533ba0496bbed167c56d0aabefd965584557d80"},
- {file = "multidict-5.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:7df80d07818b385f3129180369079bd6934cf70469f99daaebfac89dca288359"},
- {file = "multidict-5.1.0.tar.gz", hash = "sha256:25b4e5f22d3a37ddf3effc0710ba692cfc792c2b9edfb9c05aefe823256e84d5"},
-]
-pillow = [
- {file = "Pillow-8.3.2-cp310-cp310-macosx_10_10_universal2.whl", hash = "sha256:c691b26283c3a31594683217d746f1dad59a7ae1d4cfc24626d7a064a11197d4"},
- {file = "Pillow-8.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f514c2717012859ccb349c97862568fdc0479aad85b0270d6b5a6509dbc142e2"},
- {file = "Pillow-8.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be25cb93442c6d2f8702c599b51184bd3ccd83adebd08886b682173e09ef0c3f"},
- {file = "Pillow-8.3.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d675a876b295afa114ca8bf42d7f86b5fb1298e1b6bb9a24405a3f6c8338811c"},
- {file = "Pillow-8.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59697568a0455764a094585b2551fd76bfd6b959c9f92d4bdec9d0e14616303a"},
- {file = "Pillow-8.3.2-cp310-cp310-win32.whl", hash = "sha256:2d5e9dc0bf1b5d9048a94c48d0813b6c96fccfa4ccf276d9c36308840f40c228"},
- {file = "Pillow-8.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:11c27e74bab423eb3c9232d97553111cc0be81b74b47165f07ebfdd29d825875"},
- {file = "Pillow-8.3.2-cp36-cp36m-macosx_10_10_x86_64.whl", hash = "sha256:11eb7f98165d56042545c9e6db3ce394ed8b45089a67124298f0473b29cb60b2"},
- {file = "Pillow-8.3.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f23b2d3079522fdf3c09de6517f625f7a964f916c956527bed805ac043799b8"},
- {file = "Pillow-8.3.2-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:19ec4cfe4b961edc249b0e04b5618666c23a83bc35842dea2bfd5dfa0157f81b"},
- {file = "Pillow-8.3.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5a31c07cea5edbaeb4bdba6f2b87db7d3dc0f446f379d907e51cc70ea375629"},
- {file = "Pillow-8.3.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:15ccb81a6ffc57ea0137f9f3ac2737ffa1d11f786244d719639df17476d399a7"},
- {file = "Pillow-8.3.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:8f284dc1695caf71a74f24993b7c7473d77bc760be45f776a2c2f4e04c170550"},
- {file = "Pillow-8.3.2-cp36-cp36m-win32.whl", hash = "sha256:4abc247b31a98f29e5224f2d31ef15f86a71f79c7f4d2ac345a5d551d6393073"},
- {file = "Pillow-8.3.2-cp36-cp36m-win_amd64.whl", hash = "sha256:a048dad5ed6ad1fad338c02c609b862dfaa921fcd065d747194a6805f91f2196"},
- {file = "Pillow-8.3.2-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:06d1adaa284696785375fa80a6a8eb309be722cf4ef8949518beb34487a3df71"},
- {file = "Pillow-8.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd24054aaf21e70a51e2a2a5ed1183560d3a69e6f9594a4bfe360a46f94eba83"},
- {file = "Pillow-8.3.2-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27a330bf7014ee034046db43ccbb05c766aa9e70b8d6c5260bfc38d73103b0ba"},
- {file = "Pillow-8.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13654b521fb98abdecec105ea3fb5ba863d1548c9b58831dd5105bb3873569f1"},
- {file = "Pillow-8.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a1bd983c565f92779be456ece2479840ec39d386007cd4ae83382646293d681b"},
- {file = "Pillow-8.3.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:4326ea1e2722f3dc00ed77c36d3b5354b8fb7399fb59230249ea6d59cbed90da"},
- {file = "Pillow-8.3.2-cp37-cp37m-win32.whl", hash = "sha256:085a90a99404b859a4b6c3daa42afde17cb3ad3115e44a75f0d7b4a32f06a6c9"},
- {file = "Pillow-8.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:18a07a683805d32826c09acfce44a90bf474e6a66ce482b1c7fcd3757d588df3"},
- {file = "Pillow-8.3.2-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:4e59e99fd680e2b8b11bbd463f3c9450ab799305d5f2bafb74fefba6ac058616"},
- {file = "Pillow-8.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4d89a2e9219a526401015153c0e9dd48319ea6ab9fe3b066a20aa9aee23d9fd3"},
- {file = "Pillow-8.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56fd98c8294f57636084f4b076b75f86c57b2a63a8410c0cd172bc93695ee979"},
- {file = "Pillow-8.3.2-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b11c9d310a3522b0fd3c35667914271f570576a0e387701f370eb39d45f08a4"},
- {file = "Pillow-8.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0412516dcc9de9b0a1e0ae25a280015809de8270f134cc2c1e32c4eeb397cf30"},
- {file = "Pillow-8.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bcb04ff12e79b28be6c9988f275e7ab69f01cc2ba319fb3114f87817bb7c74b6"},
- {file = "Pillow-8.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:0b9911ec70731711c3b6ebcde26caea620cbdd9dcb73c67b0730c8817f24711b"},
- {file = "Pillow-8.3.2-cp38-cp38-win32.whl", hash = "sha256:ce2e5e04bb86da6187f96d7bab3f93a7877830981b37f0287dd6479e27a10341"},
- {file = "Pillow-8.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:35d27687f027ad25a8d0ef45dd5208ef044c588003cdcedf05afb00dbc5c2deb"},
- {file = "Pillow-8.3.2-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:04835e68ef12904bc3e1fd002b33eea0779320d4346082bd5b24bec12ad9c3e9"},
- {file = "Pillow-8.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:10e00f7336780ca7d3653cf3ac26f068fa11b5a96894ea29a64d3dc4b810d630"},
- {file = "Pillow-8.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cde7a4d3687f21cffdf5bb171172070bb95e02af448c4c8b2f223d783214056"},
- {file = "Pillow-8.3.2-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c3ff00110835bdda2b1e2b07f4a2548a39744bb7de5946dc8e95517c4fb2ca6"},
- {file = "Pillow-8.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35d409030bf3bd05fa66fb5fdedc39c521b397f61ad04309c90444e893d05f7d"},
- {file = "Pillow-8.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6bff50ba9891be0a004ef48828e012babaaf7da204d81ab9be37480b9020a82b"},
- {file = "Pillow-8.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7dbfbc0020aa1d9bc1b0b8bcf255a7d73f4ad0336f8fd2533fcc54a4ccfb9441"},
- {file = "Pillow-8.3.2-cp39-cp39-win32.whl", hash = "sha256:963ebdc5365d748185fdb06daf2ac758116deecb2277ec5ae98139f93844bc09"},
- {file = "Pillow-8.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:cc9d0dec711c914ed500f1d0d3822868760954dce98dfb0b7382a854aee55d19"},
- {file = "Pillow-8.3.2-pp36-pypy36_pp73-macosx_10_10_x86_64.whl", hash = "sha256:2c661542c6f71dfd9dc82d9d29a8386287e82813b0375b3a02983feac69ef864"},
- {file = "Pillow-8.3.2-pp36-pypy36_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:548794f99ff52a73a156771a0402f5e1c35285bd981046a502d7e4793e8facaa"},
- {file = "Pillow-8.3.2-pp36-pypy36_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8b68f565a4175e12e68ca900af8910e8fe48aaa48fd3ca853494f384e11c8bcd"},
- {file = "Pillow-8.3.2-pp36-pypy36_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:838eb85de6d9307c19c655c726f8d13b8b646f144ca6b3771fa62b711ebf7624"},
- {file = "Pillow-8.3.2-pp36-pypy36_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:feb5db446e96bfecfec078b943cc07744cc759893cef045aa8b8b6d6aaa8274e"},
- {file = "Pillow-8.3.2-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:fc0db32f7223b094964e71729c0361f93db43664dd1ec86d3df217853cedda87"},
- {file = "Pillow-8.3.2-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:fd4fd83aa912d7b89b4b4a1580d30e2a4242f3936882a3f433586e5ab97ed0d5"},
- {file = "Pillow-8.3.2-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d0c8ebbfd439c37624db98f3877d9ed12c137cadd99dde2d2eae0dab0bbfc355"},
- {file = "Pillow-8.3.2-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6cb3dd7f23b044b0737317f892d399f9e2f0b3a02b22b2c692851fb8120d82c6"},
- {file = "Pillow-8.3.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a66566f8a22561fc1a88dc87606c69b84fa9ce724f99522cf922c801ec68f5c1"},
- {file = "Pillow-8.3.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:ce651ca46d0202c302a535d3047c55a0131a720cf554a578fc1b8a2aff0e7d96"},
- {file = "Pillow-8.3.2.tar.gz", hash = "sha256:dde3f3ed8d00c72631bc19cbfff8ad3b6215062a5eed402381ad365f82f0c18c"},
+ {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"},
+ {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"},
+ {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e"},
+ {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5"},
+ {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4"},
+ {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f"},
+ {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e"},
+ {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933"},
+ {file = "MarkupSafe-2.1.1-cp310-cp310-win32.whl", hash = "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6"},
+ {file = "MarkupSafe-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417"},
+ {file = "MarkupSafe-2.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02"},
+ {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a"},
+ {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37"},
+ {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980"},
+ {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a"},
+ {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3"},
+ {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a"},
+ {file = "MarkupSafe-2.1.1-cp37-cp37m-win32.whl", hash = "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff"},
+ {file = "MarkupSafe-2.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a"},
+ {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452"},
+ {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003"},
+ {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1"},
+ {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601"},
+ {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925"},
+ {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f"},
+ {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88"},
+ {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63"},
+ {file = "MarkupSafe-2.1.1-cp38-cp38-win32.whl", hash = "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1"},
+ {file = "MarkupSafe-2.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"},
+ {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a"},
+ {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f"},
+ {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6"},
+ {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77"},
+ {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603"},
+ {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7"},
+ {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135"},
+ {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96"},
+ {file = "MarkupSafe-2.1.1-cp39-cp39-win32.whl", hash = "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c"},
+ {file = "MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247"},
+ {file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"},
]
+multidict = []
+pillow = []
priority = [
{file = "priority-2.0.0-py3-none-any.whl", hash = "sha256:6f8eefce5f3ad59baf2c080a664037bb4725cd0a790d53d59ab4059288faf6aa"},
{file = "priority-2.0.0.tar.gz", hash = "sha256:c965d54f1b8d0d0b19479db3924c7c36cf672dbf2aec92d43fbdaf4492ba18c0"},
]
-pycparser = [
- {file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"},
- {file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"},
-]
-quart = [
- {file = "Quart-0.15.1-py3-none-any.whl", hash = "sha256:f35134fb1d81af61624e6d89bca33cd611dcedce2dc4e291f527ab04395f4e1a"},
- {file = "Quart-0.15.1.tar.gz", hash = "sha256:f80c91d1e0588662483e22dd9c368a5778886b62e128c5399d2cc1b1898482cf"},
-]
-six = [
- {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
- {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
-]
+pycparser = []
+quart = []
toml = [
{file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
{file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
]
-typing-extensions = [
- {file = "typing_extensions-3.10.0.2-py2-none-any.whl", hash = "sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7"},
- {file = "typing_extensions-3.10.0.2-py3-none-any.whl", hash = "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34"},
- {file = "typing_extensions-3.10.0.2.tar.gz", hash = "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e"},
-]
-websockets = [
- {file = "websockets-10.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cd8c6f2ec24aedace251017bc7a414525171d4e6578f914acab9349362def4da"},
- {file = "websockets-10.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:1f6b814cff6aadc4288297cb3a248614829c6e4ff5556593c44a115e9dd49939"},
- {file = "websockets-10.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:01db0ecd1a0ca6702d02a5ed40413e18b7d22f94afb3bbe0d323bac86c42c1c8"},
- {file = "websockets-10.0-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:82b17524b1ce6ae7f7dd93e4d18e9b9474071e28b65dbf1dfe9b5767778db379"},
- {file = "websockets-10.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:8bbf8660c3f833ddc8b1afab90213f2e672a9ddac6eecb3cde968e6b2807c1c7"},
- {file = "websockets-10.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b8176deb6be540a46695960a765a77c28ac8b2e3ef2ec95d50a4f5df901edb1c"},
- {file = "websockets-10.0-cp37-cp37m-win32.whl", hash = "sha256:706e200fc7f03bed99ad0574cd1ea8b0951477dd18cc978ccb190683c69dba76"},
- {file = "websockets-10.0-cp37-cp37m-win_amd64.whl", hash = "sha256:5b2600e01c7ca6f840c42c747ffbe0254f319594ed108db847eb3d75f4aacb80"},
- {file = "websockets-10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:085bb8a6e780d30eaa1ba48ac7f3a6707f925edea787cfb761ce5a39e77ac09b"},
- {file = "websockets-10.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:9a4d889162bd48588e80950e07fa5e039eee9deb76a58092e8c3ece96d7ef537"},
- {file = "websockets-10.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:b4ade7569b6fd17912452f9c3757d96f8e4044016b6d22b3b8391e641ca50456"},
- {file = "websockets-10.0-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:2a43072e434c041a99f2e1eb9b692df0232a38c37c61d00e9f24db79474329e4"},
- {file = "websockets-10.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:7f79f02c7f9a8320aff7d3321cd1c7e3a7dbc15d922ac996cca827301ee75238"},
- {file = "websockets-10.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:1ac35426fe3e7d3d0fac3d63c8965c76ed67a8fd713937be072bf0ce22808539"},
- {file = "websockets-10.0-cp38-cp38-win32.whl", hash = "sha256:ff59c6bdb87b31f7e2d596f09353d5a38c8c8ff571b0e2238e8ee2d55ad68465"},
- {file = "websockets-10.0-cp38-cp38-win_amd64.whl", hash = "sha256:d67646ddd17a86117ae21c27005d83c1895c0cef5d7be548b7549646372f868a"},
- {file = "websockets-10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:82bd921885231f4a30d9bc550552495b3fc36b1235add6d374e7c65c3babd805"},
- {file = "websockets-10.0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:7d2e12e4f901f1bc062dfdf91831712c4106ed18a9a4cdb65e2e5f502124ca37"},
- {file = "websockets-10.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:71358c7816e2762f3e4af3adf0040f268e219f5a38cb3487a9d0fc2e554fef6a"},
- {file = "websockets-10.0-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:fe83b3ec9ef34063d86dfe1029160a85f24a5a94271036e5714a57acfdd089a1"},
- {file = "websockets-10.0-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:eb282127e9c136f860c6068a4fba5756eb25e755baffb5940b6f1eae071928b2"},
- {file = "websockets-10.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:62160772314920397f9d219147f958b33fa27a12c662d4455c9ccbba9a07e474"},
- {file = "websockets-10.0-cp39-cp39-win32.whl", hash = "sha256:e42a1f1e03437b017af341e9bbfdc09252cd48ef32a8c3c3ead769eab3b17368"},
- {file = "websockets-10.0-cp39-cp39-win_amd64.whl", hash = "sha256:c5880442f5fc268f1ef6d37b2c152c114deccca73f48e3a8c48004d2f16f4567"},
- {file = "websockets-10.0.tar.gz", hash = "sha256:c4fc9a1d242317892590abe5b61a9127f1a61740477bfb121743f290b8054002"},
-]
-werkzeug = [
- {file = "Werkzeug-2.0.1-py3-none-any.whl", hash = "sha256:6c1ec500dcdba0baa27600f6a22f6333d8b662d22027ff9f6202e3367413caa8"},
- {file = "Werkzeug-2.0.1.tar.gz", hash = "sha256:1de1db30d010ff1af14a009224ec49ab2329ad2cde454c8a708130642d579c42"},
-]
+websockets = []
+werkzeug = []
winter = []
wsproto = [
- {file = "wsproto-1.0.0-py3-none-any.whl", hash = "sha256:d8345d1808dd599b5ffb352c25a367adb6157e664e140dbecba3f9bc007edb9f"},
- {file = "wsproto-1.0.0.tar.gz", hash = "sha256:868776f8456997ad0d9720f7322b746bbe9193751b5b290b7f924659377c8c38"},
-]
-yarl = [
- {file = "yarl-1.6.3-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:0355a701b3998dcd832d0dc47cc5dedf3874f966ac7f870e0f3a6788d802d434"},
- {file = "yarl-1.6.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:bafb450deef6861815ed579c7a6113a879a6ef58aed4c3a4be54400ae8871478"},
- {file = "yarl-1.6.3-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:547f7665ad50fa8563150ed079f8e805e63dd85def6674c97efd78eed6c224a6"},
- {file = "yarl-1.6.3-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:63f90b20ca654b3ecc7a8d62c03ffa46999595f0167d6450fa8383bab252987e"},
- {file = "yarl-1.6.3-cp36-cp36m-manylinux2014_ppc64le.whl", hash = "sha256:97b5bdc450d63c3ba30a127d018b866ea94e65655efaf889ebeabc20f7d12406"},
- {file = "yarl-1.6.3-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:d8d07d102f17b68966e2de0e07bfd6e139c7c02ef06d3a0f8d2f0f055e13bb76"},
- {file = "yarl-1.6.3-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:15263c3b0b47968c1d90daa89f21fcc889bb4b1aac5555580d74565de6836366"},
- {file = "yarl-1.6.3-cp36-cp36m-win32.whl", hash = "sha256:b5dfc9a40c198334f4f3f55880ecf910adebdcb2a0b9a9c23c9345faa9185721"},
- {file = "yarl-1.6.3-cp36-cp36m-win_amd64.whl", hash = "sha256:b2e9a456c121e26d13c29251f8267541bd75e6a1ccf9e859179701c36a078643"},
- {file = "yarl-1.6.3-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:ce3beb46a72d9f2190f9e1027886bfc513702d748047b548b05dab7dfb584d2e"},
- {file = "yarl-1.6.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:2ce4c621d21326a4a5500c25031e102af589edb50c09b321049e388b3934eec3"},
- {file = "yarl-1.6.3-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:d26608cf178efb8faa5ff0f2d2e77c208f471c5a3709e577a7b3fd0445703ac8"},
- {file = "yarl-1.6.3-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:4c5bcfc3ed226bf6419f7a33982fb4b8ec2e45785a0561eb99274ebbf09fdd6a"},
- {file = "yarl-1.6.3-cp37-cp37m-manylinux2014_ppc64le.whl", hash = "sha256:4736eaee5626db8d9cda9eb5282028cc834e2aeb194e0d8b50217d707e98bb5c"},
- {file = "yarl-1.6.3-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:68dc568889b1c13f1e4745c96b931cc94fdd0defe92a72c2b8ce01091b22e35f"},
- {file = "yarl-1.6.3-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:7356644cbed76119d0b6bd32ffba704d30d747e0c217109d7979a7bc36c4d970"},
- {file = "yarl-1.6.3-cp37-cp37m-win32.whl", hash = "sha256:00d7ad91b6583602eb9c1d085a2cf281ada267e9a197e8b7cae487dadbfa293e"},
- {file = "yarl-1.6.3-cp37-cp37m-win_amd64.whl", hash = "sha256:69ee97c71fee1f63d04c945f56d5d726483c4762845400a6795a3b75d56b6c50"},
- {file = "yarl-1.6.3-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:e46fba844f4895b36f4c398c5af062a9808d1f26b2999c58909517384d5deda2"},
- {file = "yarl-1.6.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:31ede6e8c4329fb81c86706ba8f6bf661a924b53ba191b27aa5fcee5714d18ec"},
- {file = "yarl-1.6.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:fcbb48a93e8699eae920f8d92f7160c03567b421bc17362a9ffbbd706a816f71"},
- {file = "yarl-1.6.3-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:72a660bdd24497e3e84f5519e57a9ee9220b6f3ac4d45056961bf22838ce20cc"},
- {file = "yarl-1.6.3-cp38-cp38-manylinux2014_ppc64le.whl", hash = "sha256:324ba3d3c6fee56e2e0b0d09bf5c73824b9f08234339d2b788af65e60040c959"},
- {file = "yarl-1.6.3-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:e6b5460dc5ad42ad2b36cca524491dfcaffbfd9c8df50508bddc354e787b8dc2"},
- {file = "yarl-1.6.3-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:6d6283d8e0631b617edf0fd726353cb76630b83a089a40933043894e7f6721e2"},
- {file = "yarl-1.6.3-cp38-cp38-win32.whl", hash = "sha256:9ede61b0854e267fd565e7527e2f2eb3ef8858b301319be0604177690e1a3896"},
- {file = "yarl-1.6.3-cp38-cp38-win_amd64.whl", hash = "sha256:f0b059678fd549c66b89bed03efcabb009075bd131c248ecdf087bdb6faba24a"},
- {file = "yarl-1.6.3-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:329412812ecfc94a57cd37c9d547579510a9e83c516bc069470db5f75684629e"},
- {file = "yarl-1.6.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:c49ff66d479d38ab863c50f7bb27dee97c6627c5fe60697de15529da9c3de724"},
- {file = "yarl-1.6.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f040bcc6725c821a4c0665f3aa96a4d0805a7aaf2caf266d256b8ed71b9f041c"},
- {file = "yarl-1.6.3-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:d5c32c82990e4ac4d8150fd7652b972216b204de4e83a122546dce571c1bdf25"},
- {file = "yarl-1.6.3-cp39-cp39-manylinux2014_ppc64le.whl", hash = "sha256:d597767fcd2c3dc49d6eea360c458b65643d1e4dbed91361cf5e36e53c1f8c96"},
- {file = "yarl-1.6.3-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:8aa3decd5e0e852dc68335abf5478a518b41bf2ab2f330fe44916399efedfae0"},
- {file = "yarl-1.6.3-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:73494d5b71099ae8cb8754f1df131c11d433b387efab7b51849e7e1e851f07a4"},
- {file = "yarl-1.6.3-cp39-cp39-win32.whl", hash = "sha256:5b883e458058f8d6099e4420f0cc2567989032b5f34b271c0827de9f1079a424"},
- {file = "yarl-1.6.3-cp39-cp39-win_amd64.whl", hash = "sha256:4953fb0b4fdb7e08b2f3b3be80a00d28c5c8a2056bb066169de00e6501b986b6"},
- {file = "yarl-1.6.3.tar.gz", hash = "sha256:8a9066529240171b68893d60dca86a763eae2139dd42f42106b03cf4b426bf10"},
-]
-zstandard = [
- {file = "zstandard-0.15.2-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:7b16bd74ae7bfbaca407a127e11058b287a4267caad13bd41305a5e630472549"},
- {file = "zstandard-0.15.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:8baf7991547441458325ca8fafeae79ef1501cb4354022724f3edd62279c5b2b"},
- {file = "zstandard-0.15.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:5752f44795b943c99be367fee5edf3122a1690b0d1ecd1bd5ec94c7fd2c39c94"},
- {file = "zstandard-0.15.2-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:3547ff4eee7175d944a865bbdf5529b0969c253e8a148c287f0668fe4eb9c935"},
- {file = "zstandard-0.15.2-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:ac43c1821ba81e9344d818c5feed574a17f51fca27976ff7d022645c378fbbf5"},
- {file = "zstandard-0.15.2-cp35-cp35m-manylinux2014_i686.whl", hash = "sha256:1fb23b1754ce834a3a1a1e148cc2faad76eeadf9d889efe5e8199d3fb839d3c6"},
- {file = "zstandard-0.15.2-cp35-cp35m-manylinux2014_x86_64.whl", hash = "sha256:1faefe33e3d6870a4dce637bcb41f7abb46a1872a595ecc7b034016081c37543"},
- {file = "zstandard-0.15.2-cp35-cp35m-win32.whl", hash = "sha256:b7d3a484ace91ed827aa2ef3b44895e2ec106031012f14d28bd11a55f24fa734"},
- {file = "zstandard-0.15.2-cp35-cp35m-win_amd64.whl", hash = "sha256:ff5b75f94101beaa373f1511319580a010f6e03458ee51b1a386d7de5331440a"},
- {file = "zstandard-0.15.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c9e2dcb7f851f020232b991c226c5678dc07090256e929e45a89538d82f71d2e"},
- {file = "zstandard-0.15.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:4800ab8ec94cbf1ed09c2b4686288750cab0642cb4d6fba2a56db66b923aeb92"},
- {file = "zstandard-0.15.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:ec58e84d625553d191a23d5988a19c3ebfed519fff2a8b844223e3f074152163"},
- {file = "zstandard-0.15.2-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:bd3c478a4a574f412efc58ba7e09ab4cd83484c545746a01601636e87e3dbf23"},
- {file = "zstandard-0.15.2-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:6f5d0330bc992b1e267a1b69fbdbb5ebe8c3a6af107d67e14c7a5b1ede2c5945"},
- {file = "zstandard-0.15.2-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:b4963dad6cf28bfe0b61c3265d1c74a26a7605df3445bfcd3ba25de012330b2d"},
- {file = "zstandard-0.15.2-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:77d26452676f471223571efd73131fd4a626622c7960458aab2763e025836fc5"},
- {file = "zstandard-0.15.2-cp36-cp36m-win32.whl", hash = "sha256:6ffadd48e6fe85f27ca3ca10cfd3ef3d0f933bef7316870285ffeb58d791ca9c"},
- {file = "zstandard-0.15.2-cp36-cp36m-win_amd64.whl", hash = "sha256:92d49cc3b49372cfea2d42f43a2c16a98a32a6bc2f42abcde121132dbfc2f023"},
- {file = "zstandard-0.15.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:af5a011609206e390b44847da32463437505bf55fd8985e7a91c52d9da338d4b"},
- {file = "zstandard-0.15.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:31e35790434da54c106f05fa93ab4d0fab2798a6350e8a73928ec602e8505836"},
- {file = "zstandard-0.15.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:a4f8af277bb527fa3d56b216bda4da931b36b2d3fe416b6fc1744072b2c1dbd9"},
- {file = "zstandard-0.15.2-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:72a011678c654df8323aa7b687e3147749034fdbe994d346f139ab9702b59cea"},
- {file = "zstandard-0.15.2-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:5d53f02aeb8fdd48b88bc80bece82542d084fb1a7ba03bf241fd53b63aee4f22"},
- {file = "zstandard-0.15.2-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:f8bb00ced04a8feff05989996db47906673ed45b11d86ad5ce892b5741e5f9dd"},
- {file = "zstandard-0.15.2-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:7a88cc773ffe55992ff7259a8df5fb3570168d7138c69aadba40142d0e5ce39a"},
- {file = "zstandard-0.15.2-cp37-cp37m-win32.whl", hash = "sha256:1c5ef399f81204fbd9f0df3debf80389fd8aa9660fe1746d37c80b0d45f809e9"},
- {file = "zstandard-0.15.2-cp37-cp37m-win_amd64.whl", hash = "sha256:22f127ff5da052ffba73af146d7d61db874f5edb468b36c9cb0b857316a21b3d"},
- {file = "zstandard-0.15.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9867206093d7283d7de01bd2bf60389eb4d19b67306a0a763d1a8a4dbe2fb7c3"},
- {file = "zstandard-0.15.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f98fc5750aac2d63d482909184aac72a979bfd123b112ec53fd365104ea15b1c"},
- {file = "zstandard-0.15.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:3fe469a887f6142cc108e44c7f42c036e43620ebaf500747be2317c9f4615d4f"},
- {file = "zstandard-0.15.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:edde82ce3007a64e8434ccaf1b53271da4f255224d77b880b59e7d6d73df90c8"},
- {file = "zstandard-0.15.2-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:855d95ec78b6f0ff66e076d5461bf12d09d8e8f7e2b3fc9de7236d1464fd730e"},
- {file = "zstandard-0.15.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:d25c8eeb4720da41e7afbc404891e3a945b8bb6d5230e4c53d23ac4f4f9fc52c"},
- {file = "zstandard-0.15.2-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:2353b61f249a5fc243aae3caa1207c80c7e6919a58b1f9992758fa496f61f839"},
- {file = "zstandard-0.15.2-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:6cc162b5b6e3c40b223163a9ea86cd332bd352ddadb5fd142fc0706e5e4eaaff"},
- {file = "zstandard-0.15.2-cp38-cp38-win32.whl", hash = "sha256:94d0de65e37f5677165725f1fc7fb1616b9542d42a9832a9a0bdcba0ed68b63b"},
- {file = "zstandard-0.15.2-cp38-cp38-win_amd64.whl", hash = "sha256:b0975748bb6ec55b6d0f6665313c2cf7af6f536221dccd5879b967d76f6e7899"},
- {file = "zstandard-0.15.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eda0719b29792f0fea04a853377cfff934660cb6cd72a0a0eeba7a1f0df4a16e"},
- {file = "zstandard-0.15.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8fb77dd152054c6685639d855693579a92f276b38b8003be5942de31d241ebfb"},
- {file = "zstandard-0.15.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:24cdcc6f297f7c978a40fb7706877ad33d8e28acc1786992a52199502d6da2a4"},
- {file = "zstandard-0.15.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:69b7a5720b8dfab9005a43c7ddb2e3ccacbb9a2442908ae4ed49dd51ab19698a"},
- {file = "zstandard-0.15.2-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:dc8c03d0c5c10c200441ffb4cce46d869d9e5c4ef007f55856751dc288a2dffd"},
- {file = "zstandard-0.15.2-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:3e1cd2db25117c5b7c7e86a17cde6104a93719a9df7cb099d7498e4c1d13ee5c"},
- {file = "zstandard-0.15.2-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:ab9f19460dfa4c5dd25431b75bee28b5f018bf43476858d64b1aa1046196a2a0"},
- {file = "zstandard-0.15.2-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:f36722144bc0a5068934e51dca5a38a5b4daac1be84f4423244277e4baf24e7a"},
- {file = "zstandard-0.15.2-cp39-cp39-win32.whl", hash = "sha256:378ac053c0cfc74d115cbb6ee181540f3e793c7cca8ed8cd3893e338af9e942c"},
- {file = "zstandard-0.15.2-cp39-cp39-win_amd64.whl", hash = "sha256:9ee3c992b93e26c2ae827404a626138588e30bdabaaf7aa3aa25082a4e718790"},
- {file = "zstandard-0.15.2.tar.gz", hash = "sha256:52de08355fd5cfb3ef4533891092bb96229d43c2069703d4aff04fdbedf9c92f"},
+ {file = "wsproto-1.1.0-py3-none-any.whl", hash = "sha256:2218cb57952d90b9fca325c0dcfb08c3bda93e8fd8070b0a17f048e2e47a521b"},
+ {file = "wsproto-1.1.0.tar.gz", hash = "sha256:a2e56bfd5c7cd83c1369d83b5feccd6d37798b74872866e62616e0ecf111bda8"},
]
+yarl = []
+zipp = []
+zstandard = []
diff --git a/pyproject.toml b/pyproject.toml
index dd5ba59..4f996c0 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -7,18 +7,19 @@ license = "GPLv3-only"
[tool.poetry.dependencies]
python = "^3.9"
-bcrypt = "^3.2.0"
-itsdangerous = "^1.1.0"
-asyncpg = "^0.24.0"
-websockets = "^10.0"
+bcrypt = "^3.2.2"
+itsdangerous = "^2.1.2"
+asyncpg = "^0.26.0"
+websockets = "^10.3"
Earl-ETF = "^2.1.2"
logbook = "^1.5.3"
Cerberus = "^1.3.4"
-quart = "^0.15.1"
-pillow = "^8.3.2"
-aiohttp = "^3.7.4"
-zstandard = "^0.15.2"
+quart = "^0.18.0"
+pillow = "^9.2.0"
+aiohttp = "^3.8.1"
+zstandard = "^0.18.0"
winter = {git = "https://gitlab.com/elixire/winter"}
+wsproto = "^1.1.0"
diff --git a/run.py b/run.py
index b85e894..a966b48 100644
--- a/run.py
+++ b/run.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -18,6 +18,7 @@ along with this program. If not, see .
"""
import asyncio
+import ssl
import sys
import asyncpg
@@ -104,7 +105,13 @@ from litecord.pubsub.lazy_guild import LazyGuildManager
from litecord.gateway.gateway import websocket_handler
-from litecord.utils import LitecordJSONEncoder
+from litecord.json import LitecordJSONProvider
+
+# == HACKY PATCH ==
+# this MUST be removed once Hypercorn gets py3.10 support.
+from asyncio import start_server as _start_server
+
+asyncio.start_server = lambda *args, loop=None, **kwargs: _start_server(*args, **kwargs)
# setup logbook
handler = StreamHandler(sys.stdout, level=logbook.INFO)
@@ -128,12 +135,12 @@ def make_app():
logging.getLogger("websockets").setLevel(logbook.INFO)
# use our custom json encoder for custom data types
- app.json_encoder = LitecordJSONEncoder
+ app.json_provider_class = LitecordJSONProvider
return app
-PREFIXES = ("/api/v6", "/api/v7", "/api/v8", "/api/v9")
+PREFIXES = ("/api/v6", "/api/v7", "/api/v8", "/api/v9", "/api/v10")
def set_blueprints(app_):
@@ -367,7 +374,15 @@ def start_websocket(host, port, ws_handler) -> asyncio.Future:
# so we can pass quart's app object.
await ws_handler(app, ws, url)
- return websockets.serve(_wrapper, host, port)
+ kwargs = {"ws_handler": _wrapper, "host": host, "port": port}
+ tls_cert_path = getattr(app.config, "WEBSOCKET_TLS_CERT_PATH", None)
+ tls_key_path = getattr(app.config, "WEBSOCKET_TLS_CERT_PATH", None)
+ if tls_cert_path:
+ context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
+ context.load_cert_chain(tls_cert_path, tls_key_path)
+ kwargs["ssl"] = context
+
+ return websockets.serve(**kwargs)
@app.before_serving
diff --git a/setup.py b/setup.py
index ee848cf..0b312ed 100644
--- a/setup.py
+++ b/setup.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/tests/common.py b/tests/common.py
index 1c25743..aed8d44 100644
--- a/tests/common.py
+++ b/tests/common.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/tests/conftest.py b/tests/conftest.py
index e625dba..e73a1f0 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -143,3 +143,25 @@ async def test_cli_staff(test_cli):
yield client
await client.cleanup()
await _user_fixture_teardown(test_cli.app, test_user)
+
+
+@pytest.fixture
+async def test_cli_bot(test_cli):
+ """Yield a TestClient with a bot user."""
+ # do not create a new test user to prevent race conditions caused
+ # by a test wanting both fixtures
+ app = test_cli.app
+ test_user = await _user_fixture_setup(app)
+ user_id = test_user["id"]
+
+ assert await app.db.fetchval(
+ """
+ UPDATE users SET bot = true WHERE id = $1 RETURNING bot
+ """,
+ user_id,
+ )
+
+ client = TestClient(test_cli, test_user)
+ yield client
+ await client.cleanup()
+ await _user_fixture_teardown(test_cli.app, test_user)
diff --git a/tests/test_admin_api/test_guilds.py b/tests/test_admin_api/test_guilds.py
index cdb4110..846fd75 100644
--- a/tests/test_admin_api/test_guilds.py
+++ b/tests/test_admin_api/test_guilds.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/tests/test_admin_api/test_instance_invites.py b/tests/test_admin_api/test_instance_invites.py
index e9149c6..6bd423a 100644
--- a/tests/test_admin_api/test_instance_invites.py
+++ b/tests/test_admin_api/test_instance_invites.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/tests/test_admin_api/test_users.py b/tests/test_admin_api/test_users.py
index 814cd29..6fb7cd8 100644
--- a/tests/test_admin_api/test_users.py
+++ b/tests/test_admin_api/test_users.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/tests/test_channels.py b/tests/test_channels.py
index 0a7203b..4d2a70f 100644
--- a/tests/test_channels.py
+++ b/tests/test_channels.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/tests/test_embeds.py b/tests/test_embeds.py
index 3ec0448..6e76732 100644
--- a/tests/test_embeds.py
+++ b/tests/test_embeds.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/tests/test_gateway.py b/tests/test_gateway.py
index 073c1e0..f6d374f 100644
--- a/tests/test_gateway.py
+++ b/tests/test_gateway.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/tests/test_guild.py b/tests/test_guild.py
index b5c9e97..f776ad6 100644
--- a/tests/test_guild.py
+++ b/tests/test_guild.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/tests/test_invites.py b/tests/test_invites.py
index 7f4b8f7..dbfeec6 100644
--- a/tests/test_invites.py
+++ b/tests/test_invites.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/tests/test_main.py b/tests/test_main.py
index 729b37d..ab72813 100644
--- a/tests/test_main.py
+++ b/tests/test_main.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/tests/test_messages.py b/tests/test_messages.py
index a92b58d..874a514 100644
--- a/tests/test_messages.py
+++ b/tests/test_messages.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/tests/test_no_tracking.py b/tests/test_no_tracking.py
index aefc4f5..e9a93dd 100644
--- a/tests/test_no_tracking.py
+++ b/tests/test_no_tracking.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/tests/test_ratelimits.py b/tests/test_ratelimits.py
index bd675d0..8c22cae 100644
--- a/tests/test_ratelimits.py
+++ b/tests/test_ratelimits.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/tests/test_reactions.py b/tests/test_reactions.py
new file mode 100644
index 0000000..f98bf15
--- /dev/null
+++ b/tests/test_reactions.py
@@ -0,0 +1,45 @@
+"""
+
+Litecord
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 3 of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+
+"""
+
+import pytest
+import urllib.parse
+
+pytestmark = pytest.mark.asyncio
+
+
+async def test_reaction_flow(test_cli_user):
+ guild = await test_cli_user.create_guild()
+ channel = await test_cli_user.create_guild_channel(guild_id=guild.id)
+ message = await test_cli_user.create_message(
+ guild_id=guild.id, channel_id=channel.id
+ )
+
+ reaction = urllib.parse.quote("\N{THINKING FACE}")
+
+ resp = await test_cli_user.put(
+ f"/api/v6/channels/{channel.id}/messages/{message.id}/reactions/{reaction}/@me"
+ )
+ assert resp.status_code == 204
+
+ resp = await test_cli_user.get(
+ f"/api/v6/channels/{channel.id}/messages/{message.id}/reactions/{reaction}"
+ )
+ assert resp.status_code == 200
+ rjson = await resp.json
+ assert len(rjson) == 1
diff --git a/tests/test_user.py b/tests/test_user.py
index 9e0c77a..470ca75 100644
--- a/tests/test_user.py
+++ b/tests/test_user.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/tests/test_webhooks.py b/tests/test_webhooks.py
index e73c615..f253df6 100644
--- a/tests/test_webhooks.py
+++ b/tests/test_webhooks.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/tests/test_websocket.py b/tests/test_websocket.py
index f9a6153..ee8d3fe 100644
--- a/tests/test_websocket.py
+++ b/tests/test_websocket.py
@@ -1,7 +1,7 @@
"""
Litecord
-Copyright (C) 2018-2019 Luna Mendes
+Copyright (C) 2018-2021 Luna Mendes and Litecord Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -18,22 +18,172 @@ along with this program. If not, see .
"""
import json
+import zlib
+import asyncio
+import urllib.parse
+import collections
+from typing import Optional
import pytest
import websockets
+from logbook import Logger
+from wsproto import WSConnection, ConnectionType
+from wsproto.connection import ConnectionState
+from wsproto.events import (
+ Request,
+ Message,
+ AcceptConnection,
+ CloseConnection,
+ Ping,
+)
from litecord.gateway.opcodes import OP
from litecord.gateway.websocket import decode_etf
-
-async def _json(conn):
- frame = await conn.recv()
- return json.loads(frame)
+# Z_SYNC_FLUSH suffix
+ZLIB_SUFFIX = b"\x00\x00\xff\xff"
-async def _etf(conn):
- frame = await conn.recv()
- return decode_etf(frame)
+log = Logger("test_websocket")
+
+RcvdWrapper = collections.namedtuple("RcvdWrapper", "code reason")
+
+
+class AsyncWebsocket:
+ """websockets-compatible websocket object"""
+
+ def __init__(self, url):
+ self.url = url
+ self.ws = WSConnection(ConnectionType.CLIENT)
+ self.reader, self.writer = None, None
+
+ async def send(self, data):
+ assert self.writer is not None
+
+ # wrap all strings in Message
+ if isinstance(data, str):
+ data = Message(data=data)
+
+ log.debug("sending {} event", type(data))
+
+ self.writer.write(self.ws.send(data))
+ await self.writer.drain()
+
+ async def recv(self, *, expect=Message, process_event: bool = True):
+
+ # this loop is only done so we reply to pings while also being
+ # able to receive any other event in the middle.
+ #
+ # CloseConnection does not lead us to reading other events, so
+ # that's why it's left out.
+
+ while True:
+ # if there's already an unprocessed event we can try getting
+ # it from wsproto first
+ event = None
+ for event in self.ws.events():
+ break
+
+ if event is None:
+ data = await self.reader.read(4096)
+ assert data # We expect the WebSocket to be closed correctly
+ self.ws.receive_data(data)
+ continue
+
+ # if we get a ping, reply with pong immediately
+ # and fetch the next event
+ if isinstance(event, Ping):
+ await self.send(event.response())
+ continue
+
+ break
+
+ if isinstance(event, CloseConnection):
+ assert self.ws.state is ConnectionState.REMOTE_CLOSING
+ await self.send(event.response())
+ if process_event:
+ raise websockets.ConnectionClosed(
+ RcvdWrapper(event.code, event.reason), None
+ )
+
+ if expect is not None and not isinstance(event, expect):
+ raise AssertionError(
+ f"Expected {expect!r} websocket event, got {type(event)!r}"
+ )
+
+ # this keeps compatibility with code written for aaugustin/websockets
+ if expect is Message and process_event:
+ return event.data
+
+ return event
+
+ async def close(self, close_code: int, close_reason: str):
+ log.info("closing connection")
+ event = CloseConnection(code=close_code, reason=close_reason)
+ await self.send(event)
+ self.writer.close()
+ await self.writer.wait_closed()
+ self.ws.receive_data(None)
+
+ async def connect(self):
+ parsed = urllib.parse.urlparse(self.url)
+ if parsed.scheme == "wss":
+ port = 443
+ elif parsed.scheme == "ws":
+ port = 80
+ else:
+ raise AssertionError("Invalid url scheme")
+
+ host, *rest = parsed.netloc.split(":")
+ if rest:
+ port = rest[0]
+
+ log.info("connecting to {!r} {}", host, port)
+ self.reader, self.writer = await asyncio.open_connection(host, port)
+
+ path = parsed.path or "/"
+ target = f"{path}?{parsed.query}" if parsed.query else path
+ await self.send(Request(host=parsed.netloc, target=target))
+ await self.recv(expect=AcceptConnection)
+
+
+async def _recv(conn, *, zlib_stream: bool):
+ if zlib_stream:
+ try:
+ conn._zlib_context
+ except AttributeError:
+ conn._zlib_context = zlib.decompressobj()
+
+ # inspired by
+ # https://discord.com/developers/docs/topics/gateway#transport-compression-transport-compression-example
+ zlib_buffer = bytearray()
+ while True:
+ # keep receiving frames until we find the zlib prefix inside
+ # we set process_event to false so that we get the entire event
+ # instead of only data
+ event = await conn.recv(process_event=False)
+ zlib_buffer.extend(event.data)
+ if not event.message_finished:
+ continue
+
+ if len(zlib_buffer) < 4 or zlib_buffer[-4:] != ZLIB_SUFFIX:
+ raise RuntimeError("Finished compressed message without ZLIB suffix")
+
+ # NOTE: the message is utf-8 encoded.
+ msg = conn._zlib_context.decompress(zlib_buffer)
+ return msg
+ else:
+ return await conn.recv()
+
+
+async def _json(conn, *, zlib_stream: bool = False):
+ data = await _recv(conn, zlib_stream=zlib_stream)
+ return json.loads(data)
+
+
+async def _etf(conn, *, zlib_stream: bool = False):
+ data = await _recv(conn, zlib_stream=zlib_stream)
+ return decode_etf(data)
async def _json_send(conn, data):
@@ -49,6 +199,28 @@ async def _close(conn):
await conn.close(1000, "test end")
+async def extract_and_verify_ready(conn, **kwargs):
+ ready = await _json(conn, **kwargs)
+ assert ready["op"] == OP.DISPATCH
+ assert ready["t"] == "READY"
+
+ data = ready["d"]
+
+ # NOTE: change if default gateway changes
+ assert data["v"] == 6
+
+ # make sure other fields exist and are with
+ # proper types.
+ assert isinstance(data["user"], dict)
+ assert isinstance(data["private_channels"], list)
+ assert isinstance(data["guilds"], list)
+ assert isinstance(data["session_id"], str)
+ assert isinstance(data["_trace"], list)
+
+ if "shard" in data:
+ assert isinstance(data["shard"], list)
+
+
async def get_gw(test_cli, version: int) -> str:
"""Get the Gateway URL."""
gw_resp = await test_cli.get(f"/api/v{version}/gateway")
@@ -56,7 +228,9 @@ async def get_gw(test_cli, version: int) -> str:
return gw_json["url"]
-async def gw_start(test_cli, *, version: int = 6, etf=False):
+async def gw_start(
+ test_cli, *, version: int = 6, etf=False, compress: Optional[str] = None
+):
"""Start a websocket connection"""
gw_url = await get_gw(test_cli, version)
@@ -65,7 +239,11 @@ async def gw_start(test_cli, *, version: int = 6, etf=False):
else:
gw_url = f"{gw_url}?v={version}&encoding=json"
- return await websockets.connect(gw_url)
+ compress = f"&compress={compress}" if compress else ""
+
+ ws = AsyncWebsocket(f"{gw_url}{compress}")
+ await ws.connect()
+ return ws
@pytest.mark.asyncio
@@ -120,8 +298,6 @@ async def test_broken_identify(test_cli_user):
raise AssertionError("Received a JSON message but expected close")
except websockets.ConnectionClosed as exc:
assert exc.code == 4002
- finally:
- await _close(conn)
@pytest.mark.asyncio
@@ -136,27 +312,8 @@ async def test_ready_fields(test_cli_user):
)
try:
- ready = await _json(conn)
- assert isinstance(ready, dict)
- assert ready["op"] == OP.DISPATCH
- assert ready["t"] == "READY"
+ await extract_and_verify_ready(conn)
- data = ready["d"]
- assert isinstance(data, dict)
-
- # NOTE: change if default gateway changes
- assert data["v"] == 6
-
- # make sure other fields exist and are with
- # proper types.
- assert isinstance(data["user"], dict)
- assert isinstance(data["private_channels"], list)
- assert isinstance(data["guilds"], list)
- assert isinstance(data["session_id"], str)
- assert isinstance(data["_trace"], list)
-
- if "shard" in data:
- assert isinstance(data["shard"], list)
finally:
await _close(conn)
@@ -301,3 +458,32 @@ async def test_resume(test_cli_user):
assert isinstance(msg, dict)
assert isinstance(msg["op"], int)
assert msg["op"] == OP.INVALID_SESSION
+
+
+@pytest.mark.asyncio
+async def test_ready_bot(test_cli_bot):
+ conn = await gw_start(test_cli_bot.cli)
+ await _json(conn) # ignore hello
+ await _json_send(
+ conn, {"op": OP.IDENTIFY, "d": {"token": test_cli_bot.user["token"]}}
+ )
+
+ try:
+ await extract_and_verify_ready(conn)
+ finally:
+ await _close(conn)
+
+
+@pytest.mark.asyncio
+async def test_ready_bot_zlib_stream(test_cli_bot):
+ conn = await gw_start(test_cli_bot.cli, compress="zlib-stream")
+ await _json(conn, zlib_stream=True) # ignore hello
+ await _json_send(
+ conn,
+ {"op": OP.IDENTIFY, "d": {"token": test_cli_bot.user["token"]}},
+ )
+
+ try:
+ await extract_and_verify_ready(conn, zlib_stream=True)
+ finally:
+ await _close(conn)
diff --git a/tox.ini b/tox.ini
index ed53a2f..43fde9a 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,22 +1,22 @@
[tox]
-envlist = py3.9
+envlist = py3.10
isolated_build = true
[testenv]
ignore_errors = true
deps =
- pytest==6.2.5
- pytest-asyncio==0.15.1
- pytest-cov==2.12.1
- flake8==3.9.2
- black==21.6b0
- mypy==0.910
+ pytest==7.1.2
+ pytest-asyncio==0.19.0
+ pytest-cov==3.0.0
+ flake8==5.0.4
+ black==22.6.0
+ mypy==0.971
pytest-instafail==0.4.2
commands =
python3 ./manage.py migrate
black --check litecord run.py tests manage
flake8 litecord run.py tests manage
- pytest {posargs:tests}
+ pytest --asyncio-mode=auto {posargs:tests}
[flake8]
max-line-length = 88