Compare commits

...

140 commits

Author SHA1 Message Date
3a52efeac0
Merge pull request 'Add Pterodactyl cog' (#19) from pterodactyl into main
All checks were successful
Actions / Lint Code (Ruff & Pylint) (push) Successful in 18s
Actions / Build Documentation (MkDocs) (push) Successful in 25s
Reviewed-on: https://www.coastalcommits.com/SeaswimmerTheFsh/SeaCogs/pulls/19
2024-03-02 05:07:42 +00:00
882b0386f2
fix(pterodactyl): pylint fixes
All checks were successful
Actions / Lint Code (Ruff & Pylint) (pull_request) Successful in 21s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 24s
2024-03-01 23:43:46 -05:00
45797361a6
docs(pterodactyl): flushed out the docs more
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 24s
2024-03-01 23:35:12 -05:00
12862ccea7
fix(pterodactyl): docstring change
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 23s
2024-03-01 23:04:33 -05:00
0b0afa53d6
fix(pterodactyl): docstring change
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 23s
2024-03-01 23:03:43 -05:00
9e8bcb952a
fix(pterodactyl): made configuration command arguments required
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-03-01 23:01:11 -05:00
0882a498b6
fix(pterodactyl): forgot to move something in the config view command
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 20s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 22s
2024-03-01 22:57:00 -05:00
d1966fb05f
fix(pterodactyl): cleaned up the pterodactyl config view command
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 27s
2024-03-01 22:55:07 -05:00
987a29afff
feat(pterodactyl): added [p]pterodactyl config view command
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 22s
2024-03-01 22:53:08 -05:00
f93223fd36
fix(pterodactyl): use an escaped * for ip masking so markdown isn't triggered
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 23s
2024-03-01 22:39:58 -05:00
306148ea69
feat(pterodactyl): added masking of IP addresses in the console output
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 21s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 24s
2024-03-01 22:38:49 -05:00
fb177ff8ad
fix(pterodactyl): fixed broken placeholder replacement
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-03-01 22:25:21 -05:00
e9523d5f70
fix(pterodactyl): fixed server messages sometimes not logging
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 20s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 23s
2024-03-01 22:24:02 -05:00
6a02381e89
feat(pterodactyl): add power commands
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 21s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 25s
2024-03-01 22:20:50 -05:00
b75bacb811
docs(pterodactyl): restarting is not a server power status type
All checks were successful
Actions / Lint Code (Ruff & Pylint) (pull_request) Successful in 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 23s
2024-03-01 15:45:54 -05:00
88c77b4aa5
fix(pterodactyl): fixed error if base_url ends in /
All checks were successful
Actions / Lint Code (Ruff & Pylint) (pull_request) Successful in 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 24s
2024-03-01 15:44:26 -05:00
af29b950c2
docs(pterodactyl): consistency
All checks were successful
Actions / Lint Code (Ruff & Pylint) (pull_request) Successful in 20s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 22s
2024-03-01 15:30:46 -05:00
95bf863f7e
fix(pterodactyl): alphabetized a dict and the docs
All checks were successful
Actions / Lint Code (Ruff & Pylint) (pull_request) Successful in 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 22s
2024-03-01 15:28:14 -05:00
dab56bed94
feat(pterodactyl): added more placeholders and updated documentation to match
All checks were successful
Actions / Lint Code (Ruff & Pylint) (pull_request) Successful in 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 22s
2024-03-01 15:27:13 -05:00
4979e44b7c
feat(pterodactyl): updated how placeholders are parsed in get_chat_command(), updated documentation to match
All checks were successful
Actions / Lint Code (Ruff & Pylint) (pull_request) Successful in 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 23s
2024-03-01 15:21:44 -05:00
1bc1c7a90e
fix(pterodactyl): fixed retry functionality - no longer blocks the bot
All checks were successful
Actions / Lint Code (Ruff & Pylint) (pull_request) Successful in 21s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 23s
2024-03-01 15:11:57 -05:00
a166168507
fix(pterodactyl): maybe?
All checks were successful
Actions / Lint Code (Ruff & Pylint) (pull_request) Successful in 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 22s
2024-03-01 15:02:42 -05:00
8b50c0376d
fix(pterodactyl): asyncio sleep instead of blocking
All checks were successful
Actions / Lint Code (Ruff & Pylint) (pull_request) Successful in 20s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 22s
2024-03-01 14:59:20 -05:00
a0b1773185
fix(pterodactyl): added another info logging statement
All checks were successful
Actions / Lint Code (Ruff & Pylint) (pull_request) Successful in 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 22s
2024-03-01 14:57:21 -05:00
b6819192b0
fix(pterodactyl): use time.sleep instead
All checks were successful
Actions / Lint Code (Ruff & Pylint) (pull_request) Successful in 20s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 26s
2024-03-01 14:56:44 -05:00
b775439967
fix(pterodactyl): cleanup
All checks were successful
Actions / Lint Code (Ruff & Pylint) (pull_request) Successful in 20s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 24s
2024-03-01 14:52:14 -05:00
f2d54ce23b
feat(pterodactyl): added a retry counter and sleep cooldown to the error_callback
All checks were successful
Actions / Lint Code (Ruff & Pylint) (pull_request) Successful in 21s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 25s
2024-03-01 14:42:45 -05:00
b7f5ae644a
fix(pterodactyl): check if websocket_credentials is None 2024-03-01 14:18:44 -05:00
684f2559e2
fix(pterodactyl): pylint fixes
All checks were successful
Actions / Lint Code (Ruff & Pylint) (pull_request) Successful in 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-03-01 14:11:11 -05:00
a1a33ebfca
docs(pterodactyl): flushed out setup page
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 24s
2024-03-01 14:08:57 -05:00
8b1e42716b
fix(pterodactyl): use a custom logger for the websocket instead of websockets.client
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 21s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 25s
2024-03-01 14:04:10 -05:00
837bf4aa34
fix(pterodactyl): changed a bunch of logger messages to be info and not debug
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 20s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 27s
2024-03-01 13:16:22 -05:00
1bbabd495f
fix(pterodactyl): added logging for if the WebSocket task is cancelled
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 20s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 22s
2024-03-01 13:14:55 -05:00
8cbad26e1d
fix(pterodactyl): removed some debugging stuff
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 21s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 23s
2024-03-01 13:13:30 -05:00
6f4f13e623
fix(pterodactyl): adding some debugging code
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 21s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 26s
2024-03-01 13:08:10 -05:00
b18b99075e
misc(pterodactyl): added a space to fix an embed
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 26s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 34s
2024-03-01 01:21:10 -05:00
3795d7d13a
fix(pterodactyl): updated info.json
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 17s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-03-01 01:19:51 -05:00
dd6184ccd0
fix(pterodactyl): remove useless config key
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-03-01 01:17:48 -05:00
afc5868e9e
feat(pterodactyl): use red's api key storage system for api key storage and not a config key
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 24s
2024-03-01 01:17:31 -05:00
7e03696e10
feat(pterodactyl): added achievements
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 20s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-03-01 00:46:51 -05:00
8954df4c1d
fix(pterodactyl): fixed a docstring
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 20s
2024-03-01 00:30:38 -05:00
f2c56e0382
fix(pterodactyl): restrict [p]pterodactyl config to bot owners
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-03-01 00:29:08 -05:00
bd7aa54efe
fix(pterodactyl): fixed an issue with colors in generate_join_leave_embed
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-03-01 00:25:39 -05:00
f91cd82d1b
fix(pterodactyl): added config key I forgot to register
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-03-01 00:23:59 -05:00
2fbd8cde9e
feat(pterodactyl): added user join/leave
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 20s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 22s
2024-03-01 00:23:00 -05:00
7a39c9a75d
feat(pterodactyl): added startup and shutdown messages
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-03-01 00:05:06 -05:00
d39f0ba104
feat(pterodactyl): server status will persist through reloads
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 22s
2024-03-01 00:02:42 -05:00
a4f68d55eb
fix(pterodactyl): register config on cog class initialization
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 20s
2024-02-29 23:55:51 -05:00
8387064ab4
fix(pterodactyl): maybe fixed config issue
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 20s
2024-02-29 23:54:35 -05:00
9e63b4e798
fix(pterodactyl): oops lol
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-02-29 23:52:48 -05:00
0d21a52ce3
feat(pterodactyl): added support for bridging messages sent by the server
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-02-29 23:50:54 -05:00
457f1da7f4
fix(pterodactyl): pylint "fix"
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 22s
2024-02-29 23:44:28 -05:00
c0289a86fc
fix(pterodactyl): pylint fixes
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-02-29 23:42:12 -05:00
7f8d70ccae
fix(pterodactyl): fixed circular import
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-02-29 23:33:00 -05:00
2bf8629e4c
fix(pterodactyl): updated typehints
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-02-29 23:31:30 -05:00
e1c98aa78f
cleanup(pterodactyl): split out a bunch of stuff into separate files
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 23s
2024-02-29 23:26:24 -05:00
417f297193
misc(pterodactyl): renamed tellraw to chat_command
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 20s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 23s
2024-02-29 22:41:06 -05:00
37cdca09ec
fix(pterodactyl): pylint fixes
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 24s
2024-02-29 22:15:44 -05:00
84b0201662
docs(pterodactyl): added docs pages 2024-02-29 22:11:37 -05:00
839ead56eb
fix(pterodactyl): remove looping functionality from websocket.connect on line 62 as it's irrelevant now and was broken regardless 2024-02-29 22:07:22 -05:00
9e15730af9
fix(pterodactyl): cancel the task upon error 2024-02-29 22:06:59 -05:00
de5d0194c8
fix(pterodactyl): don't send chat messages to minecraft containing bot commands
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 24s
2024-02-29 21:51:18 -05:00
ef7f574306
fix(pterodactyl): testing a fix to tellraw
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-02-29 21:46:47 -05:00
07835e7b13
fix(pterodactyl): fixed TypeError
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 20s
2024-02-29 21:41:00 -05:00
cccc941e26
fix(pterodactyl): restart the websocket task if it fails
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 22s
2024-02-29 21:38:54 -05:00
0aa17e8807
fix(pterodactyl): fixed exceptions in the websocket task being suppressed
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 22s
2024-02-29 21:35:09 -05:00
366bafcd27
fix(pterodactyl): don't trim content
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 20s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 23s
2024-02-29 21:18:42 -05:00
d5600e8cf7
fix(pterodactyl): fixed chat messages breaking and removed debug logging
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 22s
2024-02-29 21:15:46 -05:00
97213a5025
fix(pterodactyl): maybe?
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 20s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 23s
2024-02-29 21:14:10 -05:00
2e4b664760
fix(pterodactyl): maybe?
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-02-29 21:11:16 -05:00
925e402819
fix(pterodactyl): try to match regex early for debugging
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 22s
2024-02-29 21:08:50 -05:00
502ffbee84
fix(pterodactyl): adding some debug logging
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 22s
2024-02-29 21:07:28 -05:00
f87f4ee37f
fix(pterodactyl): don't try to send messages from bots to the server (for real this time)
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 20s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 22s
2024-02-29 21:00:35 -05:00
50dd5c64b4
fix(pterodactyl): added error messages for if the websocket connection is closed
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-02-29 20:59:47 -05:00
579855af02
fix(pterodactyl): reverted previous commit
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 22s
2024-02-29 20:45:31 -05:00
2fb201a9cb
fix(pterodactyl): happy now?
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-02-29 20:44:46 -05:00
236cb1d815
fix(pterodactyl): adding debug strings to check_if_chat_message
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 22s
2024-02-29 20:43:11 -05:00
f588caf25f
fix(pterodactyl): fixed broken tellraw string
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 22s
2024-02-29 20:40:03 -05:00
4108bb22bb
fix(pterodactyl): moved chatchannel into the chat command group
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 22s
2024-02-29 20:31:29 -05:00
76aa99c3f9
feat(pterodactyl): configuration update + a bunch of other stuff
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 23s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 25s
2024-02-29 20:28:26 -05:00
f792ad58a0
fix(pterodactyl): use display_name and not name
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-02-29 19:01:17 -05:00
5a4dc4866c
feat(pterodactyl): added role coloring for discord roles
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 20s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 23s
2024-02-29 19:00:07 -05:00
d3cc445802
feat(pterodactyl): testing allowing custom colors in tellraw
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 22s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 27s
2024-02-29 18:53:47 -05:00
4174bc4be7
fix(pterodactyl): don't accept messages from bots
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 23s
2024-02-29 18:53:17 -05:00
d00b70758a
fix(pterodactyl): hopefully fixed tellraw error
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 20s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 25s
2024-02-29 18:50:22 -05:00
b0a110e4f8
fix(pterodactyl): added more debug logging
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 21s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 23s
2024-02-29 18:39:01 -05:00
9023ea160b
feat(pterodactyl): added console channel logging for chat messages
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-02-29 17:27:36 -05:00
0e638ca9e3
fix(pterodactyl): fixing tellraw command
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-02-29 17:24:08 -05:00
5dc55b52e7
fix(pterodactyl): testing fix to sending chat messages to minecraft
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 22s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-02-29 17:22:41 -05:00
4f95955a04
fix(pterodactyl): fixed broken formatting
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 22s
2024-02-29 17:19:26 -05:00
510f8c788e
feat(pterodactyl): added sending messages from discord to the server
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 20s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 22s
2024-02-29 17:18:03 -05:00
a791c27fc3
fix(pterodactyl): fixed broken debug statement
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 24s
2024-02-29 17:14:06 -05:00
07e2497aac
fix(pterodactyl): fixed incorrect dictionary key causing an error
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-02-29 17:01:00 -05:00
e12ded9d42
fix(pterodactyl): add more verbose debug logging
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 22s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 22s
2024-02-29 16:58:19 -05:00
ee6e900e7d
fix(pterodactyl): fixed incorrect config name
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-02-29 16:55:45 -05:00
f42c536f7c
fix(pterodactyl): awaited a coroutine
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 25s
2024-02-29 16:53:09 -05:00
7e728087c4
fix(pterodactyl): adding debug logging so i can figure out what's failing in the chat system
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 17s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 23s
2024-02-29 16:52:10 -05:00
9a698fbac6
feat(pterodactyl): added one-way chat messages (minecraft --> discord)
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 22s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 24s
2024-02-29 16:47:20 -05:00
dab7343ca6
fix(pterodactyl): use running, not started
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-02-28 13:44:13 -05:00
239f7cf613
fix(pterodactyl): fixed current_status
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-02-28 13:41:51 -05:00
39ae8b5ea0
fix(pterodactyl): do not log during startup/shutdown to avoid the console channel getting flooded and ratelimited
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-02-28 13:39:40 -05:00
142336e233
feat(pterodactyl): handle server status changes
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 23s
2024-02-28 13:32:31 -05:00
f6f0a31763
fix(pterodactyl): don't log console command executions
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-02-28 13:22:46 -05:00
ec2cd09f8e
fix(pterodactyl): removed ansi escape codes
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 20s
2024-02-28 13:21:39 -05:00
c740cdc6dc
feat(pterodactyl): fixed some issues and added logging for what user executed a command through the console
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-02-28 13:18:15 -05:00
a8f60b1aec
fix(pterodactyl): do not ratelimit yourself
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 20s
2024-02-28 13:08:24 -05:00
d297a2181d
fix(pterodactyl): i'm dumb
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-02-28 13:07:31 -05:00
60f94c4499
fix(pterodactyl): testing a ""solution"" to the websocket closing problem
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 17s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-02-28 13:05:04 -05:00
ccbce180dd
fix(pterodactyl): hopefully fixed the websocket closing on console output event
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 20s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-02-28 13:03:31 -05:00
2017cbb226
cleanup(pterodactyl): making some changes to establish_websocket_connection
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 22s
2024-02-28 13:00:11 -05:00
caa03a63e6
fix(pterodactyl): set origin header through websockets.connect and not through extra_headers 2024-02-28 12:54:34 -05:00
b7635f06f5
fix(pterodactyl): added a character limit to the channel.send call in the websocket method
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 20s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-02-28 12:50:16 -05:00
ff93fd8527
fix(pterodactyl): awaited a coroutine
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-02-28 12:47:15 -05:00
3d8f479347
fix(pterodactyl): cog ->Cog
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 17s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 20s
2024-02-28 12:44:54 -05:00
0961985168
feat(pterodactyl): added configuration command for setting the console channel
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 17s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 22s
2024-02-28 12:44:12 -05:00
cebc2223d9
feat(pterodactyl): added console channel support
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 21s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 24s
2024-02-28 12:43:26 -05:00
d9f5d14f40
fix(pterodactyl): origin, not Origin
All checks were successful
Actions / Lint Code (Ruff & Pylint) (pull_request) Successful in 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 22s
2024-02-28 12:03:16 -05:00
7b83513d63
cleanup(pterodactyl): removed debug loggers
All checks were successful
Actions / Lint Code (Ruff & Pylint) (pull_request) Successful in 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-02-28 11:59:49 -05:00
48634ac903
fix(pterodactyl): enabled debug mode on the pterodactylclient
All checks were successful
Actions / Lint Code (Ruff & Pylint) (pull_request) Successful in 19s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 21s
2024-02-28 11:57:39 -05:00
2312cce011
fix(pterodactyl): added temporary debugging logs
All checks were successful
Actions / Lint Code (Ruff & Pylint) (pull_request) Successful in 20s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 20s
2024-02-28 11:55:48 -05:00
09d48082e5 Revert "fix(pterodactyl): awaited a coroutine"
All checks were successful
Actions / Lint Code (Ruff & Pylint) (pull_request) Successful in 20s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 22s
This reverts commit 08cd13d7c7.
2024-02-28 11:54:16 -05:00
08cd13d7c7
fix(pterodactyl): awaited a coroutine
All checks were successful
Actions / Lint Code (Ruff & Pylint) (pull_request) Successful in 20s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 26s
2024-02-28 11:52:35 -05:00
d391aeeb7b
fix(pterodactyl): handle disconnecting from the websocket
All checks were successful
Actions / Lint Code (Ruff & Pylint) (pull_request) Successful in 21s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 25s
2024-02-28 11:46:00 -05:00
e6ca4071f3
fix(pterodactyl): fixed broken poetry.lock file
All checks were successful
Actions / Lint Code (Ruff & Pylint) (pull_request) Successful in 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 23s
2024-02-28 11:31:47 -05:00
6738ab17ca Merge branch 'main' into pterodactyl
All checks were successful
Actions / Lint Code (Ruff & Pylint) (pull_request) Successful in 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 25s
2024-02-28 11:30:16 -05:00
8a22d5ce23
fix(pterodactyl): pylint fixes
All checks were successful
Actions / Lint Code (Ruff & Pylint) (pull_request) Successful in 21s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 24s
2024-02-28 11:08:16 -05:00
f485df856c
Merge remote-tracking branch 'origin/main' into pterodactyl
Some checks failed
Actions / Lint Code (Ruff & Pylint) (pull_request) Failing after 18s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 24s
2024-02-28 11:06:32 -05:00
be27d882f2
fix(pterodactyl): don't await something that isn't a coroutine
All checks were successful
Actions / Lint Code (Ruff) (pull_request) Successful in 10s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 24s
2024-02-28 10:46:42 -05:00
d092f78502
feat(pterodactyl): added more debug logging to the configuration commands
All checks were successful
Actions / Lint Code (Ruff) (pull_request) Successful in 7s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 23s
2024-02-28 08:56:47 -05:00
d92831f3db
misc(pterodactyl): added a debug logging statement to the first line of establish_websocket_connection
All checks were successful
Actions / Lint Code (Ruff) (pull_request) Successful in 8s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 23s
2024-02-28 08:49:02 -05:00
2d4e372784
fix(pterodactyl): fixed the cog load process being blocked by the establish_websocket_connection method
All checks were successful
Actions / Lint Code (Ruff) (pull_request) Successful in 7s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 24s
2024-02-28 08:47:24 -05:00
5e3ab08d6d
fix(pterodactyl): fixed a broken debug logging statement
All checks were successful
Actions / Lint Code (Ruff) (pull_request) Successful in 7s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 25s
2024-02-28 08:37:02 -05:00
f377dc9250
fix(pterodactyl): added websockets as a dependency in info.json 2024-02-28 08:36:47 -05:00
680f92572c
fix(pterodactyl): fixed debug logging causing an error in establish_websocket_connection
All checks were successful
Actions / Lint Code (Ruff) (pull_request) Successful in 6s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 24s
2024-02-28 08:20:35 -05:00
ea84044e73
fix(pterodactyl): fix failing to connect to the websocket due to a 403 error
All checks were successful
Actions / Lint Code (Ruff) (pull_request) Successful in 6s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 22s
2024-02-28 08:14:40 -05:00
53adeb4b80
feat(pterodactyl): added configuration commands
All checks were successful
Actions / Lint Code (Ruff) (pull_request) Successful in 7s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 24s
2024-02-28 08:11:23 -05:00
9d4d8b8267
misc(pterodactyl): moved configuration calls into establish_websocket_connection 2024-02-28 08:11:15 -05:00
6e6559d80c
feat(pterodactyl): added more verbose debug logging to establish_websocket_connection 2024-02-28 08:10:46 -05:00
dcf0165a8a
misc(pterodactyl): removed credentials from default configs
All checks were successful
Actions / Lint Code (Ruff) (pull_request) Successful in 6s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 24s
api key has been invalidated
2024-02-27 23:18:17 -05:00
6158d05960
feat(pterodactyl): introduced the cog
All checks were successful
Actions / Lint Code (Ruff) (pull_request) Successful in 9s
Actions / Build Documentation (MkDocs) (pull_request) Successful in 24s
2024-02-27 23:02:03 -05:00
22 changed files with 1047 additions and 63 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

View file

@ -0,0 +1,165 @@
# Configuration
This page will go over all of the configuration options for the Pterodactyl cog.
All of the commands below can be accessed through `[p]pterodactyl config`.
## `api`
This option determines which [PlayerDB](https://playerdb.co/) endpoint the cog will use to retrieve player avatars.
This is only used for webhook avatars in the chat integration system. You should probably leave this as default.
Default value: `minecraft`
## `chat`
### `channel`
This option determines what channel chat messages will be sent to. If this is unset, the chat integration won't work.
**Make sure the bot has permissions to speak in this channel!**
Default value: `None`
### `command`
This option determines what command will be sent to the server whenever a message is sent in the configured chat channel. The JSON format Minecraft uses for this is very janky sometimes, if you need help with changing the command, you can join my [Discord server](https://discord.gg/eMUMe77Yb8).
Available placeholders:
- `.$C` - replaced with hex color of the author's top colored role
- `.$D` - replaced with the author's discriminator (will usually be 0, you shouldn't use this)
- `.$I` - replaced with the author's ID
- `.$M` - replaced with message content
- `.$N` - replaced with author's display name (or guild nickname, if set)
- `.$U` - replaced with the author's username (NOT display name, you should usually use `.$N`)
Default value:
```json
tellraw @a ["",{"text":".$D ","color":".$C"},{"text":" (DISCORD): ","color":"blue"},{"text":".$M","color":"white"}]
```
## `consolechannel`
/// admonition | Only give access to the console channel to people you trust!
type: danger
If a user account has access to the console channel, they can execute ***any*** command on your server, including some power actions.
They will also be able to see potentially sensitive information, such as player IPs, if [IP Masking](configuration.md#ip) is disabled.
///
This option determines what channel console logs will be sent to. If this is unset, the console integration won't work.
**Make sure the bot has permissions to speak in this channel!**
Server status changes, Discord --> Minecraft chat messages, and command executions will all be logged here.
/// admonition
type: info
Please note that, in order to avoid Discord ratelimits, logs will not be posted when the server status is one of the following:
- `starting`
- `stopping`
This is to prevent the console channel from flooding and getting backed up by Discord's message ratelimits.
///
Default value: `None`
## `ip`
This option determines whether or not IP's will be redacted when posted in chat or to the console channel.
Default value: `True`
## `messages`
### `join`
This option determines what the description in embeds will be when a user joins the server. Has no effect if embeds aren't used.
Default value: `Welcome to the server! 👋`
### `leave`
This option determines what the description in embeds will be when a user leaves the server. Has no effect if embeds aren't used.
Default value: `Goodbye! 👋`
### `shutdown`
This option determines what the bot will send in the chat channel when the server stops.
Default value: `Server stopped!`
### `startup`
This option determines what the bot will send in the chat channel when the server is started.
Default value: `Server started!`
## `regex`
If you're not running on recent versions of Paper, which this cog was developed against, or you're otherwise changing for format of chat messages, you'll need to add custom regex through the `[p]pterodactyl config regex` command. Same thing applies if any other type of message isn't being detected. I recomend using ChatGPT or something similar for this, or if you need help, you can join my [Discord server](https://discord.gg/eMUMe77Yb8).
### `achievement`
This regex pattern is used to detect advacnements/challenges. The default should work for most Minecraft servers.
Default value:
```re
^\[\d{2}:\d{2}:\d{2} INFO\]: (.*) has (made the advancement|completed the challenge) \[(.*)\]$
```
### `chat`
This regex pattern is used to detect chat messages. You will probably have to change this if you're using any plugins or mods that use custom chat formatting, like EssentialsX Chat or Styled Chat.
Default value:
```re
\[(\d{2}:\d{2}:\d{2})\sINFO\]:\s<(\w+)>\s(.*)
```
### `join`
This regex pattern is used to detect whenever a user joins the server. You shouldn't usually need to change this.
Default value:
```re
^\[\d{2}:\d{2}:\d{2} INFO\]: ([^<\n]+) joined the game$
```
### `leave`
This regex pattern is used to detect whenever a user leaves the server. You shouldn't usually need to change this.
Default value:
```re
^\[\d{2}:\d{2}:\d{2} INFO\]: ([^<\n]+) left the game$
```
### `server`
This regex pattern is used to detect whenever a server message is sent. You will have to change this if you aren't running on Paper, most likely.
Default value:
```re
^\[\d{2}:\d{2}:\d{2} INFO\]:( \[Not Secure\])? \[.*\] (.*)
```
## `serverid`
This option determines which server's websocket to connect to. See [Getting Started](getting-started.md#getting-server-information) for more information on this.
Default value: `None`
## `url`
This option determines what panel the cog will send requests to. See [Getting Started](getting-started.md#getting-server-information) for more information on this.
Default value: `None`
## `view`
Lists all of the configuration options offered by the cog.

View file

@ -0,0 +1,81 @@
# Getting Started
This page will go over the steps required to get started with the Pterodactyl cog.
/// admonition | Screenshots may be visually distinct
type: info
For the purpose of this guide, I'll be using [Bloom Host's](https://bloom.host/) [Pterodactyl fork](https://mc.bloom.host/).
The steps should be basically identical for other panels, but screenshots will look visually different.
If in doubt, contact your host's support.
///
## Creating a sub-user
This is **optional**, but highly recommended, for security reasons.
Navigate to your `Users` page, and click the `New User` button.
Type in an email address, and press `Select all permissions`.
*The bot doesn't need all of the permissions you just gave it to function, we'll deal with that in a moment.*
![image](/img/pterodactyl/setup/1.png)
Now, you'll need to check the email you just entered into the subusers page, and create an account. I won't cover this, as it'll change depending on what host you're using.
Moving on, the bot doesn't need all of the permissions you just gave it. This poses a security risk, should the bot be compromised. We can fix this by importing only the permissions the bot requires. Import the following string into your subuser's permissions.
```json
["websocket.connect","control.read-console","control.console","control.start","control.stop","control.restart","startup.read","startup.update","settings.rename","settings.reinstall"]
```
![image](/img/pterodactyl/setup/2.png)
## Getting an API Key
**Log out of your primary account, and switch to the sub-user you just created.**
Navigate to your sub-user account's `API Credentials` page.
![image](/img/pterodactyl/setup/3.png)
Create a new API key.
![image](/img/pterodactyl/setup/4.png)
You don't have to specify an allowed IP if you don't want to, but I recommend it. If you chose to, you'll need to retrieve your bot's IP address. You can do this through SSH or through a cog like [AAA3A's IP cog](https://github.com/AAA3A-AAA3A/AAA3A-cogs).
![image](/img/pterodactyl/setup/5.png)
Now, use the `[p]set api` command on your bot to add the API key.
The format is as follows:
```
# Service: pterodactyl
# Keys and Tokens: api_key ptlc_...
```
![image](/img/pterodactyl/setup/6.png)
## Getting server information
There's some other information that the Pterodactyl cog needs to function.
First, get the base url for your panel. This does not include any extra information, like server ids, or whatnot. In my case, I'm using `https://mc.bloom.host/`.
![image](/img/pterodactyl/setup/7.png)
Use the `[p]pterodactyl config url` command to set the URL the cog will use.
In my case, I'd use `-pterodactyl config url https://mc.bloom.host/`.
![image](/img/pterodactyl/setup/8.png)
Now, we need to get the id of your server. Navigate to the `Settings` page in your panel.
![image](/img/pterodactyl/setup/9.png)
Use the `[p]pterodactyl config serverid` command to add the server id to the bot.
In my case, I'd use `-pterodactyl config serverid ad712016-df3d-47a5-b1df-6b71baf50340`.
![image](/img/pterodactyl/setup/10.png)
Once you've done all of this, you should see a connection message in the bot's logs. Now, we need to configure some other things.
See the [Configuration](configuration.md) page for more information.

View file

@ -0,0 +1,16 @@
# Pterodactyl
/// admonition | This project is in active development
type: warning
These docs are not complete yet, and there is a lot still to do.
///
Pterodactyl allows for connecting to a Pterodactyl server through websockets. It is intended primarily for use with Minecraft servers, as it allows for version & server platform-agnostic Discord integration, including console logging and two-way chat bridging.
## Installation
```bash
[p]repo add seacogs https://coastalcommits.com/SeaswimmerTheFsh/SeaCogs
[p]cog install seacogs pterodactyl
[p]cog load aurora
```

View file

@ -19,6 +19,10 @@ nav:
- Bible: bible.md - Bible: bible.md
- Backup: backup.md - Backup: backup.md
- Nerdify: nerdify.md - Nerdify: nerdify.md
- Pterodactyl:
- pterodactyl/index.md
- Getting Started: pterodactyl/getting-started.md
- Configuration: pterodactyl/configuration.md
plugins: plugins:
- git-authors - git-authors
@ -105,3 +109,4 @@ watch:
- ./backup - ./backup
- ./bible - ./bible
- ./nerdify - ./nerdify
- ./pterodactyl

195
poetry.lock generated
View file

@ -222,9 +222,6 @@ files = [
{file = "astroid-3.1.0.tar.gz", hash = "sha256:ac248253bfa4bd924a0de213707e7ebeeb3138abeb48d798784ead1e56d419d4"}, {file = "astroid-3.1.0.tar.gz", hash = "sha256:ac248253bfa4bd924a0de213707e7ebeeb3138abeb48d798784ead1e56d419d4"},
] ]
[package.dependencies]
typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""}
[[package]] [[package]]
name = "async-timeout" name = "async-timeout"
version = "4.0.3" version = "4.0.3"
@ -784,30 +781,30 @@ smmap = ">=3.0.1,<6"
[[package]] [[package]]
name = "gitpython" name = "gitpython"
version = "3.1.41" version = "3.1.42"
description = "GitPython is a Python library used to interact with Git repositories" description = "GitPython is a Python library used to interact with Git repositories"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "GitPython-3.1.41-py3-none-any.whl", hash = "sha256:c36b6634d069b3f719610175020a9aed919421c87552185b085e04fbbdb10b7c"}, {file = "GitPython-3.1.42-py3-none-any.whl", hash = "sha256:1bf9cd7c9e7255f77778ea54359e54ac22a72a5b51288c457c881057b7bb9ecd"},
{file = "GitPython-3.1.41.tar.gz", hash = "sha256:ed66e624884f76df22c8e16066d567aaa5a37d5b5fa19db2c6df6f7156db9048"}, {file = "GitPython-3.1.42.tar.gz", hash = "sha256:2d99869e0fef71a73cbd242528105af1d6c1b108c60dfabd994bf292f76c3ceb"},
] ]
[package.dependencies] [package.dependencies]
gitdb = ">=4.0.1,<5" gitdb = ">=4.0.1,<5"
[package.extras] [package.extras]
test = ["black", "coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock", "mypy", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-instafail", "pytest-mock", "pytest-sugar", "sumtypes"] test = ["black", "coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock", "mypy", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-instafail", "pytest-mock", "pytest-sugar"]
[[package]] [[package]]
name = "griffe" name = "griffe"
version = "0.40.1" version = "0.41.0"
description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API." description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API."
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
files = [ files = [
{file = "griffe-0.40.1-py3-none-any.whl", hash = "sha256:5b8c023f366fe273e762131fe4bfd141ea56c09b3cb825aa92d06a82681cfd93"}, {file = "griffe-0.41.0-py3-none-any.whl", hash = "sha256:8aa7fc6eb00cb80af9c0198178c6b7110cb59fa2c5187bb13ea25eebbe4dd928"},
{file = "griffe-0.40.1.tar.gz", hash = "sha256:66c48a62e2ce5784b6940e603300fcfb807b6f099b94e7f753f1841661fd5c7c"}, {file = "griffe-0.41.0.tar.gz", hash = "sha256:850128c3198c18713eaf0a6cc8572e590a16b1965f72a4e871e66cf84740903f"},
] ]
[package.dependencies] [package.dependencies]
@ -899,9 +896,6 @@ files = [
{file = "Markdown-3.4.4.tar.gz", hash = "sha256:225c6123522495d4119a90b3a3ba31a1e87a70369e03f14799ea9c0d7183a3d6"}, {file = "Markdown-3.4.4.tar.gz", hash = "sha256:225c6123522495d4119a90b3a3ba31a1e87a70369e03f14799ea9c0d7183a3d6"},
] ]
[package.dependencies]
importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""}
[package.extras] [package.extras]
docs = ["mdx-gh-links (>=0.2)", "mkdocs (>=1.0)", "mkdocs-nature (>=0.4)"] docs = ["mdx-gh-links (>=0.2)", "mkdocs (>=1.0)", "mkdocs-nature (>=0.4)"]
testing = ["coverage", "pyyaml"] testing = ["coverage", "pyyaml"]
@ -1047,7 +1041,6 @@ files = [
click = ">=7.0" click = ">=7.0"
colorama = {version = ">=0.4", markers = "platform_system == \"Windows\""} colorama = {version = ">=0.4", markers = "platform_system == \"Windows\""}
ghp-import = ">=1.0" ghp-import = ">=1.0"
importlib-metadata = {version = ">=4.3", markers = "python_version < \"3.10\""}
jinja2 = ">=2.11.1" jinja2 = ">=2.11.1"
markdown = ">=3.2.1" markdown = ">=3.2.1"
markupsafe = ">=2.0.1" markupsafe = ">=2.0.1"
@ -1065,17 +1058,18 @@ min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-imp
[[package]] [[package]]
name = "mkdocs-autorefs" name = "mkdocs-autorefs"
version = "0.5.0" version = "1.0.0"
description = "Automatically link across pages in MkDocs." description = "Automatically link across pages in MkDocs."
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
files = [ files = [
{file = "mkdocs_autorefs-0.5.0-py3-none-any.whl", hash = "sha256:7930fcb8ac1249f10e683967aeaddc0af49d90702af111a5e390e8b20b3d97ff"}, {file = "mkdocs_autorefs-1.0.0-py3-none-any.whl", hash = "sha256:2b6d288f0582589d1be7c99ce4470c8e7c5077892014051ff0d4ff574a73dbe8"},
{file = "mkdocs_autorefs-0.5.0.tar.gz", hash = "sha256:9a5054a94c08d28855cfab967ada10ed5be76e2bfad642302a610b252c3274c0"}, {file = "mkdocs_autorefs-1.0.0.tar.gz", hash = "sha256:1b20db41cade632b07b7a73dee818977b52e869c9deb438f6f20e2896ff01859"},
] ]
[package.dependencies] [package.dependencies]
Markdown = ">=3.3" Markdown = ">=3.3"
markupsafe = ">=2.0.1"
mkdocs = ">=1.1" mkdocs = ">=1.1"
[[package]] [[package]]
@ -1111,13 +1105,13 @@ pytz = "*"
[[package]] [[package]]
name = "mkdocs-material" name = "mkdocs-material"
version = "9.5.9" version = "9.5.11"
description = "Documentation that simply works" description = "Documentation that simply works"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
files = [ files = [
{file = "mkdocs_material-9.5.9-py3-none-any.whl", hash = "sha256:a5d62b73b3b74349e45472bfadc129c871dd2d4add68d84819580597b2f50d5d"}, {file = "mkdocs_material-9.5.11-py3-none-any.whl", hash = "sha256:788ee0f3e036dca2dc20298d65e480297d348a44c9d7b2ee05c5262983e66072"},
{file = "mkdocs_material-9.5.9.tar.gz", hash = "sha256:635df543c01c25c412d6c22991872267723737d5a2f062490f33b2da1c013c6d"}, {file = "mkdocs_material-9.5.11.tar.gz", hash = "sha256:7af7f8af0dea16175558f3fb9245d26c83a17199baa5f157755e63d7437bf971"},
] ]
[package.dependencies] [package.dependencies]
@ -1182,7 +1176,6 @@ files = [
[package.dependencies] [package.dependencies]
click = ">=7.0" click = ">=7.0"
importlib-metadata = {version = ">=4.6", markers = "python_version < \"3.10\""}
Jinja2 = ">=2.11.1" Jinja2 = ">=2.11.1"
Markdown = ">=3.3" Markdown = ">=3.3"
MarkupSafe = ">=1.1" MarkupSafe = ">=1.1"
@ -1191,7 +1184,6 @@ mkdocs-autorefs = ">=0.3.1"
mkdocstrings-python = {version = ">=0.5.2", optional = true, markers = "extra == \"python\""} mkdocstrings-python = {version = ">=0.5.2", optional = true, markers = "extra == \"python\""}
platformdirs = ">=2.2.0" platformdirs = ">=2.2.0"
pymdown-extensions = ">=6.3" pymdown-extensions = ">=6.3"
typing-extensions = {version = ">=4.1", markers = "python_version < \"3.10\""}
[package.extras] [package.extras]
crystal = ["mkdocstrings-crystal (>=0.3.4)"] crystal = ["mkdocstrings-crystal (>=0.3.4)"]
@ -1523,6 +1515,20 @@ files = [
[package.extras] [package.extras]
test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"]
[[package]]
name = "py-dactyl"
version = "2.0.4"
description = "An easy to use Python wrapper for the Pterodactyl Panel API."
optional = false
python-versions = ">=3.4"
files = [
{file = "py-dactyl-2.0.4.tar.gz", hash = "sha256:a16e13a37ee7743b07931f17a9a049e6a22f3fe0c4475e661684deea5f510e77"},
{file = "py_dactyl-2.0.4-py3-none-any.whl", hash = "sha256:7868d528d9a8080c68f49e87418e3ca8a853db2bdff835cf40045400ce6d31b3"},
]
[package.dependencies]
requests = ">=2.21.0"
[[package]] [[package]]
name = "pycares" name = "pycares"
version = "4.3.0" version = "4.3.0"
@ -1629,16 +1635,11 @@ files = [
[package.dependencies] [package.dependencies]
astroid = ">=3.1.0,<=3.2.0-dev0" astroid = ">=3.1.0,<=3.2.0-dev0"
colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""}
dill = [ dill = {version = ">=0.3.6", markers = "python_version >= \"3.11\""}
{version = ">=0.2", markers = "python_version < \"3.11\""},
{version = ">=0.3.6", markers = "python_version >= \"3.11\""},
]
isort = ">=4.2.5,<5.13.0 || >5.13.0,<6" isort = ">=4.2.5,<5.13.0 || >5.13.0,<6"
mccabe = ">=0.6,<0.8" mccabe = ">=0.6,<0.8"
platformdirs = ">=2.2.0" platformdirs = ">=2.2.0"
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
tomlkit = ">=0.10.1" tomlkit = ">=0.10.1"
typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""}
[package.extras] [package.extras]
spelling = ["pyenchant (>=3.2,<4.0)"] spelling = ["pyenchant (>=3.2,<4.0)"]
@ -2136,28 +2137,28 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"]
[[package]] [[package]]
name = "ruff" name = "ruff"
version = "0.2.1" version = "0.2.2"
description = "An extremely fast Python linter and code formatter, written in Rust." description = "An extremely fast Python linter and code formatter, written in Rust."
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "ruff-0.2.1-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:dd81b911d28925e7e8b323e8d06951554655021df8dd4ac3045d7212ac4ba080"}, {file = "ruff-0.2.2-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:0a9efb032855ffb3c21f6405751d5e147b0c6b631e3ca3f6b20f917572b97eb6"},
{file = "ruff-0.2.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:dc586724a95b7d980aa17f671e173df00f0a2eef23f8babbeee663229a938fec"}, {file = "ruff-0.2.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:d450b7fbff85913f866a5384d8912710936e2b96da74541c82c1b458472ddb39"},
{file = "ruff-0.2.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c92db7101ef5bfc18e96777ed7bc7c822d545fa5977e90a585accac43d22f18a"}, {file = "ruff-0.2.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecd46e3106850a5c26aee114e562c329f9a1fbe9e4821b008c4404f64ff9ce73"},
{file = "ruff-0.2.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:13471684694d41ae0f1e8e3a7497e14cd57ccb7dd72ae08d56a159d6c9c3e30e"}, {file = "ruff-0.2.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e22676a5b875bd72acd3d11d5fa9075d3a5f53b877fe7b4793e4673499318ba"},
{file = "ruff-0.2.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a11567e20ea39d1f51aebd778685582d4c56ccb082c1161ffc10f79bebe6df35"}, {file = "ruff-0.2.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1695700d1e25a99d28f7a1636d85bafcc5030bba9d0578c0781ba1790dbcf51c"},
{file = "ruff-0.2.1-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:00a818e2db63659570403e44383ab03c529c2b9678ba4ba6c105af7854008105"}, {file = "ruff-0.2.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:b0c232af3d0bd8f521806223723456ffebf8e323bd1e4e82b0befb20ba18388e"},
{file = "ruff-0.2.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be60592f9d218b52f03384d1325efa9d3b41e4c4d55ea022cd548547cc42cd2b"}, {file = "ruff-0.2.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f63d96494eeec2fc70d909393bcd76c69f35334cdbd9e20d089fb3f0640216ca"},
{file = "ruff-0.2.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbd2288890b88e8aab4499e55148805b58ec711053588cc2f0196a44f6e3d855"}, {file = "ruff-0.2.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6a61ea0ff048e06de273b2e45bd72629f470f5da8f71daf09fe481278b175001"},
{file = "ruff-0.2.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3ef052283da7dec1987bba8d8733051c2325654641dfe5877a4022108098683"}, {file = "ruff-0.2.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e1439c8f407e4f356470e54cdecdca1bd5439a0673792dbe34a2b0a551a2fe3"},
{file = "ruff-0.2.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:7022d66366d6fded4ba3889f73cd791c2d5621b2ccf34befc752cb0df70f5fad"}, {file = "ruff-0.2.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:940de32dc8853eba0f67f7198b3e79bc6ba95c2edbfdfac2144c8235114d6726"},
{file = "ruff-0.2.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:0a725823cb2a3f08ee743a534cb6935727d9e47409e4ad72c10a3faf042ad5ba"}, {file = "ruff-0.2.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:0c126da55c38dd917621552ab430213bdb3273bb10ddb67bc4b761989210eb6e"},
{file = "ruff-0.2.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:0034d5b6323e6e8fe91b2a1e55b02d92d0b582d2953a2b37a67a2d7dedbb7acc"}, {file = "ruff-0.2.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:3b65494f7e4bed2e74110dac1f0d17dc8e1f42faaa784e7c58a98e335ec83d7e"},
{file = "ruff-0.2.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e5cb5526d69bb9143c2e4d2a115d08ffca3d8e0fddc84925a7b54931c96f5c02"}, {file = "ruff-0.2.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1ec49be4fe6ddac0503833f3ed8930528e26d1e60ad35c2446da372d16651ce9"},
{file = "ruff-0.2.1-py3-none-win32.whl", hash = "sha256:6b95ac9ce49b4fb390634d46d6ece32ace3acdd52814671ccaf20b7f60adb232"}, {file = "ruff-0.2.2-py3-none-win32.whl", hash = "sha256:d920499b576f6c68295bc04e7b17b6544d9d05f196bb3aac4358792ef6f34325"},
{file = "ruff-0.2.1-py3-none-win_amd64.whl", hash = "sha256:e3affdcbc2afb6f5bd0eb3130139ceedc5e3f28d206fe49f63073cb9e65988e0"}, {file = "ruff-0.2.2-py3-none-win_amd64.whl", hash = "sha256:cc9a91ae137d687f43a44c900e5d95e9617cb37d4c989e462980ba27039d239d"},
{file = "ruff-0.2.1-py3-none-win_arm64.whl", hash = "sha256:efababa8e12330aa94a53e90a81eb6e2d55f348bc2e71adbf17d9cad23c03ee6"}, {file = "ruff-0.2.2-py3-none-win_arm64.whl", hash = "sha256:c9d15fc41e6054bfc7200478720570078f0b41c9ae4f010bcc16bd6f4d1aacdd"},
{file = "ruff-0.2.1.tar.gz", hash = "sha256:3b42b5d8677cd0c72b99fcaf068ffc62abb5a19e71b4a3b9cfa50658a0af02f1"}, {file = "ruff-0.2.2.tar.gz", hash = "sha256:e62ed7f36b3068a30ba39193a14274cd706bc486fad521276458022f7bccb31d"},
] ]
[[package]] [[package]]
@ -2214,17 +2215,6 @@ webencodings = ">=0.4"
doc = ["sphinx", "sphinx_rtd_theme"] doc = ["sphinx", "sphinx_rtd_theme"]
test = ["flake8", "isort", "pytest"] test = ["flake8", "isort", "pytest"]
[[package]]
name = "tomli"
version = "2.0.1"
description = "A lil' TOML parser"
optional = false
python-versions = ">=3.7"
files = [
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
]
[[package]] [[package]]
name = "tomlkit" name = "tomlkit"
version = "0.12.4" version = "0.12.4"
@ -2249,13 +2239,13 @@ files = [
[[package]] [[package]]
name = "urllib3" name = "urllib3"
version = "2.2.0" version = "2.2.1"
description = "HTTP library with thread-safe connection pooling, file post, and more." description = "HTTP library with thread-safe connection pooling, file post, and more."
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
files = [ files = [
{file = "urllib3-2.2.0-py3-none-any.whl", hash = "sha256:ce3711610ddce217e6d113a2732fafad960a03fd0318c91faa79481e35c11224"}, {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"},
{file = "urllib3-2.2.0.tar.gz", hash = "sha256:051d961ad0c62a94e50ecf1af379c3aba230c66c710493493560c0c223c49f20"}, {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"},
] ]
[package.extras] [package.extras]
@ -2360,6 +2350,87 @@ files = [
{file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"},
] ]
[[package]]
name = "websockets"
version = "12.0"
description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)"
optional = false
python-versions = ">=3.8"
files = [
{file = "websockets-12.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d554236b2a2006e0ce16315c16eaa0d628dab009c33b63ea03f41c6107958374"},
{file = "websockets-12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2d225bb6886591b1746b17c0573e29804619c8f755b5598d875bb4235ea639be"},
{file = "websockets-12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:eb809e816916a3b210bed3c82fb88eaf16e8afcf9c115ebb2bacede1797d2547"},
{file = "websockets-12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c588f6abc13f78a67044c6b1273a99e1cf31038ad51815b3b016ce699f0d75c2"},
{file = "websockets-12.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5aa9348186d79a5f232115ed3fa9020eab66d6c3437d72f9d2c8ac0c6858c558"},
{file = "websockets-12.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6350b14a40c95ddd53e775dbdbbbc59b124a5c8ecd6fbb09c2e52029f7a9f480"},
{file = "websockets-12.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:70ec754cc2a769bcd218ed8d7209055667b30860ffecb8633a834dde27d6307c"},
{file = "websockets-12.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6e96f5ed1b83a8ddb07909b45bd94833b0710f738115751cdaa9da1fb0cb66e8"},
{file = "websockets-12.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4d87be612cbef86f994178d5186add3d94e9f31cc3cb499a0482b866ec477603"},
{file = "websockets-12.0-cp310-cp310-win32.whl", hash = "sha256:befe90632d66caaf72e8b2ed4d7f02b348913813c8b0a32fae1cc5fe3730902f"},
{file = "websockets-12.0-cp310-cp310-win_amd64.whl", hash = "sha256:363f57ca8bc8576195d0540c648aa58ac18cf85b76ad5202b9f976918f4219cf"},
{file = "websockets-12.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5d873c7de42dea355d73f170be0f23788cf3fa9f7bed718fd2830eefedce01b4"},
{file = "websockets-12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3f61726cae9f65b872502ff3c1496abc93ffbe31b278455c418492016e2afc8f"},
{file = "websockets-12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed2fcf7a07334c77fc8a230755c2209223a7cc44fc27597729b8ef5425aa61a3"},
{file = "websockets-12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e332c210b14b57904869ca9f9bf4ca32f5427a03eeb625da9b616c85a3a506c"},
{file = "websockets-12.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5693ef74233122f8ebab026817b1b37fe25c411ecfca084b29bc7d6efc548f45"},
{file = "websockets-12.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e9e7db18b4539a29cc5ad8c8b252738a30e2b13f033c2d6e9d0549b45841c04"},
{file = "websockets-12.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6e2df67b8014767d0f785baa98393725739287684b9f8d8a1001eb2839031447"},
{file = "websockets-12.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bea88d71630c5900690fcb03161ab18f8f244805c59e2e0dc4ffadae0a7ee0ca"},
{file = "websockets-12.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dff6cdf35e31d1315790149fee351f9e52978130cef6c87c4b6c9b3baf78bc53"},
{file = "websockets-12.0-cp311-cp311-win32.whl", hash = "sha256:3e3aa8c468af01d70332a382350ee95f6986db479ce7af14d5e81ec52aa2b402"},
{file = "websockets-12.0-cp311-cp311-win_amd64.whl", hash = "sha256:25eb766c8ad27da0f79420b2af4b85d29914ba0edf69f547cc4f06ca6f1d403b"},
{file = "websockets-12.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0e6e2711d5a8e6e482cacb927a49a3d432345dfe7dea8ace7b5790df5932e4df"},
{file = "websockets-12.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:dbcf72a37f0b3316e993e13ecf32f10c0e1259c28ffd0a85cee26e8549595fbc"},
{file = "websockets-12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12743ab88ab2af1d17dd4acb4645677cb7063ef4db93abffbf164218a5d54c6b"},
{file = "websockets-12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b645f491f3c48d3f8a00d1fce07445fab7347fec54a3e65f0725d730d5b99cb"},
{file = "websockets-12.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9893d1aa45a7f8b3bc4510f6ccf8db8c3b62120917af15e3de247f0780294b92"},
{file = "websockets-12.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f38a7b376117ef7aff996e737583172bdf535932c9ca021746573bce40165ed"},
{file = "websockets-12.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f764ba54e33daf20e167915edc443b6f88956f37fb606449b4a5b10ba42235a5"},
{file = "websockets-12.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1e4b3f8ea6a9cfa8be8484c9221ec0257508e3a1ec43c36acdefb2a9c3b00aa2"},
{file = "websockets-12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9fdf06fd06c32205a07e47328ab49c40fc1407cdec801d698a7c41167ea45113"},
{file = "websockets-12.0-cp312-cp312-win32.whl", hash = "sha256:baa386875b70cbd81798fa9f71be689c1bf484f65fd6fb08d051a0ee4e79924d"},
{file = "websockets-12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ae0a5da8f35a5be197f328d4727dbcfafa53d1824fac3d96cdd3a642fe09394f"},
{file = "websockets-12.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5f6ffe2c6598f7f7207eef9a1228b6f5c818f9f4d53ee920aacd35cec8110438"},
{file = "websockets-12.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9edf3fc590cc2ec20dc9d7a45108b5bbaf21c0d89f9fd3fd1685e223771dc0b2"},
{file = "websockets-12.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8572132c7be52632201a35f5e08348137f658e5ffd21f51f94572ca6c05ea81d"},
{file = "websockets-12.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:604428d1b87edbf02b233e2c207d7d528460fa978f9e391bd8aaf9c8311de137"},
{file = "websockets-12.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a9d160fd080c6285e202327aba140fc9a0d910b09e423afff4ae5cbbf1c7205"},
{file = "websockets-12.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87b4aafed34653e465eb77b7c93ef058516cb5acf3eb21e42f33928616172def"},
{file = "websockets-12.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b2ee7288b85959797970114deae81ab41b731f19ebcd3bd499ae9ca0e3f1d2c8"},
{file = "websockets-12.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7fa3d25e81bfe6a89718e9791128398a50dec6d57faf23770787ff441d851967"},
{file = "websockets-12.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a571f035a47212288e3b3519944f6bf4ac7bc7553243e41eac50dd48552b6df7"},
{file = "websockets-12.0-cp38-cp38-win32.whl", hash = "sha256:3c6cc1360c10c17463aadd29dd3af332d4a1adaa8796f6b0e9f9df1fdb0bad62"},
{file = "websockets-12.0-cp38-cp38-win_amd64.whl", hash = "sha256:1bf386089178ea69d720f8db6199a0504a406209a0fc23e603b27b300fdd6892"},
{file = "websockets-12.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ab3d732ad50a4fbd04a4490ef08acd0517b6ae6b77eb967251f4c263011a990d"},
{file = "websockets-12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1d9697f3337a89691e3bd8dc56dea45a6f6d975f92e7d5f773bc715c15dde28"},
{file = "websockets-12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1df2fbd2c8a98d38a66f5238484405b8d1d16f929bb7a33ed73e4801222a6f53"},
{file = "websockets-12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23509452b3bc38e3a057382c2e941d5ac2e01e251acce7adc74011d7d8de434c"},
{file = "websockets-12.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e5fc14ec6ea568200ea4ef46545073da81900a2b67b3e666f04adf53ad452ec"},
{file = "websockets-12.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46e71dbbd12850224243f5d2aeec90f0aaa0f2dde5aeeb8fc8df21e04d99eff9"},
{file = "websockets-12.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b81f90dcc6c85a9b7f29873beb56c94c85d6f0dac2ea8b60d995bd18bf3e2aae"},
{file = "websockets-12.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a02413bc474feda2849c59ed2dfb2cddb4cd3d2f03a2fedec51d6e959d9b608b"},
{file = "websockets-12.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bbe6013f9f791944ed31ca08b077e26249309639313fff132bfbf3ba105673b9"},
{file = "websockets-12.0-cp39-cp39-win32.whl", hash = "sha256:cbe83a6bbdf207ff0541de01e11904827540aa069293696dd528a6640bd6a5f6"},
{file = "websockets-12.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc4e7fa5414512b481a2483775a8e8be7803a35b30ca805afa4998a84f9fd9e8"},
{file = "websockets-12.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:248d8e2446e13c1d4326e0a6a4e9629cb13a11195051a73acf414812700badbd"},
{file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f44069528d45a933997a6fef143030d8ca8042f0dfaad753e2906398290e2870"},
{file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c4e37d36f0d19f0a4413d3e18c0d03d0c268ada2061868c1e6f5ab1a6d575077"},
{file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d829f975fc2e527a3ef2f9c8f25e553eb7bc779c6665e8e1d52aa22800bb38b"},
{file = "websockets-12.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:2c71bd45a777433dd9113847af751aae36e448bc6b8c361a566cb043eda6ec30"},
{file = "websockets-12.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0bee75f400895aef54157b36ed6d3b308fcab62e5260703add87f44cee9c82a6"},
{file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:423fc1ed29f7512fceb727e2d2aecb952c46aa34895e9ed96071821309951123"},
{file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27a5e9964ef509016759f2ef3f2c1e13f403725a5e6a1775555994966a66e931"},
{file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3181df4583c4d3994d31fb235dc681d2aaad744fbdbf94c4802485ececdecf2"},
{file = "websockets-12.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:b067cb952ce8bf40115f6c19f478dc71c5e719b7fbaa511359795dfd9d1a6468"},
{file = "websockets-12.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:00700340c6c7ab788f176d118775202aadea7602c5cc6be6ae127761c16d6b0b"},
{file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e469d01137942849cff40517c97a30a93ae79917752b34029f0ec72df6b46399"},
{file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffefa1374cd508d633646d51a8e9277763a9b78ae71324183693959cf94635a7"},
{file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba0cab91b3956dfa9f512147860783a1829a8d905ee218a9837c18f683239611"},
{file = "websockets-12.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2cb388a5bfb56df4d9a406783b7f9dbefb888c09b71629351cc6b036e9259370"},
{file = "websockets-12.0-py3-none-any.whl", hash = "sha256:dc284bbc8d7c78a6c69e0c7325ab46ee5e40bb4d50e494d8131a07ef47500e9e"},
{file = "websockets-12.0.tar.gz", hash = "sha256:81df9cbcbb6c260de1e007e58c011bfebe2dafc8435107b0537f393dd38c8b1b"},
]
[[package]] [[package]]
name = "yarl" name = "yarl"
version = "1.9.2" version = "1.9.2"
@ -2464,5 +2535,5 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = ">=3.9,<3.12" python-versions = ">=3.11,<3.12"
content-hash = "d7de093d6aa891ac2825cb6927b22659b72b0df83b87b0fe48cb575831831d71" content-hash = "f9f78f0ab56a0a981f792cfca9a7729a747fee41777f8d169162a98e382c5ecd"

5
pterodactyl/__init__.py Normal file
View file

@ -0,0 +1,5 @@
from .pterodactyl import Pterodactyl
async def setup(bot):
await bot.add_cog(Pterodactyl(bot))

26
pterodactyl/config.py Normal file
View file

@ -0,0 +1,26 @@
from redbot.core import Config
config: Config = Config.get_conf(None, identifier=457581387213637448123567, cog_name="Pterodactyl", force_registration=True)
def register_config(config_obj: Config) -> None:
config_obj.register_global(
base_url=None,
server_id=None,
console_channel=None,
startup_jar=None,
startup_arguments=None,
current_status='',
chat_regex=r"\[(\d{2}:\d{2}:\d{2})\sINFO\]:\s<(\w+)>\s(.*)",
server_regex=r"^\[\d{2}:\d{2}:\d{2} INFO\]:( \[Not Secure\])? \[.*\] (.*)",
join_regex=r"^\[\d{2}:\d{2}:\d{2} INFO\]: ([^<\n]+) joined the game$",
leave_regex=r"^\[\d{2}:\d{2}:\d{2} INFO\]: ([^<\n]+) left the game$",
achievement_regex=r"^\[\d{2}:\d{2}:\d{2} INFO\]: (.*) has (made the advancement|completed the challenge) \[(.*)\]$",
chat_command='tellraw @a ["",{"text":".$D ","color":".$C"},{"text":" (DISCORD): ","color":"blue"},{"text":".$M","color":"white"}]',
api_endpoint="minecraft",
chat_channel=None,
startup_msg='Server started!',
shutdown_msg='Server stopped!',
join_msg='Welcome to the server! 👋',
leave_msg='Goodbye! 👋',
mask_ip=True,
)

19
pterodactyl/info.json Normal file
View file

@ -0,0 +1,19 @@
{
"author" : ["SeaswimmerTheFsh (seasw.)"],
"install_msg" : "Thank you for installing Pterodactyl!\nYou can find the source code of this cog [here](https://coastalcommits.com/SeaswimmerTheFsh/SeaCogs).\nDocumentation can be found [here](https://seacogs.coastalcommits.com/pterodactyl ).",
"name" : "Pterodactyl",
"short" : "Interface with Pterodactyl through websockets.",
"description" : "Interface with Pterodactyl through websockets.",
"end_user_data_statement" : "This cog does not store end user data.",
"hidden": false,
"disabled": false,
"min_bot_version": "3.5.0",
"min_python_version": [3, 8, 0],
"requirements": ["py-dactyl", "websockets"],
"tags": [
"pterodactyl",
"minecraft",
"server",
"management"
]
}

3
pterodactyl/logger.py Normal file
View file

@ -0,0 +1,3 @@
import logging
logger = logging.getLogger('red.sea.pterodactyl')

330
pterodactyl/pterodactyl.py Normal file
View file

@ -0,0 +1,330 @@
import asyncio
import json
from typing import Mapping, Optional
import discord
import websockets
from pydactyl import PterodactylClient
from redbot.core import commands
from redbot.core.bot import Red
from redbot.core.utils.chat_formatting import box
from pterodactyl.config import config, register_config
from pterodactyl.logger import logger
class Pterodactyl(commands.Cog):
"""Pterodactyl allows you to manage your Pterodactyl Panel from Discord."""
def __init__(self, bot: Red):
self.bot = bot
self.client: Optional[PterodactylClient] = None
self.task: Optional[asyncio.Task] = None
self.websocket: Optional[websockets.WebSocketClientProtocol] = None
self.retry_counter: int = 0
register_config(config)
async def cog_load(self) -> None:
self.retry_counter = 0
self.task = self.get_task()
async def cog_unload(self) -> None:
self.task.cancel()
self.retry_counter = 0
await self.client._session.close() # pylint: disable=protected-access
def get_task(self) -> asyncio.Task:
from pterodactyl.websocket import establish_websocket_connection
task = self.bot.loop.create_task(establish_websocket_connection(self), name="Pterodactyl Websocket Connection")
task.add_done_callback(self.error_callback)
return task
def error_callback(self, fut) -> None: #NOTE - Thanks flame442 and zephyrkul for helping me figure this out
try:
fut.result()
except asyncio.CancelledError:
logger.info("WebSocket task has been cancelled.")
except Exception as e: # pylint: disable=broad-exception-caught
logger.error("WebSocket task has failed: %s", e, exc_info=e)
self.task.cancel()
if self.retry_counter < 5:
self.retry_counter += 1
logger.info("Retrying in %s seconds...", 5 * self.retry_counter)
self.task = self.bot.loop.call_later(5 * self.retry_counter, self.get_task)
else:
logger.info("Retry limit reached. Stopping task.")
@commands.Cog.listener()
async def on_message_without_command(self, message: discord.Message) -> None:
if message.channel.id == await config.console_channel() and message.author.bot is False:
logger.debug("Received console command from %s: %s", message.author.id, message.content)
await message.channel.send(f"Received console command from {message.author.id}: {message.content[:1900]}")
try:
await self.websocket.send(json.dumps({"event": "send command", "args": [message.content]}))
except websockets.exceptions.ConnectionClosed as e:
logger.error("WebSocket connection closed: %s", e)
self.task.cancel()
self.retry_counter = 0
self.task = self.get_task()
if message.channel.id == await config.chat_channel() and message.author.bot is False:
logger.debug("Received chat message from %s: %s", message.author.id, message.content)
channel = self.bot.get_channel(await config.console_channel())
if channel:
await channel.send(f"Received chat message from {message.author.id}: {message.content[:1900]}")
msg = json.dumps({"event": "send command", "args": [await self.get_chat_command(message)]})
logger.debug("Sending chat message to server:\n%s", msg)
try:
await self.websocket.send(msg)
except websockets.exceptions.ConnectionClosed as e:
logger.error("WebSocket connection closed: %s", e)
self.task.cancel()
self.retry_counter = 0
self.task = self.get_task()
async def get_chat_command(self, message: discord.Message) -> str:
command: str = await config.chat_command()
placeholders = {
"C": str(message.author.color),
"D": message.author.discriminator,
"I": str(message.author.id),
"M": message.content,
"N": message.author.display_name,
"U": message.author.name,
}
for key, value in placeholders.items():
command = command.replace('.$' + key, value)
return command
@commands.Cog.listener()
async def on_red_api_tokens_update(self, service_name: str, api_tokens: Mapping[str,str]): # pylint: disable=unused-argument
if service_name == "pterodactyl":
logger.info("Configuration value set: api_key\nRestarting task...")
self.task.cancel()
self.retry_counter = 0
self.task = self.get_task()
@commands.group(autohelp = True, name = "pterodactyl", aliases = ["ptero"])
async def pterodactyl(self, ctx: commands.Context) -> None:
"""Pterodactyl allows you to manage your Pterodactyl Panel from Discord."""
@pterodactyl.group(autohelp = True, name = "power")
@commands.admin()
async def pterodactyl_power(self, ctx: commands.Context) -> None:
"""Send power actions to the server."""
@pterodactyl_power.command(name = "start")
async def pterodactyl_power_start(self, ctx: commands.Context) -> None:
"""Start the server."""
current_status = await config.current_status()
if current_status == "running":
return await ctx.send("Server is already running.")
if current_status in ["starting", "stopping"]:
return await ctx.send("Another power action is already in progress.")
message = await ctx.send("Sending websocket command to start server...")
await self.websocket.send(json.dumps({"event": "set state", "args": ["start"]}))
await message.edit(content="Server starting...")
@pterodactyl_power.command(name = "stop")
async def pterodactyl_power_stop(self, ctx: commands.Context) -> None:
"""Stop the server."""
current_status = await config.current_status()
if current_status == "stopped":
return await ctx.send("Server is already stopped.")
if current_status in ["starting", "stopping"]:
return await ctx.send("Another power action is already in progress.")
message = await ctx.send("Sending websocket command to stop server...")
await self.websocket.send(json.dumps({"event": "set state", "args": ["stop"]}))
await message.edit(content="Server stopping...")
@pterodactyl_power.command(name = "restart")
async def pterodactyl_power_restart(self, ctx: commands.Context) -> None:
"""Restart the server."""
current_status = await config.current_status()
if current_status in ["starting", "stopping"]:
return await ctx.send("Another power action is already in progress.")
message = await ctx.send("Sending websocket command to restart server...")
await self.websocket.send(json.dumps({"event": "set state", "args": ["restart"]}))
await message.edit(content="Server restarting...")
@pterodactyl.group(autohelp = True, name = "config", aliases = ["settings", "set"])
@commands.is_owner()
async def pterodactyl_config(self, ctx: commands.Context) -> None:
"""Configure Pterodactyl settings."""
@pterodactyl_config.command(name = "url")
async def pterodactyl_config_base_url(self, ctx: commands.Context, *, base_url: str) -> None:
"""Set the base URL of your Pterodactyl Panel.
Please include the protocol (http/https).
Example: `https://panel.example.com`"""
await config.base_url.set(base_url)
await ctx.send(f"Base URL set to {base_url}")
logger.info("Configuration value set: base_url = %s\nRestarting task...", base_url)
self.task.cancel()
self.retry_counter = 0
self.task = self.get_task()
@pterodactyl_config.command(name = "serverid")
async def pterodactyl_config_server_id(self, ctx: commands.Context, *, server_id: str) -> None:
"""Set the ID of your server."""
await config.server_id.set(server_id)
await ctx.send(f"Server ID set to {server_id}")
logger.info("Configuration value set: server_id = %s\nRestarting task...", server_id)
self.task.cancel()
self.retry_counter = 0
self.task = self.get_task()
@pterodactyl_config.command(name = "consolechannel")
async def pterodactyl_config_console_channel(self, ctx: commands.Context, channel: discord.TextChannel) -> None:
"""Set the channel to send console output to."""
await config.console_channel.set(channel.id)
await ctx.send(f"Console channel set to {channel.mention}")
@pterodactyl_config.group(name = "chat")
async def pterodactyl_config_chat(self, ctx: commands.Context):
"""Configure chat settings."""
@pterodactyl_config_chat.command(name = "channel")
async def pterodactyl_config_chat_channel(self, ctx: commands.Context, channel: discord.TextChannel) -> None:
"""Set the channel to send chat output to."""
await config.chat_channel.set(channel.id)
await ctx.send(f"Chat channel set to {channel.mention}")
@pterodactyl_config_chat.command(name = "command")
async def pterodactyl_config_chat_command(self, ctx: commands.Context, *, command: str) -> None:
"""Set the command that will be used to send messages from Discord.
Required placeholders: `.$U` (username), `.$M` (message), `.$C` (color)
See [documentation](https://seacogs.coastalcommits.com/pterodactyl/setup/#changing-the-tellraw-command) for more information."""
await config.chat_command.set(command)
await ctx.send(f"Chat command set to:\n{box(command, 'json')}")
@pterodactyl_config.group(name = "regex")
async def pterodactyl_config_regex(self, ctx: commands.Context) -> None:
"""Set regex patterns."""
@pterodactyl_config_regex.command(name = "chat")
async def pterodactyl_config_regex_chat(self, ctx: commands.Context, *, regex: str) -> None:
"""Set the regex pattern to match chat messages on the server.
See [documentation](https://seacogs.coastalcommits.com/pterodactyl/setup/#my-chat-messages-arent-detected) for more information."""
await config.chat_regex.set(regex)
await ctx.send(f"Chat regex set to:\n{box(regex, 'regex')}")
@pterodactyl_config_regex.command(name = "server")
async def pterodactyl_config_regex_server(self, ctx: commands.Context, *, regex: str) -> None:
"""Set the regex pattern to match server messages on the server.
See [documentation](https://seacogs.coastalcommits.com/pterodactyl/setup/#my-chat-messages-arent-detected) for more information."""
await config.server_regex.set(regex)
await ctx.send(f"Server regex set to:\n{box(regex, 'regex')}")
@pterodactyl_config_regex.command(name = "join")
async def pterodactyl_config_regex_join(self, ctx: commands.Context, *, regex: str) -> None:
"""Set the regex pattern to match join messages on the server.
See [documentation](https://seacogs.coastalcommits.com/pterodactyl/setup/#my-chat-messages-arent-detected) for more information."""
await config.join_regex.set(regex)
await ctx.send(f"Join regex set to:\n{box(regex, 'regex')}")
@pterodactyl_config_regex.command(name = "leave")
async def pterodactyl_config_regex_leave(self, ctx: commands.Context, *, regex: str) -> None:
"""Set the regex pattern to match leave messages on the server.
See [documentation](https://seacogs.coastalcommits.com/pterodactyl/setup/#my-chat-messages-arent-detected) for more information."""
await config.leave_regex.set(regex)
await ctx.send(f"Leave regex set to:\n{box(regex, 'regex')}")
@pterodactyl_config_regex.command(name = "achievement")
async def pterodactyl_config_regex_achievement(self, ctx: commands.Context, *, regex: str) -> None:
"""Set the regex pattern to match achievement messages on the server.
See [documentation](https://seacogs.coastalcommits.com/pterodactyl/setup/#my-chat-messages-arent-detected) for more information."""
await config.achievement_regex.set(regex)
await ctx.send(f"Achievement regex set to:\n{box(regex, 'regex')}")
@pterodactyl_config.group(name = "messages", aliases = ['msg', 'msgs', 'message'])
async def pterodactyl_config_messages(self, ctx: commands.Context):
"""Configure message settings."""
@pterodactyl_config_messages.command(name = "startup")
async def pterodactyl_config_messages_startup(self, ctx: commands.Context, *, message: str) -> None:
"""Set the message that will be sent when the server starts."""
await config.startup_msg.set(message)
await ctx.send(f"Startup message set to: {message}")
@pterodactyl_config_messages.command(name = "shutdown")
async def pterodactyl_config_messages_shutdown(self, ctx: commands.Context, *, message: str) -> None:
"""Set the message that will be sent when the server stops."""
await config.shutdown_msg.set(message)
await ctx.send(f"Shutdown message set to: {message}")
@pterodactyl_config_messages.command(name = "join")
async def pterodactyl_config_messages_join(self, ctx: commands.Context, *, message: str) -> None:
"""Set the message that will be sent when a user joins the server. This is only shown in embeds."""
await config.join_msg.set(message)
await ctx.send(f"Join message set to: {message}")
@pterodactyl_config_messages.command(name = "leave")
async def pterodactyl_config_messages_leave(self, ctx: commands.Context, *, message: str) -> None:
"""Set the message that will be sent when a user leaves the server. This is only shown in embeds."""
await config.leave_msg.set(message)
await ctx.send(f"Leave message set to: {message}")
@pterodactyl_config.command(name = "ip")
async def pterodactyl_config_mask_ip(self, ctx: commands.Context, mask: bool) -> None:
"""Mask the IP addresses of users in console messages."""
await config.mask_ip.set(mask)
await ctx.send(f"IP masking set to {mask}")
@pterodactyl_config.command(name = "api")
async def pterodactyl_config_api(self, ctx: commands.Context, endpoint: str) -> None:
"""Set the API endpoint for retrieving user avatars.
This is only used for retrieving user avatars for webhook messages.
See [PlayerDB](https://playerdb.co/) for valid endpoints. Usually, you should leave this as default."""
await config.api_endpoint.set(endpoint)
await ctx.send(f"API endpoint set to {endpoint}")
@pterodactyl_config.command(name = 'view', aliases = ['show'])
async def pterodactyl_config_view(self, ctx: commands.Context) -> None:
"""View the current configuration."""
base_url = await config.base_url()
server_id = await config.server_id()
console_channel = await config.console_channel()
chat_channel = await config.chat_channel()
chat_command = await config.chat_command()
chat_regex = await config.chat_regex()
server_regex = await config.server_regex()
join_regex = await config.join_regex()
leave_regex = await config.leave_regex()
achievement_regex = await config.achievement_regex()
startup_msg = await config.startup_msg()
shutdown_msg = await config.shutdown_msg()
join_msg = await config.join_msg()
leave_msg = await config.leave_msg()
mask_ip = await config.mask_ip()
api_endpoint = await config.api_endpoint()
embed = discord.Embed(color = await ctx.embed_color(), title="Pterodactyl Configuration")
embed.description = f"""**Base URL:** {base_url}
**Server ID:** `{server_id}`
**Console Channel:** <#{console_channel}>
**Chat Channel:** <#{chat_channel}>
**Startup Message:** {startup_msg}
**Shutdown Message:** {shutdown_msg}
**Join Message:** {join_msg}
**Leave Message:** {leave_msg}
**Mask IP:** {self.get_bool_str(mask_ip)}
**API Endpoint:** `{api_endpoint}`
**Chat Command:** {box(chat_command, 'json')}
**Chat Regex:** {box(chat_regex, 're')}
**Server Regex:** {box(server_regex, 're')}
**Join Regex:** {box(join_regex, 're')}
**Leave Regex:** {box(leave_regex, 're')}
**Achievement Regex:** {box(achievement_regex, 're')}"""
await ctx.send(embed=embed)
def get_bool_str(self, inp: bool) -> str:
"""Return a string representation of a boolean."""
return "Enabled" if inp else "Disabled"

261
pterodactyl/websocket.py Normal file
View file

@ -0,0 +1,261 @@
# pylint: disable=cyclic-import
import json
import re
from logging import getLogger
from typing import Optional, Union
import aiohttp
import discord
import websockets
from pydactyl import PterodactylClient
from redbot.core.utils.chat_formatting import pagify
from pterodactyl.config import config
from pterodactyl.logger import logger
from pterodactyl.pterodactyl import Pterodactyl
async def establish_websocket_connection(coginstance: Pterodactyl) -> None:
base_url = await config.base_url()
base_url = base_url[:-1] if base_url.endswith('/') else base_url
logger.info("Establishing WebSocket connection")
websocket_credentials = await retrieve_websocket_credentials(coginstance)
async with websockets.connect(websocket_credentials['data']['socket'], origin=base_url, ping_timeout=60, logger=getLogger("red.sea.pterodactyl.websocket")) as websocket:
logger.info("WebSocket connection established")
auth_message = json.dumps({"event": "auth", "args": [websocket_credentials['data']['token']]})
await websocket.send(auth_message)
logger.info("Authentication message sent")
coginstance.websocket = websocket
while True: # pylint: disable=too-many-nested-blocks
message = await websocket.recv()
if json.loads(message)['event'] in ('token expiring', 'token expired'):
logger.info("Received token expiring/expired event. Refreshing token.")
websocket_credentials = await retrieve_websocket_credentials(coginstance)
auth_message = json.dumps({"event": "auth", "args": [websocket_credentials['data']['token']]})
await websocket.send(auth_message)
logger.info("Authentication message sent")
if json.loads(message)['event'] == 'auth success':
logger.info("WebSocket authentication successful")
if json.loads(message)['event'] == 'console output' and await config.console_channel() is not None:
if await config.current_status() in ('running', 'offline', ''):
content = remove_ansi_escape_codes(json.loads(message)['args'][0])
if await config.mask_ip() is True:
content = mask_ip(content)
channel = coginstance.bot.get_channel(await config.console_channel())
if channel is not None:
if content.startswith('['):
pagified_content = pagify(content, delims=[" ", "\n"])
for page in pagified_content:
await channel.send(content=page)
chat_message = await check_if_chat_message(content)
if chat_message:
info = await get_info(chat_message['username'])
if info is not None:
await send_chat_discord(coginstance, chat_message['username'], chat_message['message'], info['data']['player']['avatar'])
else:
await send_chat_discord(coginstance, chat_message['username'], chat_message['message'], 'https://seafsh.cc/u/j3AzqQ.png')
server_message = await check_if_server_message(content)
if server_message:
channel = coginstance.bot.get_channel(await config.chat_channel())
if channel is not None:
await channel.send(server_message if len(server_message) < 2000 else server_message[:1997] + '...')
join_message = await check_if_join_message(content)
if join_message:
channel = coginstance.bot.get_channel(await config.chat_channel())
if channel is not None:
if coginstance.bot.embed_requested(channel):
await channel.send(embed=await generate_join_leave_embed(join_message, True))
else:
await channel.send(f"{join_message} joined the game")
leave_message = await check_if_leave_message(content)
if leave_message:
channel = coginstance.bot.get_channel(await config.chat_channel())
if channel is not None:
if coginstance.bot.embed_requested(channel):
await channel.send(embed=await generate_join_leave_embed(leave_message, False))
else:
await channel.send(f"{leave_message} left the game")
achievement_message = await check_if_achievement_message(content)
if achievement_message:
channel = coginstance.bot.get_channel(await config.chat_channel())
if channel is not None:
if coginstance.bot.embed_requested(channel):
await channel.send(embed=await generate_achievement_embed(achievement_message['username'], achievement_message['achievement'], achievement_message['challenge']))
else:
await channel.send(f"{achievement_message['username']} has {'completed the challenge' if achievement_message['challenge'] else 'made the advancement'} {achievement_message['achievement']}")
if json.loads(message)['event'] == 'status':
old_status = await config.current_status()
current_status = json.loads(message)['args'][0]
if old_status != current_status:
await config.current_status.set(current_status)
if await config.console_channel() is not None:
console = coginstance.bot.get_channel(await config.console_channel())
if console is not None:
await console.send(f"Server status changed! `{current_status}`")
if await config.chat_channel() is not None:
if current_status == 'running' and await config.startup_msg() is not None:
chat = coginstance.bot.get_channel(await config.chat_channel())
if chat is not None:
await chat.send(await config.startup_msg())
if current_status == 'stopping' and await config.shutdown_msg() is not None:
chat = coginstance.bot.get_channel(await config.chat_channel())
if chat is not None:
await chat.send(await config.shutdown_msg())
async def retrieve_websocket_credentials(coginstance: Pterodactyl) -> Optional[dict]:
pterodactyl_keys = await coginstance.bot.get_shared_api_tokens("pterodactyl")
api_key = pterodactyl_keys.get("api_key")
if api_key is None:
coginstance.task.cancel()
raise ValueError("Pterodactyl API key not set. Please set it using `[p]set api`.")
base_url = await config.base_url()
if base_url is None:
coginstance.task.cancel()
raise ValueError("Pterodactyl base URL not set. Please set it using `[p]pterodactyl config url`.")
server_id = await config.server_id()
if server_id is None:
coginstance.task.cancel()
raise ValueError("Pterodactyl server ID not set. Please set it using `[p]pterodactyl config serverid`.")
client = PterodactylClient(base_url, api_key, debug=True).client
coginstance.client = client
websocket_credentials = client.servers.get_websocket(server_id)
logger.debug("""Websocket connection details retrieved:
Socket: %s
Token: %s...""",
websocket_credentials['data']['socket'],
websocket_credentials['data']['token'][:20]
)
return websocket_credentials
#NOTE - The token is truncated to prevent it from being logged in its entirety, for security reasons
def remove_ansi_escape_codes(text: str) -> str:
ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
#NOTE - https://chat.openai.com/share/d92f9acf-d776-4fd6-a53f-b14ac15dd540
return ansi_escape.sub('', text)
async def check_if_server_message(text: str) -> Union[bool, str]:
logger.debug("Checking if message is a server message")
regex = await config.server_regex()
match: Optional[re.Match[str]] = re.match(regex, text)
if match:
logger.debug("Message is a server message")
return match.group(2)
logger.debug("Message is not a server message")
return False
async def check_if_chat_message(text: str) -> Union[bool, dict]:
logger.debug("Checking if message is a chat message")
regex = await config.chat_regex()
match: Optional[re.Match[str]] = re.match(regex, text)
if match:
groups = {"time": match.group(1), "username": match.group(2), "message": match.group(3)}
logger.debug("Message is a chat message\n%s", json.dumps(groups))
return groups
logger.debug("Message is not a chat message")
return False
async def check_if_join_message(text: str) -> Union[bool, str]:
logger.debug("Checking if message is a join message")
regex = await config.join_regex()
match: Optional[re.Match[str]] = re.match(regex, text)
if match:
logger.debug("Message is a join message")
return match.group(1)
logger.debug("Message is not a join message")
return False
async def check_if_leave_message(text: str) -> Union[bool, str]:
logger.debug("Checking if message is a leave message")
regex = await config.leave_regex()
match: Optional[re.Match[str]] = re.match(regex, text)
if match:
logger.debug("Message is a leave message")
return match.group(1)
logger.debug("Message is not a leave message")
return False
async def check_if_achievement_message(text: str) -> Union[bool, dict]:
logger.debug("Checking if message is an achievement message")
regex = await config.achievement_regex()
match: Optional[re.Match[str]] = re.match(regex, text)
if match:
groups = {"username": match.group(1), "achievement": match.group(3)}
if match.group(2) == "completed the challenge":
groups["challenge"] = True
else:
groups["challenge"] = False
logger.debug("Message is an achievement message\n%s", json.dumps(groups))
return groups
logger.debug("Message is not an achievement message")
return False
async def get_info(username: str) -> Optional[dict]:
logger.debug("Retrieving player info for %s", username)
endpoint = await config.api_endpoint()
async with aiohttp.ClientSession() as session:
async with session.get(f"https://playerdb.co/api/player/{endpoint}/{username}") as response:
if response.status == 200:
logger.debug("Player info retrieved for %s\n%s", username, json.dumps(await response.json()))
return await response.json()
logger.error("Failed to retrieve player info for %s: %s", username, response.status)
return None
async def send_chat_discord(coginstance: Pterodactyl, username: str, message: str, avatar_url: str) -> None:
logger.debug("Sending chat message to Discord")
channel = coginstance.bot.get_channel(await config.chat_channel())
if channel is not None:
webhooks = await channel.webhooks()
webhook = discord.utils.get(webhooks, name="Pterodactyl Chat")
if webhook is None:
webhook = await channel.create_webhook(name="Pterodactyl Chat")
await webhook.send(content=message, username=username, avatar_url=avatar_url)
logger.debug("Chat message sent to Discord")
else:
logger.debug("Chat channel not set. Skipping sending chat message to Discord")
async def generate_join_leave_embed(username: str, join: bool) -> discord.Embed:
embed = discord.Embed()
embed.color = discord.Color.green() if join else discord.Color.red()
embed.description = await config.join_msg() if join else await config.leave_msg()
info = await get_info(username)
if info:
embed.set_author(name=username, icon_url=info['data']['player']['avatar'])
else:
embed.set_author(name=username, icon_url='https://seafsh.cc/u/j3AzqQ.png')
embed.timestamp = discord.utils.utcnow()
return embed
async def generate_achievement_embed(username: str, achievement: str, challenge: bool) -> discord.Embed:
embed = discord.Embed()
embed.color = discord.Color.dark_purple() if challenge else discord.Color.brand_green()
embed.description = f"{username} has {'completed the challenge' if challenge else 'made the advancement'} {achievement}"
info = await get_info(username)
if info:
embed.set_author(name=username, icon_url=info['data']['player']['avatar'])
else:
embed.set_author(name=username, icon_url='https://seafsh.cc/u/j3AzqQ.png')
embed.timestamp = discord.utils.utcnow()
return embed
def mask_ip(string: str) -> str:
def check(match):
ip = match.group(0)
masked_ip = '.'.join(r'\*' * len(octet) for octet in ip.split('.'))
return masked_ip
return re.sub(r'\b(?:\d{1,3}\.){3}\d{1,3}\b', check, string)

View file

@ -7,10 +7,12 @@ license = "MPL 2"
readme = "README.md" readme = "README.md"
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = ">=3.9,<3.12" python = ">=3.11,<3.12"
Red-DiscordBot = "^3.5.5" Red-DiscordBot = "^3.5.5"
pytimeparse2 = "^1.7.1" pytimeparse2 = "^1.7.1"
humanize = "^4.8.0" humanize = "^4.8.0"
py-dactyl = "^2.0.4"
websockets = "^12.0"
[tool.poetry.group.dev] [tool.poetry.group.dev]
optional = true optional = true