blueprints.guild: add implementations for more routes

- Pipfile: add Cerberus for data validation
 - blueprints.guilds: add guild_owner_check
 - blueprints.guilds: simplify GUILD_MEMBER_UPDATE dispatch
 - litecord: add schemas.py
 - run: get json of errors
This commit is contained in:
Luna Mendes 2018-06-23 17:19:22 -03:00
parent b0d5a97c36
commit 21da0e0d3a
6 changed files with 265 additions and 217 deletions

View File

@ -11,6 +11,7 @@ websockets = "==5.0.1"
Quart = "==0.6.0"
Earl-ETF = "==2.1.2"
logbook = "*"
Cerberus = "==1.2"
[dev-packages]

238
Pipfile.lock generated
View File

@ -1,7 +1,20 @@
{
"_meta": {
"hash": {
"sha256": "ee2ebfbf41d6d6fbbb819a835e56ff70fd816601d4df9809b3c135484c8e1801"
"sha256": "bb7c65515934e11ebf3b17724f95fb8f1740a9c5aecb9bc2e8802bb54fa43574"
},
"host-environment-markers": {
"implementation_name": "cpython",
"implementation_version": "3.6.5",
"os_name": "posix",
"platform_machine": "x86_64",
"platform_python_implementation": "CPython",
"platform_release": "4.17.2-1-ARCH",
"platform_system": "Linux",
"platform_version": "#1 SMP PREEMPT Sat Jun 16 11:08:59 UTC 2018",
"python_full_version": "3.6.5",
"python_version": "3.6",
"sys_platform": "linux"
},
"pipfile-spec": 6,
"requires": {
@ -17,266 +30,107 @@
},
"default": {
"aiofiles": {
"hashes": [
"sha256:25c66ea3872d05d53292a6b3f7fa0f86691512076446d83a505d227b5e76f668",
"sha256:852a493a877b73e11823bfd4e8e5ef2610d70d12c9eaed961bcd9124d8de8c10"
],
"hashes": [],
"version": "==0.3.2"
},
"asyncpg": {
"hashes": [
"sha256:166c8e094de78ccbfc598a5342037a6ca5d7ee1e8144b3cfade244dd591b1ed0",
"sha256:2913b7cffdfb5bf1da5ed751485b559d1f1990be005d6d63d3ca0bf09a9d8ee6",
"sha256:31d5a9d993ce97924d9601bf6a37bb8b542d63bc8716b36238511e5e5915b14c",
"sha256:440dc17ec98c2e69f58947a591eed5967724794c876b1d6e53950e9b0b561788",
"sha256:5791554375c71ef339ee01fafb931f593c9f3ec85a5db9753c185199cee6c87e",
"sha256:600e6e14078be26e2322dfded808af55248301633592a27337b192ca2137bf04",
"sha256:cca8de381ffca375dd7cbf13f918dd68ca493e9082e7fe3f5827c08e3cfd2432",
"sha256:d201b4851a39c1f2303d99f4199974d8e01d48cec7512b59e532979ba6277def",
"sha256:d70fee2708e538a7333bca94170da8ab9233e5eae136143e2275f7b2d9bb4c24",
"sha256:e0387c4a584394997335375e897b9d63a7a31a1c77482d8b94f9a1be77bcfd08",
"sha256:e6755dd3318c0b170d4727db0e310c26e569faa101c7506b6a3e041f16ef8df9"
],
"index": "pypi",
"hashes": [],
"version": "==0.16.0"
},
"bcrypt": {
"hashes": [
"sha256:01477981abf74e306e8ee31629a940a5e9138de000c6b0898f7f850461c4a0a5",
"sha256:054d6e0acaea429e6da3613fcd12d05ee29a531794d96f6ab959f29a39f33391",
"sha256:0872eeecdf9a429c1420158500eedb323a132bc5bf3339475151c52414729e70",
"sha256:09a3b8c258b815eadb611bad04ca15ec77d86aa9ce56070e1af0d5932f17642a",
"sha256:0f317e4ffbdd15c3c0f8ab5fbd86aa9aabc7bea18b5cc5951b456fe39e9f738c",
"sha256:2788c32673a2ad0062bea850ab73cffc0dba874db10d7a3682b6f2f280553f20",
"sha256:321d4d48be25b8d77594d8324c0585c80ae91ac214f62db9098734e5e7fb280f",
"sha256:346d6f84ff0b493dbc90c6b77136df83e81f903f0b95525ee80e5e6d5e4eef84",
"sha256:34dd60b90b0f6de94a89e71fcd19913a30e83091c8468d0923a93a0cccbfbbff",
"sha256:3b4c23300c4eded8895442c003ae9b14328ae69309ac5867e7530de8bdd7875d",
"sha256:43d1960e7db14042319c46925892d5fa99b08ff21d57482e6f5328a1aca03588",
"sha256:49e96267cd9be55a349fd74f9852eb9ae2c427cd7f6455d0f1765d7332292832",
"sha256:67ed1a374c9155ec0840214ce804616de49c3df9c5bc66740687c1c9b1cd9e8d",
"sha256:6efd9ca20aefbaf2e7e6817a2c6ed4a50ff6900fafdea1bcb1d0e9471743b144",
"sha256:8569844a5d8e1fdde4d7712a05ab2e6061343ac34af6e7e3d7935b2bd1907bfd",
"sha256:8629ea6a8a59f865add1d6a87464c3c676e60101b8d16ef404d0a031424a8491",
"sha256:988cac675e25133d01a78f2286189c1f01974470817a33eaf4cfee573cfb72a5",
"sha256:9a6fedda73aba1568962f7543a1f586051c54febbc74e87769bad6a4b8587c39",
"sha256:9eced8962ce3b7124fe20fd358cf8c7470706437fa064b9874f849ad4c5866fc",
"sha256:a005ed6163490988711ff732386b08effcbf8df62ae93dd1e5bda0714fad8afb",
"sha256:ae35dbcb6b011af6c840893b32399252d81ff57d52c13e12422e16b5fea1d0fb",
"sha256:b1e8491c6740f21b37cca77bc64677696a3fb9f32360794d57fa8477b7329eda",
"sha256:c906bdb482162e9ef48eea9f8c0d967acceb5c84f2d25574c7d2a58d04861df1",
"sha256:cb18ffdc861dbb244f14be32c47ab69604d0aca415bee53485fcea4f8e93d5ef",
"sha256:d86da365dda59010ba0d1ac45aa78390f56bf7f992e65f70b3b081d5e5257b09",
"sha256:e22f0997622e1ceec834fd25947dc2ee2962c2133ea693d61805bc867abaf7ea",
"sha256:f2fe545d27a619a552396533cddf70d83cecd880a611cdfdbb87ca6aec52f66b",
"sha256:f7fd3ed3745fe6e81e28dc3b3d76cce31525a91f32a387e1febd6b982caf8cdb",
"sha256:f9210820ee4818d84658ed7df16a7f30c9fba7d8b139959950acef91745cc0f7"
],
"index": "pypi",
"hashes": [],
"version": "==3.1.4"
},
"blinker": {
"hashes": [
"sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"
],
"hashes": [],
"version": "==1.4"
},
"cerberus": {
"hashes": [],
"version": "==1.2"
},
"cffi": {
"hashes": [
"sha256:151b7eefd035c56b2b2e1eb9963c90c6302dc15fbd8c1c0a83a163ff2c7d7743",
"sha256:1553d1e99f035ace1c0544050622b7bc963374a00c467edafac50ad7bd276aef",
"sha256:1b0493c091a1898f1136e3f4f991a784437fac3673780ff9de3bcf46c80b6b50",
"sha256:2ba8a45822b7aee805ab49abfe7eec16b90587f7f26df20c71dd89e45a97076f",
"sha256:3c85641778460581c42924384f5e68076d724ceac0f267d66c757f7535069c93",
"sha256:3eb6434197633b7748cea30bf0ba9f66727cdce45117a712b29a443943733257",
"sha256:4c91af6e967c2015729d3e69c2e51d92f9898c330d6a851bf8f121236f3defd3",
"sha256:770f3782b31f50b68627e22f91cb182c48c47c02eb405fd689472aa7b7aa16dc",
"sha256:79f9b6f7c46ae1f8ded75f68cf8ad50e5729ed4d590c74840471fc2823457d04",
"sha256:7a33145e04d44ce95bcd71e522b478d282ad0eafaf34fe1ec5bbd73e662f22b6",
"sha256:857959354ae3a6fa3da6651b966d13b0a8bed6bbc87a0de7b38a549db1d2a359",
"sha256:87f37fe5130574ff76c17cab61e7d2538a16f843bb7bca8ebbc4b12de3078596",
"sha256:95d5251e4b5ca00061f9d9f3d6fe537247e145a8524ae9fd30a2f8fbce993b5b",
"sha256:9d1d3e63a4afdc29bd76ce6aa9d58c771cd1599fbba8cf5057e7860b203710dd",
"sha256:a36c5c154f9d42ec176e6e620cb0dd275744aa1d804786a71ac37dc3661a5e95",
"sha256:ae5e35a2c189d397b91034642cb0eab0e346f776ec2eb44a49a459e6615d6e2e",
"sha256:b0f7d4a3df8f06cf49f9f121bead236e328074de6449866515cea4907bbc63d6",
"sha256:b75110fb114fa366b29a027d0c9be3709579602ae111ff61674d28c93606acca",
"sha256:ba5e697569f84b13640c9e193170e89c13c6244c24400fc57e88724ef610cd31",
"sha256:be2a9b390f77fd7676d80bc3cdc4f8edb940d8c198ed2d8c0be1319018c778e1",
"sha256:d5d8555d9bfc3f02385c1c37e9f998e2011f0db4f90e250e5bc0c0a85a813085",
"sha256:e55e22ac0a30023426564b1059b035973ec82186ddddbac867078435801c7801",
"sha256:e90f17980e6ab0f3c2f3730e56d1fe9bcba1891eeea58966e89d352492cc74f4",
"sha256:ecbb7b01409e9b782df5ded849c178a0aa7c906cf8c5a67368047daab282b184",
"sha256:ed01918d545a38998bfa5902c7c00e0fee90e957ce036a4000a88e3fe2264917",
"sha256:edabd457cd23a02965166026fd9bfd196f4324fe6032e866d0f3bd0301cd486f",
"sha256:fdf1c1dc5bafc32bc5d08b054f94d659422b05aba244d6be4ddc1c72d9aa70fb"
],
"hashes": [],
"version": "==1.11.5"
},
"click": {
"hashes": [
"sha256:29f99fc6125fbc931b758dc053b3114e55c77a6e4c6c3a2674a2dc986016381d",
"sha256:f15516df478d5a56180fbf80e68f206010e6d160fc39fa508b65e035fd75130b"
],
"hashes": [],
"version": "==6.7"
},
"earl-etf": {
"hashes": [
"sha256:46bea44c3a3bf3914b01eb6a3bd42e3fb6dee6f45d68372b1237a153bf9fe4fc",
"sha256:52155ec379ec96560938f295bfa1f055743dc8be275423bdfebef14b16acfdab",
"sha256:6e3595ca9642d33cc5644c923826271f960c7df567fdaf62b5b439a0a6a9b619",
"sha256:870b40778ef6f644d6568a5afd481ce53bc87cb21fd92bfcf5b6072ede8e3078",
"sha256:d6f3e3bdbe2b74571f57b2c23f68233b464785ddf0c41870c3d8ff88db06b40e",
"sha256:f43cffbcf754e45f6716d82bb885c5072f3f8b16c1f1e26b46cb63f27e838640",
"sha256:f6a77049a21ed04095ef64f7e39ed26a2a88c17fffaf361119cd739683d25d55"
],
"index": "pypi",
"hashes": [],
"version": "==2.1.2"
},
"h11": {
"hashes": [
"sha256:1c0fbb1cba6f809fe3e6b27f8f6d517ca171f848922708871403636143d530d9",
"sha256:af77d5d82fa027c032650fb8afdef3cd0a3735ba01480bee908cddad9be1bdce"
],
"hashes": [],
"version": "==0.7.0"
},
"h2": {
"hashes": [
"sha256:4be613e35caad5680dc48f98f3bf4e7338c7c429e6375a5137be7fbe45219981",
"sha256:b2962f883fa392a23cbfcc4ad03c335bcc661be0cf9627657b589f0df2206e64"
],
"hashes": [],
"version": "==3.0.1"
},
"hpack": {
"hashes": [
"sha256:0edd79eda27a53ba5be2dfabf3b15780928a0dff6eb0c60a3d6767720e970c89",
"sha256:8eec9c1f4bfae3408a3f30500261f7e6a65912dc138526ea054f9ad98892e9d2"
],
"hashes": [],
"version": "==3.0.0"
},
"hypercorn": {
"hashes": [
"sha256:4c7cbc92e134d913d23815155fc190c8f52425fc2e0ce8131d192c310a43b91e",
"sha256:5a56a2e56f157516ea95fa589ee72d996894efba0530b411752d16e461af62e0"
],
"hashes": [],
"version": "==0.1.0"
},
"hyperframe": {
"hashes": [
"sha256:87567c9eb1540de1e7f48805adf00e87856409342fdebd0cd20cf5d381c38b69",
"sha256:a25944539db36d6a2e47689e7915dcee562b3f8d10c6cdfa0d53c91ed692fb04"
],
"hashes": [],
"version": "==5.1.0"
},
"itsdangerous": {
"hashes": [
"sha256:cbb3fcf8d3e33df861709ecaf89d9e6629cff0a217bc2848f1b41cd30d360519"
],
"index": "pypi",
"hashes": [],
"version": "==0.24"
},
"jinja2": {
"hashes": [
"sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd",
"sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4"
],
"hashes": [],
"version": "==2.10"
},
"logbook": {
"hashes": [
"sha256:3c0a3ebd48e89fcdd725fe393eb9226c789dca5a4e7842d65e2f256645fd1cd9",
"sha256:97a827a49db0f543cf67a87dbbb7f3164383c801c28641630e200d00c396baa8",
"sha256:e273188067df6c82b09a0b51d1034628fcd2dab300a074c89e64c4dbbbec0328",
"sha256:f25f247eed81b7befca3a4646a266c7f6f328a7152d75223f9d3d0ee6476c015",
"sha256:f4d0b079756f99181d7d87b701b09af1f5d8b17110fe39465cc7afd94db1e95c"
],
"index": "pypi",
"hashes": [],
"version": "==1.4.0"
},
"markupsafe": {
"hashes": [
"sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665"
],
"hashes": [],
"version": "==1.0"
},
"multidict": {
"hashes": [
"sha256:1a1d76374a1e7fe93acef96b354a03c1d7f83e7512e225a527d283da0d7ba5e0",
"sha256:1d6e191965505652f194bc4c40270a842922685918a4f45e6936a6b15cc5816d",
"sha256:295961a6a88f1199e19968e15d9b42f3a191c89ec13034dbc212bf9c394c3c82",
"sha256:2be5af084de6c3b8e20d6421cb0346378a9c867dcf7c86030d6b0b550f9888e4",
"sha256:2eb99617c7a0e9f2b90b64bc1fb742611718618572747d6f3d6532b7b78755ab",
"sha256:4ba654c6b5ad1ae4a4d792abeb695b29ce981bb0f157a41d0fd227b385f2bef0",
"sha256:5ba766433c30d703f6b2c17eb0b6826c6f898e5f58d89373e235f07764952314",
"sha256:a59d58ee85b11f337b54933e8d758b2356fcdcc493248e004c9c5e5d11eedbe4",
"sha256:a6e35d28900cf87bcc11e6ca9e474db0099b78f0be0a41d95bef02d49101b5b2",
"sha256:b4df7ca9c01018a51e43937eaa41f2f5dce17a6382fda0086403bcb1f5c2cf8e",
"sha256:bbd5a6bffd3ba8bfe75b16b5e28af15265538e8be011b0b9fddc7d86a453fd4a",
"sha256:d870f399fcd58a1889e93008762a3b9a27cf7ea512818fc6e689f59495648355",
"sha256:e9404e2e19e901121c3c5c6cffd5a8ae0d1d67919c970e3b3262231175713068"
],
"hashes": [],
"version": "==4.3.1"
},
"pycparser": {
"hashes": [
"sha256:99a8ca03e29851d96616ad0404b4aad7d9ee16f25c9f9708a11faf2810f7b226"
],
"hashes": [],
"version": "==2.18"
},
"quart": {
"hashes": [
"sha256:a5f64f15ffa5e063c07ad3675c7fe82d3945a4d48c4e3f8d0bda0494c4964a1d",
"sha256:d6da4f0e99403918874ad9e7124f13f3c0a1bb4da10021c56a89433527909d52"
],
"index": "pypi",
"hashes": [],
"version": "==0.6.0"
},
"six": {
"hashes": [
"sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9",
"sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"
],
"hashes": [],
"version": "==1.11.0"
},
"sortedcontainers": {
"hashes": [
"sha256:607294c6e291a270948420f7ffa1fb3ed47384a4c08db6d1e9c92d08a6981982",
"sha256:ef38b128302ee8f65d81e31c9d8fbf10d81df4d6d06c9c0b66f01d33747525bb"
],
"hashes": [],
"version": "==2.0.4"
},
"typing": {
"hashes": [],
"version": "==3.6.4"
},
"typing-extensions": {
"hashes": [
"sha256:1c0a8e3b4ce55207a03dd0dcb98bc47a704c71f14fe4311ec860cc8af8f4bd27",
"sha256:8b0962ecb92847974514b1724c8ae2b6dd1ffe86bcdfac429517f5e583ada658",
"sha256:be7b05ddab71727fabf1f071365043cf034e4cdac9cade1f1d61a6cc526aaafe"
],
"hashes": [],
"version": "==3.6.5"
},
"websockets": {
"hashes": [
"sha256:0b7b561bcbf992edd54e961b89551b5b6073415a0446fe445bd6554d41dabb95",
"sha256:2469c98f2254878a49a6eda248d3ed8a89bbdca85cc316ff72ea15924cec9e1f",
"sha256:29b676568e4fcb1a05064473b96243ef4e9391f251b4c485cf7f93507787b459",
"sha256:2a05e42400de009c1c330167cd6d90b300d2364d2dd1e6539d01a6a22901967b",
"sha256:39241fb291c1648e33dc41208be876a5771466291f0f6f7bff8f6732373084bd",
"sha256:43c332fc331541c57d40c124089b270d668c25a6b04908bd688969375db7327f",
"sha256:480259ec6e80f28859f23b5c231beb856fb96ab30e64ee621fdaf27da1515604",
"sha256:9049ec652713f5132b512d3498c2d37264580714ccc95dbc0f7f9622c3f6da7e",
"sha256:a17c45716178a42cc8f66f587507f01e169a75556749d88f714e4c1d295885d1",
"sha256:a49d315db5a7a19d55422e1678e8a1c3b9661d7296bef3179fa620cf80b12674",
"sha256:a911beb8149d7dae9d4c942927c448c05c41dfaa9c002a6bc26e269df932769b",
"sha256:cf34479130704797ce28a478f0b5985abe71ea90999a1c956e15fe0b0b11d0dc",
"sha256:d3724acff61ee1029fefc614cf005982338b033998a0b71fbb13a0a2fd99ab6f"
],
"index": "pypi",
"hashes": [],
"version": "==5.0.1"
},
"wsproto": {
"hashes": [
"sha256:02f214f6bb43cda62a511e2e8f1d5fa4703ed83d376d18d042bd2bbf2e995824",
"sha256:d2a7f718ab3144ec956a3267d57b5c172f0668827f5803e7d670837b0125b9fa"
],
"hashes": [],
"version": "==0.11.0"
}
},

View File

@ -4,6 +4,7 @@ from ..auth import token_check
from ..snowflake import get_snowflake
from ..enums import ChannelType
from ..errors import Forbidden, GuildNotFound, BadRequest
from ..schemas import validate, GUILD_UPDATE
bp = Blueprint('guilds', __name__)
@ -20,6 +21,21 @@ async def guild_check(user_id: int, guild_id: int):
raise GuildNotFound()
async def guild_owner_check(user_id: int, guild_id: int):
"""Check if a user is the owner of the guild."""
owner_id = await app.db.fetchval("""
SELECT owner_id
FROM guilds
WHERE guild_id = $1
""", guild_id)
if not owner_id:
raise GuildNotFound()
if user_id != owner_id:
raise Forbidden('You are not the owner of the guild')
@bp.route('', methods=['POST'])
async def create_guild():
user_id = await token_check()
@ -80,28 +96,82 @@ async def create_guild():
@bp.route('/<int:guild_id>', methods=['GET'])
async def get_guild(guild_id):
user_id = await token_check()
gj = await app.storage.get_guild(guild_id, user_id)
gj_extra = await app.storage.get_guild_extra(guild_id, user_id, 250)
return jsonify({**gj, **gj_extra})
@bp.route('/<int:guild_id>', methods=['UPDATE'])
async def update_guild(guild_id):
user_id = await token_check()
await guild_check(user_id, guild_id)
j = validate(await request.get_json(), GUILD_UPDATE)
# TODO: check MANAGE_GUILD
if 'owner_id' in j:
await guild_owner_check(user_id, guild_id)
await app.db.execute("""
UPDATE guilds
SET owner_id = $1
WHERE guild_id = $2
""", int(j['owner_id']), guild_id)
if 'name' in j:
await app.db.execute("""
UPDATE guilds
SET name = $1
WHERE guild_id = $2
""", j['name'], guild_id)
if 'region' in j:
# TODO: check region value
await app.db.execute("""
UPDATE guilds
SET region = $1
WHERE guild_id = $2
""", j['region'], guild_id)
fields = ['verification_level', 'default_message_notifications',
'explicit_content_filter', 'afk_timeout']
for field in [f for f in fields if f in j]:
await app.db.execute("""
UPDATE guilds
SET {field} = $1
WHERE guild_id = $2
""", j[field], guild_id)
channel_fields = ['afk_channel_id', 'system_channel_id']
for field in [f for f in channel_fields if f in j]:
# TODO: check channel link to guild
await app.db.execute("""
UPDATE guilds
SET {field} = $1
WHERE guild_id = $2
""", j[field], guild_id)
# return guild object
gj = await app.storage.get_guild(guild_id, user_id)
gj_extra = await app.storage.get_guild_extra(guild_id, user_id, 250)
gj_total = {**gj, **gj_extra}
await app.dispatcher.dispatch_guild(guild_id, 'GUILD_UPDATE', gj_total)
return jsonify({**gj, **gj_extra})
@bp.route('/<int:guild_id>', methods=['DELETE'])
async def delete_guild(guild_id):
"""Delete a guild."""
user_id = await token_check()
owner_id = await app.db.fetchval("""
SELECT owner_id
FROM guilds
WHERE guild_id = $1
""", guild_id)
if not owner_id:
raise GuildNotFound()
if user_id != owner_id:
raise Forbidden('You are not the owner of the guild')
await guild_owner_check(user_id, guild_id)
await app.db.execute("""
DELETE FROM guild
@ -188,6 +258,17 @@ async def create_channel(guild_id):
return jsonify(channel)
@bp.route('/<int:guild_id>/channels', methods=['PATCH'])
async def modify_channel_pos(guild_id):
user_id = await token_check()
await guild_check(user_id, guild_id)
await request.get_json()
# TODO: this route
raise NotImplementedError
@bp.route('/<int:guild_id>/members/<int:member_id>', methods=['GET'])
async def get_guild_member(guild_id, member_id):
user_id = await token_check()
@ -221,6 +302,52 @@ async def get_members(guild_id):
return jsonify(members)
@bp.route('/<int:guild_id>/members/<int:member_id>', methods=['PATCH'])
async def modify_guild_member(guild_id, member_id):
j = await request.get_json()
if 'nick' in j:
# TODO: check MANAGE_NICKNAMES
await app.db.execute("""
UPDATE members
SET nickname = $1
WHERE user_id = $2 AND guild_id = $3
""", j['nick'], member_id, guild_id)
if 'mute' in j:
# TODO: check MUTE_MEMBERS
await app.db.execute("""
UPDATE members
SET muted = $1
WHERE user_id = $2 AND guild_id = $3
""", j['mute'], member_id, guild_id)
if 'deaf' in j:
# TODO: check DEAFEN_MEMBERS
await app.db.execute("""
UPDATE members
SET deafened = $1
WHERE user_id = $2 AND guild_id = $3
""", j['deaf'], member_id, guild_id)
if 'channel_id' in j:
# TODO: check MOVE_MEMBERS
# TODO: change the member's voice channel
pass
member = await app.storage.get_member_data_one(guild_id, member_id)
member.pop('joined_at')
await app.dispatcher.dispatch_guild(guild_id, 'GUILD_MEMBER_UPDATE', {**{
'guild_id': str(guild_id)
}, **member})
return '', 204
@bp.route('/<int:guild_id>/members/@me/nick', methods=['PATCH'])
async def update_nickname(guild_id):
user_id = await token_check()
@ -234,17 +361,11 @@ async def update_nickname(guild_id):
WHERE user_id = $2 AND guild_id = $3
""", j['nick'], user_id, guild_id)
roles = await app.db.fetch("""
SELECT role_id
FROM member_roles
WHERE user_id = $1 AND guild_id = $2
""", user_id, guild_id)
member = await app.storage.get_member_data_one(guild_id, user_id)
member.pop('joined_at')
await app.dispatcher.dispatch_guild(guild_id, 'GUILD_MEMBER_UPDATE', {
'guild_id': str(guild_id),
'roles': list(map(str, roles)),
'user': await app.storage.get_user(user_id),
'nick': j['nick'],
})
await app.dispatcher.dispatch_guild(guild_id, 'GUILD_MEMBER_UPDATE', {**{
'guild_id': str(guild_id)
}, **member})
return j['nick']

View File

@ -5,6 +5,10 @@ class LitecordError(Exception):
def message(self):
return self.args[0]
@property
def json(self):
return self.args[1]
class BadRequest(LitecordError):
status_code = 400

63
litecord/schemas.py Normal file
View File

@ -0,0 +1,63 @@
import re
from cerberus import Validator
from .errors import BadRequest
USERNAME_REGEX = re.compile(r'^[a-zA-Z0-9_]{2,19}$', re.A)
EMAIL_REGEX = re.compile(r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$',
re.A)
class LitecordValidator(Validator):
def _validate_type_username(self, value: str) -> bool:
"""Validate against the username regex."""
return bool(USERNAME_REGEX.match(value))
def validate(reqjson, schema):
validator = LitecordValidator(schema)
if not validator.validate(reqjson):
errs = validator.errors
raise BadRequest('bad payload', errs)
return reqjson
GUILD_UPDATE = {
'name': {
'type': 'string',
'minlength': 2,
'maxlength': 100,
'required': False
},
'region': {'type': 'voice_region', 'required': False},
'icon': {'type': 'icon', 'required': False},
'verification_level': {'type': 'verification_level', 'required': False},
'default_message_notifications': {
'type': 'msg_notifications',
'required': False,
},
'explicit_content_filter': {'type': 'explicit_content', 'required': False},
'afk_channel_id': {'type': 'snowflake', 'required': False},
'afk_timeout': {'type': 'number', 'required': False},
'owner_id': {'type': 'snowflake', 'required': False},
'system_channel_id': {'type': 'snowflake', 'required': False},
}
MEMBER_UPDATE = {
'nick': {
'type': 'nickname',
'minlength': 1, 'maxlength': 100,
'required': False,
},
'roles': {'type': 'list', 'required': False},
'mute': {'type': 'bool', 'required': False},
'deaf': {'type': 'bool', 'required': False},
'channel_id': {'type': 'snowflake', 'required': False},
}

9
run.py
View File

@ -76,12 +76,17 @@ async def app_after_serving():
@app.errorhandler(LitecordError)
async def handle_litecord_err(err):
return jsonify({
try:
ejson = err.json
except IndexError:
ejson = {}
return jsonify({**{
'error': True,
# 'code': err.code,
'status': err.status_code,
'message': err.message,
}), err.status_code
}, **ejson}), err.status_code
@app.errorhandler(500)