1
0
mirror of https://gitlab.com/ddorn/tfjm-discord-bot.git synced 2025-07-07 17:48:31 +02:00

Compare commits

..

12 Commits

Author SHA1 Message Date
45d760135b fix missing import 2021-01-21 22:11:57 +00:00
5bfc32e478 Add member intents 2021-01-21 22:11:00 +00:00
4fe31e3f7b 🐛 fix order of commands in !help 2020-09-11 22:24:53 +02:00
a93181bcd8 calc: more functions and implicit multiplication 2020-06-03 15:18:00 +02:00
62dc5b7fd7 :sparles: safe calc cmd 2020-06-03 14:58:28 +02:00
533b81a615 🚧 enable joke top again 2020-06-01 13:47:57 +02:00
b8a9041e36 add nix env 2020-06-01 13:43:49 +02:00
abb1f16129 add RAINBOW_HEART + remove AQT from hugs 2020-05-27 13:12:50 +02:00
0f541291f2 💩 improved bad code 2020-05-23 22:45:09 +02:00
e0c288289d tourist for final 2020-05-23 20:18:21 +02:00
fd000958a7 🐛 fix tirages for finale 2020-05-20 12:54:46 +02:00
161478caf8 trirages in two parts for finale 2020-05-20 02:52:42 +02:00
11 changed files with 489 additions and 198 deletions

1
.envrc Normal file
View File

@ -0,0 +1 @@
use_nix

237
poetry.lock generated
View File

@ -30,7 +30,7 @@ description = "A small Python module for determining appropriate platform-specif
name = "appdirs"
optional = false
python-versions = "*"
version = "1.4.3"
version = "1.4.4"
[[package]]
category = "main"
@ -46,13 +46,13 @@ description = "Classes Without Boilerplate"
name = "attrs"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "19.3.0"
version = "20.2.0"
[package.extras]
azure-pipelines = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "pytest-azurepipelines"]
dev = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "sphinx", "pre-commit"]
docs = ["sphinx", "zope.interface"]
tests = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"]
dev = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "sphinx", "sphinx-rtd-theme", "pre-commit"]
docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"]
tests = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"]
tests_no_zope = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six"]
[[package]]
category = "main"
@ -79,11 +79,10 @@ description = "A Python wrapper for the Discord API"
name = "discord.py"
optional = false
python-versions = ">=3.5.3"
version = "1.3.3"
version = "1.4.1"
[package.dependencies]
aiohttp = ">=3.6.0,<3.7.0"
websockets = ">=6.0,<7.0 || >7.0,<8.0 || >8.0,<8.0.1 || >8.0.1,<9.0"
[package.extras]
docs = ["sphinx (1.8.5)", "sphinxcontrib-trio (1.1.1)", "sphinxcontrib-websupport"]
@ -95,7 +94,7 @@ description = "Internationalized Domain Names in Applications (IDNA)"
name = "idna"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "2.9"
version = "2.10"
[[package]]
category = "main"
@ -109,20 +108,36 @@ version = "1.1.0"
[package.dependencies]
idna = ">=2.0"
[[package]]
category = "main"
description = "Read metadata from Python packages"
marker = "python_version < \"3.8\""
name = "importlib-metadata"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
version = "1.7.0"
[package.dependencies]
zipp = ">=0.5"
[package.extras]
docs = ["sphinx", "rst.linker"]
testing = ["packaging", "pep517", "importlib-resources (>=1.3)"]
[[package]]
category = "main"
description = "An autocompletion tool for Python that can be used for text editors."
name = "jedi"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
version = "0.17.0"
version = "0.17.2"
[package.dependencies]
parso = ">=0.7.0"
parso = ">=0.7.0,<0.8.0"
[package.extras]
qa = ["flake8 (3.7.9)"]
testing = ["colorama", "docopt", "pytest (>=3.9.0,<5.0.0)"]
testing = ["Django (<3.1)", "colorama", "docopt", "pytest (>=3.9.0,<5.0.0)"]
[[package]]
category = "main"
@ -130,7 +145,7 @@ description = "multidict implementation"
name = "multidict"
optional = false
python-versions = ">=3.5"
version = "4.7.5"
version = "4.7.6"
[[package]]
category = "main"
@ -138,7 +153,7 @@ description = "A Python Parser"
name = "parso"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "0.7.0"
version = "0.7.1"
[package.extras]
testing = ["docopt", "pytest (>=3.0.7)"]
@ -160,10 +175,10 @@ description = "Cross-platform lib for process and system monitoring in Python."
name = "psutil"
optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "5.7.0"
version = "5.7.2"
[package.extras]
enum = ["enum34"]
test = ["ipaddress", "mock", "unittest2", "enum34", "pywin32", "wmi"]
[[package]]
category = "main"
@ -171,7 +186,7 @@ description = "Python REPL build on top of prompt_toolkit"
name = "ptpython"
optional = false
python-versions = ">=3.6"
version = "3.0.2"
version = "3.0.5"
[package.dependencies]
appdirs = "*"
@ -179,6 +194,10 @@ jedi = ">=0.9.0"
prompt-toolkit = ">=3.0.0,<3.1.0"
pygments = "*"
[package.dependencies.importlib-metadata]
python = "<3.8"
version = "*"
[package.extras]
ptipython = ["ipython"]
@ -201,27 +220,19 @@ version = "5.3.1"
[[package]]
category = "main"
description = "Backported and Experimental Type Hints for Python 3.5+"
marker = "python_version < \"3.7\""
marker = "python_version < \"3.8\""
name = "typing-extensions"
optional = false
python-versions = "*"
version = "3.7.4.2"
version = "3.7.4.3"
[[package]]
category = "main"
description = "Measures number of Terminal column cells of wide-character codes"
description = "Measures the displayed width of unicode strings in a terminal"
name = "wcwidth"
optional = false
python-versions = "*"
version = "0.1.9"
[[package]]
category = "main"
description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)"
name = "websockets"
optional = false
python-versions = ">=3.6"
version = "8.0.2"
version = "0.2.5"
[[package]]
category = "main"
@ -229,12 +240,29 @@ description = "Yet another URL library"
name = "yarl"
optional = false
python-versions = ">=3.5"
version = "1.4.2"
version = "1.5.1"
[package.dependencies]
idna = ">=2.0"
multidict = ">=4.0"
[package.dependencies.typing-extensions]
python = "<3.8"
version = ">=3.7.4"
[[package]]
category = "main"
description = "Backport of pathlib-compatible object wrapper for zip files"
marker = "python_version < \"3.8\""
name = "zipp"
optional = false
python-versions = ">=3.6"
version = "3.1.0"
[package.extras]
docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"]
testing = ["jaraco.itertools", "func-timeout"]
[metadata]
content-hash = "9c9fe13eda9abe2a52c99a38f8bd1183b208d8f8ac72f478061376066c4a105e"
python-versions = "^3.6"
@ -255,16 +283,16 @@ aiohttp = [
{file = "aiohttp-3.6.2.tar.gz", hash = "sha256:259ab809ff0727d0e834ac5e8a283dc5e3e0ecc30c4d80b3cd17a4139ce1f326"},
]
appdirs = [
{file = "appdirs-1.4.3-py2.py3-none-any.whl", hash = "sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e"},
{file = "appdirs-1.4.3.tar.gz", hash = "sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92"},
{file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"},
{file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"},
]
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"},
]
attrs = [
{file = "attrs-19.3.0-py2.py3-none-any.whl", hash = "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c"},
{file = "attrs-19.3.0.tar.gz", hash = "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"},
{file = "attrs-20.2.0-py2.py3-none-any.whl", hash = "sha256:fce7fc47dfc976152e82d53ff92fa0407700c21acd20886a13777a0d20e655dc"},
{file = "attrs-20.2.0.tar.gz", hash = "sha256:26b54ddbbb9ee1d34d5d3668dd37d6cf74990ab23c828c2888dccdceee395594"},
]
chardet = [
{file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"},
@ -275,63 +303,67 @@ discord = [
{file = "discord-1.0.1.tar.gz", hash = "sha256:ff6653655e342e7721dfb3f10421345fd852c2a33f2cca912b1c39b3778a9429"},
]
"discord.py" = [
{file = "discord.py-1.3.3-py3-none-any.whl", hash = "sha256:406871b06d86c3dc49fba63238519f28628dac946fef8a0e22988ff58ec05580"},
{file = "discord.py-1.3.3.tar.gz", hash = "sha256:ad00e34c72d2faa8db2157b651d05f3c415d7d05078e7e41dc9e8dc240051beb"},
{file = "discord.py-1.4.1-py3-none-any.whl", hash = "sha256:98ea3096a3585c9c379209926f530808f5fcf4930928d8cfb579d2562d119570"},
{file = "discord.py-1.4.1.tar.gz", hash = "sha256:f9decb3bfa94613d922376288617e6a6f969260923643e2897f4540c34793442"},
]
idna = [
{file = "idna-2.9-py2.py3-none-any.whl", hash = "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"},
{file = "idna-2.9.tar.gz", hash = "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb"},
{file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"},
{file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"},
]
idna-ssl = [
{file = "idna-ssl-1.1.0.tar.gz", hash = "sha256:a933e3bb13da54383f9e8f35dc4f9cb9eb9b3b78c6b36f311254d6d0d92c6c7c"},
]
importlib-metadata = [
{file = "importlib_metadata-1.7.0-py2.py3-none-any.whl", hash = "sha256:dc15b2969b4ce36305c51eebe62d418ac7791e9a157911d58bfb1f9ccd8e2070"},
{file = "importlib_metadata-1.7.0.tar.gz", hash = "sha256:90bb658cdbbf6d1735b6341ce708fc7024a3e14e99ffdc5783edea9f9b077f83"},
]
jedi = [
{file = "jedi-0.17.0-py2.py3-none-any.whl", hash = "sha256:cd60c93b71944d628ccac47df9a60fec53150de53d42dc10a7fc4b5ba6aae798"},
{file = "jedi-0.17.0.tar.gz", hash = "sha256:df40c97641cb943661d2db4c33c2e1ff75d491189423249e989bcea4464f3030"},
{file = "jedi-0.17.2-py2.py3-none-any.whl", hash = "sha256:98cc583fa0f2f8304968199b01b6b4b94f469a1f4a74c1560506ca2a211378b5"},
{file = "jedi-0.17.2.tar.gz", hash = "sha256:86ed7d9b750603e4ba582ea8edc678657fb4007894a12bcf6f4bb97892f31d20"},
]
multidict = [
{file = "multidict-4.7.5-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:fc3b4adc2ee8474cb3cd2a155305d5f8eda0a9c91320f83e55748e1fcb68f8e3"},
{file = "multidict-4.7.5-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:42f56542166040b4474c0c608ed051732033cd821126493cf25b6c276df7dd35"},
{file = "multidict-4.7.5-cp35-cp35m-win32.whl", hash = "sha256:7774e9f6c9af3f12f296131453f7b81dabb7ebdb948483362f5afcaac8a826f1"},
{file = "multidict-4.7.5-cp35-cp35m-win_amd64.whl", hash = "sha256:c2c37185fb0af79d5c117b8d2764f4321eeb12ba8c141a95d0aa8c2c1d0a11dd"},
{file = "multidict-4.7.5-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:e439c9a10a95cb32abd708bb8be83b2134fa93790a4fb0535ca36db3dda94d20"},
{file = "multidict-4.7.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:85cb26c38c96f76b7ff38b86c9d560dea10cf3459bb5f4caf72fc1bb932c7136"},
{file = "multidict-4.7.5-cp36-cp36m-win32.whl", hash = "sha256:620b37c3fea181dab09267cd5a84b0f23fa043beb8bc50d8474dd9694de1fa6e"},
{file = "multidict-4.7.5-cp36-cp36m-win_amd64.whl", hash = "sha256:6e6fef114741c4d7ca46da8449038ec8b1e880bbe68674c01ceeb1ac8a648e78"},
{file = "multidict-4.7.5-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:a326f4240123a2ac66bb163eeba99578e9d63a8654a59f4688a79198f9aa10f8"},
{file = "multidict-4.7.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:dc561313279f9d05a3d0ffa89cd15ae477528ea37aa9795c4654588a3287a9ab"},
{file = "multidict-4.7.5-cp37-cp37m-win32.whl", hash = "sha256:4b7df040fb5fe826d689204f9b544af469593fb3ff3a069a6ad3409f742f5928"},
{file = "multidict-4.7.5-cp37-cp37m-win_amd64.whl", hash = "sha256:317f96bc0950d249e96d8d29ab556d01dd38888fbe68324f46fd834b430169f1"},
{file = "multidict-4.7.5-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:b51249fdd2923739cd3efc95a3d6c363b67bbf779208e9f37fd5e68540d1a4d4"},
{file = "multidict-4.7.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:ae402f43604e3b2bc41e8ea8b8526c7fa7139ed76b0d64fc48e28125925275b2"},
{file = "multidict-4.7.5-cp38-cp38-win32.whl", hash = "sha256:bb519becc46275c594410c6c28a8a0adc66fe24fef154a9addea54c1adb006f5"},
{file = "multidict-4.7.5-cp38-cp38-win_amd64.whl", hash = "sha256:544fae9261232a97102e27a926019100a9db75bec7b37feedd74b3aa82f29969"},
{file = "multidict-4.7.5.tar.gz", hash = "sha256:aee283c49601fa4c13adc64c09c978838a7e812f85377ae130a24d7198c0331e"},
{file = "multidict-4.7.6-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:275ca32383bc5d1894b6975bb4ca6a7ff16ab76fa622967625baeebcf8079000"},
{file = "multidict-4.7.6-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:1ece5a3369835c20ed57adadc663400b5525904e53bae59ec854a5d36b39b21a"},
{file = "multidict-4.7.6-cp35-cp35m-win32.whl", hash = "sha256:5141c13374e6b25fe6bf092052ab55c0c03d21bd66c94a0e3ae371d3e4d865a5"},
{file = "multidict-4.7.6-cp35-cp35m-win_amd64.whl", hash = "sha256:9456e90649005ad40558f4cf51dbb842e32807df75146c6d940b6f5abb4a78f3"},
{file = "multidict-4.7.6-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:e0d072ae0f2a179c375f67e3da300b47e1a83293c554450b29c900e50afaae87"},
{file = "multidict-4.7.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:3750f2205b800aac4bb03b5ae48025a64e474d2c6cc79547988ba1d4122a09e2"},
{file = "multidict-4.7.6-cp36-cp36m-win32.whl", hash = "sha256:f07acae137b71af3bb548bd8da720956a3bc9f9a0b87733e0899226a2317aeb7"},
{file = "multidict-4.7.6-cp36-cp36m-win_amd64.whl", hash = "sha256:6513728873f4326999429a8b00fc7ceddb2509b01d5fd3f3be7881a257b8d463"},
{file = "multidict-4.7.6-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:feed85993dbdb1dbc29102f50bca65bdc68f2c0c8d352468c25b54874f23c39d"},
{file = "multidict-4.7.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:fcfbb44c59af3f8ea984de67ec7c306f618a3ec771c2843804069917a8f2e255"},
{file = "multidict-4.7.6-cp37-cp37m-win32.whl", hash = "sha256:4538273208e7294b2659b1602490f4ed3ab1c8cf9dbdd817e0e9db8e64be2507"},
{file = "multidict-4.7.6-cp37-cp37m-win_amd64.whl", hash = "sha256:d14842362ed4cf63751648e7672f7174c9818459d169231d03c56e84daf90b7c"},
{file = "multidict-4.7.6-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:c026fe9a05130e44157b98fea3ab12969e5b60691a276150db9eda71710cd10b"},
{file = "multidict-4.7.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:51a4d210404ac61d32dada00a50ea7ba412e6ea945bbe992e4d7a595276d2ec7"},
{file = "multidict-4.7.6-cp38-cp38-win32.whl", hash = "sha256:5cf311a0f5ef80fe73e4f4c0f0998ec08f954a6ec72b746f3c179e37de1d210d"},
{file = "multidict-4.7.6-cp38-cp38-win_amd64.whl", hash = "sha256:7388d2ef3c55a8ba80da62ecfafa06a1c097c18032a501ffd4cabbc52d7f2b19"},
{file = "multidict-4.7.6.tar.gz", hash = "sha256:fbb77a75e529021e7c4a8d4e823d88ef4d23674a202be4f5addffc72cbb91430"},
]
parso = [
{file = "parso-0.7.0-py2.py3-none-any.whl", hash = "sha256:158c140fc04112dc45bca311633ae5033c2c2a7b732fa33d0955bad8152a8dd0"},
{file = "parso-0.7.0.tar.gz", hash = "sha256:908e9fae2144a076d72ae4e25539143d40b8e3eafbaeae03c1bfe226f4cdf12c"},
{file = "parso-0.7.1-py2.py3-none-any.whl", hash = "sha256:97218d9159b2520ff45eb78028ba8b50d2bc61dcc062a9682666f2dc4bd331ea"},
{file = "parso-0.7.1.tar.gz", hash = "sha256:caba44724b994a8a5e086460bb212abc5a8bc46951bf4a9a1210745953622eb9"},
]
prompt-toolkit = [
{file = "prompt_toolkit-3.0.3-py3-none-any.whl", hash = "sha256:c93e53af97f630f12f5f62a3274e79527936ed466f038953dfa379d4941f651a"},
{file = "prompt_toolkit-3.0.3.tar.gz", hash = "sha256:a402e9bf468b63314e37460b68ba68243d55b2f8c4d0192f85a019af3945050e"},
]
psutil = [
{file = "psutil-5.7.0-cp27-none-win32.whl", hash = "sha256:298af2f14b635c3c7118fd9183843f4e73e681bb6f01e12284d4d70d48a60953"},
{file = "psutil-5.7.0-cp27-none-win_amd64.whl", hash = "sha256:75e22717d4dbc7ca529ec5063000b2b294fc9a367f9c9ede1f65846c7955fd38"},
{file = "psutil-5.7.0-cp35-cp35m-win32.whl", hash = "sha256:f344ca230dd8e8d5eee16827596f1c22ec0876127c28e800d7ae20ed44c4b310"},
{file = "psutil-5.7.0-cp35-cp35m-win_amd64.whl", hash = "sha256:e2d0c5b07c6fe5a87fa27b7855017edb0d52ee73b71e6ee368fae268605cc3f5"},
{file = "psutil-5.7.0-cp36-cp36m-win32.whl", hash = "sha256:a02f4ac50d4a23253b68233b07e7cdb567bd025b982d5cf0ee78296990c22d9e"},
{file = "psutil-5.7.0-cp36-cp36m-win_amd64.whl", hash = "sha256:1413f4158eb50e110777c4f15d7c759521703bd6beb58926f1d562da40180058"},
{file = "psutil-5.7.0-cp37-cp37m-win32.whl", hash = "sha256:d008ddc00c6906ec80040d26dc2d3e3962109e40ad07fd8a12d0284ce5e0e4f8"},
{file = "psutil-5.7.0-cp37-cp37m-win_amd64.whl", hash = "sha256:73f35ab66c6c7a9ce82ba44b1e9b1050be2a80cd4dcc3352cc108656b115c74f"},
{file = "psutil-5.7.0-cp38-cp38-win32.whl", hash = "sha256:60b86f327c198561f101a92be1995f9ae0399736b6eced8f24af41ec64fb88d4"},
{file = "psutil-5.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:d84029b190c8a66a946e28b4d3934d2ca1528ec94764b180f7d6ea57b0e75e26"},
{file = "psutil-5.7.0.tar.gz", hash = "sha256:685ec16ca14d079455892f25bd124df26ff9137664af445563c1bd36629b5e0e"},
{file = "psutil-5.7.2-cp27-none-win32.whl", hash = "sha256:f2018461733b23f308c298653c8903d32aaad7873d25e1d228765e91ae42c3f2"},
{file = "psutil-5.7.2-cp27-none-win_amd64.whl", hash = "sha256:66c18ca7680a31bf16ee22b1d21b6397869dda8059dbdb57d9f27efa6615f195"},
{file = "psutil-5.7.2-cp35-cp35m-win32.whl", hash = "sha256:5e9d0f26d4194479a13d5f4b3798260c20cecf9ac9a461e718eb59ea520a360c"},
{file = "psutil-5.7.2-cp35-cp35m-win_amd64.whl", hash = "sha256:4080869ed93cce662905b029a1770fe89c98787e543fa7347f075ade761b19d6"},
{file = "psutil-5.7.2-cp36-cp36m-win32.whl", hash = "sha256:d8a82162f23c53b8525cf5f14a355f5d1eea86fa8edde27287dd3a98399e4fdf"},
{file = "psutil-5.7.2-cp36-cp36m-win_amd64.whl", hash = "sha256:0ee3c36428f160d2d8fce3c583a0353e848abb7de9732c50cf3356dd49ad63f8"},
{file = "psutil-5.7.2-cp37-cp37m-win32.whl", hash = "sha256:ff1977ba1a5f71f89166d5145c3da1cea89a0fdb044075a12c720ee9123ec818"},
{file = "psutil-5.7.2-cp37-cp37m-win_amd64.whl", hash = "sha256:a5b120bb3c0c71dfe27551f9da2f3209a8257a178ed6c628a819037a8df487f1"},
{file = "psutil-5.7.2-cp38-cp38-win32.whl", hash = "sha256:10512b46c95b02842c225f58fa00385c08fa00c68bac7da2d9a58ebe2c517498"},
{file = "psutil-5.7.2-cp38-cp38-win_amd64.whl", hash = "sha256:68d36986ded5dac7c2dcd42f2682af1db80d4bce3faa126a6145c1637e1b559f"},
{file = "psutil-5.7.2.tar.gz", hash = "sha256:90990af1c3c67195c44c9a889184f84f5b2320dce3ee3acbd054e3ba0b4a7beb"},
]
ptpython = [
{file = "ptpython-3.0.2-py2.py3-none-any.whl", hash = "sha256:126a9e2126816066e6ad57661a15715649a5a4d4b3ca9387d7825dc7d9040c38"},
{file = "ptpython-3.0.2.tar.gz", hash = "sha256:556e5367d4d58231b575dc619493dc0d8ef4c2d15ee85c727a88beb60fa5c52b"},
{file = "ptpython-3.0.5-py2.py3-none-any.whl", hash = "sha256:382d080e4130b9be254776787206380359be4f73c25e6b4e8cc371905c4fa587"},
{file = "ptpython-3.0.5.tar.gz", hash = "sha256:5094e7e4daa77453d3c33eb7b7ebbf1060be4446521865a94e698bc85ff15930"},
]
pygments = [
{file = "Pygments-2.6.1-py3-none-any.whl", hash = "sha256:ff7a40b4860b727ab48fad6360eb351cc1b33cbf9b15a0f689ca5353e9463324"},
@ -351,43 +383,34 @@ pyyaml = [
{file = "PyYAML-5.3.1.tar.gz", hash = "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d"},
]
typing-extensions = [
{file = "typing_extensions-3.7.4.2-py2-none-any.whl", hash = "sha256:f8d2bd89d25bc39dabe7d23df520442fa1d8969b82544370e03d88b5a591c392"},
{file = "typing_extensions-3.7.4.2-py3-none-any.whl", hash = "sha256:6e95524d8a547a91e08f404ae485bbb71962de46967e1b71a0cb89af24e761c5"},
{file = "typing_extensions-3.7.4.2.tar.gz", hash = "sha256:79ee589a3caca649a9bfd2a8de4709837400dfa00b6cc81962a1e6a1815969ae"},
{file = "typing_extensions-3.7.4.3-py2-none-any.whl", hash = "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f"},
{file = "typing_extensions-3.7.4.3-py3-none-any.whl", hash = "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918"},
{file = "typing_extensions-3.7.4.3.tar.gz", hash = "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c"},
]
wcwidth = [
{file = "wcwidth-0.1.9-py2.py3-none-any.whl", hash = "sha256:cafe2186b3c009a04067022ce1dcd79cb38d8d65ee4f4791b8888d6599d1bbe1"},
{file = "wcwidth-0.1.9.tar.gz", hash = "sha256:ee73862862a156bf77ff92b09034fc4825dd3af9cf81bc5b360668d425f3c5f1"},
]
websockets = [
{file = "websockets-8.0.2-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:e906128532a14b9d264a43eb48f9b3080d53a9bda819ab45bf56b8039dc606ac"},
{file = "websockets-8.0.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:83e63aa73331b9ca21af61df8f115fb5fbcba3f281bee650a4ad16a40cd1ef15"},
{file = "websockets-8.0.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:e9102043a81cdc8b7c8032ff4bce39f6229e4ac39cb2010946c912eeb84e2cb6"},
{file = "websockets-8.0.2-cp36-cp36m-win32.whl", hash = "sha256:8d7a20a2f97f1e98c765651d9fb9437201a9ccc2c70e94b0270f1c5ef29667a3"},
{file = "websockets-8.0.2-cp36-cp36m-win_amd64.whl", hash = "sha256:c82e286555f839846ef4f0fdd6910769a577952e1e26aa8ee7a6f45f040e3c2b"},
{file = "websockets-8.0.2-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:73ce69217e4655783ec72ce11c151053fcbd5b837cc39de7999e19605182e28a"},
{file = "websockets-8.0.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:8c77f7d182a6ea2a9d09c2612059f3ad859a90243e899617137ee3f6b7f2b584"},
{file = "websockets-8.0.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:a7affaeffbc5d55681934c16bb6b8fc82bb75b175e7fd4dcca798c938bde8dda"},
{file = "websockets-8.0.2-cp37-cp37m-win32.whl", hash = "sha256:f5cb2683367e32da6a256b60929a3af9c29c212b5091cf5bace9358d03011bf5"},
{file = "websockets-8.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:049e694abe33f8a1d99969fee7bfc0ae6761f7fd5f297c58ea933b27dd6805f2"},
{file = "websockets-8.0.2.tar.gz", hash = "sha256:882a7266fa867a2ebb2c0baaa0f9159cabf131cf18c1b4270d79ad42f9208dc5"},
{file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"},
{file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"},
]
yarl = [
{file = "yarl-1.4.2-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:3ce3d4f7c6b69c4e4f0704b32eca8123b9c58ae91af740481aa57d7857b5e41b"},
{file = "yarl-1.4.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:a4844ebb2be14768f7994f2017f70aca39d658a96c786211be5ddbe1c68794c1"},
{file = "yarl-1.4.2-cp35-cp35m-win32.whl", hash = "sha256:d8cdee92bc930d8b09d8bd2043cedd544d9c8bd7436a77678dd602467a993080"},
{file = "yarl-1.4.2-cp35-cp35m-win_amd64.whl", hash = "sha256:c2b509ac3d4b988ae8769901c66345425e361d518aecbe4acbfc2567e416626a"},
{file = "yarl-1.4.2-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:308b98b0c8cd1dfef1a0311dc5e38ae8f9b58349226aa0533f15a16717ad702f"},
{file = "yarl-1.4.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:944494be42fa630134bf907714d40207e646fd5a94423c90d5b514f7b0713fea"},
{file = "yarl-1.4.2-cp36-cp36m-win32.whl", hash = "sha256:5b10eb0e7f044cf0b035112446b26a3a2946bca9d7d7edb5e54a2ad2f6652abb"},
{file = "yarl-1.4.2-cp36-cp36m-win_amd64.whl", hash = "sha256:a161de7e50224e8e3de6e184707476b5a989037dcb24292b391a3d66ff158e70"},
{file = "yarl-1.4.2-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:26d7c90cb04dee1665282a5d1a998defc1a9e012fdca0f33396f81508f49696d"},
{file = "yarl-1.4.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:0c2ab325d33f1b824734b3ef51d4d54a54e0e7a23d13b86974507602334c2cce"},
{file = "yarl-1.4.2-cp37-cp37m-win32.whl", hash = "sha256:e15199cdb423316e15f108f51249e44eb156ae5dba232cb73be555324a1d49c2"},
{file = "yarl-1.4.2-cp37-cp37m-win_amd64.whl", hash = "sha256:2098a4b4b9d75ee352807a95cdf5f10180db903bc5b7270715c6bbe2551f64ce"},
{file = "yarl-1.4.2-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:c9959d49a77b0e07559e579f38b2f3711c2b8716b8410b320bf9713013215a1b"},
{file = "yarl-1.4.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:25e66e5e2007c7a39541ca13b559cd8ebc2ad8fe00ea94a2aad28a9b1e44e5ae"},
{file = "yarl-1.4.2-cp38-cp38-win32.whl", hash = "sha256:6faa19d3824c21bcbfdfce5171e193c8b4ddafdf0ac3f129ccf0cdfcb083e462"},
{file = "yarl-1.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:0ca2f395591bbd85ddd50a82eb1fde9c1066fafe888c5c7cc1d810cf03fd3cc6"},
{file = "yarl-1.4.2.tar.gz", hash = "sha256:58cd9c469eced558cd81aa3f484b2924e8897049e06889e8ff2510435b7ef74b"},
{file = "yarl-1.5.1-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:db6db0f45d2c63ddb1a9d18d1b9b22f308e52c83638c26b422d520a815c4b3fb"},
{file = "yarl-1.5.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:17668ec6722b1b7a3a05cc0167659f6c95b436d25a36c2d52db0eca7d3f72593"},
{file = "yarl-1.5.1-cp35-cp35m-win32.whl", hash = "sha256:040b237f58ff7d800e6e0fd89c8439b841f777dd99b4a9cca04d6935564b9409"},
{file = "yarl-1.5.1-cp35-cp35m-win_amd64.whl", hash = "sha256:f18d68f2be6bf0e89f1521af2b1bb46e66ab0018faafa81d70f358153170a317"},
{file = "yarl-1.5.1-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:c52ce2883dc193824989a9b97a76ca86ecd1fa7955b14f87bf367a61b6232511"},
{file = "yarl-1.5.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:ce584af5de8830d8701b8979b18fcf450cef9a382b1a3c8ef189bedc408faf1e"},
{file = "yarl-1.5.1-cp36-cp36m-win32.whl", hash = "sha256:df89642981b94e7db5596818499c4b2219028f2a528c9c37cc1de45bf2fd3a3f"},
{file = "yarl-1.5.1-cp36-cp36m-win_amd64.whl", hash = "sha256:3a584b28086bc93c888a6c2aa5c92ed1ae20932f078c46509a66dce9ea5533f2"},
{file = "yarl-1.5.1-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:da456eeec17fa8aa4594d9a9f27c0b1060b6a75f2419fe0c00609587b2695f4a"},
{file = "yarl-1.5.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:bc2f976c0e918659f723401c4f834deb8a8e7798a71be4382e024bcc3f7e23a8"},
{file = "yarl-1.5.1-cp37-cp37m-win32.whl", hash = "sha256:4439be27e4eee76c7632c2427ca5e73703151b22cae23e64adb243a9c2f565d8"},
{file = "yarl-1.5.1-cp37-cp37m-win_amd64.whl", hash = "sha256:48e918b05850fffb070a496d2b5f97fc31d15d94ca33d3d08a4f86e26d4e7c5d"},
{file = "yarl-1.5.1-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:9b930776c0ae0c691776f4d2891ebc5362af86f152dd0da463a6614074cb1b02"},
{file = "yarl-1.5.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:b3b9ad80f8b68519cc3372a6ca85ae02cc5a8807723ac366b53c0f089db19e4a"},
{file = "yarl-1.5.1-cp38-cp38-win32.whl", hash = "sha256:f379b7f83f23fe12823085cd6b906edc49df969eb99757f58ff382349a3303c6"},
{file = "yarl-1.5.1-cp38-cp38-win_amd64.whl", hash = "sha256:9102b59e8337f9874638fcfc9ac3734a0cfadb100e47d55c20d0dc6087fb4692"},
{file = "yarl-1.5.1.tar.gz", hash = "sha256:c22c75b5f394f3d47105045ea551e08a3e804dc7e01b37800ca35b58f856c3d6"},
]
zipp = [
{file = "zipp-3.1.0-py3-none-any.whl", hash = "sha256:aa36550ff0c0b7ef7fa639055d797116ee891440eac1a56f378e2d3179e0320b"},
{file = "zipp-3.1.0.tar.gz", hash = "sha256:c599e4d75c98f6798c509911d08a22e6c021d074469042177c8c86fb92eefd96"},
]

10
shell.nix Normal file
View File

@ -0,0 +1,10 @@
{ pkgs? import <nixpkgs> {}, ... }:
let
pythonEnv = pkgs.poetry2nix.mkPoetryEnv {
projectDir = ./.;
};
in pkgs.mkShell {
buildInputs = [ pythonEnv ];
PYTHONPATH = ".";
}

View File

@ -13,6 +13,22 @@ import discord
import yaml
from src.constants import *
from src.utils import pprint_send
def skip_if(check, default=None):
"""Decorator that skips running the function if the check is False, and returns the default."""
def decorator(f):
@wraps(f)
def wrapper(*args, **kwargs):
if check(*args, **kwargs):
return default
return f(*args, **kwargs)
return wrapper
return decorator
class Event(asyncio.Event):
@ -145,14 +161,16 @@ class BaseTirage(yaml.YAMLObject):
return event
event.clear()
async def run(self):
async def run(self, rounds=(0, 1)):
await self.info_start()
self.poules = await self.make_poules()
for i in rounds:
new_poules = await self.make_poules(i)
self.poules.update(new_poules)
for poule in self.poules:
await self.draw_poule(poule)
for poule in new_poules:
await self.draw_poule(poule)
await self.info_finish()
@ -181,19 +199,20 @@ class BaseTirage(yaml.YAMLObject):
return dices
async def make_poules(self):
async def make_poules(self, rnd):
"""Put teams in poules for a given round (0 or 1)."""
poules = {}
for rnd in (0, 1):
await self.start_make_poule(rnd)
await self.start_make_poule(rnd)
dices = await self.get_dices(self.teams)
sorted_teams = sorted(self.teams, key=lambda t: dices[t])
dices = await self.get_dices(self.teams)
sorted_teams = sorted(self.teams, key=lambda t: dices[t])
idx = 0
for i, qte in enumerate(self.format):
letter = chr(ord("A") + i)
poules[Poule(letter, rnd)] = sorted_teams[idx : idx + qte]
idx += qte
idx = 0
for i, qte in enumerate(self.format):
letter = chr(ord("A") + i)
poules[Poule(letter, rnd)] = sorted_teams[idx : idx + qte]
idx += qte
await self.annonce_poules(poules)
return poules
@ -262,7 +281,8 @@ class BaseTirage(yaml.YAMLObject):
i += 1
# The conflicts
order = doubles + order
self.poules[poule] = order
self.poules[poule] = [t.name for t in order]
await self.annonce_poule(poule)

View File

@ -288,7 +288,7 @@ class DevCog(Cog, name="Dev tools"):
pprint(resp, out)
embed = discord.Embed(title="Result", color=discord.Colour.green())
embed.add_field(name="Query", value=f"```py\n{full_query}```", inline=False)
embed.add_field(name="Query", value=f"```py\n{query}```", inline=False)
value = self.to_field_value(out)
if resp is not None and value:

View File

@ -1,15 +1,17 @@
import ast
import asyncio
import datetime
import io
import itertools
import operator as op
import random
import re
import traceback
import urllib
from collections import defaultdict, Counter
from collections import Counter, defaultdict
from dataclasses import dataclass, field
from functools import partial
from itertools import groupby
from math import log
import math
from operator import attrgetter, itemgetter
from time import time
from typing import List, Set, Union
@ -19,26 +21,27 @@ import discord
import yaml
from discord import Guild, Member
from discord.ext import commands
from discord.ext.commands import (
Cog,
command,
Context,
Command,
CommandError,
Group,
group,
MemberConverter,
BadArgument,
RoleConverter,
)
from discord.ext.commands import (BadArgument, Cog, command, Command, CommandError, Context, Group, group, is_owner,
MemberConverter, RoleConverter)
from discord.utils import get
from src.constants import *
from src.constants import Emoji
from src.core import CustomBot
from src.errors import TfjmError
from src.utils import has_role, start_time, send_and_bin
from src.utils import has_role, send_and_bin, start_time
# supported operators
OPS = {
ast.Add: op.add, ast.Sub: op.sub, ast.Mult: op.mul,
ast.FloorDiv: op.floordiv, ast.Mod: op.mod,
ast.Div: op.truediv, ast.Pow: op.pow, ast.BitXor: op.xor,
ast.USub: op.neg, "abs": abs, "π": math.pi, "τ": math.tau,
"i": 1j,
}
for name in dir(math):
if not name.startswith("_"):
OPS[name] = getattr(math, name)
@dataclass
class Joke(yaml.YAMLObject):
@ -191,9 +194,99 @@ class MiscCog(Cog, name="Divers"):
f"iel sera un membre influent du CNO ?"
)
@command(name="calc", aliases=["="])
async def calc_cmd(self, ctx, *args):
"""Effectue un calcul simple"""
with_tb = has_role(ctx.author, Role.DEV)
embed = self._calc(ctx.message.content, with_tb)
resp = await ctx.send(embed=embed)
def check(before, after):
return after.id == ctx.message.id
while True:
try:
before, after = await self.bot.wait_for(
"message_edit", check=check, timeout=600
)
except asyncio.TimeoutError:
break
embed = self._calc(after.content, with_tb)
await resp.edit(embed=embed)
# Remove the "You may edit your message"
embed.set_footer()
try:
await resp.edit(embed=embed)
except discord.NotFound:
pass
def _calc(self, query: str, with_tb=False):
for prefix in ("! ", "!", "calc", "="):
if query.startswith(prefix):
query = query[len(prefix):]
query = re.sub(r"\b((\d)+(\.\d+)?)(?P<name>[a-zA-Z]+)\b", r"\1*\4", query)
query = query.strip().strip("`")
ex = None
result = 42
try:
result = self._eval(ast.parse(query, mode='eval').body)
except Exception as e:
ex = e
if isinstance(result, complex):
if abs(result.imag) < 1e-12:
result = result.real
else:
r, i = result.real, result.imag
r = r if abs(int(r) - r) > 1e-12 else int(r)
i = i if abs(int(i) - i) > 1e-12 else int(i)
if not r:
result = f"{i if i != 1 else ''}i"
else:
result = f"{r}{i if i != 1 else '':+}i"
if isinstance(result, float):
result = round(result, 12)
embed = discord.Embed(title=discord.utils.escape_markdown(query), color=EMBED_COLOR)
# embed.add_field(name="Entrée", value=f"`{query}`", inline=False)
embed.add_field(name="Valeur", value=f"`{result}`", inline=False)
if ex and with_tb:
embed.add_field(name="Erreur", value=f"{ex.__class__.__name__}: {ex}", inline=False)
trace = io.StringIO()
traceback.print_exception(type(ex), ex, ex.__traceback__, file=trace)
trace.seek(0)
embed.add_field(name="Traceback", value=f"```\n{trace.read()}```")
embed.set_footer(text="You may edit your message")
return embed
def _eval(self, node):
if isinstance(node, ast.Num): # <number>
return node.n
elif isinstance(node, ast.BinOp): # <left> <operator> <right>
return OPS[type(node.op)](self._eval(node.left), self._eval(node.right))
elif isinstance(node, ast.UnaryOp): # <operator> <operand> e.g., -1
return OPS[type(node.op)](self._eval(node.operand))
elif isinstance(node, ast.Call):
if isinstance(node.func, ast.Name):
return OPS[node.func.id](*(self._eval(n) for n in node.args), **{k.arg: self._eval(k.value) for k in node.keywords})
elif isinstance(node, ast.Name):
return OPS[node.id]
fields = ", ".join(
f"{k}={getattr(node, k).__class__.__name__}" for k in node._fields
)
raise TypeError(f"Type de noeud non supporté: {node.__class__.__name__}({fields})")
# ----------------- Hugs ---------------- #
@command(aliases=["<3", "❤️", ":heart:"])
@command(aliases=["<3", "❤️", ":heart:", Emoji.RAINBOW_HEART])
async def hug(self, ctx: Context, who="everyone"):
"""Fait un câlin à quelqu'un. :heart:"""
@ -222,7 +315,7 @@ class MiscCog(Cog, name="Divers"):
":hugging:",
":smiling_face_with_3_hearts:",
"Oh wiiii",
f"{'Je me sens' if bot_hug else 'Iel se sent'} désormais prêt à travailler à fond sur les solutions de AQT",
# f"{'Je me sens' if bot_hug else 'Iel se sent'} désormais prêt à travailler à fond sur les solutions de AQT",
f"{who.mention} en redemande un !"
if not bot_hug
else "J'en veux un autre ! :heart_eyes:",
@ -454,12 +547,15 @@ class MiscCog(Cog, name="Divers"):
":orange_heart:",
":heart:",
":sparkling_heart:",
Emoji.RAINBOW_HEART,
]
if v <= 0:
return hearts[0]
elif v >= 2000:
elif v >= 5000:
return hearts[-1]
elif v >= 2000:
return hearts[-2]
else:
return hearts[len(str(v))]
@ -522,14 +618,15 @@ class MiscCog(Cog, name="Divers"):
yaml.safe_dump_all(jokes, f)
@group(name="joke", invoke_without_command=True, case_insensitive=True)
async def joke(self, ctx: Context):
async def joke(self, ctx: Context, id=None):
"""Fait discretement une blague aléatoire."""
m: discord.Message = ctx.message
await m.delete()
jokes = self.load_jokes()
if False:
if id is not None:
id = int(id)
joke_id = id
jokes = sorted(
jokes, key=lambda j: len(j.likes) - len(j.dislikes), reverse=True
@ -610,7 +707,8 @@ class MiscCog(Cog, name="Divers"):
self.save_jokes(jokes)
@joke.command(name="top", hidden=True, enabled=False)
@joke.command(name="top", hidden=True)
@commands.has_any_role(*Role.ORGAS)
async def best_jokes(self, ctx: Context):
"""Affiche le palmares des blagues."""
@ -626,8 +724,9 @@ class MiscCog(Cog, name="Divers"):
if joke.file:
text += " - image non inclue - "
name = who.display_name if who else "Inconnu"
embed.add_field(
name=f"{i} - {who.display_name} - {len(joke.likes)}", value=text
name=f"{i} - {name} - {len(joke.likes)} :heart: {len(joke.dislikes)} :broken_heart:", value=text, inline=False
)
await ctx.send(embed=embed)
@ -655,7 +754,8 @@ class MiscCog(Cog, name="Divers"):
color=0xFFA500,
)
commands = itertools.groupby(self.bot.walk_commands(), attrgetter("cog_name"))
cog_getter = attrgetter("cog_name")
commands = itertools.groupby(sorted(self.bot.walk_commands(), key=cog_getter), cog_getter)
for cat_name, cat in commands:
cat = {c.qualified_name: c for c in cat}

View File

@ -89,9 +89,9 @@ class TeamsCog(Cog, name="Teams"):
# return str(channel.changed_roles)
return "C'est fait !"
@commands.command(name="tourist")
@commands.command(name="tourist", aliases=["touriste"])
@send_and_bin
async def touriste_cmd(self, ctx: Context, tournoi):
async def touriste_cmd(self, ctx: Context, tournoi="Finale"):
"""
Permet de voir et ecouter dans les salons d'un certain tournoi.
@ -99,9 +99,13 @@ class TeamsCog(Cog, name="Teams"):
`!tourist Bordeaux-Nancy` - Donne les droits de spectateurs pour Bordeaux-Nancy
"""
if ctx.author.top_role != ctx.guild.default_role:
if ctx.author.top_role not in (
ctx.guild.default_role,
get(ctx.guild.roles, name=Role.TOURIST),
):
return f"{ctx.author.mention} tu as déjà un role, devenir spéctateur t'enlèverait des droits."
tournoi = tournoi.title()
if tournoi not in TOURNOIS:
return f"{tournoi} n'est pas un nom de tournoi. Possibilités: {french_join(TOURNOIS)}"
@ -109,11 +113,15 @@ class TeamsCog(Cog, name="Teams"):
tournoi_role = get(guild.roles, name=tournoi)
touriste_role = get(guild.roles, name=Role.TOURIST)
await ctx.author.add_roles(
touriste_role, tournoi_role, reason="Demande via le bot."
)
if tournoi == "Finale":
# we don't give the "Finaliste" role to the tourists, it would give them rights.1
roles = (touriste_role,)
else:
roles = touriste_role, tournoi_role
return f"{ctx.author.mention} à été ajouté comme spectateur dans à {tournoi}."
await ctx.author.add_roles(*roles, reason="Demande via le bot.")
return f"{ctx.author.mention} à été ajouté comme spectateur pour {tournoi}."
@group(name="team", invoke_without_command=True, case_insensitive=True, hidden=True)
async def team(self, ctx):

View File

@ -2,6 +2,7 @@
import asyncio
import random
import re
import sys
import traceback
from collections import defaultdict, namedtuple
@ -25,8 +26,11 @@ from src.errors import TfjmError, UnwantedCommand
__all__ = ["TirageCog"]
from src.utils import send_and_bin, french_join
from src.utils import send_and_bin, french_join, pprint_send, confirm
RE_DRAW_START = re.compile(
r"^((?P<fmt>\d(\+\d)*) )?(?P<teams>[A-Z]{3}(\s[A-Z]{3})+)((?P<finale>\s--finale)|(\s--continue[= ](?P<continue>\d+)))$"
)
Record = namedtuple("Record", ["name", "pb", "penalite"])
@ -244,7 +248,9 @@ class DiscordTirage(BaseTirage):
@safe
async def start_select_pb(self, team):
await self.ctx.send(f"C'est au tour de {team.mention} de choisir un problème.")
await self.ctx.send(
f"C'est au tour de {team.mention} de choisir un problème (`!rp`)."
)
@safe
@send_all
@ -255,12 +261,10 @@ class DiscordTirage(BaseTirage):
second = "\n".join(
f"{p}: {french_join(t)}" for p, t in poules.items() if p.rnd == 1
)
yield (
f"Les poules sont donc, pour le premier tour :"
f"```{first}```\n"
f"Et pour le second tour :"
f"```{second}```"
)
if first:
yield (f"Les poules sont donc, pour le premier tour :" f"```{first}```\n")
if second:
yield (f"Pour le second tour les poules sont :" f"```{second}```")
@safe
@send_all
@ -275,8 +279,8 @@ class DiscordTirage(BaseTirage):
if len(teams) == 3:
table = """```
╔═════╦═════════╦═════════╦═════════╗
║ Phase 1 ║ Phase 2 ║ Phase 3 ║
Pb {0.pb} Pb {1.pb} Pb {2.pb}
T F ║ Phase 1 ║ Phase 2 ║ Phase 3 ║
J M ║ Pb. {0.pb} ║ Pb. {1.pb} ║ Pb. {2.pb}
╠═════╬═════════╬═════════╬═════════╣
{0.name} ║ Def ║ Rap ║ Opp ║
╠═════╬═════════╬═════════╬═════════╣
@ -288,7 +292,7 @@ class DiscordTirage(BaseTirage):
table = """```
+-----+---------+---------+---------+---------+
| | Phase 1 | Phase 2 | Phase 3 | Phase 4 |
| | Pb {0.pb} | Pb {1.pb} | Pb {2.pb} | Pb {3.pb} |
| | Pb {0.pb} | Pb {1.pb} | Pb {2.pb} | Pb {3.pb} |
+-----+---------+---------+---------+---------+
| {0.name} | Déf | | Rap | Opp |
+-----+---------+---------+---------+---------+
@ -300,22 +304,22 @@ class DiscordTirage(BaseTirage):
+-----+---------+---------+---------+---------+```"""
elif len(teams) == 5:
table = """```
╔═════╦═══════════════════╦═══════════════════╦═════════╗
║ Phase 1 ║ Phase 2 ║ Phase 3 ║
╠═════╬═════════╦═════════╬═════════╦═════════╬═════════╣
║ Salle 1 ║ Salle 2 ║ Salle 1 ║ Salle 2 ║ Salle 1 ║
Pb {0.pb} Pb {1.pb} Pb {2.pb} Pb {3.pb} Pb {4.pb}
╠═════╬═════════╬═════════╬═════════╬═════════╬═════════╣
{0.name} ║ Def ║ ║ Opp ║ Rap ║ ║
╠═════╬═════════╬═════════╬═════════╬═════════╬═════════╣
{1.name} ║ ║ Def ║ Rap ║ ║ Opp ║
╠═════╬═════════╬═════════╬═════════╬═════════╬═════════╣
{2.name} ║ Opp ║ ║ Def ║ ║ Rap ║
╠═════╬═════════╬═════════╬═════════╬═════════╬═════════╣
{3.name} ║ Rap ║ Opp ║ ║ Def ║ ║
╠═════╬═════════╬═════════╬═════════╬═════════╬═════════╣
{4.name} ║ ║ Rap ║ ║ Opp ║ Def ║
╚═════╩═════════╩═════════╩═════════╩═════════╩═════════╝```"""
╔═══╦═══════════════════╦═══════════════════╦═════════╗
║ ║ Phase 1 ║ Phase 2 ║ Phase 3 ║
╠═══╬═════════╦═════════╬═════════╦═════════╬═════════╣
║ ║ Salle 1 ║ Salle 2 ║ Salle 1 ║ Salle 2 ║ Salle 1 ║
Pb. {0.pb} ║ Pb. {1.pb} ║ Pb. {2.pb} ║ Pb. {3.pb} ║ Pb. {4.pb}
╠═══╬═════════╬═════════╬═════════╬═════════╬═════════╣
{0.name}║ Def ║ ║ Opp ║ Rap ║ ║
╠═══╬═════════╬═════════╬═════════╬═════════╬═════════╣
{1.name}║ ║ Def ║ Rap ║ ║ Opp ║
╠═══╬═════════╬═════════╬═════════╬═════════╬═════════╣
{2.name}║ Opp ║ ║ Def ║ ║ Rap ║
╠═══╬═════════╬═════════╬═════════╬═════════╬═════════╣
{3.name}║ Rap ║ Opp ║ ║ Def ║ ║
╠═══╬═════════╬═════════╬═════════╬═════════╬═════════╣
{4.name}║ ║ Rap ║ ║ Opp ║ Def ║
╚═══╩═════════╩═════════╩═════════╩═════════╩═════════╝```"""
else:
table = "WTF il n'y a pas 3,4 ou 5 equipes ici."
@ -532,7 +536,8 @@ class TirageCog(Cog, name="Tirages"):
await ctx.send(f"Le problème tiré est... **{problem}**")
@commands.command(
name="oui", aliases=["accept", "yes", "o", "oh-yeaaah", "accepte", "ouiiiiiii"],
name="oui",
aliases=["accept", "yes", "o", "oh-yeaaah", "accepte", "ouiiiiiii", "owi"],
)
async def accept_cmd(self, ctx):
"""
@ -578,17 +583,20 @@ class TirageCog(Cog, name="Tirages"):
await ctx.invoke(self.bot.get_command("help"), "draw")
@draw_group.command(
name="start", usage="équipe1 équipe2 équipe3 (équipe4)",
name="start", usage="FMT TRI1 TRI2... [--finale] [--continue=ID]",
)
@commands.has_any_role(*Role.ORGAS)
async def start(self, ctx: Context, fmt, *teams: discord.Role):
async def start(self, ctx: Context, *args):
"""
(orga) Commence un tirage avec 3 ou 4 équipes.
Cette commande attend des trigrames d'équipes.
Exemple:
`!draw start AAA BBB CCC`
`!draw start 5 AAA BBB CCC DDD EEE` - Tirage à une poule de 5 équipes
`!draw start 3+3 AAA BBB CCC DDD EEE FFF` - Deux poules de 3 équipes
`!draw start 3 AAA BBB CCC --finale` - Tirage seulement du premier tour
`!draw start AAA BBB CCC --continue=7` - Continue un tirage commencé avec `--finale`
"""
channel: discord.TextChannel = ctx.channel
@ -599,22 +607,70 @@ class TirageCog(Cog, name="Tirages"):
"il est possible d'en commencer un autre sur une autre channel."
)
try:
fmt = list(map(int, fmt.split("+")))
except ValueError:
raise TfjmError(
"Le premier argument doit être le format du tournoi, "
"par exemple `3+3` pour deux poules à trois équipes"
query = " ".join(args)
match = re.match(RE_DRAW_START, query)
if match is None:
await ctx.send("La commande est mal formée.")
return await ctx.invoke(self.bot.get_command("help"), "draw start")
teams = match["teams"].split()
finale = bool(match["finale"])
continue_id = int(match["continue"]) if match["continue"] else None
if match["fmt"]:
fmt = list(map(int, match["fmt"].split()))
else:
l = len(teams)
if l <= 5:
fmt = [l]
else:
fmt = [3] * (l // 3 - 1) + [3 + l % 3]
yes = await confirm(
ctx,
self.bot,
f"Le format déterminé est {'+'.join(map(str, fmt))}, "
f"cela est-il correct ?",
)
if not yes:
raise TfjmError(
"Le tirage est annulé, vous pouvez le recommencer en précisant le format."
)
if not set(fmt).issubset({3, 4, 5}):
raise TfjmError("Seuls les poules à 3, 4 ou 5 équipes sont suportées.")
teams_roles = [get(ctx.guild.roles, name=tri) for tri in teams]
if not all(teams_roles):
raise TfjmError("Toutes les équipes ne sont pas sur le discord.")
# Here all data should be valid
self.tirages[channel_id] = DiscordTirage(ctx, *teams, fmt=fmt)
if continue_id is None:
# New tirage
tirage = DiscordTirage(ctx, *teams_roles, fmt=fmt)
if finale:
rounds = (0,)
else:
rounds = 0, 1
else:
try:
tirage = self.get_tirages()[continue_id]
except KeyError:
raise TfjmError(
f"Il n'y pas de tirage {continue_id}. ID possibles {french_join(self.get_tirages())}"
)
await self.tirages[channel_id].run()
rounds = (1,)
tirage.ctx = ctx
tirage.queue = asyncio.Queue()
for i, t in enumerate(teams_roles):
await tirage.event(Event(t.name, i + 1))
self.tirages[channel_id] = tirage
await self.tirages[channel_id].run(rounds)
if self.tirages[channel_id]:
# Check if aborted in an other way
@ -622,10 +678,12 @@ class TirageCog(Cog, name="Tirages"):
@draw_group.command(name="abort")
@commands.has_any_role(*Role.ORGAS)
async def abort_draw_cmd(self, ctx):
async def abort_draw_cmd(self, ctx, force: bool = False):
"""
(orga) Annule le tirage en cours.
Si oui est passé en paramettre, le tirage sera supprímé en même temps.
Le tirage ne pourra pas être continué. Si besoin,
n'hésitez pas à appeller un @dev : il peut réparer
plus de choses qu'on imagine (mais moins qu'on voudrait).
@ -633,9 +691,18 @@ class TirageCog(Cog, name="Tirages"):
channel_id = ctx.channel.id
if channel_id in self.tirages:
await ctx.send(f"Le tirage {self.tirages[channel_id].id} est annulé.")
id = self.tirages[channel_id].id
await ctx.send(f"Le tirage {id} est annulé.")
self.tirages[channel_id].save()
del self.tirages[channel_id]
if force:
tirages = self.get_tirages()
del tirages[id]
File.TIRAGES.touch()
with open(File.TIRAGES, "w") as f:
yaml.dump(tirages, f)
else:
await ctx.send("Il n'y a pas de tirage en cours.")
@ -739,6 +806,16 @@ class TirageCog(Cog, name="Tirages"):
await ctx.send(str(resp.reason))
await ctx.send(await resp.content.read())
@draw_group.command(name="order")
@commands.has_role(Role.DEV)
async def set_order(self, ctx, *teams: discord.Role):
"""(dev) L'ordre des équipes sera celui du message."""
channel = ctx.channel.id
if channel in self.tirages:
for i, t in enumerate(teams):
await self.tirages[channel].event(Event(t.name, i + 1))
def setup(bot):
bot.add_cog(TirageCog(bot))

View File

@ -88,8 +88,10 @@ class Emoji:
BIN = "🗑️"
DICE = "🎲"
CHECK = ""
CROSS = ""
PLUS_1 = "👍"
MINUS_1 = "👎"
RAINBOW_HEART = "<:rainbow_heart:714172834632564818>"
class File:

View File

@ -1,5 +1,7 @@
#!/bin/python
from discord import Intents
from src.constants import *
from src.core import CustomBot
@ -7,7 +9,6 @@ from src.core import CustomBot
# It must be in first otherwise "!" always match first and the space is not recognised
from src.utils import fg
# Global variable to hold the tirages.
# We *want* it to be global so we can reload the tirages cog without
# removing all the running tirages
@ -15,7 +16,7 @@ tirages = {}
def start():
bot = CustomBot(("! ", "!"), case_insensitive=True)
bot = CustomBot(("! ", "!"), case_insensitive=True, owner_id=DIEGO, intents=Intents.all())
@bot.event
async def on_ready():

View File

@ -1,9 +1,15 @@
import asyncio
from pprint import pprint
from functools import wraps
from io import StringIO
from typing import Union
import discord
import psutil
from discord.ext.commands import Bot
from src.constants import *
def fg(text, color: int = 0xFFA500):
r = color >> 16
@ -14,6 +20,10 @@ def fg(text, color: int = 0xFFA500):
def french_join(l):
l = list(l)
if not l:
return ""
if len(l) < 2:
return l[0]
start = ", ".join(l[:-1])
return f"{start} et {l[-1]}"
@ -44,6 +54,45 @@ def send_and_bin(f):
return wrapped
async def pprint_send(ctx, *objs, **nobjs):
embed = discord.Embed(title="Debug")
nobjs.update({f"Object {i}": o for i, o in enumerate(objs)})
for name, obj in nobjs.items():
out = StringIO()
pprint(obj, out)
out.seek(0)
value = out.read()
if len(value) > 1000:
value = value[:500] + "\n...\n" + value[-500:]
value = f"```py\n{value}\n```"
embed.add_field(name=name, value=value)
return await ctx.send(embed=embed)
async def confirm(ctx, bot, prompt):
msg: discord.Message = await ctx.send(prompt)
await msg.add_reaction(Emoji.CHECK)
await msg.add_reaction(Emoji.CROSS)
def check(reaction: discord.Reaction, u):
return (
ctx.author == u
and msg.id == reaction.message.id
and str(reaction.emoji) in (Emoji.CHECK, Emoji.CROSS)
)
reaction, u = await bot.wait_for("reaction_add", check=check)
if str(reaction) == Emoji.CHECK:
await msg.clear_reaction(Emoji.CROSS)
return True
else:
await msg.clear_reaction(Emoji.CHECK)
return False
def start_time():
return psutil.Process().create_time()