mcserver-cli 4.3.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.
Files changed (87) hide show
  1. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/CHANGELOG.md +27 -1
  2. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/NOTES.txt +4 -1
  3. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/PKG-INFO +30 -8
  4. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/README.md +29 -7
  5. mcserver_cli-4.5.0/src/mcserver/__init__.py +1 -0
  6. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/cli.py +70 -4
  7. mcserver_cli-4.5.0/src/mcserver/commands/op_grant.py +103 -0
  8. mcserver_cli-4.5.0/src/mcserver/commands/op_list.py +35 -0
  9. mcserver_cli-4.5.0/src/mcserver/commands/op_revoke.py +34 -0
  10. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/commands/search_projects.py +8 -4
  11. mcserver_cli-4.5.0/src/mcserver/commands/whitelist_add.py +81 -0
  12. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/commands/whitelist_list.py +11 -11
  13. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/commands/whitelist_remove.py +5 -12
  14. mcserver_cli-4.5.0/src/mcserver/minecraft/api.py +112 -0
  15. mcserver_cli-4.5.0/src/mcserver/minecraft/player_identity.py +41 -0
  16. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/modrinth/apis/get_project_informations.py +1 -1
  17. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/modrinth/apis/search_projects.py +1 -2
  18. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/modrinth/slug_index.py +12 -18
  19. mcserver_cli-4.5.0/src/mcserver/server_files/ops.py +170 -0
  20. mcserver_cli-4.5.0/src/mcserver/server_files/paths.py +5 -0
  21. mcserver_cli-4.5.0/src/mcserver/server_files/server_properties.py +42 -0
  22. mcserver_cli-4.5.0/src/mcserver/server_files/whitelist.py +150 -0
  23. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/shared.py +1 -1
  24. mcserver_cli-4.3.0/src/mcserver/__init__.py +0 -1
  25. mcserver_cli-4.3.0/src/mcserver/commands/op_grant.py +0 -9
  26. mcserver_cli-4.3.0/src/mcserver/commands/op_list.py +0 -32
  27. mcserver_cli-4.3.0/src/mcserver/commands/op_revoke.py +0 -9
  28. mcserver_cli-4.3.0/src/mcserver/commands/whitelist_add.py +0 -9
  29. mcserver_cli-4.3.0/src/mcserver/minecraft/api.py +0 -94
  30. mcserver_cli-4.3.0/src/mcserver/minecraft/player_identity.py +0 -21
  31. mcserver_cli-4.3.0/src/mcserver/modrinth/projects.py +0 -80
  32. mcserver_cli-4.3.0/src/mcserver/server_files/ops.py +0 -143
  33. mcserver_cli-4.3.0/src/mcserver/server_files/paths.py +0 -3
  34. mcserver_cli-4.3.0/src/mcserver/server_files/whitelist.py +0 -138
  35. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/.gitignore +0 -0
  36. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/CONTRIBUTING.md +0 -0
  37. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/LICENSE +0 -0
  38. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/legacy/mcserver_v2.0.0.py +0 -0
  39. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/pyproject.toml +0 -0
  40. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/__main__.py +0 -0
  41. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/__main__.py +0 -0
  42. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/app.py +0 -0
  43. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/caching.py +0 -0
  44. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/commands/__init__.py +0 -0
  45. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/commands/add_projects.py +0 -0
  46. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/commands/import_setup.py +0 -0
  47. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/commands/initialize_server.py +0 -0
  48. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/commands/list_projects.py +0 -0
  49. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/commands/print_help.py +0 -0
  50. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/commands/remove_projects.py +0 -0
  51. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/commands/server_status.py +0 -0
  52. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/commands/show_projects.py +0 -0
  53. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/commands/start_server.py +0 -0
  54. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/commands/stop_server.py +0 -0
  55. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/commands/update_projects.py +0 -0
  56. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/config.py +0 -0
  57. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/constants.py +0 -0
  58. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/fabricmc/meta.py +0 -0
  59. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/legacy_fabric/meta.py +0 -0
  60. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/metadata.py +0 -0
  61. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/modrinth/apis/__init__.py +0 -0
  62. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/modrinth/apis/get_project_versions.py +0 -0
  63. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/modrinth/constants.py +0 -0
  64. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/modrinth/modpack.py +0 -0
  65. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/modrinth/paths.py +0 -0
  66. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/modrinth/project_records.py +0 -0
  67. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/modrinth/shared.py +0 -0
  68. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/modrinth/typings/__init__.py +0 -0
  69. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/modrinth/typings/project_information.py +0 -0
  70. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/modrinth/typings/project_version.py +0 -0
  71. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/modrinth/typings/search_projects.py +0 -0
  72. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/modrinth/typings/shared.py +0 -0
  73. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/mojang/eula.py +0 -0
  74. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/mojang/manifest.py +0 -0
  75. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/mysterious.py +0 -0
  76. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/networking.py +0 -0
  77. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/papermc/api.py +0 -0
  78. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/paths.py +0 -0
  79. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/purpurmc/api.py +0 -0
  80. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/quiltmc/meta.py +0 -0
  81. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/resolver.py +0 -0
  82. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/server_files/banned_ips.py +0 -0
  83. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/server_files/banned_players.py +0 -0
  84. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/server_files/properties.py +0 -0
  85. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/server_files/usercaches.py +0 -0
  86. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/src/mcserver/state.py +0 -0
  87. {mcserver_cli-4.3.0 → mcserver_cli-4.5.0}/zip_app.py +0 -0
@@ -5,6 +5,30 @@ 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]
9
+
10
+ ## [4.5.0] - 2026-11-04
11
+
12
+ ### Added
13
+
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
25
+ - Player count to `whitelist list`
26
+
27
+ ### Fixes
28
+
29
+ - Wrong description for `whitelist remove`
30
+ - Fixing the wrong singular text in whitelist when no whitelisted player
31
+
8
32
  ## [4.3.0] - 2026-11-02
9
33
 
10
34
  ### Added
@@ -234,7 +258,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
234
258
  - Better mod conflict error
235
259
  - Faster mod resolving
236
260
 
237
- [unreleased]: https://github.com/Othecat35/MCServer/compare/v4.3.0...HEAD
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
263
+ [4.4.0]: https://github.com/Othecat35/MCServer/compare/v4.3.0...v4.4.0
238
264
  [4.3.0]: https://github.com/Othecat35/MCServer/compare/v4.2.0...v4.3.0
239
265
  [4.2.0]: https://github.com/Othecat35/MCServer/compare/v4.1.0...v4.2.0
240
266
  [4.1.0]: https://github.com/Othecat35/MCServer/compare/v4.0.0...v4.1.0
@@ -390,4 +390,7 @@ it can be the default config of all your new Minecraft server derived from
390
390
  and yea
391
391
 
392
392
 
393
- 2026-11-01, let's start not using AI?
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 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.0
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,8 +25,7 @@ Supported platforms:
25
25
  - JRE (depends on Minecraft version)
26
26
 
27
27
  ## How to install
28
- - Using pip:
29
- 1. Run `pip install mcserver-cli`
28
+ - Using pip: Just run `pip install mcserver-cli`
30
29
 
31
30
  - System-wide (Requires root):
32
31
  1. Download the `mcserver` script file from GitHub releases
@@ -44,28 +43,51 @@ Supported platforms:
44
43
  ## Usage
45
44
  - Initialize a server: `mcserver init [options]`
46
45
  - List operator players: `mcserver op list`
46
+ - Revoke operator players: `mcserver op revoke <players>`
47
+ - Search projects: `mcserver search [query] [options]`
47
48
  - Show information about projects: `mcserver show <projects>`
48
49
  - Start the server: `mcserver start`
49
- - Stop the server: `mcserver stop [--force-stop]`
50
+ - Stop the server: `mcserver stop`
50
51
  - List whitelisted players: `mcserver whitelist list`
52
+ - Remove whitelisted players: `mcserver whitelist remove <players>`
51
53
 
52
- ### Example
53
- - Create and start a Fabric 1.20.1 server on current directory
54
+ ### Examples
55
+ - Create and start a Fabric 1.20.1 server in the current directory
54
56
  ```bash
55
57
  mcserver init --game-version=1.20.1 --loader=fabric
56
58
  mcserver start
57
59
  ```
58
60
 
61
+ - Search top 50 Fabric mods for Minecraft 1.20.1 on modrinth
62
+ ```bash
63
+ mcserver search --loader=fabric --game-version=1.20.1 --limit=50
64
+ ```
65
+
59
66
  - List all operator and whitelisted players on current directory
60
67
  ```bash
61
68
  mcserver op list
62
69
  mcserver whitelist list
63
70
  ```
64
71
 
65
- - Stop (sigterm) a server on current directory
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
66
88
  ```bash
67
89
  mcserver stop
68
90
  ```
69
91
 
70
92
  ## Note
71
- This is a **Personal Project**, things may be unstable.
93
+ This is a **Personal Project** by Othecat35, so don't expect much from me :>
@@ -12,8 +12,7 @@ Supported platforms:
12
12
  - JRE (depends on Minecraft version)
13
13
 
14
14
  ## How to install
15
- - Using pip:
16
- 1. Run `pip install mcserver-cli`
15
+ - Using pip: Just run `pip install mcserver-cli`
17
16
 
18
17
  - System-wide (Requires root):
19
18
  1. Download the `mcserver` script file from GitHub releases
@@ -31,28 +30,51 @@ Supported platforms:
31
30
  ## Usage
32
31
  - Initialize a server: `mcserver init [options]`
33
32
  - List operator players: `mcserver op list`
33
+ - Revoke operator players: `mcserver op revoke <players>`
34
+ - Search projects: `mcserver search [query] [options]`
34
35
  - Show information about projects: `mcserver show <projects>`
35
36
  - Start the server: `mcserver start`
36
- - Stop the server: `mcserver stop [--force-stop]`
37
+ - Stop the server: `mcserver stop`
37
38
  - List whitelisted players: `mcserver whitelist list`
39
+ - Remove whitelisted players: `mcserver whitelist remove <players>`
38
40
 
39
- ### Example
40
- - Create and start a Fabric 1.20.1 server on current directory
41
+ ### Examples
42
+ - Create and start a Fabric 1.20.1 server in the current directory
41
43
  ```bash
42
44
  mcserver init --game-version=1.20.1 --loader=fabric
43
45
  mcserver start
44
46
  ```
45
47
 
48
+ - Search top 50 Fabric mods for Minecraft 1.20.1 on modrinth
49
+ ```bash
50
+ mcserver search --loader=fabric --game-version=1.20.1 --limit=50
51
+ ```
52
+
46
53
  - List all operator and whitelisted players on current directory
47
54
  ```bash
48
55
  mcserver op list
49
56
  mcserver whitelist list
50
57
  ```
51
58
 
52
- - Stop (sigterm) a server on current directory
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
53
75
  ```bash
54
76
  mcserver stop
55
77
  ```
56
78
 
57
79
  ## Note
58
- This is a **Personal Project**, things may be unstable.
80
+ This is a **Personal Project** by Othecat35, so don't expect much from me :>
@@ -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
- # op_grant and op_revoke is not going to be implemented in this version
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."
@@ -224,6 +257,18 @@ def main() -> int:
224
257
 
225
258
  op_list_command.set_defaults(command_name="op_list")
226
259
 
260
+ # 'op revoke'
261
+ op_revoke_command = op_subcommands.add_parser(
262
+ "revoke",
263
+ help="Revoke operator players permission",
264
+ description="Revoke operator players permission.",
265
+ )
266
+
267
+ op_revoke_command.set_defaults(command_name="op_revoke")
268
+ op_revoke_command.add_argument(
269
+ "players", nargs="+", type=str, help="List of player names or UUIDs"
270
+ )
271
+
227
272
  # 'search' command
228
273
  search_command = commands.add_parser(
229
274
  "search",
@@ -322,7 +367,26 @@ def main() -> int:
322
367
  whitelist_command.set_defaults(parser=whitelist_command)
323
368
  whitelist_subcommands = whitelist_command.add_subparsers(title="Subcommands")
324
369
 
325
- # whitelist_add and whitelist_remove is not going to be implemented in this version
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
+
326
390
  # 'whitelist list'
327
391
  whitelist_list_command = whitelist_subcommands.add_parser(
328
392
  "list",
@@ -336,11 +400,13 @@ def main() -> int:
336
400
  whitelist_remove_command = whitelist_subcommands.add_parser(
337
401
  "remove",
338
402
  help="Remove players from the whitelist",
339
- description="List all whitelisted players.",
403
+ description="Remove players from the whitelist.",
340
404
  )
341
405
 
342
406
  whitelist_remove_command.set_defaults(command_name="whitelist_remove")
343
- whitelist_remove_command.add_argument("players", nargs="+", type=str, help="List of player names or UUIDs")
407
+ whitelist_remove_command.add_argument(
408
+ "players", nargs="+", type=str, help="List of player names or UUIDs"
409
+ )
344
410
 
345
411
  args = parser.parse_args()
346
412
  return args.func(args)
@@ -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
@@ -0,0 +1,35 @@
1
+ import logging
2
+ from argparse import Namespace
3
+
4
+ from ..server_files import ops
5
+ from ..shared import pluralize
6
+
7
+ logger = logging.getLogger(__name__)
8
+
9
+
10
+ def run(args: Namespace) -> int:
11
+ ops_file = ops.ops_file_path
12
+ if not ops_file.exists():
13
+ logger.error(f"Operator file '{ops.ops_file_path}' not found.")
14
+ return 1
15
+
16
+ operator_players = ops.list_players()
17
+
18
+ player_count = len(operator_players)
19
+ if player_count == 0:
20
+ logger.info("There's no operator player.")
21
+ return 0
22
+
23
+ player_list: list[str] = []
24
+ for player in operator_players:
25
+ player_list.append(
26
+ f"{player['player_name']} ({player['player_uuid']}) Level: {player['permission_level']}"
27
+ )
28
+
29
+ logger.info(
30
+ f"There {pluralize('is', player_count)} {player_count} {pluralize('operator', player_count)}:"
31
+ )
32
+
33
+ player_list.sort()
34
+ print("\n".join(player_list))
35
+ return 0
@@ -0,0 +1,34 @@
1
+ import logging
2
+ from argparse import Namespace
3
+
4
+ from ..minecraft.player_identity import separate_uuids_and_names
5
+ from ..server_files import ops
6
+ from ..shared import pluralize
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+
11
+ def run(args: Namespace) -> int:
12
+ player_ids: list[str] = args.players
13
+
14
+ player_uuids, player_names = separate_uuids_and_names(player_ids)
15
+ removed_players = ops.remove_players(player_uuids, player_names)
16
+
17
+ player_count: int = len(removed_players)
18
+ if player_count == 0:
19
+ logger.info("No matching player found.")
20
+ return 0
21
+
22
+ player_list: list[str] = []
23
+ for player in removed_players:
24
+ player_list.append(
25
+ f"{player['player_name']} ({player['player_uuid']}) Level: {player['permission_level']}"
26
+ )
27
+
28
+ logger.info(
29
+ f"There {pluralize('is', player_count)} {player_count} operator {pluralize('player', player_count)} that {pluralize('is', player_count)} removed:"
30
+ )
31
+
32
+ player_list.sort()
33
+ print("\n".join(player_list))
34
+ return 0
@@ -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
- project_label, _ = get_loader_context(loader_name)
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,5 +1,5 @@
1
- import argparse
2
1
  import logging
2
+ from argparse import Namespace
3
3
 
4
4
  from ..server_files import whitelist
5
5
  from ..shared import pluralize
@@ -7,26 +7,26 @@ from ..shared import pluralize
7
7
  logger = logging.getLogger(__name__)
8
8
 
9
9
 
10
- def run(args: argparse.Namespace) -> int:
10
+ def run(args: Namespace) -> int:
11
11
  whitelist_file = whitelist.whitelist_file_path
12
12
  if not whitelist_file.exists():
13
- logger.error(f"Whitelist file ({whitelist_file}) does not exist!")
13
+ logger.error(f"Whitelist file ({whitelist_file}) not found!")
14
14
  return 1
15
15
 
16
16
  whitelisted_players = whitelist.list_players()
17
17
 
18
+ player_count: int = len(whitelisted_players)
19
+ if player_count == 0:
20
+ logger.info("There are no whitelisted player.")
21
+ return 0
22
+
18
23
  player_list: list[str] = []
19
24
  for player in whitelisted_players:
20
25
  player_list.append(f"{player['player_name']} ({player['player_uuid']})")
21
26
 
22
- player_count: int = len(player_list)
23
- if player_count == 0:
24
- logger.info("There are no whitelisted players.")
25
- return 0
26
- else:
27
- logger.info(
28
- f"There {pluralize('is', player_count)} whitelisted {pluralize('player', player_count)}:"
29
- )
27
+ logger.info(
28
+ f"There {pluralize('is', player_count)} {player_count} whitelisted {pluralize('player', player_count)}:"
29
+ )
30
30
 
31
31
  player_list.sort()
32
32
  print("\n".join(player_list))
@@ -1,24 +1,17 @@
1
- import argparse
2
1
  import logging
2
+ from argparse import Namespace
3
3
 
4
+ from ..minecraft.player_identity import separate_uuids_and_names
4
5
  from ..server_files import whitelist
5
6
  from ..shared import pluralize
6
7
 
7
8
  logger = logging.getLogger(__name__)
8
9
 
9
- def run(args: argparse.Namespace) -> int:
10
- player_identifiers: list[str] = args.players
11
10
 
12
- player_uuids: list[str] = []
13
- player_names: list[str] = []
14
- for player in player_identifiers:
15
- if len(player) > 16:
16
- logger.debug(f"{player} is probably an UUID")
17
- player_uuids.append(player)
18
- else:
19
- logger.debug(f"{player} is probably a name")
20
- player_names.append(player)
11
+ def run(args: Namespace) -> int:
12
+ player_ids: list[str] = args.players
21
13
 
14
+ player_uuids, player_names = separate_uuids_and_names(player_ids)
22
15
  removed_players = whitelist.remove_players(player_uuids, player_names)
23
16
 
24
17
  player_count: int = len(removed_players)