mcserver-cli 4.4.0__tar.gz → 4.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/CHANGELOG.md +15 -3
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/NOTES.txt +3 -1
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/PKG-INFO +20 -5
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/README.md +19 -4
- mcserver_cli-4.5.0/src/mcserver/__init__.py +1 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/cli.py +54 -2
- mcserver_cli-4.5.0/src/mcserver/commands/op_grant.py +103 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/commands/op_revoke.py +3 -12
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/commands/search_projects.py +8 -4
- mcserver_cli-4.5.0/src/mcserver/commands/whitelist_add.py +81 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/commands/whitelist_remove.py +3 -12
- mcserver_cli-4.5.0/src/mcserver/minecraft/api.py +112 -0
- mcserver_cli-4.5.0/src/mcserver/minecraft/player_identity.py +41 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/modrinth/apis/get_project_informations.py +1 -1
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/modrinth/apis/search_projects.py +1 -2
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/modrinth/slug_index.py +12 -18
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/server_files/ops.py +82 -26
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/server_files/paths.py +1 -0
- mcserver_cli-4.5.0/src/mcserver/server_files/server_properties.py +42 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/server_files/whitelist.py +74 -26
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/shared.py +1 -1
- mcserver_cli-4.4.0/src/mcserver/__init__.py +0 -1
- mcserver_cli-4.4.0/src/mcserver/commands/op_grant.py +0 -9
- mcserver_cli-4.4.0/src/mcserver/commands/whitelist_add.py +0 -9
- mcserver_cli-4.4.0/src/mcserver/minecraft/api.py +0 -94
- mcserver_cli-4.4.0/src/mcserver/minecraft/player_identity.py +0 -21
- mcserver_cli-4.4.0/src/mcserver/modrinth/projects.py +0 -80
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/.gitignore +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/CONTRIBUTING.md +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/LICENSE +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/legacy/mcserver_v2.0.0.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/pyproject.toml +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/__main__.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/__main__.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/app.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/caching.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/commands/__init__.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/commands/add_projects.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/commands/import_setup.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/commands/initialize_server.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/commands/list_projects.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/commands/op_list.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/commands/print_help.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/commands/remove_projects.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/commands/server_status.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/commands/show_projects.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/commands/start_server.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/commands/stop_server.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/commands/update_projects.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/commands/whitelist_list.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/config.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/constants.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/fabricmc/meta.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/legacy_fabric/meta.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/metadata.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/modrinth/apis/__init__.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/modrinth/apis/get_project_versions.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/modrinth/constants.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/modrinth/modpack.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/modrinth/paths.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/modrinth/project_records.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/modrinth/shared.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/modrinth/typings/__init__.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/modrinth/typings/project_information.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/modrinth/typings/project_version.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/modrinth/typings/search_projects.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/modrinth/typings/shared.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/mojang/eula.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/mojang/manifest.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/mysterious.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/networking.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/papermc/api.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/paths.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/purpurmc/api.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/quiltmc/meta.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/resolver.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/server_files/banned_ips.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/server_files/banned_players.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/server_files/properties.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/server_files/usercaches.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/state.py +0 -0
- {mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/zip_app.py +0 -0
|
@@ -5,12 +5,23 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [Unreleased]
|
|
8
9
|
|
|
9
|
-
## [4.
|
|
10
|
+
## [4.5.0] - 2026-11-04
|
|
10
11
|
|
|
11
12
|
### Added
|
|
12
13
|
|
|
13
|
-
- `op
|
|
14
|
+
- `whitelist add` and `op add` command (limited to 10 players at once for online mode for name)
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- `op remove` and `whitelist remove` to name is now case insensitive
|
|
19
|
+
|
|
20
|
+
## [4.4.0] - 2026-11-03
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
- `op revoke` to revoke operator players permission based on UUIDs or names
|
|
14
25
|
- Player count to `whitelist list`
|
|
15
26
|
|
|
16
27
|
### Fixes
|
|
@@ -247,7 +258,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
247
258
|
- Better mod conflict error
|
|
248
259
|
- Faster mod resolving
|
|
249
260
|
|
|
250
|
-
[unreleased]: https://github.com/Othecat35/MCServer/compare/v4.
|
|
261
|
+
[unreleased]: https://github.com/Othecat35/MCServer/compare/v4.5.0...HEAD
|
|
262
|
+
[4.4.0]: https://github.com/Othecat35/MCServer/compare/v4.4.0...v4.5.0
|
|
251
263
|
[4.4.0]: https://github.com/Othecat35/MCServer/compare/v4.3.0...v4.4.0
|
|
252
264
|
[4.3.0]: https://github.com/Othecat35/MCServer/compare/v4.2.0...v4.3.0
|
|
253
265
|
[4.2.0]: https://github.com/Othecat35/MCServer/compare/v4.1.0...v4.2.0
|
|
@@ -391,4 +391,6 @@ and yea
|
|
|
391
391
|
|
|
392
392
|
|
|
393
393
|
Ah yes... rcon, and also swrver management protocol.
|
|
394
|
-
Don't forget to add a warning fof whitelist remove if the server is running to run whitelist
|
|
394
|
+
Don't forget to add a warning fof whitelist remove if the server is running to run whitelist remover
|
|
395
|
+
|
|
396
|
+
about whitelist add or op grant, remember to make the internal function does remove and add together, then call it upsert according to deepseek
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: mcserver-cli
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.5.0
|
|
4
4
|
Summary: A CLI tool to manage Minecraft: Java Edition servers.
|
|
5
5
|
Project-URL: Homepage, https://github.com/Othecat35/MCServer
|
|
6
6
|
Project-URL: Repository, https://github.com/Othecat35/MCServer.git
|
|
@@ -25,7 +25,7 @@ Supported platforms:
|
|
|
25
25
|
- JRE (depends on Minecraft version)
|
|
26
26
|
|
|
27
27
|
## How to install
|
|
28
|
-
- Using pip:
|
|
28
|
+
- Using pip: Just run `pip install mcserver-cli`
|
|
29
29
|
|
|
30
30
|
- System-wide (Requires root):
|
|
31
31
|
1. Download the `mcserver` script file from GitHub releases
|
|
@@ -52,13 +52,13 @@ Supported platforms:
|
|
|
52
52
|
- Remove whitelisted players: `mcserver whitelist remove <players>`
|
|
53
53
|
|
|
54
54
|
### Examples
|
|
55
|
-
- Create and start a Fabric 1.20.1 server
|
|
55
|
+
- Create and start a Fabric 1.20.1 server in the current directory
|
|
56
56
|
```bash
|
|
57
57
|
mcserver init --game-version=1.20.1 --loader=fabric
|
|
58
58
|
mcserver start
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
-
- Search top 50 Fabric mods for Minecraft 1.20.1
|
|
61
|
+
- Search top 50 Fabric mods for Minecraft 1.20.1 on modrinth
|
|
62
62
|
```bash
|
|
63
63
|
mcserver search --loader=fabric --game-version=1.20.1 --limit=50
|
|
64
64
|
```
|
|
@@ -69,7 +69,22 @@ mcserver op list
|
|
|
69
69
|
mcserver whitelist list
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
-
-
|
|
72
|
+
- Adding a player to the whitelist
|
|
73
|
+
```bash
|
|
74
|
+
mcserver whitelist add Notch
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
- Granting Notch operator level 4 and can bypass player limit
|
|
78
|
+
```bash
|
|
79
|
+
mcserver op grant Notch --permission-level=4 --bypasses-player-limit
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
- Remove me from the whitelist
|
|
83
|
+
```bash
|
|
84
|
+
mcserver whitelist remove Othecat35
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
- Stop a running server on current directory with sigterm
|
|
73
88
|
```bash
|
|
74
89
|
mcserver stop
|
|
75
90
|
```
|
|
@@ -12,7 +12,7 @@ Supported platforms:
|
|
|
12
12
|
- JRE (depends on Minecraft version)
|
|
13
13
|
|
|
14
14
|
## How to install
|
|
15
|
-
- Using pip:
|
|
15
|
+
- Using pip: Just run `pip install mcserver-cli`
|
|
16
16
|
|
|
17
17
|
- System-wide (Requires root):
|
|
18
18
|
1. Download the `mcserver` script file from GitHub releases
|
|
@@ -39,13 +39,13 @@ Supported platforms:
|
|
|
39
39
|
- Remove whitelisted players: `mcserver whitelist remove <players>`
|
|
40
40
|
|
|
41
41
|
### Examples
|
|
42
|
-
- Create and start a Fabric 1.20.1 server
|
|
42
|
+
- Create and start a Fabric 1.20.1 server in the current directory
|
|
43
43
|
```bash
|
|
44
44
|
mcserver init --game-version=1.20.1 --loader=fabric
|
|
45
45
|
mcserver start
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
- Search top 50 Fabric mods for Minecraft 1.20.1
|
|
48
|
+
- Search top 50 Fabric mods for Minecraft 1.20.1 on modrinth
|
|
49
49
|
```bash
|
|
50
50
|
mcserver search --loader=fabric --game-version=1.20.1 --limit=50
|
|
51
51
|
```
|
|
@@ -56,7 +56,22 @@ mcserver op list
|
|
|
56
56
|
mcserver whitelist list
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
-
|
|
59
|
+
- Adding a player to the whitelist
|
|
60
|
+
```bash
|
|
61
|
+
mcserver whitelist add Notch
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
- Granting Notch operator level 4 and can bypass player limit
|
|
65
|
+
```bash
|
|
66
|
+
mcserver op grant Notch --permission-level=4 --bypasses-player-limit
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
- Remove me from the whitelist
|
|
70
|
+
```bash
|
|
71
|
+
mcserver whitelist remove Othecat35
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
- Stop a running server on current directory with sigterm
|
|
60
75
|
```bash
|
|
61
76
|
mcserver stop
|
|
62
77
|
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "4.5.0"
|
|
@@ -216,7 +216,40 @@ def main() -> int:
|
|
|
216
216
|
op_command.set_defaults(parser=op_command)
|
|
217
217
|
op_subcommands = op_command.add_subparsers(title="Subcommands")
|
|
218
218
|
|
|
219
|
-
#
|
|
219
|
+
# 'op grant'
|
|
220
|
+
op_grant_command = op_subcommands.add_parser(
|
|
221
|
+
"grant",
|
|
222
|
+
help="Grant player operator permission",
|
|
223
|
+
description="Add players to the whitelist.",
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
op_grant_command.set_defaults(command_name="op_grant")
|
|
227
|
+
op_grant_command.add_argument(
|
|
228
|
+
"players", nargs="+", type=str, help="List of player names or UUIDs"
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
op_grant_command.add_argument(
|
|
232
|
+
"--bypasses-player-limit",
|
|
233
|
+
action="store_true",
|
|
234
|
+
help="Player can bypass player limit",
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
op_grant_command.add_argument(
|
|
238
|
+
"--online-mode",
|
|
239
|
+
type=str,
|
|
240
|
+
choices=["true","false"],
|
|
241
|
+
metavar="Boolean",
|
|
242
|
+
help="The server's online mode (true/false)",
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
op_grant_command.add_argument(
|
|
246
|
+
"--permission-level",
|
|
247
|
+
type=int,
|
|
248
|
+
choices=[1, 2, 3, 4],
|
|
249
|
+
metavar="Level",
|
|
250
|
+
help="The perator permission level",
|
|
251
|
+
)
|
|
252
|
+
|
|
220
253
|
# 'op list'
|
|
221
254
|
op_list_command = op_subcommands.add_parser(
|
|
222
255
|
"list", help="List operator players", description="List all operator players."
|
|
@@ -334,7 +367,26 @@ def main() -> int:
|
|
|
334
367
|
whitelist_command.set_defaults(parser=whitelist_command)
|
|
335
368
|
whitelist_subcommands = whitelist_command.add_subparsers(title="Subcommands")
|
|
336
369
|
|
|
337
|
-
#
|
|
370
|
+
# 'whitelist add'
|
|
371
|
+
whitelist_add_command = whitelist_subcommands.add_parser(
|
|
372
|
+
"add",
|
|
373
|
+
help="Add players to the whitelist",
|
|
374
|
+
description="Add players to the whitelist.",
|
|
375
|
+
)
|
|
376
|
+
|
|
377
|
+
whitelist_add_command.set_defaults(command_name="whitelist_add")
|
|
378
|
+
whitelist_add_command.add_argument(
|
|
379
|
+
"players", nargs="+", type=str, help="List of player names or UUIDs"
|
|
380
|
+
)
|
|
381
|
+
|
|
382
|
+
whitelist_add_command.add_argument(
|
|
383
|
+
"--online-mode",
|
|
384
|
+
type=str,
|
|
385
|
+
choices=["true","false"],
|
|
386
|
+
metavar="Boolean",
|
|
387
|
+
help="The server's online mode (true/false)",
|
|
388
|
+
)
|
|
389
|
+
|
|
338
390
|
# 'whitelist list'
|
|
339
391
|
whitelist_list_command = whitelist_subcommands.add_parser(
|
|
340
392
|
"list",
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from argparse import Namespace
|
|
3
|
+
from uuid import UUID
|
|
4
|
+
|
|
5
|
+
from ..minecraft.player_identity import separate_uuids_and_names
|
|
6
|
+
from ..server_files.ops import OperatorPlayer
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def run(args: Namespace) -> int:
|
|
12
|
+
player_ids: list[str] = args.players
|
|
13
|
+
online_mode: str | None = args.online_mode
|
|
14
|
+
permission_level: int | None = args.permission_level
|
|
15
|
+
bypasses_player_limit: bool = args.bypasses_player_limit
|
|
16
|
+
|
|
17
|
+
# UUID vs name seperator
|
|
18
|
+
player_uuids, player_names = separate_uuids_and_names(player_ids)
|
|
19
|
+
uuids: set[UUID] = set(player_uuids)
|
|
20
|
+
names: set[str] = set(player_names)
|
|
21
|
+
|
|
22
|
+
player_uuids: list[UUID] = list(uuids)
|
|
23
|
+
player_names: list[str] = list(names)
|
|
24
|
+
|
|
25
|
+
is_online_mode: bool = True
|
|
26
|
+
if online_mode is None:
|
|
27
|
+
from ..server_files import server_properties
|
|
28
|
+
is_online_mode = server_properties.get_online_mode()
|
|
29
|
+
else:
|
|
30
|
+
is_online_mode = online_mode != "false"
|
|
31
|
+
|
|
32
|
+
if permission_level is None:
|
|
33
|
+
from ..server_files import server_properties
|
|
34
|
+
permission_level = server_properties.get_operator_permission_level()
|
|
35
|
+
|
|
36
|
+
operator_players: list[OperatorPlayer] = []
|
|
37
|
+
if is_online_mode:
|
|
38
|
+
from ..minecraft import api as minecraft_api
|
|
39
|
+
for player_uuid in player_uuids:
|
|
40
|
+
player_profile = minecraft_api.get_player_from_uuid(player_uuid)
|
|
41
|
+
operator_player: OperatorPlayer = {
|
|
42
|
+
"player_uuid": player_profile["player_uuid"],
|
|
43
|
+
"player_name": player_profile["player_name"],
|
|
44
|
+
"permission_level": permission_level,
|
|
45
|
+
"bypasses_player_limit": bypasses_player_limit
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
operator_players.append(operator_player)
|
|
49
|
+
if len(player_names) > 10:
|
|
50
|
+
logger.error("Cannot add more than 10 players by name at once.")
|
|
51
|
+
return 1
|
|
52
|
+
|
|
53
|
+
player_profiles = minecraft_api.get_players_from_names(player_names)
|
|
54
|
+
for player_profile in player_profiles:
|
|
55
|
+
operator_player: OperatorPlayer = {
|
|
56
|
+
"player_uuid": player_profile["player_uuid"],
|
|
57
|
+
"player_name": player_profile["player_name"],
|
|
58
|
+
"permission_level": permission_level,
|
|
59
|
+
"bypasses_player_limit": bypasses_player_limit
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
operator_players.append(operator_player)
|
|
63
|
+
else:
|
|
64
|
+
for player_uuid in uuids:
|
|
65
|
+
logger.error(f"Cannot add by UUID in offline mode: {player_uuid}, use name instead.")
|
|
66
|
+
return 1
|
|
67
|
+
|
|
68
|
+
from ..minecraft.player_identity import get_offline_player_identities
|
|
69
|
+
player_profiles = get_offline_player_identities(player_names)
|
|
70
|
+
for player_profile in player_profiles:
|
|
71
|
+
operator_player: OperatorPlayer = {
|
|
72
|
+
"player_uuid": player_profile["player_uuid"],
|
|
73
|
+
"player_name": player_profile["player_name"],
|
|
74
|
+
"permission_level": permission_level,
|
|
75
|
+
"bypasses_player_limit": bypasses_player_limit
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
operator_players.append(operator_player)
|
|
79
|
+
|
|
80
|
+
from ..server_files import ops
|
|
81
|
+
ops.upsert_players(operator_players)
|
|
82
|
+
|
|
83
|
+
from ..shared import pluralize
|
|
84
|
+
player_count: int = len(operator_players)
|
|
85
|
+
if player_count == 0:
|
|
86
|
+
logger.info("There are no player to be granted operator.")
|
|
87
|
+
return 0
|
|
88
|
+
|
|
89
|
+
player_list: list[str] = []
|
|
90
|
+
for player in operator_players:
|
|
91
|
+
player_list.append(f"{player['player_name']} ({player['player_uuid']})")
|
|
92
|
+
|
|
93
|
+
info_message = f"Granted {player_count} {pluralize('player', player_count)} operator with permission level {permission_level}"
|
|
94
|
+
|
|
95
|
+
if bypasses_player_limit:
|
|
96
|
+
info_message += " and can bypass player limit"
|
|
97
|
+
|
|
98
|
+
info_message += ":"
|
|
99
|
+
logger.info(info_message)
|
|
100
|
+
|
|
101
|
+
player_list.sort()
|
|
102
|
+
print("\n".join(player_list))
|
|
103
|
+
return 0
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from argparse import Namespace
|
|
3
|
-
from uuid import UUID
|
|
4
3
|
|
|
4
|
+
from ..minecraft.player_identity import separate_uuids_and_names
|
|
5
5
|
from ..server_files import ops
|
|
6
6
|
from ..shared import pluralize
|
|
7
7
|
|
|
@@ -9,18 +9,9 @@ logger = logging.getLogger(__name__)
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def run(args: Namespace) -> int:
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
player_uuids: list[UUID] = []
|
|
15
|
-
player_names: list[str] = []
|
|
16
|
-
for player in player_identifiers:
|
|
17
|
-
if len(player) > 16:
|
|
18
|
-
logger.debug(f"{player} is probably an UUID")
|
|
19
|
-
player_uuids.append(UUID(player))
|
|
20
|
-
else:
|
|
21
|
-
logger.debug(f"{player} is probably a name")
|
|
22
|
-
player_names.append(player)
|
|
12
|
+
player_ids: list[str] = args.players
|
|
23
13
|
|
|
14
|
+
player_uuids, player_names = separate_uuids_and_names(player_ids)
|
|
24
15
|
removed_players = ops.remove_players(player_uuids, player_names)
|
|
25
16
|
|
|
26
17
|
player_count: int = len(removed_players)
|
|
@@ -7,6 +7,7 @@ from mcserver import paths
|
|
|
7
7
|
from .. import config
|
|
8
8
|
from ..modrinth import apis as modrinth_apis
|
|
9
9
|
from ..modrinth.shared import SearchSortIndex
|
|
10
|
+
from ..modrinth.typings import Environment
|
|
10
11
|
from ..shared import (
|
|
11
12
|
default_configs,
|
|
12
13
|
format_number,
|
|
@@ -98,7 +99,10 @@ def run(args: Namespace) -> int:
|
|
|
98
99
|
logger.error("Vanilla does not support mods or plugin.")
|
|
99
100
|
return 1
|
|
100
101
|
|
|
101
|
-
|
|
102
|
+
if loader_name is not None:
|
|
103
|
+
project_label, _ = get_loader_context(loader_name)
|
|
104
|
+
else:
|
|
105
|
+
project_label = "project"
|
|
102
106
|
|
|
103
107
|
search_offset = search_limit * (page_number - 1)
|
|
104
108
|
search_facets = [
|
|
@@ -158,13 +162,13 @@ def run(args: Namespace) -> int:
|
|
|
158
162
|
project_author = f"by {hit['author_username']}"
|
|
159
163
|
|
|
160
164
|
environments: list[Environment] = hit["environments"]
|
|
161
|
-
if len(environments) == 0:
|
|
162
|
-
environments.append("No environment")
|
|
163
|
-
|
|
164
165
|
readable_environments: list[str] = []
|
|
165
166
|
for environment in environments:
|
|
166
167
|
readable_environments.append(project_environment_name(environment))
|
|
167
168
|
|
|
169
|
+
if len(readable_environments) == 0:
|
|
170
|
+
readable_environments.append("No environment")
|
|
171
|
+
|
|
168
172
|
print(f"{hit['project_name']} ({slug_or_id}) {project_author}")
|
|
169
173
|
print(
|
|
170
174
|
f"> Downloads: {format_number(hit['download_count'])} | Follows: {format_number(hit['follower_count'])}"
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from argparse import Namespace
|
|
3
|
+
from uuid import UUID
|
|
4
|
+
|
|
5
|
+
from ..minecraft.player_identity import separate_uuids_and_names
|
|
6
|
+
from ..server_files.whitelist import WhitelistedPlayer
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def run(args: Namespace) -> int:
|
|
12
|
+
player_ids: list[str] = args.players
|
|
13
|
+
online_mode: str | None = args.online_mode
|
|
14
|
+
|
|
15
|
+
# UUID vs name seperator
|
|
16
|
+
player_uuids, player_names = separate_uuids_and_names(player_ids)
|
|
17
|
+
uuids: set[UUID] = set(player_uuids)
|
|
18
|
+
names: set[str] = set(player_names)
|
|
19
|
+
|
|
20
|
+
player_uuids: list[UUID] = list(uuids)
|
|
21
|
+
player_names: list[str] = list(names)
|
|
22
|
+
|
|
23
|
+
is_online_mode: bool = True
|
|
24
|
+
if online_mode is None:
|
|
25
|
+
from ..server_files import server_properties
|
|
26
|
+
is_online_mode = server_properties.get_online_mode()
|
|
27
|
+
else:
|
|
28
|
+
is_online_mode = online_mode != "false"
|
|
29
|
+
|
|
30
|
+
whitelisted_players: list[WhitelistedPlayer] = []
|
|
31
|
+
if is_online_mode:
|
|
32
|
+
from ..minecraft import api as minecraft_api
|
|
33
|
+
for player_uuid in player_uuids:
|
|
34
|
+
player_profile = minecraft_api.get_player_from_uuid(player_uuid)
|
|
35
|
+
whitelisted_player: WhitelistedPlayer = {
|
|
36
|
+
"player_uuid": player_profile["player_uuid"],
|
|
37
|
+
"player_name": player_profile["player_name"]
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
whitelisted_players.append(whitelisted_player)
|
|
41
|
+
if len(player_names) > 10:
|
|
42
|
+
logger.error("Cannot add more than 10 players by name at once.")
|
|
43
|
+
return 1
|
|
44
|
+
|
|
45
|
+
player_profiles = minecraft_api.get_players_from_names(player_names)
|
|
46
|
+
for player_profile in player_profiles:
|
|
47
|
+
whitelisted_player: WhitelistedPlayer = {
|
|
48
|
+
"player_uuid": player_profile["player_uuid"],
|
|
49
|
+
"player_name": player_profile["player_name"]
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
whitelisted_players.append(whitelisted_player)
|
|
53
|
+
else:
|
|
54
|
+
for player_uuid in uuids:
|
|
55
|
+
logger.error(f"Cannot add by UUID in offline mode: {player_uuid}, use name instead.")
|
|
56
|
+
return 1
|
|
57
|
+
|
|
58
|
+
from ..minecraft.player_identity import get_offline_player_identities
|
|
59
|
+
whitelisted_players = get_offline_player_identities(player_names)
|
|
60
|
+
|
|
61
|
+
from ..server_files import whitelist
|
|
62
|
+
whitelist.upsert_players(whitelisted_players)
|
|
63
|
+
|
|
64
|
+
from ..shared import pluralize
|
|
65
|
+
player_count: int = len(whitelisted_players)
|
|
66
|
+
if player_count == 0:
|
|
67
|
+
logger.info("There are no whitelisted player.")
|
|
68
|
+
return 0
|
|
69
|
+
|
|
70
|
+
player_list: list[str] = []
|
|
71
|
+
for player in whitelisted_players:
|
|
72
|
+
player_list.append(f"{player['player_name']} ({player['player_uuid']})")
|
|
73
|
+
|
|
74
|
+
logger.info(
|
|
75
|
+
f"Added {player_count} {pluralize('player', player_count)} to the whitelist:"
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
player_list.sort()
|
|
79
|
+
print("\n".join(player_list))
|
|
80
|
+
|
|
81
|
+
return 0
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from argparse import Namespace
|
|
3
|
-
from uuid import UUID
|
|
4
3
|
|
|
4
|
+
from ..minecraft.player_identity import separate_uuids_and_names
|
|
5
5
|
from ..server_files import whitelist
|
|
6
6
|
from ..shared import pluralize
|
|
7
7
|
|
|
@@ -9,18 +9,9 @@ logger = logging.getLogger(__name__)
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def run(args: Namespace) -> int:
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
player_uuids: list[UUID] = []
|
|
15
|
-
player_names: list[str] = []
|
|
16
|
-
for player in player_identifiers:
|
|
17
|
-
if len(player) > 16:
|
|
18
|
-
logger.debug(f"{player} is probably an UUID")
|
|
19
|
-
player_uuids.append(UUID(player))
|
|
20
|
-
else:
|
|
21
|
-
logger.debug(f"{player} is probably a name")
|
|
22
|
-
player_names.append(player)
|
|
12
|
+
player_ids: list[str] = args.players
|
|
23
13
|
|
|
14
|
+
player_uuids, player_names = separate_uuids_and_names(player_ids)
|
|
24
15
|
removed_players = whitelist.remove_players(player_uuids, player_names)
|
|
25
16
|
|
|
26
17
|
player_count: int = len(removed_players)
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Modules
|
|
2
|
+
# Standard
|
|
3
|
+
import json
|
|
4
|
+
from typing import NotRequired
|
|
5
|
+
from uuid import UUID
|
|
6
|
+
|
|
7
|
+
from .. import networking
|
|
8
|
+
from ..constants import minecraft_api_url
|
|
9
|
+
from .player_identity import PlayerIdentity
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class GetPlayerError(Exception):
|
|
13
|
+
pass
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# TypedDict
|
|
17
|
+
class PlayerProfile(PlayerIdentity):
|
|
18
|
+
is_legacy: NotRequired[bool]
|
|
19
|
+
is_demo: NotRequired[bool]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# Functions
|
|
23
|
+
def get_player_from_name(player_name: str) -> PlayerIdentity:
|
|
24
|
+
response = networking.request(
|
|
25
|
+
f"{minecraft_api_url}/minecraft/profile/lookup/name/{player_name}"
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
if "json" not in response:
|
|
29
|
+
raise GetPlayerError("Response does not have JSON")
|
|
30
|
+
|
|
31
|
+
response_json = response["json"]
|
|
32
|
+
if not isinstance(response_json, dict):
|
|
33
|
+
raise TypeError("Response JSON is not a dictionary")
|
|
34
|
+
|
|
35
|
+
player_profile: PlayerProfile = {
|
|
36
|
+
"player_uuid": UUID(response_json["id"]),
|
|
37
|
+
"player_name": response_json["name"],
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if "legacy" in response_json:
|
|
41
|
+
player_profile["is_legacy"] = response_json["legacy"]
|
|
42
|
+
|
|
43
|
+
if "demo" in response_json:
|
|
44
|
+
player_profile["is_demo"] = response_json["demo"]
|
|
45
|
+
|
|
46
|
+
return player_profile
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def get_players_from_names(player_names: list[str] | str) -> list[PlayerProfile]:
|
|
50
|
+
if isinstance(player_names, str):
|
|
51
|
+
player_names = [player_names]
|
|
52
|
+
|
|
53
|
+
if len(player_names) > 10:
|
|
54
|
+
raise ValueError("Cannot query more than 10 player names at once")
|
|
55
|
+
|
|
56
|
+
data_payload = json.dumps(player_names).encode("utf-8")
|
|
57
|
+
response = networking.request(
|
|
58
|
+
f"{minecraft_api_url}/minecraft/profile/lookup/bulk/byname",
|
|
59
|
+
data=data_payload,
|
|
60
|
+
headers={"Content-Type": "application/json"},
|
|
61
|
+
method="POST",
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
if "json" not in response:
|
|
65
|
+
raise GetPlayerError("Response does not have JSON")
|
|
66
|
+
|
|
67
|
+
response_json = response["json"]
|
|
68
|
+
if not isinstance(response_json, list):
|
|
69
|
+
raise TypeError("Response JSON is not a list")
|
|
70
|
+
|
|
71
|
+
player_identities: list[PlayerProfile] = []
|
|
72
|
+
for player in response_json:
|
|
73
|
+
player_profile: PlayerProfile = {
|
|
74
|
+
"player_uuid": UUID(player["id"]),
|
|
75
|
+
"player_name": player["name"],
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if "legacy" in player:
|
|
79
|
+
player_profile["is_legacy"] = player["legacy"]
|
|
80
|
+
|
|
81
|
+
if "demo" in player:
|
|
82
|
+
player_profile["is_demo"] = player["demo"]
|
|
83
|
+
|
|
84
|
+
player_identities.append(player_profile)
|
|
85
|
+
|
|
86
|
+
return player_identities
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def get_player_from_uuid(player_uuid: UUID) -> PlayerProfile:
|
|
90
|
+
response = networking.request(
|
|
91
|
+
f"{minecraft_api_url}/minecraft/profile/lookup/{player_uuid}"
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
if "json" not in response:
|
|
95
|
+
raise GetPlayerError("Response does not have JSON")
|
|
96
|
+
|
|
97
|
+
response_json = response["json"]
|
|
98
|
+
if not isinstance(response_json, dict):
|
|
99
|
+
raise TypeError("Response JSON is not a dictionary")
|
|
100
|
+
|
|
101
|
+
player_profile: PlayerProfile = {
|
|
102
|
+
"player_uuid": UUID(response_json["id"]),
|
|
103
|
+
"player_name": response_json["name"],
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if "legacy" in response_json:
|
|
107
|
+
player_profile["is_legacy"] = response_json["legacy"]
|
|
108
|
+
|
|
109
|
+
if "demo" in response_json:
|
|
110
|
+
player_profile["is_demo"] = response_json["demo"]
|
|
111
|
+
|
|
112
|
+
return player_profile
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Modules
|
|
2
|
+
import hashlib
|
|
3
|
+
import logging
|
|
4
|
+
from typing import TypedDict
|
|
5
|
+
from uuid import UUID
|
|
6
|
+
|
|
7
|
+
logger = logging.getLogger(__name__)
|
|
8
|
+
|
|
9
|
+
# TypedDicts
|
|
10
|
+
class PlayerIdentity(TypedDict):
|
|
11
|
+
player_uuid: UUID
|
|
12
|
+
player_name: str
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def separate_uuids_and_names(player_ids: list[str]) -> tuple[list[UUID], list[str]]:
|
|
16
|
+
player_uuids: list[UUID] = []
|
|
17
|
+
player_names: list[str] = []
|
|
18
|
+
for player_id in player_ids:
|
|
19
|
+
try:
|
|
20
|
+
player_uuids.append(UUID(player_id))
|
|
21
|
+
except ValueError:
|
|
22
|
+
player_names.append(player_id)
|
|
23
|
+
|
|
24
|
+
return (player_uuids, player_names)
|
|
25
|
+
|
|
26
|
+
def get_offline_player_identities(
|
|
27
|
+
player_names: list[str] | str,
|
|
28
|
+
) -> list[PlayerIdentity]:
|
|
29
|
+
player_identities: list[PlayerIdentity] = []
|
|
30
|
+
for player_name in player_names:
|
|
31
|
+
offline_player = f"OfflinePlayer:{player_name}".encode()
|
|
32
|
+
player_uuid: UUID = UUID(hashlib.md5(offline_player).hexdigest())
|
|
33
|
+
logger.debug(f"Offline UUID for '{player_name}' is '{player_uuid}'")
|
|
34
|
+
player_identity: PlayerIdentity = {
|
|
35
|
+
"player_uuid": player_uuid,
|
|
36
|
+
"player_name": player_name,
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
player_identities.append(player_identity)
|
|
40
|
+
|
|
41
|
+
return player_identities
|
{mcserver_cli-4.4.0 → mcserver_cli-4.5.0}/src/mcserver/modrinth/apis/get_project_informations.py
RENAMED
|
@@ -163,7 +163,7 @@ def get_project_informations(project_ids: list[str] | str) -> list[ProjectInform
|
|
|
163
163
|
and requested_project_status not in shared.REQUESTED_PROJECT_STATUS
|
|
164
164
|
):
|
|
165
165
|
logger.warning(
|
|
166
|
-
f"Unknown requested_project_status
|
|
166
|
+
f"Unknown requested_project_status: {requested_project_status}"
|
|
167
167
|
)
|
|
168
168
|
|
|
169
169
|
project_information["requested_project_status"] = requested_project_status
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import logging
|
|
3
3
|
|
|
4
|
-
from mcserver.modrinth.typings.search_projects import DisclosureType
|
|
5
|
-
|
|
6
4
|
from ... import networking
|
|
7
5
|
from ...constants import modrinth_api_url
|
|
8
6
|
from .. import shared
|
|
9
7
|
from ..shared import SearchSortIndex
|
|
10
8
|
from ..typings import (
|
|
11
9
|
AllProjectType,
|
|
10
|
+
DisclosureType,
|
|
12
11
|
Environment,
|
|
13
12
|
EnvironmentSide,
|
|
14
13
|
ProjectType,
|