1
0
mirror of https://gitlab.com/ddorn/tfjm-discord-bot.git synced 2025-07-08 03:30:21 +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" name = "appdirs"
optional = false optional = false
python-versions = "*" python-versions = "*"
version = "1.4.3" version = "1.4.4"
[[package]] [[package]]
category = "main" category = "main"
@ -46,13 +46,13 @@ description = "Classes Without Boilerplate"
name = "attrs" name = "attrs"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "19.3.0" version = "20.2.0"
[package.extras] [package.extras]
azure-pipelines = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "pytest-azurepipelines"] dev = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "sphinx", "sphinx-rtd-theme", "pre-commit"]
dev = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "sphinx", "pre-commit"] docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"]
docs = ["sphinx", "zope.interface"] tests = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"]
tests = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"] tests_no_zope = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six"]
[[package]] [[package]]
category = "main" category = "main"
@ -79,11 +79,10 @@ description = "A Python wrapper for the Discord API"
name = "discord.py" name = "discord.py"
optional = false optional = false
python-versions = ">=3.5.3" python-versions = ">=3.5.3"
version = "1.3.3" version = "1.4.1"
[package.dependencies] [package.dependencies]
aiohttp = ">=3.6.0,<3.7.0" 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] [package.extras]
docs = ["sphinx (1.8.5)", "sphinxcontrib-trio (1.1.1)", "sphinxcontrib-websupport"] 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" name = "idna"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "2.9" version = "2.10"
[[package]] [[package]]
category = "main" category = "main"
@ -109,20 +108,36 @@ version = "1.1.0"
[package.dependencies] [package.dependencies]
idna = ">=2.0" 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]] [[package]]
category = "main" category = "main"
description = "An autocompletion tool for Python that can be used for text editors." description = "An autocompletion tool for Python that can be used for text editors."
name = "jedi" name = "jedi"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
version = "0.17.0" version = "0.17.2"
[package.dependencies] [package.dependencies]
parso = ">=0.7.0" parso = ">=0.7.0,<0.8.0"
[package.extras] [package.extras]
qa = ["flake8 (3.7.9)"] 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]] [[package]]
category = "main" category = "main"
@ -130,7 +145,7 @@ description = "multidict implementation"
name = "multidict" name = "multidict"
optional = false optional = false
python-versions = ">=3.5" python-versions = ">=3.5"
version = "4.7.5" version = "4.7.6"
[[package]] [[package]]
category = "main" category = "main"
@ -138,7 +153,7 @@ description = "A Python Parser"
name = "parso" name = "parso"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "0.7.0" version = "0.7.1"
[package.extras] [package.extras]
testing = ["docopt", "pytest (>=3.0.7)"] testing = ["docopt", "pytest (>=3.0.7)"]
@ -160,10 +175,10 @@ description = "Cross-platform lib for process and system monitoring in Python."
name = "psutil" name = "psutil"
optional = false optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "5.7.0" version = "5.7.2"
[package.extras] [package.extras]
enum = ["enum34"] test = ["ipaddress", "mock", "unittest2", "enum34", "pywin32", "wmi"]
[[package]] [[package]]
category = "main" category = "main"
@ -171,7 +186,7 @@ description = "Python REPL build on top of prompt_toolkit"
name = "ptpython" name = "ptpython"
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.6"
version = "3.0.2" version = "3.0.5"
[package.dependencies] [package.dependencies]
appdirs = "*" appdirs = "*"
@ -179,6 +194,10 @@ jedi = ">=0.9.0"
prompt-toolkit = ">=3.0.0,<3.1.0" prompt-toolkit = ">=3.0.0,<3.1.0"
pygments = "*" pygments = "*"
[package.dependencies.importlib-metadata]
python = "<3.8"
version = "*"
[package.extras] [package.extras]
ptipython = ["ipython"] ptipython = ["ipython"]
@ -201,27 +220,19 @@ version = "5.3.1"
[[package]] [[package]]
category = "main" category = "main"
description = "Backported and Experimental Type Hints for Python 3.5+" description = "Backported and Experimental Type Hints for Python 3.5+"
marker = "python_version < \"3.7\"" marker = "python_version < \"3.8\""
name = "typing-extensions" name = "typing-extensions"
optional = false optional = false
python-versions = "*" python-versions = "*"
version = "3.7.4.2" version = "3.7.4.3"
[[package]] [[package]]
category = "main" 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" name = "wcwidth"
optional = false optional = false
python-versions = "*" python-versions = "*"
version = "0.1.9" version = "0.2.5"
[[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"
[[package]] [[package]]
category = "main" category = "main"
@ -229,12 +240,29 @@ description = "Yet another URL library"
name = "yarl" name = "yarl"
optional = false optional = false
python-versions = ">=3.5" python-versions = ">=3.5"
version = "1.4.2" version = "1.5.1"
[package.dependencies] [package.dependencies]
idna = ">=2.0" idna = ">=2.0"
multidict = ">=4.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] [metadata]
content-hash = "9c9fe13eda9abe2a52c99a38f8bd1183b208d8f8ac72f478061376066c4a105e" content-hash = "9c9fe13eda9abe2a52c99a38f8bd1183b208d8f8ac72f478061376066c4a105e"
python-versions = "^3.6" python-versions = "^3.6"
@ -255,16 +283,16 @@ aiohttp = [
{file = "aiohttp-3.6.2.tar.gz", hash = "sha256:259ab809ff0727d0e834ac5e8a283dc5e3e0ecc30c4d80b3cd17a4139ce1f326"}, {file = "aiohttp-3.6.2.tar.gz", hash = "sha256:259ab809ff0727d0e834ac5e8a283dc5e3e0ecc30c4d80b3cd17a4139ce1f326"},
] ]
appdirs = [ appdirs = [
{file = "appdirs-1.4.3-py2.py3-none-any.whl", hash = "sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e"}, {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"},
{file = "appdirs-1.4.3.tar.gz", hash = "sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92"}, {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"},
] ]
async-timeout = [ async-timeout = [
{file = "async-timeout-3.0.1.tar.gz", hash = "sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f"}, {file = "async-timeout-3.0.1.tar.gz", hash = "sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f"},
{file = "async_timeout-3.0.1-py3-none-any.whl", hash = "sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3"}, {file = "async_timeout-3.0.1-py3-none-any.whl", hash = "sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3"},
] ]
attrs = [ attrs = [
{file = "attrs-19.3.0-py2.py3-none-any.whl", hash = "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c"}, {file = "attrs-20.2.0-py2.py3-none-any.whl", hash = "sha256:fce7fc47dfc976152e82d53ff92fa0407700c21acd20886a13777a0d20e655dc"},
{file = "attrs-19.3.0.tar.gz", hash = "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"}, {file = "attrs-20.2.0.tar.gz", hash = "sha256:26b54ddbbb9ee1d34d5d3668dd37d6cf74990ab23c828c2888dccdceee395594"},
] ]
chardet = [ chardet = [
{file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"}, {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"}, {file = "discord-1.0.1.tar.gz", hash = "sha256:ff6653655e342e7721dfb3f10421345fd852c2a33f2cca912b1c39b3778a9429"},
] ]
"discord.py" = [ "discord.py" = [
{file = "discord.py-1.3.3-py3-none-any.whl", hash = "sha256:406871b06d86c3dc49fba63238519f28628dac946fef8a0e22988ff58ec05580"}, {file = "discord.py-1.4.1-py3-none-any.whl", hash = "sha256:98ea3096a3585c9c379209926f530808f5fcf4930928d8cfb579d2562d119570"},
{file = "discord.py-1.3.3.tar.gz", hash = "sha256:ad00e34c72d2faa8db2157b651d05f3c415d7d05078e7e41dc9e8dc240051beb"}, {file = "discord.py-1.4.1.tar.gz", hash = "sha256:f9decb3bfa94613d922376288617e6a6f969260923643e2897f4540c34793442"},
] ]
idna = [ idna = [
{file = "idna-2.9-py2.py3-none-any.whl", hash = "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"}, {file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"},
{file = "idna-2.9.tar.gz", hash = "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb"}, {file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"},
] ]
idna-ssl = [ idna-ssl = [
{file = "idna-ssl-1.1.0.tar.gz", hash = "sha256:a933e3bb13da54383f9e8f35dc4f9cb9eb9b3b78c6b36f311254d6d0d92c6c7c"}, {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 = [ jedi = [
{file = "jedi-0.17.0-py2.py3-none-any.whl", hash = "sha256:cd60c93b71944d628ccac47df9a60fec53150de53d42dc10a7fc4b5ba6aae798"}, {file = "jedi-0.17.2-py2.py3-none-any.whl", hash = "sha256:98cc583fa0f2f8304968199b01b6b4b94f469a1f4a74c1560506ca2a211378b5"},
{file = "jedi-0.17.0.tar.gz", hash = "sha256:df40c97641cb943661d2db4c33c2e1ff75d491189423249e989bcea4464f3030"}, {file = "jedi-0.17.2.tar.gz", hash = "sha256:86ed7d9b750603e4ba582ea8edc678657fb4007894a12bcf6f4bb97892f31d20"},
] ]
multidict = [ multidict = [
{file = "multidict-4.7.5-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:fc3b4adc2ee8474cb3cd2a155305d5f8eda0a9c91320f83e55748e1fcb68f8e3"}, {file = "multidict-4.7.6-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:275ca32383bc5d1894b6975bb4ca6a7ff16ab76fa622967625baeebcf8079000"},
{file = "multidict-4.7.5-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:42f56542166040b4474c0c608ed051732033cd821126493cf25b6c276df7dd35"}, {file = "multidict-4.7.6-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:1ece5a3369835c20ed57adadc663400b5525904e53bae59ec854a5d36b39b21a"},
{file = "multidict-4.7.5-cp35-cp35m-win32.whl", hash = "sha256:7774e9f6c9af3f12f296131453f7b81dabb7ebdb948483362f5afcaac8a826f1"}, {file = "multidict-4.7.6-cp35-cp35m-win32.whl", hash = "sha256:5141c13374e6b25fe6bf092052ab55c0c03d21bd66c94a0e3ae371d3e4d865a5"},
{file = "multidict-4.7.5-cp35-cp35m-win_amd64.whl", hash = "sha256:c2c37185fb0af79d5c117b8d2764f4321eeb12ba8c141a95d0aa8c2c1d0a11dd"}, {file = "multidict-4.7.6-cp35-cp35m-win_amd64.whl", hash = "sha256:9456e90649005ad40558f4cf51dbb842e32807df75146c6d940b6f5abb4a78f3"},
{file = "multidict-4.7.5-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:e439c9a10a95cb32abd708bb8be83b2134fa93790a4fb0535ca36db3dda94d20"}, {file = "multidict-4.7.6-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:e0d072ae0f2a179c375f67e3da300b47e1a83293c554450b29c900e50afaae87"},
{file = "multidict-4.7.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:85cb26c38c96f76b7ff38b86c9d560dea10cf3459bb5f4caf72fc1bb932c7136"}, {file = "multidict-4.7.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:3750f2205b800aac4bb03b5ae48025a64e474d2c6cc79547988ba1d4122a09e2"},
{file = "multidict-4.7.5-cp36-cp36m-win32.whl", hash = "sha256:620b37c3fea181dab09267cd5a84b0f23fa043beb8bc50d8474dd9694de1fa6e"}, {file = "multidict-4.7.6-cp36-cp36m-win32.whl", hash = "sha256:f07acae137b71af3bb548bd8da720956a3bc9f9a0b87733e0899226a2317aeb7"},
{file = "multidict-4.7.5-cp36-cp36m-win_amd64.whl", hash = "sha256:6e6fef114741c4d7ca46da8449038ec8b1e880bbe68674c01ceeb1ac8a648e78"}, {file = "multidict-4.7.6-cp36-cp36m-win_amd64.whl", hash = "sha256:6513728873f4326999429a8b00fc7ceddb2509b01d5fd3f3be7881a257b8d463"},
{file = "multidict-4.7.5-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:a326f4240123a2ac66bb163eeba99578e9d63a8654a59f4688a79198f9aa10f8"}, {file = "multidict-4.7.6-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:feed85993dbdb1dbc29102f50bca65bdc68f2c0c8d352468c25b54874f23c39d"},
{file = "multidict-4.7.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:dc561313279f9d05a3d0ffa89cd15ae477528ea37aa9795c4654588a3287a9ab"}, {file = "multidict-4.7.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:fcfbb44c59af3f8ea984de67ec7c306f618a3ec771c2843804069917a8f2e255"},
{file = "multidict-4.7.5-cp37-cp37m-win32.whl", hash = "sha256:4b7df040fb5fe826d689204f9b544af469593fb3ff3a069a6ad3409f742f5928"}, {file = "multidict-4.7.6-cp37-cp37m-win32.whl", hash = "sha256:4538273208e7294b2659b1602490f4ed3ab1c8cf9dbdd817e0e9db8e64be2507"},
{file = "multidict-4.7.5-cp37-cp37m-win_amd64.whl", hash = "sha256:317f96bc0950d249e96d8d29ab556d01dd38888fbe68324f46fd834b430169f1"}, {file = "multidict-4.7.6-cp37-cp37m-win_amd64.whl", hash = "sha256:d14842362ed4cf63751648e7672f7174c9818459d169231d03c56e84daf90b7c"},
{file = "multidict-4.7.5-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:b51249fdd2923739cd3efc95a3d6c363b67bbf779208e9f37fd5e68540d1a4d4"}, {file = "multidict-4.7.6-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:c026fe9a05130e44157b98fea3ab12969e5b60691a276150db9eda71710cd10b"},
{file = "multidict-4.7.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:ae402f43604e3b2bc41e8ea8b8526c7fa7139ed76b0d64fc48e28125925275b2"}, {file = "multidict-4.7.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:51a4d210404ac61d32dada00a50ea7ba412e6ea945bbe992e4d7a595276d2ec7"},
{file = "multidict-4.7.5-cp38-cp38-win32.whl", hash = "sha256:bb519becc46275c594410c6c28a8a0adc66fe24fef154a9addea54c1adb006f5"}, {file = "multidict-4.7.6-cp38-cp38-win32.whl", hash = "sha256:5cf311a0f5ef80fe73e4f4c0f0998ec08f954a6ec72b746f3c179e37de1d210d"},
{file = "multidict-4.7.5-cp38-cp38-win_amd64.whl", hash = "sha256:544fae9261232a97102e27a926019100a9db75bec7b37feedd74b3aa82f29969"}, {file = "multidict-4.7.6-cp38-cp38-win_amd64.whl", hash = "sha256:7388d2ef3c55a8ba80da62ecfafa06a1c097c18032a501ffd4cabbc52d7f2b19"},
{file = "multidict-4.7.5.tar.gz", hash = "sha256:aee283c49601fa4c13adc64c09c978838a7e812f85377ae130a24d7198c0331e"}, {file = "multidict-4.7.6.tar.gz", hash = "sha256:fbb77a75e529021e7c4a8d4e823d88ef4d23674a202be4f5addffc72cbb91430"},
] ]
parso = [ parso = [
{file = "parso-0.7.0-py2.py3-none-any.whl", hash = "sha256:158c140fc04112dc45bca311633ae5033c2c2a7b732fa33d0955bad8152a8dd0"}, {file = "parso-0.7.1-py2.py3-none-any.whl", hash = "sha256:97218d9159b2520ff45eb78028ba8b50d2bc61dcc062a9682666f2dc4bd331ea"},
{file = "parso-0.7.0.tar.gz", hash = "sha256:908e9fae2144a076d72ae4e25539143d40b8e3eafbaeae03c1bfe226f4cdf12c"}, {file = "parso-0.7.1.tar.gz", hash = "sha256:caba44724b994a8a5e086460bb212abc5a8bc46951bf4a9a1210745953622eb9"},
] ]
prompt-toolkit = [ prompt-toolkit = [
{file = "prompt_toolkit-3.0.3-py3-none-any.whl", hash = "sha256:c93e53af97f630f12f5f62a3274e79527936ed466f038953dfa379d4941f651a"}, {file = "prompt_toolkit-3.0.3-py3-none-any.whl", hash = "sha256:c93e53af97f630f12f5f62a3274e79527936ed466f038953dfa379d4941f651a"},
{file = "prompt_toolkit-3.0.3.tar.gz", hash = "sha256:a402e9bf468b63314e37460b68ba68243d55b2f8c4d0192f85a019af3945050e"}, {file = "prompt_toolkit-3.0.3.tar.gz", hash = "sha256:a402e9bf468b63314e37460b68ba68243d55b2f8c4d0192f85a019af3945050e"},
] ]
psutil = [ psutil = [
{file = "psutil-5.7.0-cp27-none-win32.whl", hash = "sha256:298af2f14b635c3c7118fd9183843f4e73e681bb6f01e12284d4d70d48a60953"}, {file = "psutil-5.7.2-cp27-none-win32.whl", hash = "sha256:f2018461733b23f308c298653c8903d32aaad7873d25e1d228765e91ae42c3f2"},
{file = "psutil-5.7.0-cp27-none-win_amd64.whl", hash = "sha256:75e22717d4dbc7ca529ec5063000b2b294fc9a367f9c9ede1f65846c7955fd38"}, {file = "psutil-5.7.2-cp27-none-win_amd64.whl", hash = "sha256:66c18ca7680a31bf16ee22b1d21b6397869dda8059dbdb57d9f27efa6615f195"},
{file = "psutil-5.7.0-cp35-cp35m-win32.whl", hash = "sha256:f344ca230dd8e8d5eee16827596f1c22ec0876127c28e800d7ae20ed44c4b310"}, {file = "psutil-5.7.2-cp35-cp35m-win32.whl", hash = "sha256:5e9d0f26d4194479a13d5f4b3798260c20cecf9ac9a461e718eb59ea520a360c"},
{file = "psutil-5.7.0-cp35-cp35m-win_amd64.whl", hash = "sha256:e2d0c5b07c6fe5a87fa27b7855017edb0d52ee73b71e6ee368fae268605cc3f5"}, {file = "psutil-5.7.2-cp35-cp35m-win_amd64.whl", hash = "sha256:4080869ed93cce662905b029a1770fe89c98787e543fa7347f075ade761b19d6"},
{file = "psutil-5.7.0-cp36-cp36m-win32.whl", hash = "sha256:a02f4ac50d4a23253b68233b07e7cdb567bd025b982d5cf0ee78296990c22d9e"}, {file = "psutil-5.7.2-cp36-cp36m-win32.whl", hash = "sha256:d8a82162f23c53b8525cf5f14a355f5d1eea86fa8edde27287dd3a98399e4fdf"},
{file = "psutil-5.7.0-cp36-cp36m-win_amd64.whl", hash = "sha256:1413f4158eb50e110777c4f15d7c759521703bd6beb58926f1d562da40180058"}, {file = "psutil-5.7.2-cp36-cp36m-win_amd64.whl", hash = "sha256:0ee3c36428f160d2d8fce3c583a0353e848abb7de9732c50cf3356dd49ad63f8"},
{file = "psutil-5.7.0-cp37-cp37m-win32.whl", hash = "sha256:d008ddc00c6906ec80040d26dc2d3e3962109e40ad07fd8a12d0284ce5e0e4f8"}, {file = "psutil-5.7.2-cp37-cp37m-win32.whl", hash = "sha256:ff1977ba1a5f71f89166d5145c3da1cea89a0fdb044075a12c720ee9123ec818"},
{file = "psutil-5.7.0-cp37-cp37m-win_amd64.whl", hash = "sha256:73f35ab66c6c7a9ce82ba44b1e9b1050be2a80cd4dcc3352cc108656b115c74f"}, {file = "psutil-5.7.2-cp37-cp37m-win_amd64.whl", hash = "sha256:a5b120bb3c0c71dfe27551f9da2f3209a8257a178ed6c628a819037a8df487f1"},
{file = "psutil-5.7.0-cp38-cp38-win32.whl", hash = "sha256:60b86f327c198561f101a92be1995f9ae0399736b6eced8f24af41ec64fb88d4"}, {file = "psutil-5.7.2-cp38-cp38-win32.whl", hash = "sha256:10512b46c95b02842c225f58fa00385c08fa00c68bac7da2d9a58ebe2c517498"},
{file = "psutil-5.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:d84029b190c8a66a946e28b4d3934d2ca1528ec94764b180f7d6ea57b0e75e26"}, {file = "psutil-5.7.2-cp38-cp38-win_amd64.whl", hash = "sha256:68d36986ded5dac7c2dcd42f2682af1db80d4bce3faa126a6145c1637e1b559f"},
{file = "psutil-5.7.0.tar.gz", hash = "sha256:685ec16ca14d079455892f25bd124df26ff9137664af445563c1bd36629b5e0e"}, {file = "psutil-5.7.2.tar.gz", hash = "sha256:90990af1c3c67195c44c9a889184f84f5b2320dce3ee3acbd054e3ba0b4a7beb"},
] ]
ptpython = [ ptpython = [
{file = "ptpython-3.0.2-py2.py3-none-any.whl", hash = "sha256:126a9e2126816066e6ad57661a15715649a5a4d4b3ca9387d7825dc7d9040c38"}, {file = "ptpython-3.0.5-py2.py3-none-any.whl", hash = "sha256:382d080e4130b9be254776787206380359be4f73c25e6b4e8cc371905c4fa587"},
{file = "ptpython-3.0.2.tar.gz", hash = "sha256:556e5367d4d58231b575dc619493dc0d8ef4c2d15ee85c727a88beb60fa5c52b"}, {file = "ptpython-3.0.5.tar.gz", hash = "sha256:5094e7e4daa77453d3c33eb7b7ebbf1060be4446521865a94e698bc85ff15930"},
] ]
pygments = [ pygments = [
{file = "Pygments-2.6.1-py3-none-any.whl", hash = "sha256:ff7a40b4860b727ab48fad6360eb351cc1b33cbf9b15a0f689ca5353e9463324"}, {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"}, {file = "PyYAML-5.3.1.tar.gz", hash = "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d"},
] ]
typing-extensions = [ typing-extensions = [
{file = "typing_extensions-3.7.4.2-py2-none-any.whl", hash = "sha256:f8d2bd89d25bc39dabe7d23df520442fa1d8969b82544370e03d88b5a591c392"}, {file = "typing_extensions-3.7.4.3-py2-none-any.whl", hash = "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f"},
{file = "typing_extensions-3.7.4.2-py3-none-any.whl", hash = "sha256:6e95524d8a547a91e08f404ae485bbb71962de46967e1b71a0cb89af24e761c5"}, {file = "typing_extensions-3.7.4.3-py3-none-any.whl", hash = "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918"},
{file = "typing_extensions-3.7.4.2.tar.gz", hash = "sha256:79ee589a3caca649a9bfd2a8de4709837400dfa00b6cc81962a1e6a1815969ae"}, {file = "typing_extensions-3.7.4.3.tar.gz", hash = "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c"},
] ]
wcwidth = [ wcwidth = [
{file = "wcwidth-0.1.9-py2.py3-none-any.whl", hash = "sha256:cafe2186b3c009a04067022ce1dcd79cb38d8d65ee4f4791b8888d6599d1bbe1"}, {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"},
{file = "wcwidth-0.1.9.tar.gz", hash = "sha256:ee73862862a156bf77ff92b09034fc4825dd3af9cf81bc5b360668d425f3c5f1"}, {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"},
]
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"},
] ]
yarl = [ yarl = [
{file = "yarl-1.4.2-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:3ce3d4f7c6b69c4e4f0704b32eca8123b9c58ae91af740481aa57d7857b5e41b"}, {file = "yarl-1.5.1-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:db6db0f45d2c63ddb1a9d18d1b9b22f308e52c83638c26b422d520a815c4b3fb"},
{file = "yarl-1.4.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:a4844ebb2be14768f7994f2017f70aca39d658a96c786211be5ddbe1c68794c1"}, {file = "yarl-1.5.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:17668ec6722b1b7a3a05cc0167659f6c95b436d25a36c2d52db0eca7d3f72593"},
{file = "yarl-1.4.2-cp35-cp35m-win32.whl", hash = "sha256:d8cdee92bc930d8b09d8bd2043cedd544d9c8bd7436a77678dd602467a993080"}, {file = "yarl-1.5.1-cp35-cp35m-win32.whl", hash = "sha256:040b237f58ff7d800e6e0fd89c8439b841f777dd99b4a9cca04d6935564b9409"},
{file = "yarl-1.4.2-cp35-cp35m-win_amd64.whl", hash = "sha256:c2b509ac3d4b988ae8769901c66345425e361d518aecbe4acbfc2567e416626a"}, {file = "yarl-1.5.1-cp35-cp35m-win_amd64.whl", hash = "sha256:f18d68f2be6bf0e89f1521af2b1bb46e66ab0018faafa81d70f358153170a317"},
{file = "yarl-1.4.2-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:308b98b0c8cd1dfef1a0311dc5e38ae8f9b58349226aa0533f15a16717ad702f"}, {file = "yarl-1.5.1-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:c52ce2883dc193824989a9b97a76ca86ecd1fa7955b14f87bf367a61b6232511"},
{file = "yarl-1.4.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:944494be42fa630134bf907714d40207e646fd5a94423c90d5b514f7b0713fea"}, {file = "yarl-1.5.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:ce584af5de8830d8701b8979b18fcf450cef9a382b1a3c8ef189bedc408faf1e"},
{file = "yarl-1.4.2-cp36-cp36m-win32.whl", hash = "sha256:5b10eb0e7f044cf0b035112446b26a3a2946bca9d7d7edb5e54a2ad2f6652abb"}, {file = "yarl-1.5.1-cp36-cp36m-win32.whl", hash = "sha256:df89642981b94e7db5596818499c4b2219028f2a528c9c37cc1de45bf2fd3a3f"},
{file = "yarl-1.4.2-cp36-cp36m-win_amd64.whl", hash = "sha256:a161de7e50224e8e3de6e184707476b5a989037dcb24292b391a3d66ff158e70"}, {file = "yarl-1.5.1-cp36-cp36m-win_amd64.whl", hash = "sha256:3a584b28086bc93c888a6c2aa5c92ed1ae20932f078c46509a66dce9ea5533f2"},
{file = "yarl-1.4.2-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:26d7c90cb04dee1665282a5d1a998defc1a9e012fdca0f33396f81508f49696d"}, {file = "yarl-1.5.1-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:da456eeec17fa8aa4594d9a9f27c0b1060b6a75f2419fe0c00609587b2695f4a"},
{file = "yarl-1.4.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:0c2ab325d33f1b824734b3ef51d4d54a54e0e7a23d13b86974507602334c2cce"}, {file = "yarl-1.5.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:bc2f976c0e918659f723401c4f834deb8a8e7798a71be4382e024bcc3f7e23a8"},
{file = "yarl-1.4.2-cp37-cp37m-win32.whl", hash = "sha256:e15199cdb423316e15f108f51249e44eb156ae5dba232cb73be555324a1d49c2"}, {file = "yarl-1.5.1-cp37-cp37m-win32.whl", hash = "sha256:4439be27e4eee76c7632c2427ca5e73703151b22cae23e64adb243a9c2f565d8"},
{file = "yarl-1.4.2-cp37-cp37m-win_amd64.whl", hash = "sha256:2098a4b4b9d75ee352807a95cdf5f10180db903bc5b7270715c6bbe2551f64ce"}, {file = "yarl-1.5.1-cp37-cp37m-win_amd64.whl", hash = "sha256:48e918b05850fffb070a496d2b5f97fc31d15d94ca33d3d08a4f86e26d4e7c5d"},
{file = "yarl-1.4.2-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:c9959d49a77b0e07559e579f38b2f3711c2b8716b8410b320bf9713013215a1b"}, {file = "yarl-1.5.1-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:9b930776c0ae0c691776f4d2891ebc5362af86f152dd0da463a6614074cb1b02"},
{file = "yarl-1.4.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:25e66e5e2007c7a39541ca13b559cd8ebc2ad8fe00ea94a2aad28a9b1e44e5ae"}, {file = "yarl-1.5.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:b3b9ad80f8b68519cc3372a6ca85ae02cc5a8807723ac366b53c0f089db19e4a"},
{file = "yarl-1.4.2-cp38-cp38-win32.whl", hash = "sha256:6faa19d3824c21bcbfdfce5171e193c8b4ddafdf0ac3f129ccf0cdfcb083e462"}, {file = "yarl-1.5.1-cp38-cp38-win32.whl", hash = "sha256:f379b7f83f23fe12823085cd6b906edc49df969eb99757f58ff382349a3303c6"},
{file = "yarl-1.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:0ca2f395591bbd85ddd50a82eb1fde9c1066fafe888c5c7cc1d810cf03fd3cc6"}, {file = "yarl-1.5.1-cp38-cp38-win_amd64.whl", hash = "sha256:9102b59e8337f9874638fcfc9ac3734a0cfadb100e47d55c20d0dc6087fb4692"},
{file = "yarl-1.4.2.tar.gz", hash = "sha256:58cd9c469eced558cd81aa3f484b2924e8897049e06889e8ff2510435b7ef74b"}, {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 import yaml
from src.constants import * 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): class Event(asyncio.Event):
@ -145,13 +161,15 @@ class BaseTirage(yaml.YAMLObject):
return event return event
event.clear() event.clear()
async def run(self): async def run(self, rounds=(0, 1)):
await self.info_start() 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: for poule in new_poules:
await self.draw_poule(poule) await self.draw_poule(poule)
await self.info_finish() await self.info_finish()
@ -181,9 +199,10 @@ class BaseTirage(yaml.YAMLObject):
return dices 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 = {} 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) dices = await self.get_dices(self.teams)
@ -262,7 +281,8 @@ class BaseTirage(yaml.YAMLObject):
i += 1 i += 1
# The conflicts # The conflicts
order = doubles + order order = doubles + order
self.poules[poule] = order
self.poules[poule] = [t.name for t in order]
await self.annonce_poule(poule) await self.annonce_poule(poule)

View File

@ -288,7 +288,7 @@ class DevCog(Cog, name="Dev tools"):
pprint(resp, out) pprint(resp, out)
embed = discord.Embed(title="Result", color=discord.Colour.green()) 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) value = self.to_field_value(out)
if resp is not None and value: if resp is not None and value:

View File

@ -1,15 +1,17 @@
import ast
import asyncio import asyncio
import datetime import datetime
import io import io
import itertools import itertools
import operator as op
import random import random
import re import re
import traceback
import urllib import urllib
from collections import defaultdict, Counter from collections import Counter, defaultdict
from dataclasses import dataclass, field from dataclasses import dataclass, field
from functools import partial from functools import partial
from itertools import groupby import math
from math import log
from operator import attrgetter, itemgetter from operator import attrgetter, itemgetter
from time import time from time import time
from typing import List, Set, Union from typing import List, Set, Union
@ -19,26 +21,27 @@ import discord
import yaml import yaml
from discord import Guild, Member from discord import Guild, Member
from discord.ext import commands from discord.ext import commands
from discord.ext.commands import ( from discord.ext.commands import (BadArgument, Cog, command, Command, CommandError, Context, Group, group, is_owner,
Cog, MemberConverter, RoleConverter)
command,
Context,
Command,
CommandError,
Group,
group,
MemberConverter,
BadArgument,
RoleConverter,
)
from discord.utils import get from discord.utils import get
from src.constants import * from src.constants import *
from src.constants import Emoji
from src.core import CustomBot from src.core import CustomBot
from src.errors import TfjmError 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 @dataclass
class Joke(yaml.YAMLObject): class Joke(yaml.YAMLObject):
@ -191,9 +194,99 @@ class MiscCog(Cog, name="Divers"):
f"iel sera un membre influent du CNO ?" 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 ---------------- # # ----------------- Hugs ---------------- #
@command(aliases=["<3", "❤️", ":heart:"]) @command(aliases=["<3", "❤️", ":heart:", Emoji.RAINBOW_HEART])
async def hug(self, ctx: Context, who="everyone"): async def hug(self, ctx: Context, who="everyone"):
"""Fait un câlin à quelqu'un. :heart:""" """Fait un câlin à quelqu'un. :heart:"""
@ -222,7 +315,7 @@ class MiscCog(Cog, name="Divers"):
":hugging:", ":hugging:",
":smiling_face_with_3_hearts:", ":smiling_face_with_3_hearts:",
"Oh wiiii", "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 !" f"{who.mention} en redemande un !"
if not bot_hug if not bot_hug
else "J'en veux un autre ! :heart_eyes:", else "J'en veux un autre ! :heart_eyes:",
@ -454,12 +547,15 @@ class MiscCog(Cog, name="Divers"):
":orange_heart:", ":orange_heart:",
":heart:", ":heart:",
":sparkling_heart:", ":sparkling_heart:",
Emoji.RAINBOW_HEART,
] ]
if v <= 0: if v <= 0:
return hearts[0] return hearts[0]
elif v >= 2000: elif v >= 5000:
return hearts[-1] return hearts[-1]
elif v >= 2000:
return hearts[-2]
else: else:
return hearts[len(str(v))] return hearts[len(str(v))]
@ -522,14 +618,15 @@ class MiscCog(Cog, name="Divers"):
yaml.safe_dump_all(jokes, f) yaml.safe_dump_all(jokes, f)
@group(name="joke", invoke_without_command=True, case_insensitive=True) @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.""" """Fait discretement une blague aléatoire."""
m: discord.Message = ctx.message m: discord.Message = ctx.message
await m.delete() await m.delete()
jokes = self.load_jokes() jokes = self.load_jokes()
if False: if id is not None:
id = int(id)
joke_id = id joke_id = id
jokes = sorted( jokes = sorted(
jokes, key=lambda j: len(j.likes) - len(j.dislikes), reverse=True 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) 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): async def best_jokes(self, ctx: Context):
"""Affiche le palmares des blagues.""" """Affiche le palmares des blagues."""
@ -626,8 +724,9 @@ class MiscCog(Cog, name="Divers"):
if joke.file: if joke.file:
text += " - image non inclue - " text += " - image non inclue - "
name = who.display_name if who else "Inconnu"
embed.add_field( 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) await ctx.send(embed=embed)
@ -655,7 +754,8 @@ class MiscCog(Cog, name="Divers"):
color=0xFFA500, 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: for cat_name, cat in commands:
cat = {c.qualified_name: c for c in cat} 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 str(channel.changed_roles)
return "C'est fait !" return "C'est fait !"
@commands.command(name="tourist") @commands.command(name="tourist", aliases=["touriste"])
@send_and_bin @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. 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 `!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." 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: if tournoi not in TOURNOIS:
return f"{tournoi} n'est pas un nom de tournoi. Possibilités: {french_join(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) tournoi_role = get(guild.roles, name=tournoi)
touriste_role = get(guild.roles, name=Role.TOURIST) touriste_role = get(guild.roles, name=Role.TOURIST)
await ctx.author.add_roles( if tournoi == "Finale":
touriste_role, tournoi_role, reason="Demande via le bot." # 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) @group(name="team", invoke_without_command=True, case_insensitive=True, hidden=True)
async def team(self, ctx): async def team(self, ctx):

View File

@ -2,6 +2,7 @@
import asyncio import asyncio
import random import random
import re
import sys import sys
import traceback import traceback
from collections import defaultdict, namedtuple from collections import defaultdict, namedtuple
@ -25,8 +26,11 @@ from src.errors import TfjmError, UnwantedCommand
__all__ = ["TirageCog"] __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"]) Record = namedtuple("Record", ["name", "pb", "penalite"])
@ -244,7 +248,9 @@ class DiscordTirage(BaseTirage):
@safe @safe
async def start_select_pb(self, team): 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 @safe
@send_all @send_all
@ -255,12 +261,10 @@ class DiscordTirage(BaseTirage):
second = "\n".join( second = "\n".join(
f"{p}: {french_join(t)}" for p, t in poules.items() if p.rnd == 1 f"{p}: {french_join(t)}" for p, t in poules.items() if p.rnd == 1
) )
yield ( if first:
f"Les poules sont donc, pour le premier tour :" yield (f"Les poules sont donc, pour le premier tour :" f"```{first}```\n")
f"```{first}```\n" if second:
f"Et pour le second tour :" yield (f"Pour le second tour les poules sont :" f"```{second}```")
f"```{second}```"
)
@safe @safe
@send_all @send_all
@ -275,8 +279,8 @@ class DiscordTirage(BaseTirage):
if len(teams) == 3: if len(teams) == 3:
table = """``` table = """```
╔═════╦═════════╦═════════╦═════════╗ ╔═════╦═════════╦═════════╦═════════╗
║ Phase 1 ║ Phase 2 ║ Phase 3 ║ T F ║ Phase 1 ║ Phase 2 ║ Phase 3 ║
Pb {0.pb} Pb {1.pb} Pb {2.pb} J M ║ Pb. {0.pb} ║ Pb. {1.pb} ║ Pb. {2.pb}
╠═════╬═════════╬═════════╬═════════╣ ╠═════╬═════════╬═════════╬═════════╣
{0.name} ║ Def ║ Rap ║ Opp ║ {0.name} ║ Def ║ Rap ║ Opp ║
╠═════╬═════════╬═════════╬═════════╣ ╠═════╬═════════╬═════════╬═════════╣
@ -300,22 +304,22 @@ class DiscordTirage(BaseTirage):
+-----+---------+---------+---------+---------+```""" +-----+---------+---------+---------+---------+```"""
elif len(teams) == 5: elif len(teams) == 5:
table = """``` table = """```
╔═════╦═══════════════════╦═══════════════════╦═════════╗ ╔═══╦═══════════════════╦═══════════════════╦═════════╗
║ ║ Phase 1 ║ Phase 2 ║ Phase 3 ║ ║ ║ Phase 1 ║ Phase 2 ║ Phase 3 ║
╠═════╬═════════╦═════════╬═════════╦═════════╬═════════╣ ╠═══╬═════════╦═════════╬═════════╦═════════╬═════════╣
║ ║ Salle 1 ║ Salle 2 ║ Salle 1 ║ Salle 2 ║ Salle 1 ║ ║ ║ 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} Pb. {0.pb} ║ Pb. {1.pb} ║ Pb. {2.pb} ║ Pb. {3.pb} ║ Pb. {4.pb}
╠═════╬═════════╬═════════╬═════════╬═════════╬═════════╣ ╠═══╬═════════╬═════════╬═════════╬═════════╬═════════╣
{0.name} ║ Def ║ ║ Opp ║ Rap ║ ║ {0.name}║ Def ║ ║ Opp ║ Rap ║ ║
╠═════╬═════════╬═════════╬═════════╬═════════╬═════════╣ ╠═══╬═════════╬═════════╬═════════╬═════════╬═════════╣
{1.name} ║ ║ Def ║ Rap ║ ║ Opp ║ {1.name}║ ║ Def ║ Rap ║ ║ Opp ║
╠═════╬═════════╬═════════╬═════════╬═════════╬═════════╣ ╠═══╬═════════╬═════════╬═════════╬═════════╬═════════╣
{2.name} ║ Opp ║ ║ Def ║ ║ Rap ║ {2.name}║ Opp ║ ║ Def ║ ║ Rap ║
╠═════╬═════════╬═════════╬═════════╬═════════╬═════════╣ ╠═══╬═════════╬═════════╬═════════╬═════════╬═════════╣
{3.name} ║ Rap ║ Opp ║ ║ Def ║ ║ {3.name}║ Rap ║ Opp ║ ║ Def ║ ║
╠═════╬═════════╬═════════╬═════════╬═════════╬═════════╣ ╠═══╬═════════╬═════════╬═════════╬═════════╬═════════╣
{4.name} ║ ║ Rap ║ ║ Opp ║ Def ║ {4.name}║ ║ Rap ║ ║ Opp ║ Def ║
╚═════╩═════════╩═════════╩═════════╩═════════╩═════════╝```""" ╚═══╩═════════╩═════════╩═════════╩═════════╩═════════╝```"""
else: else:
table = "WTF il n'y a pas 3,4 ou 5 equipes ici." 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}**") await ctx.send(f"Le problème tiré est... **{problem}**")
@commands.command( @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): async def accept_cmd(self, ctx):
""" """
@ -578,17 +583,20 @@ class TirageCog(Cog, name="Tirages"):
await ctx.invoke(self.bot.get_command("help"), "draw") await ctx.invoke(self.bot.get_command("help"), "draw")
@draw_group.command( @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) @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. (orga) Commence un tirage avec 3 ou 4 équipes.
Cette commande attend des trigrames d'équipes. Cette commande attend des trigrames d'équipes.
Exemple: 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 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." "il est possible d'en commencer un autre sur une autre channel."
) )
try: query = " ".join(args)
fmt = list(map(int, fmt.split("+"))) match = re.match(RE_DRAW_START, query)
except ValueError:
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( raise TfjmError(
"Le premier argument doit être le format du tournoi, " "Le tirage est annulé, vous pouvez le recommencer en précisant le format."
"par exemple `3+3` pour deux poules à trois équipes"
) )
if not set(fmt).issubset({3, 4, 5}): if not set(fmt).issubset({3, 4, 5}):
raise TfjmError("Seuls les poules à 3, 4 ou 5 équipes sont suportées.") 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 # 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]: if self.tirages[channel_id]:
# Check if aborted in an other way # Check if aborted in an other way
@ -622,10 +678,12 @@ class TirageCog(Cog, name="Tirages"):
@draw_group.command(name="abort") @draw_group.command(name="abort")
@commands.has_any_role(*Role.ORGAS) @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. (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, Le tirage ne pourra pas être continué. Si besoin,
n'hésitez pas à appeller un @dev : il peut réparer n'hésitez pas à appeller un @dev : il peut réparer
plus de choses qu'on imagine (mais moins qu'on voudrait). 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 channel_id = ctx.channel.id
if channel_id in self.tirages: 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() self.tirages[channel_id].save()
del self.tirages[channel_id] 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: else:
await ctx.send("Il n'y a pas de tirage en cours.") 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(str(resp.reason))
await ctx.send(await resp.content.read()) 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): def setup(bot):
bot.add_cog(TirageCog(bot)) bot.add_cog(TirageCog(bot))

View File

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

View File

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

View File

@ -1,9 +1,15 @@
import asyncio
from pprint import pprint
from functools import wraps from functools import wraps
from io import StringIO
from typing import Union from typing import Union
import discord
import psutil import psutil
from discord.ext.commands import Bot from discord.ext.commands import Bot
from src.constants import *
def fg(text, color: int = 0xFFA500): def fg(text, color: int = 0xFFA500):
r = color >> 16 r = color >> 16
@ -14,6 +20,10 @@ def fg(text, color: int = 0xFFA500):
def french_join(l): def french_join(l):
l = list(l) l = list(l)
if not l:
return ""
if len(l) < 2:
return l[0]
start = ", ".join(l[:-1]) start = ", ".join(l[:-1])
return f"{start} et {l[-1]}" return f"{start} et {l[-1]}"
@ -44,6 +54,45 @@ def send_and_bin(f):
return wrapped 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(): def start_time():
return psutil.Process().create_time() return psutil.Process().create_time()