diff --git a/LICENSE b/LICENSE index 979e30399..fad70566e 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. Red - A fully customizable Discord bot - Copyright (C) 2015-2018 Twentysix + Copyright (C) 2015-2019 Twentysix 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 @@ -652,7 +652,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: - Red-DiscordBot Copyright (C) 2015-2018 Twentysix + Red-DiscordBot Copyright (C) 2015-2019 Twentysix 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/Makefile b/Makefile index beecb6d28..f44b67264 100644 --- a/Makefile +++ b/Makefile @@ -9,5 +9,5 @@ gettext: REF?=rewrite update_vendor: pip install --upgrade --no-deps -t . https://github.com/Rapptz/discord.py/archive/$(REF).tar.gz#egg=discord.py - rm -r discord.py*.egg-info + rm -r discord.py*-info $(MAKE) reformat diff --git a/Pipfile.lock b/Pipfile.lock index 0b5caee71..4e38150fb 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -16,37 +16,37 @@ "default": { "aiohttp": { "hashes": [ - "sha256:0419705a36b43c0ac6f15469f9c2a08cad5c939d78bd12a5c23ea167c8253b2b", - "sha256:1812fc4bc6ac1bde007daa05d2d0f61199324e0cc893b11523e646595047ca08", - "sha256:2214b5c0153f45256d5d52d1e0cafe53f9905ed035a142191727a5fb620c03dd", - "sha256:275909137f0c92c61ba6bb1af856a522d5546f1de8ea01e4e726321c697754ac", - "sha256:3983611922b561868428ea1e7269e757803713f55b53502423decc509fef1650", - "sha256:51afec6ffa50a9da4cdef188971a802beb1ca8e8edb40fa429e5e529db3475fa", - "sha256:589f2ec8a101a0f340453ee6945bdfea8e1cd84c8d88e5be08716c34c0799d95", - "sha256:789820ddc65e1f5e71516adaca2e9022498fa5a837c79ba9c692a9f8f916c330", - "sha256:7a968a0bdaaf9abacc260911775611c9a602214a23aeb846f2eb2eeaa350c4dc", - "sha256:7aeefbed253f59ea39e70c5848de42ed85cb941165357fc7e87ab5d8f1f9592b", - "sha256:7b2eb55c66512405103485bd7d285a839d53e7fdc261ab20e5bcc51d7aaff5de", - "sha256:87bc95d3d333bb689c8d755b4a9d7095a2356108002149523dfc8e607d5d32a4", - "sha256:9d80e40db208e29168d3723d1440ecbb06054d349c5ece6a2c5a611490830dd7", - "sha256:a1b442195c2a77d33e4dbee67c9877ccbdd3a1f686f91eb479a9577ed8cc326b", - "sha256:ab3d769413b322d6092f169f316f7b21cd261a7589f7e31db779d5731b0480d8", - "sha256:b066d3dec5d0f5aee6e34e5765095dc3d6d78ef9839640141a2b20816a0642bd", - "sha256:b24e7845ae8de3e388ef4bcfcf7f96b05f52c8e633b33cf8003a6b1d726fc7c2", - "sha256:c59a953c3f8524a7c86eaeaef5bf702555be12f5668f6384149fe4bb75c52698", - "sha256:cf2cc6c2c10d242790412bea7ccf73726a9a44b4c4b073d2699ef3b48971fd95", - "sha256:e0c9c8d4150ae904f308ff27b35446990d2b1dfc944702a21925937e937394c6", - "sha256:f1839db4c2b08a9c8f9788112644f8a8557e8e0ecc77b07091afabb941dc55d0", - "sha256:f3df52362be39908f9c028a65490fae0475e4898b43a03d8aa29d1e765b45e07" + "sha256:00d198585474299c9c3b4f1d5de1a576cc230d562abc5e4a0e81d71a20a6ca55", + "sha256:0155af66de8c21b8dba4992aaeeabf55503caefae00067a3b1139f86d0ec50ed", + "sha256:09654a9eca62d1bd6d64aa44db2498f60a5c1e0ac4750953fdd79d5c88955e10", + "sha256:199f1d106e2b44b6dacdf6f9245493c7d716b01d0b7fbe1959318ba4dc64d1f5", + "sha256:296f30dedc9f4b9e7a301e5cc963012264112d78a1d3094cd83ef148fdf33ca1", + "sha256:368ed312550bd663ce84dc4b032a962fcb3c7cae099dbbd48663afc305e3b939", + "sha256:40d7ea570b88db017c51392349cf99b7aefaaddd19d2c78368aeb0bddde9d390", + "sha256:629102a193162e37102c50713e2e31dc9a2fe7ac5e481da83e5bb3c0cee700aa", + "sha256:6d5ec9b8948c3d957e75ea14d41e9330e1ac3fed24ec53766c780f82805140dc", + "sha256:87331d1d6810214085a50749160196391a712a13336cd02ce1c3ea3d05bcf8d5", + "sha256:9a02a04bbe581c8605ac423ba3a74999ec9d8bce7ae37977a3d38680f5780b6d", + "sha256:9c4c83f4fa1938377da32bc2d59379025ceeee8e24b89f72fcbccd8ca22dc9bf", + "sha256:9cddaff94c0135ee627213ac6ca6d05724bfe6e7a356e5e09ec57bd3249510f6", + "sha256:a25237abf327530d9561ef751eef9511ab56fd9431023ca6f4803f1994104d72", + "sha256:a5cbd7157b0e383738b8e29d6e556fde8726823dae0e348952a61742b21aeb12", + "sha256:a97a516e02b726e089cffcde2eea0d3258450389bbac48cbe89e0f0b6e7b0366", + "sha256:acc89b29b5f4e2332d65cd1b7d10c609a75b88ef8925d487a611ca788432dfa4", + "sha256:b05bd85cc99b06740aad3629c2585bda7b83bd86e080b44ba47faf905fdf1300", + "sha256:c2bec436a2b5dafe5eaeb297c03711074d46b6eb236d002c13c42f25c4a8ce9d", + "sha256:cc619d974c8c11fe84527e4b5e1c07238799a8c29ea1c1285149170524ba9303", + "sha256:d4392defd4648badaa42b3e101080ae3313e8f4787cb517efd3f5b8157eaefd6", + "sha256:e1c3c582ee11af7f63a34a46f0448fca58e59889396ffdae1f482085061a2889" ], - "version": "==3.4.4" + "version": "==3.5.4" }, "aiohttp-json-rpc": { "hashes": [ - "sha256:00d72f40edfc7271578d545a8c47874c0e23cc5d3201ed8128481f6a4af47e32", - "sha256:02d83b6998f8a0b7e59b46f0cb8a96b475bbf82600b1f9527df47135353f1ca8" + "sha256:1d040b7b10ff414f9174398ff6e9c647eb0434a00939450b33aa539177c51dcf", + "sha256:5f5fb141c6263d2ea52a4173babe9449eef4029620dc49936dca45cdc17ac9dd" ], - "version": "==0.11.2" + "version": "==0.12" }, "appdirs": { "hashes": [ @@ -83,13 +83,6 @@ ], "version": "==0.4.1" }, - "distro": { - "hashes": [ - "sha256:224041cef9600e72d19ae41ba006e71c05c4dc802516da715d7fda55ba3d8742", - "sha256:6ec8e539cf412830e5ccf521aecf879f2c7fcf60ce446e33cd16eef1ed8a0158" - ], - "version": "==1.3.0" - }, "dnspython": { "hashes": [ "sha256:36c5e8e38d4369a08b6780b7f27d790a292b2b08eea01607865bf0936c558e01", @@ -261,10 +254,10 @@ }, "red-lavalink": { "hashes": [ - "sha256:6348cc168572b1984e9831a29b4023f02372bb683fec8e863df5abeb605b630a", - "sha256:a5ab9d66d1a4728abe48ccb38a2a130a8a2d70fb23c9d9df2b747c82fbeb67a6" + "sha256:10a07b2b5736f52a0f5c3eeab3fbc3bf6a242ca6ee284a29ad79d6d1673ddfc3", + "sha256:9df0ddaa92d0d7294a4e236c4069765a0b8e5f258c18075dedf28f4b64a1aab5" ], - "version": "==0.2.0" + "version": "==0.2.1" }, "schema": { "hashes": [ @@ -275,29 +268,29 @@ }, "websockets": { "hashes": [ - "sha256:0e2f7d6567838369af074f0ef4d0b802d19fa1fee135d864acc656ceefa33136", - "sha256:2a16dac282b2fdae75178d0ed3d5b9bc3258dabfae50196cbb30578d84b6f6a6", - "sha256:5a1fa6072405648cb5b3688e9ed3b94be683ce4a4e5723e6f5d34859dee495c1", - "sha256:5c1f55a1274df9d6a37553fef8cff2958515438c58920897675c9bc70f5a0538", - "sha256:669d1e46f165e0ad152ed8197f7edead22854a6c90419f544e0f234cc9dac6c4", - "sha256:695e34c4dbea18d09ab2c258994a8bf6a09564e762655408241f6a14592d2908", - "sha256:6b2e03d69afa8d20253455e67b64de1a82ff8612db105113cccec35d3f8429f0", - "sha256:79ca7cdda7ad4e3663ea3c43bfa8637fc5d5604c7737f19a8964781abbd1148d", - "sha256:7fd2dd9a856f72e6ed06f82facfce01d119b88457cd4b47b7ae501e8e11eba9c", - "sha256:82c0354ac39379d836719a77ee360ef865377aa6fdead87909d50248d0f05f4d", - "sha256:8f3b956d11c5b301206382726210dc1d3bee1a9ccf7aadf895aaf31f71c3716c", - "sha256:91ec98640220ae05b34b79ee88abf27f97ef7c61cf525eec57ea8fcea9f7dddb", - "sha256:952be9540d83dba815569d5cb5f31708801e0bbfc3a8c5aef1890b57ed7e58bf", - "sha256:99ac266af38ba1b1fe13975aea01ac0e14bb5f3a3200d2c69f05385768b8568e", - "sha256:9fa122e7adb24232247f8a89f2d9070bf64b7869daf93ac5e19546b409e47e96", - "sha256:a0873eadc4b8ca93e2e848d490809e0123eea154aa44ecd0109c4d0171869584", - "sha256:cb998bd4d93af46b8b49ecf5a72c0a98e5cc6d57fdca6527ba78ad89d6606484", - "sha256:e02e57346f6a68523e3c43bbdf35dde5c440318d1f827208ae455f6a2ace446d", - "sha256:e79a5a896bcee7fff24a788d72e5c69f13e61369d055f28113e71945a7eb1559", - "sha256:ee55eb6bcf23ecc975e6b47c127c201b913598f38b6a300075f84eeef2d3baff", - "sha256:f1414e6cbcea8d22843e7eafdfdfae3dd1aba41d1945f6ca66e4806c07c4f454" + "sha256:04b42a1b57096ffa5627d6a78ea1ff7fad3bc2c0331ffc17bc32a4024da7fea0", + "sha256:08e3c3e0535befa4f0c4443824496c03ecc25062debbcf895874f8a0b4c97c9f", + "sha256:10d89d4326045bf5e15e83e9867c85d686b612822e4d8f149cf4840aab5f46e0", + "sha256:232fac8a1978fc1dead4b1c2fa27c7756750fb393eb4ac52f6bc87ba7242b2fa", + "sha256:4bf4c8097440eff22bc78ec76fe2a865a6e658b6977a504679aaf08f02c121da", + "sha256:51642ea3a00772d1e48fb0c492f0d3ae3b6474f34d20eca005a83f8c9c06c561", + "sha256:55d86102282a636e195dad68aaaf85b81d0bef449d7e2ef2ff79ac450bb25d53", + "sha256:564d2675682bd497b59907d2205031acbf7d3fadf8c763b689b9ede20300b215", + "sha256:5d13bf5197a92149dc0badcc2b699267ff65a867029f465accfca8abab95f412", + "sha256:5eda665f6789edb9b57b57a159b9c55482cbe5b046d7db458948370554b16439", + "sha256:5edb2524d4032be4564c65dc4f9d01e79fe8fad5f966e5b552f4e5164fef0885", + "sha256:79691794288bc51e2a3b8de2bc0272ca8355d0b8503077ea57c0716e840ebaef", + "sha256:7fcc8681e9981b9b511cdee7c580d5b005f3bb86b65bde2188e04a29f1d63317", + "sha256:8e447e05ec88b1b408a4c9cde85aa6f4b04f06aa874b9f0b8e8319faf51b1fee", + "sha256:90ea6b3e7787620bb295a4ae050d2811c807d65b1486749414f78cfd6fb61489", + "sha256:9e13239952694b8b831088431d15f771beace10edfcf9ef230cefea14f18508f", + "sha256:d40f081187f7b54d7a99d8a5c782eaa4edc335a057aa54c85059272ed826dc09", + "sha256:e1df1a58ed2468c7b7ce9a2f9752a32ad08eac2bcd56318625c3647c2cd2da6f", + "sha256:e98d0cec437097f09c7834a11c69d79fe6241729b23f656cfc227e93294fc242", + "sha256:f8d59627702d2ff27cb495ca1abdea8bd8d581de425c56e93bff6517134e0a9b", + "sha256:fc30cdf2e949a2225b012a7911d1d031df3d23e99b7eda7dfc982dc4a860dae9" ], - "version": "==6.0" + "version": "==7.0" }, "yarl": { "hashes": [ @@ -319,37 +312,37 @@ "develop": { "aiohttp": { "hashes": [ - "sha256:0419705a36b43c0ac6f15469f9c2a08cad5c939d78bd12a5c23ea167c8253b2b", - "sha256:1812fc4bc6ac1bde007daa05d2d0f61199324e0cc893b11523e646595047ca08", - "sha256:2214b5c0153f45256d5d52d1e0cafe53f9905ed035a142191727a5fb620c03dd", - "sha256:275909137f0c92c61ba6bb1af856a522d5546f1de8ea01e4e726321c697754ac", - "sha256:3983611922b561868428ea1e7269e757803713f55b53502423decc509fef1650", - "sha256:51afec6ffa50a9da4cdef188971a802beb1ca8e8edb40fa429e5e529db3475fa", - "sha256:589f2ec8a101a0f340453ee6945bdfea8e1cd84c8d88e5be08716c34c0799d95", - "sha256:789820ddc65e1f5e71516adaca2e9022498fa5a837c79ba9c692a9f8f916c330", - "sha256:7a968a0bdaaf9abacc260911775611c9a602214a23aeb846f2eb2eeaa350c4dc", - "sha256:7aeefbed253f59ea39e70c5848de42ed85cb941165357fc7e87ab5d8f1f9592b", - "sha256:7b2eb55c66512405103485bd7d285a839d53e7fdc261ab20e5bcc51d7aaff5de", - "sha256:87bc95d3d333bb689c8d755b4a9d7095a2356108002149523dfc8e607d5d32a4", - "sha256:9d80e40db208e29168d3723d1440ecbb06054d349c5ece6a2c5a611490830dd7", - "sha256:a1b442195c2a77d33e4dbee67c9877ccbdd3a1f686f91eb479a9577ed8cc326b", - "sha256:ab3d769413b322d6092f169f316f7b21cd261a7589f7e31db779d5731b0480d8", - "sha256:b066d3dec5d0f5aee6e34e5765095dc3d6d78ef9839640141a2b20816a0642bd", - "sha256:b24e7845ae8de3e388ef4bcfcf7f96b05f52c8e633b33cf8003a6b1d726fc7c2", - "sha256:c59a953c3f8524a7c86eaeaef5bf702555be12f5668f6384149fe4bb75c52698", - "sha256:cf2cc6c2c10d242790412bea7ccf73726a9a44b4c4b073d2699ef3b48971fd95", - "sha256:e0c9c8d4150ae904f308ff27b35446990d2b1dfc944702a21925937e937394c6", - "sha256:f1839db4c2b08a9c8f9788112644f8a8557e8e0ecc77b07091afabb941dc55d0", - "sha256:f3df52362be39908f9c028a65490fae0475e4898b43a03d8aa29d1e765b45e07" + "sha256:00d198585474299c9c3b4f1d5de1a576cc230d562abc5e4a0e81d71a20a6ca55", + "sha256:0155af66de8c21b8dba4992aaeeabf55503caefae00067a3b1139f86d0ec50ed", + "sha256:09654a9eca62d1bd6d64aa44db2498f60a5c1e0ac4750953fdd79d5c88955e10", + "sha256:199f1d106e2b44b6dacdf6f9245493c7d716b01d0b7fbe1959318ba4dc64d1f5", + "sha256:296f30dedc9f4b9e7a301e5cc963012264112d78a1d3094cd83ef148fdf33ca1", + "sha256:368ed312550bd663ce84dc4b032a962fcb3c7cae099dbbd48663afc305e3b939", + "sha256:40d7ea570b88db017c51392349cf99b7aefaaddd19d2c78368aeb0bddde9d390", + "sha256:629102a193162e37102c50713e2e31dc9a2fe7ac5e481da83e5bb3c0cee700aa", + "sha256:6d5ec9b8948c3d957e75ea14d41e9330e1ac3fed24ec53766c780f82805140dc", + "sha256:87331d1d6810214085a50749160196391a712a13336cd02ce1c3ea3d05bcf8d5", + "sha256:9a02a04bbe581c8605ac423ba3a74999ec9d8bce7ae37977a3d38680f5780b6d", + "sha256:9c4c83f4fa1938377da32bc2d59379025ceeee8e24b89f72fcbccd8ca22dc9bf", + "sha256:9cddaff94c0135ee627213ac6ca6d05724bfe6e7a356e5e09ec57bd3249510f6", + "sha256:a25237abf327530d9561ef751eef9511ab56fd9431023ca6f4803f1994104d72", + "sha256:a5cbd7157b0e383738b8e29d6e556fde8726823dae0e348952a61742b21aeb12", + "sha256:a97a516e02b726e089cffcde2eea0d3258450389bbac48cbe89e0f0b6e7b0366", + "sha256:acc89b29b5f4e2332d65cd1b7d10c609a75b88ef8925d487a611ca788432dfa4", + "sha256:b05bd85cc99b06740aad3629c2585bda7b83bd86e080b44ba47faf905fdf1300", + "sha256:c2bec436a2b5dafe5eaeb297c03711074d46b6eb236d002c13c42f25c4a8ce9d", + "sha256:cc619d974c8c11fe84527e4b5e1c07238799a8c29ea1c1285149170524ba9303", + "sha256:d4392defd4648badaa42b3e101080ae3313e8f4787cb517efd3f5b8157eaefd6", + "sha256:e1c3c582ee11af7f63a34a46f0448fca58e59889396ffdae1f482085061a2889" ], - "version": "==3.4.4" + "version": "==3.5.4" }, "aiohttp-json-rpc": { "hashes": [ - "sha256:00d72f40edfc7271578d545a8c47874c0e23cc5d3201ed8128481f6a4af47e32", - "sha256:02d83b6998f8a0b7e59b46f0cb8a96b475bbf82600b1f9527df47135353f1ca8" + "sha256:1d040b7b10ff414f9174398ff6e9c647eb0434a00939450b33aa539177c51dcf", + "sha256:5f5fb141c6263d2ea52a4173babe9449eef4029620dc49936dca45cdc17ac9dd" ], - "version": "==0.11.2" + "version": "==0.12" }, "alabaster": { "hashes": [ @@ -374,10 +367,10 @@ }, "atomicwrites": { "hashes": [ - "sha256:0312ad34fcad8fac3704d441f7b317e50af620823353ec657a53e981f92920c0", - "sha256:ec9ae8adaae229e4f8446952d204a3e4b5fdd2d099f9be3aaf556120135fb3ee" + "sha256:03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4", + "sha256:75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6" ], - "version": "==1.2.1" + "version": "==1.3.0" }, "attrs": { "hashes": [ @@ -428,13 +421,6 @@ ], "version": "==0.4.1" }, - "distro": { - "hashes": [ - "sha256:224041cef9600e72d19ae41ba006e71c05c4dc802516da715d7fda55ba3d8742", - "sha256:6ec8e539cf412830e5ccf521aecf879f2c7fcf60ce446e33cd16eef1ed8a0158" - ], - "version": "==1.3.0" - }, "docutils": { "hashes": [ "sha256:02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6", @@ -519,11 +505,10 @@ }, "more-itertools": { "hashes": [ - "sha256:38a936c0a6d98a38bcc2d03fdaaedaba9f412879461dd2ceff8d37564d6522e4", - "sha256:c0a5785b1109a6bd7fac76d6837fd1feca158e54e521ccd2ae8bfe393cc9d4fc", - "sha256:fe7a7cae1ccb57d33952113ff4fa1bc5f879963600ed74918f1236e212ee50b9" + "sha256:0125e8f60e9e031347105eb1682cef932f5e97d7b9a1a28d9bf00c22a5daef40", + "sha256:590044e3942351a1bdb1de960b739ff4ce277960f2425ad4509446dbace8d9d1" ], - "version": "==5.0.0" + "version": "==6.0.0" }, "multidict": { "hashes": [ @@ -561,10 +546,10 @@ }, "packaging": { "hashes": [ - "sha256:0886227f54515e592aaa2e5a553332c73962917f2831f1b0f9b9f4380a4b9807", - "sha256:f95a1e147590f204328170981833854229bb2912ac3d5f89e2a8ccd2834800c9" + "sha256:0c98a5d0be38ed775798ece1b9727178c4469d9c3b4ada66e8e6b7849f8732af", + "sha256:9e1cbf8c12b1f1ce0bb5344b8d7ecf66a6f8a6e91bcb0c84593ed6d3ab5c4ab3" ], - "version": "==18.0" + "version": "==19.0" }, "pluggy": { "hashes": [ @@ -589,17 +574,17 @@ }, "pyparsing": { "hashes": [ - "sha256:40856e74d4987de5d01761a22d1621ae1c7f8774585acae358aa5c5936c6c90b", - "sha256:f353aab21fd474459d97b709e527b5571314ee5f067441dc9f88e33eecd96592" + "sha256:66c9268862641abcac4a96ba74506e594c884e3f57690a696d21ad8210ed667a", + "sha256:f6c5ef0d7480ad048c054c37632c67fca55299990fff127850181659eea33fc3" ], - "version": "==2.3.0" + "version": "==2.3.1" }, "pytest": { "hashes": [ - "sha256:3e65a22eb0d4f1bdbc1eacccf4a3198bf8d4049dea5112d70a0c61b00e748d02", - "sha256:5924060b374f62608a078494b909d341720a050b5224ff87e17e12377486a71d" + "sha256:65aeaa77ae87c7fc95de56285282546cfa9c886dc8e5dc78313db1c25e21bc07", + "sha256:6ac6d467d9f053e95aaacd79f831dbecfe730f419c6c7022cb316b365cd9199d" ], - "version": "==4.1.0" + "version": "==4.2.0" }, "pytest-asyncio": { "hashes": [ @@ -679,10 +664,10 @@ }, "red-lavalink": { "hashes": [ - "sha256:6348cc168572b1984e9831a29b4023f02372bb683fec8e863df5abeb605b630a", - "sha256:a5ab9d66d1a4728abe48ccb38a2a130a8a2d70fb23c9d9df2b747c82fbeb67a6" + "sha256:10a07b2b5736f52a0f5c3eeab3fbc3bf6a242ca6ee284a29ad79d6d1673ddfc3", + "sha256:9df0ddaa92d0d7294a4e236c4069765a0b8e5f258c18075dedf28f4b64a1aab5" ], - "version": "==0.2.0" + "version": "==0.2.1" }, "requests": { "hashes": [ @@ -714,17 +699,17 @@ }, "sphinx": { "hashes": [ - "sha256:429e3172466df289f0f742471d7e30ba3ee11f3b5aecd9a840480d03f14bcfe5", - "sha256:c4cb17ba44acffae3d3209646b6baec1e215cad3065e852c68cc569d4df1b9f8" + "sha256:b53904fa7cb4b06a39409a492b949193a1b68cc7241a1a8ce9974f86f0d24287", + "sha256:c1c00fc4f6e8b101a0d037065043460dffc2d507257f2f11acaed71fd2b0c83c" ], - "version": "==1.8.3" + "version": "==1.8.4" }, "sphinx-rtd-theme": { "hashes": [ - "sha256:02f02a676d6baabb758a20c7a479d58648e0f64f13e07d1b388e9bb2afe86a09", - "sha256:d0f6bc70f98961145c5b0e26a992829363a197321ba571b31b24ea91879e0c96" + "sha256:00cf895504a7895ee433807c62094cf1e95f065843bf3acd17037c3e9a2becd4", + "sha256:728607e34d60456d736cc7991fd236afb828b21b82f956c5ea75f94c8414040a" ], - "version": "==0.4.2" + "version": "==0.4.3" }, "sphinxcontrib-asyncio": { "hashes": [ @@ -763,36 +748,36 @@ }, "virtualenv": { "hashes": [ - "sha256:58c359370401e0af817fb0070911e599c5fdc836166306b04fd0f278151ed125", - "sha256:729f0bcab430e4ef137646805b5b1d8efbb43fe53d4a0f33328624a84a5121f7" + "sha256:8b9abfc51c38b70f61634bf265e5beacf6fae11fc25d355d1871f49b8e45f0db", + "sha256:cceab52aa7d4df1e1871a70236eb2b89fcfe29b6b43510d9738689787c513261" ], - "version": "==16.3.0" + "version": "==16.4.0" }, "websockets": { "hashes": [ - "sha256:0e2f7d6567838369af074f0ef4d0b802d19fa1fee135d864acc656ceefa33136", - "sha256:2a16dac282b2fdae75178d0ed3d5b9bc3258dabfae50196cbb30578d84b6f6a6", - "sha256:5a1fa6072405648cb5b3688e9ed3b94be683ce4a4e5723e6f5d34859dee495c1", - "sha256:5c1f55a1274df9d6a37553fef8cff2958515438c58920897675c9bc70f5a0538", - "sha256:669d1e46f165e0ad152ed8197f7edead22854a6c90419f544e0f234cc9dac6c4", - "sha256:695e34c4dbea18d09ab2c258994a8bf6a09564e762655408241f6a14592d2908", - "sha256:6b2e03d69afa8d20253455e67b64de1a82ff8612db105113cccec35d3f8429f0", - "sha256:79ca7cdda7ad4e3663ea3c43bfa8637fc5d5604c7737f19a8964781abbd1148d", - "sha256:7fd2dd9a856f72e6ed06f82facfce01d119b88457cd4b47b7ae501e8e11eba9c", - "sha256:82c0354ac39379d836719a77ee360ef865377aa6fdead87909d50248d0f05f4d", - "sha256:8f3b956d11c5b301206382726210dc1d3bee1a9ccf7aadf895aaf31f71c3716c", - "sha256:91ec98640220ae05b34b79ee88abf27f97ef7c61cf525eec57ea8fcea9f7dddb", - "sha256:952be9540d83dba815569d5cb5f31708801e0bbfc3a8c5aef1890b57ed7e58bf", - "sha256:99ac266af38ba1b1fe13975aea01ac0e14bb5f3a3200d2c69f05385768b8568e", - "sha256:9fa122e7adb24232247f8a89f2d9070bf64b7869daf93ac5e19546b409e47e96", - "sha256:a0873eadc4b8ca93e2e848d490809e0123eea154aa44ecd0109c4d0171869584", - "sha256:cb998bd4d93af46b8b49ecf5a72c0a98e5cc6d57fdca6527ba78ad89d6606484", - "sha256:e02e57346f6a68523e3c43bbdf35dde5c440318d1f827208ae455f6a2ace446d", - "sha256:e79a5a896bcee7fff24a788d72e5c69f13e61369d055f28113e71945a7eb1559", - "sha256:ee55eb6bcf23ecc975e6b47c127c201b913598f38b6a300075f84eeef2d3baff", - "sha256:f1414e6cbcea8d22843e7eafdfdfae3dd1aba41d1945f6ca66e4806c07c4f454" + "sha256:04b42a1b57096ffa5627d6a78ea1ff7fad3bc2c0331ffc17bc32a4024da7fea0", + "sha256:08e3c3e0535befa4f0c4443824496c03ecc25062debbcf895874f8a0b4c97c9f", + "sha256:10d89d4326045bf5e15e83e9867c85d686b612822e4d8f149cf4840aab5f46e0", + "sha256:232fac8a1978fc1dead4b1c2fa27c7756750fb393eb4ac52f6bc87ba7242b2fa", + "sha256:4bf4c8097440eff22bc78ec76fe2a865a6e658b6977a504679aaf08f02c121da", + "sha256:51642ea3a00772d1e48fb0c492f0d3ae3b6474f34d20eca005a83f8c9c06c561", + "sha256:55d86102282a636e195dad68aaaf85b81d0bef449d7e2ef2ff79ac450bb25d53", + "sha256:564d2675682bd497b59907d2205031acbf7d3fadf8c763b689b9ede20300b215", + "sha256:5d13bf5197a92149dc0badcc2b699267ff65a867029f465accfca8abab95f412", + "sha256:5eda665f6789edb9b57b57a159b9c55482cbe5b046d7db458948370554b16439", + "sha256:5edb2524d4032be4564c65dc4f9d01e79fe8fad5f966e5b552f4e5164fef0885", + "sha256:79691794288bc51e2a3b8de2bc0272ca8355d0b8503077ea57c0716e840ebaef", + "sha256:7fcc8681e9981b9b511cdee7c580d5b005f3bb86b65bde2188e04a29f1d63317", + "sha256:8e447e05ec88b1b408a4c9cde85aa6f4b04f06aa874b9f0b8e8319faf51b1fee", + "sha256:90ea6b3e7787620bb295a4ae050d2811c807d65b1486749414f78cfd6fb61489", + "sha256:9e13239952694b8b831088431d15f771beace10edfcf9ef230cefea14f18508f", + "sha256:d40f081187f7b54d7a99d8a5c782eaa4edc335a057aa54c85059272ed826dc09", + "sha256:e1df1a58ed2468c7b7ce9a2f9752a32ad08eac2bcd56318625c3647c2cd2da6f", + "sha256:e98d0cec437097f09c7834a11c69d79fe6241729b23f656cfc227e93294fc242", + "sha256:f8d59627702d2ff27cb495ca1abdea8bd8d581de425c56e93bff6517134e0a9b", + "sha256:fc30cdf2e949a2225b012a7911d1d031df3d23e99b7eda7dfc982dc4a860dae9" ], - "version": "==6.0" + "version": "==7.0" }, "yarl": { "hashes": [ diff --git a/discord/__init__.py b/discord/__init__.py index 2f8bdd637..3f6d2e3d7 100644 --- a/discord/__init__.py +++ b/discord/__init__.py @@ -6,7 +6,7 @@ Discord API Wrapper A basic wrapper for the Discord API. -:copyright: (c) 2015-2017 Rapptz +:copyright: (c) 2015-2019 Rapptz :license: MIT, see LICENSE for more details. """ @@ -14,7 +14,7 @@ A basic wrapper for the Discord API. __title__ = "discord" __author__ = "Rapptz" __license__ = "MIT" -__copyright__ = "Copyright 2015-2017 Rapptz" +__copyright__ = "Copyright 2015-2019 Rapptz" __version__ = "1.0.0a" from collections import namedtuple diff --git a/discord/__main__.py b/discord/__main__.py index 33bb961d6..101202ecd 100644 --- a/discord/__main__.py +++ b/discord/__main__.py @@ -3,7 +3,7 @@ """ The MIT License (MIT) -Copyright (c) 2015-2017 Rapptz +Copyright (c) 2015-2019 Rapptz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/discord/abc.py b/discord/abc.py index 146f80925..52d6e0667 100644 --- a/discord/abc.py +++ b/discord/abc.py @@ -3,7 +3,7 @@ """ The MIT License (MIT) -Copyright (c) 2015-2017 Rapptz +Copyright (c) 2015-2019 Rapptz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/discord/activity.py b/discord/activity.py index edc50e9fb..8d1d17503 100644 --- a/discord/activity.py +++ b/discord/activity.py @@ -3,7 +3,7 @@ """ The MIT License (MIT) -Copyright (c) 2015-2017 Rapptz +Copyright (c) 2015-2019 Rapptz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/discord/audit_logs.py b/discord/audit_logs.py index c21e0afde..aaa008c9b 100644 --- a/discord/audit_logs.py +++ b/discord/audit_logs.py @@ -3,7 +3,7 @@ """ The MIT License (MIT) -Copyright (c) 2015-2017 Rapptz +Copyright (c) 2015-2019 Rapptz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/discord/backoff.py b/discord/backoff.py index ca289505f..20431b537 100644 --- a/discord/backoff.py +++ b/discord/backoff.py @@ -3,7 +3,7 @@ """ The MIT License (MIT) -Copyright (c) 2015-2017 Rapptz +Copyright (c) 2015-2019 Rapptz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/discord/calls.py b/discord/calls.py index 63bc96ed7..2022b0d6c 100644 --- a/discord/calls.py +++ b/discord/calls.py @@ -3,7 +3,7 @@ """ The MIT License (MIT) -Copyright (c) 2015-2017 Rapptz +Copyright (c) 2015-2019 Rapptz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/discord/channel.py b/discord/channel.py index b1b39ee71..b4cc3698d 100644 --- a/discord/channel.py +++ b/discord/channel.py @@ -3,7 +3,7 @@ """ The MIT License (MIT) -Copyright (c) 2015-2017 Rapptz +Copyright (c) 2015-2019 Rapptz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -667,6 +667,28 @@ class CategoryChannel(discord.abc.GuildChannel, Hashable): ret.sort(key=comparator) return ret + @property + def text_channels(self): + """List[:class:`TextChannel`]: Returns the text channels that are under this category.""" + ret = [ + c + for c in self.guild.channels + if c.category_id == self.id and isinstance(c, TextChannel) + ] + ret.sort(key=lambda c: (c.position, c.id)) + return ret + + @property + def voice_channels(self): + """List[:class:`VoiceChannel`]: Returns the text channels that are under this category.""" + ret = [ + c + for c in self.guild.channels + if c.category_id == self.id and isinstance(c, VoiceChannel) + ] + ret.sort(key=lambda c: (c.position, c.id)) + return ret + class DMChannel(discord.abc.Messageable, Hashable): """Represents a Discord direct message channel. diff --git a/discord/client.py b/discord/client.py index 41d5d6826..39c12c1f9 100644 --- a/discord/client.py +++ b/discord/client.py @@ -3,7 +3,7 @@ """ The MIT License (MIT) -Copyright (c) 2015-2017 Rapptz +Copyright (c) 2015-2019 Rapptz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/discord/colour.py b/discord/colour.py index f741dd3ef..aa7db29e2 100644 --- a/discord/colour.py +++ b/discord/colour.py @@ -3,7 +3,7 @@ """ The MIT License (MIT) -Copyright (c) 2015-2017 Rapptz +Copyright (c) 2015-2019 Rapptz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/discord/context_managers.py b/discord/context_managers.py index b7f21825b..030b48e7c 100644 --- a/discord/context_managers.py +++ b/discord/context_managers.py @@ -3,7 +3,7 @@ """ The MIT License (MIT) -Copyright (c) 2015-2017 Rapptz +Copyright (c) 2015-2019 Rapptz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/discord/embeds.py b/discord/embeds.py index 2c3fb9c1e..4ec8cdc46 100644 --- a/discord/embeds.py +++ b/discord/embeds.py @@ -3,7 +3,7 @@ """ The MIT License (MIT) -Copyright (c) 2015-2017 Rapptz +Copyright (c) 2015-2019 Rapptz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/discord/emoji.py b/discord/emoji.py index 11653db43..8b555a2f9 100644 --- a/discord/emoji.py +++ b/discord/emoji.py @@ -3,7 +3,7 @@ """ The MIT License (MIT) -Copyright (c) 2015-2017 Rapptz +Copyright (c) 2015-2019 Rapptz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -76,6 +76,13 @@ class PartialEmoji(namedtuple("PartialEmoji", "animated name id")): return "" % (self.name, self.id) return "<:%s:%s>" % (self.name, self.id) + def __eq__(self, other): + if self.is_unicode_emoji(): + return isinstance(other, PartialEmoji) and self.name == other.name + + if isinstance(other, (PartialEmoji, Emoji)): + return self.id == other.id + def is_custom_emoji(self): """Checks if this is a custom non-Unicode emoji.""" return self.id is not None @@ -186,6 +193,9 @@ class Emoji(Hashable): def __repr__(self): return "".format(self) + def __eq__(self, other): + return isinstance(other, (PartialEmoji, Emoji)) and self.id == other.id + @property def created_at(self): """Returns the emoji's creation time in UTC.""" diff --git a/discord/enums.py b/discord/enums.py index 8262b80c5..4383e39b3 100644 --- a/discord/enums.py +++ b/discord/enums.py @@ -3,7 +3,7 @@ """ The MIT License (MIT) -Copyright (c) 2015-2017 Rapptz +Copyright (c) 2015-2019 Rapptz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -30,6 +30,7 @@ __all__ = [ "ChannelType", "MessageType", "VoiceRegion", + "SpeakingState", "VerificationLevel", "ContentFilter", "Status", @@ -91,6 +92,16 @@ class VoiceRegion(Enum): return self.value +class SpeakingState(IntEnum): + none = 0 + voice = 1 + soundshare = 2 + priority = 4 + + def __str__(self): + return self.name + + class VerificationLevel(IntEnum): none = 0 low = 1 diff --git a/discord/errors.py b/discord/errors.py index 8a66d1d0b..5828ec1b6 100644 --- a/discord/errors.py +++ b/discord/errors.py @@ -3,7 +3,7 @@ """ The MIT License (MIT) -Copyright (c) 2015-2017 Rapptz +Copyright (c) 2015-2019 Rapptz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/discord/ext/commands/__init__.py b/discord/ext/commands/__init__.py index f5f7bb263..20749b213 100644 --- a/discord/ext/commands/__init__.py +++ b/discord/ext/commands/__init__.py @@ -6,7 +6,7 @@ discord.ext.commands An extension module to facilitate creation of bot commands. -:copyright: (c) 2017 Rapptz +:copyright: (c) 2019 Rapptz :license: MIT, see LICENSE for more details. """ diff --git a/discord/ext/commands/bot.py b/discord/ext/commands/bot.py index a13989524..33250f608 100644 --- a/discord/ext/commands/bot.py +++ b/discord/ext/commands/bot.py @@ -3,7 +3,7 @@ """ The MIT License (MIT) -Copyright (c) 2015-2017 Rapptz +Copyright (c) 2015-2019 Rapptz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -443,9 +443,9 @@ class BotBase(GroupMixin): Parameters ----------- func : :ref:`coroutine ` - The extra event to listen to. + The function to call. name : Optional[str] - The name of the command to use. Defaults to ``func.__name__``. + The name of the event to listen for. Defaults to ``func.__name__``. Example -------- diff --git a/discord/ext/commands/context.py b/discord/ext/commands/context.py index b84a0d655..80ba9054c 100644 --- a/discord/ext/commands/context.py +++ b/discord/ext/commands/context.py @@ -3,7 +3,7 @@ """ The MIT License (MIT) -Copyright (c) 2015-2017 Rapptz +Copyright (c) 2015-2019 Rapptz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/discord/ext/commands/converter.py b/discord/ext/commands/converter.py index a93123c1f..cae728a98 100644 --- a/discord/ext/commands/converter.py +++ b/discord/ext/commands/converter.py @@ -3,7 +3,7 @@ """ The MIT License (MIT) -Copyright (c) 2015-2017 Rapptz +Copyright (c) 2015-2019 Rapptz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -523,7 +523,7 @@ class clean_content(Converter): result = pattern.sub(repl, argument) if self.escape_markdown: - transformations = {re.escape(c): "\\" + c for c in ("*", "`", "_", "~", "\\")} + transformations = {re.escape(c): "\\" + c for c in ("*", "`", "_", "~", "\\", "||")} def replace(obj): return transformations.get(re.escape(obj.group(0)), "") diff --git a/discord/ext/commands/cooldowns.py b/discord/ext/commands/cooldowns.py index d3079029c..13d67221e 100644 --- a/discord/ext/commands/cooldowns.py +++ b/discord/ext/commands/cooldowns.py @@ -3,7 +3,7 @@ """ The MIT License (MIT) -Copyright (c) 2015-2017 Rapptz +Copyright (c) 2015-2019 Rapptz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/discord/ext/commands/core.py b/discord/ext/commands/core.py index d499923bc..e51e99be2 100644 --- a/discord/ext/commands/core.py +++ b/discord/ext/commands/core.py @@ -3,7 +3,7 @@ """ The MIT License (MIT) -Copyright (c) 2015-2017 Rapptz +Copyright (c) 2015-2019 Rapptz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -385,22 +385,18 @@ class Command: # for use with a manual undo previous = view.index - # parsing errors get propagated view.skip_ws() argument = quoted_word(view) try: value = await self.do_conversion(ctx, converter, argument, param) except CommandError: - if not result: - if required: - raise - else: - view.index = previous - return param.default view.index = previous break else: result.append(value) + + if not result and not required: + return param.default return result async def _transform_greedy_var_pos(self, ctx, param, converter): @@ -750,9 +746,9 @@ class Command: If that lookup leads to an empty string then the first line of the :attr:`help` attribute is used instead. """ - if self.brief: + if self.brief is not None: return self.brief - if self.help: + if self.help is not None: return self.help.split("\n", 1)[0] return "" @@ -771,7 +767,7 @@ class Command: name = self.name if not parent else parent + " " + self.name result.append(name) - if self.usage: + if self.usage is not None: result.append(self.usage) return " ".join(result) diff --git a/discord/ext/commands/errors.py b/discord/ext/commands/errors.py index 744bcb01e..241111c9f 100644 --- a/discord/ext/commands/errors.py +++ b/discord/ext/commands/errors.py @@ -3,7 +3,7 @@ """ The MIT License (MIT) -Copyright (c) 2015-2017 Rapptz +Copyright (c) 2015-2019 Rapptz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/discord/ext/commands/formatter.py b/discord/ext/commands/formatter.py index 407c56448..490dcbec7 100644 --- a/discord/ext/commands/formatter.py +++ b/discord/ext/commands/formatter.py @@ -3,7 +3,7 @@ """ The MIT License (MIT) -Copyright (c) 2015-2017 Rapptz +Copyright (c) 2015-2019 Rapptz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -26,6 +26,7 @@ DEALINGS IN THE SOFTWARE. import itertools import inspect +import discord.utils from .core import GroupMixin, Command from .errors import CommandError @@ -183,7 +184,9 @@ class HelpFormatter: if commands: return max( map( - lambda c: len(c.name) if self.show_hidden or not c.hidden else 0, + lambda c: discord.utils._string_width(c.name) + if self.show_hidden or not c.hidden + else 0, commands.values(), ) ) @@ -272,8 +275,10 @@ class HelpFormatter: if name in command.aliases: # skip aliases continue - - entry = " {0:<{width}} {1}".format(name, command.short_doc, width=max_width) + width_gap = discord.utils._string_width(name) - len(name) + entry = " {0:<{width}} {1}".format( + name, command.short_doc, width=max_width - width_gap + ) shortened = self.shorten(entry) self._paginator.add_line(shortened) diff --git a/discord/ext/commands/view.py b/discord/ext/commands/view.py index c9a0107a1..019662622 100644 --- a/discord/ext/commands/view.py +++ b/discord/ext/commands/view.py @@ -3,7 +3,7 @@ """ The MIT License (MIT) -Copyright (c) 2015-2017 Rapptz +Copyright (c) 2015-2019 Rapptz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/discord/file.py b/discord/file.py index 7392e5ff4..ecdb568b9 100644 --- a/discord/file.py +++ b/discord/file.py @@ -3,7 +3,7 @@ """ The MIT License (MIT) -Copyright (c) 2015-2017 Rapptz +Copyright (c) 2015-2019 Rapptz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/discord/gateway.py b/discord/gateway.py index bc4083711..c1e04732a 100644 --- a/discord/gateway.py +++ b/discord/gateway.py @@ -3,7 +3,7 @@ """ The MIT License (MIT) -Copyright (c) 2015-2017 Rapptz +Copyright (c) 2015-2019 Rapptz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -26,6 +26,7 @@ DEALINGS IN THE SOFTWARE. import asyncio from collections import namedtuple +import concurrent.futures import json import logging import struct @@ -38,6 +39,7 @@ import websockets from . import utils from .activity import _ActivityTag +from .enums import SpeakingState from .errors import ConnectionClosed, InvalidArgument log = logging.getLogger(__name__) @@ -72,6 +74,8 @@ class KeepAliveHandler(threading.Thread): self.daemon = True self.shard_id = shard_id self.msg = "Keeping websocket alive with sequence %s." + self.block_msg = "Heartbeat blocked for more than %s seconds." + self.behind_msg = "Can't keep up, websocket is %.1fs behind." self._stop_ev = threading.Event() self._last_ack = time.perf_counter() self._last_send = time.perf_counter() @@ -102,7 +106,15 @@ class KeepAliveHandler(threading.Thread): f = asyncio.run_coroutine_threadsafe(coro, loop=self.ws.loop) try: # block until sending is complete - f.result() + total = 0 + while True: + try: + f.result(5) + break + except concurrent.futures.TimeoutError: + total += 5 + log.warning(self.block_msg, total) + except Exception: self.stop() else: @@ -118,12 +130,16 @@ class KeepAliveHandler(threading.Thread): ack_time = time.perf_counter() self._last_ack = ack_time self.latency = ack_time - self._last_send + if self.latency > 10: + log.warning(self.behind_msg, self.latency) class VoiceKeepAliveHandler(KeepAliveHandler): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.msg = "Keeping voice websocket alive with timestamp %s." + self.block_msg = "Voice heartbeat blocked for more than %s seconds" + self.behind_msg = "Can't keep up, voice websocket is %.1fs behind" def get_payload(self): return {"op": self.ws.HEARTBEAT, "d": int(time.time() * 1000)} @@ -482,7 +498,7 @@ class DiscordWebSocket(websockets.client.WebSocketClientProtocol): async def send_as_json(self, data): try: - await super().send(utils.to_json(data)) + await self.send(utils.to_json(data)) except websockets.exceptions.ConnectionClosed as exc: if not self._can_handle_close(exc.code): raise ConnectionClosed(exc, shard_id=self.shard_id) from exc @@ -561,6 +577,10 @@ class DiscordVoiceWebSocket(websockets.client.WebSocketClientProtocol): Receive only. Tells you that your websocket connection was acknowledged. INVALIDATE_SESSION Sent only. Tells you that your RESUME request has failed and to re-IDENTIFY. + CLIENT_CONNECT + Indicates a user has connected to voice. + CLIENT_DISCONNECT + Receive only. Indicates a user has disconnected from voice. """ IDENTIFY = 0 @@ -573,6 +593,8 @@ class DiscordVoiceWebSocket(websockets.client.WebSocketClientProtocol): RESUME = 7 HELLO = 8 INVALIDATE_SESSION = 9 + CLIENT_CONNECT = 12 + CLIENT_DISCONNECT = 13 def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -611,7 +633,7 @@ class DiscordVoiceWebSocket(websockets.client.WebSocketClientProtocol): @classmethod async def from_client(cls, client, *, resume=False): """Creates a voice websocket for the :class:`VoiceClient`.""" - gateway = "wss://" + client.endpoint + "/?v=3" + gateway = "wss://" + client.endpoint + "/?v=4" ws = await websockets.connect(gateway, loop=client.loop, klass=cls, compression=None) ws.gateway = gateway ws._connection = client @@ -624,19 +646,21 @@ class DiscordVoiceWebSocket(websockets.client.WebSocketClientProtocol): return ws - async def select_protocol(self, ip, port): + async def select_protocol(self, ip, port, mode): payload = { "op": self.SELECT_PROTOCOL, - "d": { - "protocol": "udp", - "data": {"address": ip, "port": port, "mode": "xsalsa20_poly1305"}, - }, + "d": {"protocol": "udp", "data": {"address": ip, "port": port, "mode": mode}}, } await self.send_as_json(payload) - async def speak(self, is_speaking=True): - payload = {"op": self.SPEAKING, "d": {"speaking": is_speaking, "delay": 0}} + async def client_connect(self): + payload = {"op": self.CLIENT_CONNECT, "d": {"audio_ssrc": self._connection.ssrc}} + + await self.send_as_json(payload) + + async def speak(self, state=SpeakingState.voice): + payload = {"op": self.SPEAKING, "d": {"speaking": int(state), "delay": 0}} await self.send_as_json(payload) @@ -646,9 +670,6 @@ class DiscordVoiceWebSocket(websockets.client.WebSocketClientProtocol): data = msg.get("d") if op == self.READY: - interval = data["heartbeat_interval"] / 1000.0 - self._keep_alive = VoiceKeepAliveHandler(ws=self, interval=interval) - self._keep_alive.start() await self.initial_connection(data) elif op == self.HEARTBEAT_ACK: self._keep_alive.ack() @@ -656,7 +677,12 @@ class DiscordVoiceWebSocket(websockets.client.WebSocketClientProtocol): log.info("Voice RESUME failed.") await self.identify() elif op == self.SESSION_DESCRIPTION: + self._connection.mode = data["mode"] await self.load_secret_key(data) + elif op == self.HELLO: + interval = data["heartbeat_interval"] / 1000.0 + self._keep_alive = VoiceKeepAliveHandler(ws=self, interval=interval) + self._keep_alive.start() async def initial_connection(self, data): state = self._connection @@ -677,15 +703,23 @@ class DiscordVoiceWebSocket(websockets.client.WebSocketClientProtocol): # the port is a little endian unsigned short in the last two bytes # yes, this is different endianness from everything else state.port = struct.unpack_from("H", header, 2, self.sequence) struct.pack_into(">I", header, 4, self.timestamp) struct.pack_into(">I", header, 8, self.ssrc) - # Copy header to nonce's first 12 bytes + encrypt_packet = getattr(self, "_encrypt_" + self.mode) + return encrypt_packet(header, data) + + def _encrypt_xsalsa20_poly1305(self, header, data): + box = nacl.secret.SecretBox(bytes(self.secret_key)) + nonce = bytearray(24) nonce[:12] = header - # Encrypt and return the data return header + box.encrypt(bytes(data), bytes(nonce)).ciphertext + def _encrypt_xsalsa20_poly1305_suffix(self, header, data): + box = nacl.secret.SecretBox(bytes(self.secret_key)) + nonce = nacl.utils.random(nacl.secret.SecretBox.NONCE_SIZE) + + return header + box.encrypt(bytes(data), nonce).ciphertext + nonce + def play(self, source, *, after=None): """Plays an :class:`AudioSource`. diff --git a/discord/webhook.py b/discord/webhook.py index 237201a75..ed99a20b2 100644 --- a/discord/webhook.py +++ b/discord/webhook.py @@ -3,7 +3,7 @@ """ The MIT License (MIT) -Copyright (c) 2015-2017 Rapptz +Copyright (c) 2015-2019 Rapptz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -103,7 +103,7 @@ class WebhookAdapter: def store_user(self, data): # mocks a ConnectionState for appropriate use for Message - return BaseUser(state=self, data=data) + return BaseUser(state=self.webhook._state, data=data) def execute_webhook(self, *, payload, wait=False, file=None, files=None): if file is not None: @@ -195,7 +195,7 @@ class AsyncWebhookAdapter(WebhookAdapter): # transform into Message object from .message import Message - return Message(data=data, state=self, channel=self.webhook.channel) + return Message(data=data, state=self.webhook._state, channel=self.webhook.channel) class RequestsWebhookAdapter(WebhookAdapter): @@ -279,7 +279,7 @@ class RequestsWebhookAdapter(WebhookAdapter): # transform into Message object from .message import Message - return Message(data=response, state=self, channel=self.webhook.channel) + return Message(data=response, state=self.webhook._state, channel=self.webhook.channel) class Webhook: diff --git a/make.bat b/make.bat index 492871499..cbcdda020 100644 --- a/make.bat +++ b/make.bat @@ -28,7 +28,7 @@ if [%REF%] == [] ( set REF2=%REF% ) pip install --upgrade --no-deps -t . https://github.com/Rapptz/discord.py/archive/!REF2!.tar.gz#egg=discord.py -del /S /Q "discord.py*.egg-info" +del /S /Q "discord.py*-info" for /F %%i in ('dir /S /B discord.py*.egg-info') do rmdir /S /Q %%i goto reformat diff --git a/redbot/__init__.py b/redbot/__init__.py index b0a977519..0ae610154 100644 --- a/redbot/__init__.py +++ b/redbot/__init__.py @@ -1,5 +1,6 @@ import re as _re import sys as _sys +import warnings as _warnings from math import inf as _inf from typing import ( Any as _Any, @@ -157,3 +158,6 @@ class VersionInfo: __version__ = "3.0.0" version_info = VersionInfo.from_str(__version__) + +# Filter fuzzywuzzy slow sequence matcher warning +_warnings.filterwarnings("ignore", module=r"fuzzywuzzy.*") diff --git a/redbot/__main__.py b/redbot/__main__.py index 5dd9d33b2..891c0f161 100644 --- a/redbot/__main__.py +++ b/redbot/__main__.py @@ -183,7 +183,7 @@ def main(): gathered = asyncio.gather(*pending, loop=red.loop, return_exceptions=True) gathered.cancel() try: - red.rpc.server.close() + loop.run_until_complete(red.rpc.close()) except AttributeError: pass diff --git a/redbot/core/rpc.py b/redbot/core/rpc.py index 089a41b87..4be71a09c 100644 --- a/redbot/core/rpc.py +++ b/redbot/core/rpc.py @@ -1,4 +1,5 @@ import asyncio +from typing import Optional from aiohttp import web from aiohttp_json_rpc import JsonRpc @@ -63,25 +64,26 @@ class RPC: def __init__(self): self.app = web.Application() self._rpc = RedRpc() - self.app.router.add_route("*", "/", self._rpc) + self.app.router.add_route("*", "/", self._rpc.handle_request) - self.app_handler = self.app.make_handler() - - self.server = None + self._runner = web.AppRunner(self.app) + self._site: Optional[web.TCPSite] = None async def initialize(self): """ Finalizes the initialization of the RPC server and allows it to begin accepting queries. """ - self.server = await self.app.loop.create_server(self.app_handler, "127.0.0.1", 6133) + await self._runner.setup() + self._site = web.TCPSite(self._runner, host="127.0.0.1", port=6133) + await self._site.start() log.debug("Created RPC server listener.") - def close(self): + async def close(self): """ Closes the RPC server. """ - self.server.close() + await self._runner.cleanup() def add_method(self, method, prefix: str = None): if prefix is None: @@ -117,7 +119,8 @@ class RPCMixin: """ Registers a method to act as an RPC handler if the internal RPC server is active. - When calling this method through the RPC server, use the naming scheme "cogname__methodname". + When calling this method through the RPC server, use the naming scheme + "cogname__methodname". .. important:: diff --git a/setup.cfg b/setup.cfg index d9c79d91b..02d4cd1dd 100644 --- a/setup.cfg +++ b/setup.cfg @@ -26,25 +26,23 @@ classifiers = packages = find_namespace: python_requires = >=3.7 install_requires = - aiohttp-json-rpc==0.11.2 - aiohttp==3.4.4 + aiohttp-json-rpc==0.12 + aiohttp==3.5.4 appdirs==1.4.3 async-timeout==3.0.1 attrs==18.2.0 chardet==3.0.4 colorama==0.4.1 - distro==1.3.0; sys_platform == "linux" + distro==1.4.0; sys_platform == "linux" fuzzywuzzy==0.17.0 idna-ssl==1.1.0 idna==2.8 multidict==4.5.2 python-levenshtein-wheels==0.13.1 pyyaml==3.13 - raven==6.10.0 - raven-aiohttp==0.7.0 - red-lavalink==0.2.0 + red-lavalink==0.2.1 schema==0.6.8 - websockets==6.0 + websockets==7.0 yarl==1.3.0 [options.extras_require] @@ -56,15 +54,15 @@ docs = imagesize==1.1.0 Jinja2==2.10 MarkupSafe==1.1.0 - packaging==18.0 - pyparsing==2.3.0 + packaging==19.0 + pyparsing==2.3.1 Pygments==2.3.1 pytz==2018.9 requests==2.21.0 six==1.12.0 snowballstemmer==1.2.1 - sphinx==1.8.3 - sphinx_rtd_theme==0.4.2 + sphinx==1.8.4 + sphinx_rtd_theme==0.4.3 sphinxcontrib-asyncio==0.2.0 sphinxcontrib-websupport==1.1.0 urllib3==1.24.1 @@ -77,11 +75,11 @@ style = click==7.0 toml==0.10.0 test = - atomicwrites==1.2.1 - more-itertools==5.0.0 + atomicwrites==1.3.0 + more-itertools==6.0.0 pluggy==0.8.1 py==1.7.0 - pytest==4.1.0 + pytest==4.2.0 pytest-asyncio==0.10.0 six==1.12.0