mcserver-cli 4.2.0__py3-none-any.whl → 4.3.0__py3-none-any.whl

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 (34) hide show
  1. mcserver/__init__.py +1 -1
  2. mcserver/cli.py +124 -110
  3. mcserver/commands/__init__.py +24 -24
  4. mcserver/commands/{add.py → add_projects.py} +18 -11
  5. mcserver/commands/import_setup.py +1 -1
  6. mcserver/commands/{init.py → initialize_server.py} +1 -1
  7. mcserver/commands/list_projects.py +1 -1
  8. mcserver/commands/op_grant.py +1 -1
  9. mcserver/commands/op_list.py +1 -1
  10. mcserver/commands/op_revoke.py +1 -1
  11. mcserver/commands/print_help.py +1 -1
  12. mcserver/commands/remove_projects.py +1 -1
  13. mcserver/commands/{search.py → search_projects.py} +6 -10
  14. mcserver/commands/server_status.py +1 -1
  15. mcserver/commands/{show.py → show_projects.py} +1 -1
  16. mcserver/commands/{start.py → start_server.py} +1 -1
  17. mcserver/commands/{stop.py → stop_server.py} +1 -1
  18. mcserver/commands/update_projects.py +1 -1
  19. mcserver/commands/whitelist_add.py +1 -1
  20. mcserver/commands/whitelist_list.py +10 -9
  21. mcserver/commands/whitelist_remove.py +31 -25
  22. mcserver/config.py +6 -0
  23. mcserver/metadata.py +11 -3
  24. mcserver/modrinth/apis/get_project_informations.py +22 -15
  25. mcserver/modrinth/apis/get_project_versions.py +4 -1
  26. mcserver/modrinth/project_records.py +1 -0
  27. mcserver/resolver.py +1 -3
  28. mcserver/server_files/paths.py +3 -0
  29. mcserver/server_files/whitelist.py +102 -148
  30. {mcserver_cli-4.2.0.dist-info → mcserver_cli-4.3.0.dist-info}/METADATA +1 -1
  31. {mcserver_cli-4.2.0.dist-info → mcserver_cli-4.3.0.dist-info}/RECORD +34 -33
  32. {mcserver_cli-4.2.0.dist-info → mcserver_cli-4.3.0.dist-info}/WHEEL +0 -0
  33. {mcserver_cli-4.2.0.dist-info → mcserver_cli-4.3.0.dist-info}/entry_points.txt +0 -0
  34. {mcserver_cli-4.2.0.dist-info → mcserver_cli-4.3.0.dist-info}/licenses/LICENSE +0 -0
mcserver/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "4.2.0"
1
+ __version__ = "4.3.0"
mcserver/cli.py CHANGED
@@ -1,115 +1,119 @@
1
- def main() -> int:
2
- import argparse
3
- import sys
4
- from types import FunctionType
5
-
6
- from . import __version__
7
- from .modrinth.shared import search_sort_index
8
- from .shared import loader_list
9
-
10
- def bound_int(min_integer: int, max_integer: int | None = None) -> FunctionType:
11
- def parse(cli_string: str) -> int:
12
- try:
13
- integer = int(cli_string)
14
- except ValueError:
15
- raise argparse.ArgumentTypeError(f"{cli_string} is not an integer")
16
-
17
- if integer < min_integer:
18
- raise argparse.ArgumentTypeError(
19
- f"{integer} must be higher than or equal to {min_integer}"
20
- )
21
- if max_integer is not None and integer > max_integer:
22
- raise argparse.ArgumentTypeError(
23
- f"{integer} must be between {min_integer} and {max_integer} (inclusive)"
24
- )
25
- return integer
26
-
27
- return parse
28
-
29
- def command_function(args: argparse.Namespace) -> int:
30
- command_name: str = args.command_name
31
-
32
- match command_name:
33
- case "add":
34
- from .commands import add
35
-
36
- return add(args)
37
- case "import":
38
- from .commands import import_setup
39
-
40
- return import_setup(args)
41
- case "help":
42
- from .commands import print_help
43
-
44
- return print_help(args)
45
- case "init":
46
- from .commands import init
47
-
48
- return init(args)
49
- case "list":
50
- from .commands import list_projects
51
-
52
- return list_projects(args)
53
- case "op_grant":
54
- from .commands import op_grant
55
-
56
- return op_grant(args)
57
- case "op_list":
58
- from .commands import op_list
59
-
60
- return op_list(args)
61
- case "op_revoke":
62
- from .commands import op_revoke
63
-
64
- return op_revoke(args)
65
- case "remove":
66
- from .commands import remove_projects
67
-
68
- return remove_projects(args)
69
- case "search":
70
- from .commands import search
71
-
72
- return search(args)
73
- case "show":
74
- from .commands import show
75
-
76
- return show(args)
77
- case "start":
78
- from .commands import start
79
-
80
- return start(args)
81
- case "status":
82
- from .commands import server_status
83
-
84
- return server_status(args)
85
- case "stop":
86
- from .commands import stop
87
-
88
- return stop(args)
89
- case "update":
90
- from .commands import update_projects
91
-
92
- return update_projects(args)
93
- case "whitelist_add":
94
- from .commands import whitelist_add
95
-
96
- return whitelist_add(args)
97
- case "whitelist_list":
98
- from .commands import whitelist_list
99
-
100
- return whitelist_list(args)
101
- case "whitelist_remove":
102
- from .commands import whitelist_remove
103
-
104
- return whitelist_remove(args)
105
- case _:
106
- import logging as log
107
-
108
- log.error(f"Unknown command: {command_name}")
109
- return 1
1
+ import argparse
2
+ import sys
3
+ from types import FunctionType
110
4
 
111
- # Parser Setup
5
+ from . import __version__
6
+ from .modrinth.shared import search_sort_index
7
+ from .shared import loader_list
8
+
9
+
10
+ def bound_int(min_integer: int, max_integer: int | None = None) -> FunctionType:
11
+ def parse(cli_string: str) -> int:
12
+ try:
13
+ integer = int(cli_string)
14
+ except ValueError:
15
+ raise argparse.ArgumentTypeError(f"{cli_string} is not an integer")
16
+
17
+ if integer < min_integer:
18
+ raise argparse.ArgumentTypeError(
19
+ f"{integer} must be higher than or equal to {min_integer}"
20
+ )
21
+ if max_integer is not None and integer > max_integer:
22
+ raise argparse.ArgumentTypeError(
23
+ f"{integer} must be between {min_integer} and {max_integer} (inclusive)"
24
+ )
25
+ return integer
26
+
27
+ return parse
28
+
29
+
30
+ def command_function(args: argparse.Namespace) -> int:
31
+ command_name: str = args.command_name
32
+
33
+ match command_name:
34
+ case "add":
35
+ from .commands import add_projects
36
+
37
+ return add_projects(args)
38
+ case "import":
39
+ from .commands import import_setup
40
+
41
+ return import_setup(args)
42
+ case "help":
43
+ from .commands import print_help
44
+
45
+ return print_help(args)
46
+ case "init":
47
+ from .commands import initialize_server
48
+
49
+ return initialize_server(args)
50
+ case "list":
51
+ from .commands import list_projects
52
+
53
+ return list_projects(args)
54
+ case "op_grant":
55
+ from .commands import op_grant
56
+
57
+ return op_grant(args)
58
+ case "op_list":
59
+ from .commands import op_list
60
+
61
+ return op_list(args)
62
+ case "op_revoke":
63
+ from .commands import op_revoke
64
+
65
+ return op_revoke(args)
66
+ case "remove":
67
+ from .commands import remove_projects
68
+
69
+ return remove_projects(args)
70
+ case "search":
71
+ from .commands import search_projects
112
72
 
73
+ return search_projects(args)
74
+ case "show":
75
+ from .commands import show_projects
76
+
77
+ return show_projects(args)
78
+ case "start":
79
+ from .commands import start_server
80
+
81
+ return start_server(args)
82
+ case "status":
83
+ from .commands import server_status
84
+
85
+ return server_status(args)
86
+ case "stop":
87
+ from .commands import stop_server
88
+
89
+ return stop_server(args)
90
+ case "update":
91
+ from .commands import update_projects
92
+
93
+ return update_projects(args)
94
+ case "whitelist_add":
95
+ from .commands import whitelist_add
96
+
97
+ return whitelist_add(args)
98
+ case "whitelist_list":
99
+ from .commands import whitelist_list
100
+
101
+ return whitelist_list(args)
102
+ case "whitelist_remove":
103
+ from .commands import whitelist_remove
104
+
105
+ return whitelist_remove(args)
106
+ case _:
107
+ import logging
108
+
109
+ logger = logging.getLogger(__name__)
110
+
111
+ logger.error(f"Unknown command: {command_name}")
112
+ return 1
113
+
114
+
115
+ def main() -> int:
116
+ # Parser Setup
113
117
  parser = argparse.ArgumentParser(
114
118
  prog="mcserver",
115
119
  description="A CLI tool for managing Minecraft: Java Edition servers.",
@@ -328,5 +332,15 @@ def main() -> int:
328
332
 
329
333
  whitelist_list_command.set_defaults(command_name="whitelist_list")
330
334
 
335
+ # 'whitelist remove'
336
+ whitelist_remove_command = whitelist_subcommands.add_parser(
337
+ "remove",
338
+ help="Remove players from the whitelist",
339
+ description="List all whitelisted players.",
340
+ )
341
+
342
+ 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")
344
+
331
345
  args = parser.parse_args()
332
346
  return args.func(args)
@@ -1,37 +1,37 @@
1
- from .add import add
2
- from .import_setup import main as import_setup
3
- from .init import init
4
- from .list_projects import main as list_projects
5
- from .op_grant import main as op_grant
6
- from .op_list import main as op_list
7
- from .op_revoke import main as op_revoke
8
- from .print_help import main as print_help
9
- from .remove_projects import main as remove_projects
10
- from .search import search
11
- from .server_status import main as server_status
12
- from .show import show
13
- from .start import start
14
- from .stop import stop
15
- from .update_projects import main as update_projects
16
- from .whitelist_add import main as whitelist_add
17
- from .whitelist_list import main as whitelist_list
18
- from .whitelist_remove import main as whitelist_remove
1
+ from .add_projects import run as add_projects
2
+ from .import_setup import run as import_setup
3
+ from .initialize_server import run as initialize_server
4
+ from .list_projects import run as list_projects
5
+ from .op_grant import run as op_grant
6
+ from .op_list import run as op_list
7
+ from .op_revoke import run as op_revoke
8
+ from .print_help import run as print_help
9
+ from .remove_projects import run as remove_projects
10
+ from .search_projects import run as search_projects
11
+ from .server_status import run as server_status
12
+ from .show_projects import run as show_projects
13
+ from .start_server import run as start_server
14
+ from .stop_server import run as stop_server
15
+ from .update_projects import run as update_projects
16
+ from .whitelist_add import run as whitelist_add
17
+ from .whitelist_list import run as whitelist_list
18
+ from .whitelist_remove import run as whitelist_remove
19
19
 
20
20
  __all__ = [
21
- "add",
21
+ "add_projects",
22
22
  "import_setup",
23
- "init",
23
+ "initialize_server",
24
24
  "list_projects",
25
25
  "op_grant",
26
26
  "op_list",
27
27
  "op_revoke",
28
28
  "print_help",
29
29
  "remove_projects",
30
- "search",
30
+ "search_projects",
31
31
  "server_status",
32
- "show",
33
- "start",
34
- "stop",
32
+ "show_projects",
33
+ "start_server",
34
+ "stop_server",
35
35
  "update_projects",
36
36
  "whitelist_add",
37
37
  "whitelist_list",
@@ -3,7 +3,7 @@ from argparse import Namespace
3
3
 
4
4
  from .. import config, paths, shared
5
5
  from ..modrinth import apis as modrinth_apis
6
- from ..modrinth import project_records, slug_index
6
+ from ..modrinth import project_records
7
7
  from ..resolver import (
8
8
  Dependency,
9
9
  human_to_resolver,
@@ -13,13 +13,18 @@ from ..resolver import (
13
13
 
14
14
  logger = logging.getLogger(__name__)
15
15
 
16
- def add(args: Namespace) -> int:
16
+
17
+ def run(args: Namespace) -> int:
17
18
  projects: list[str] = args.projects
18
19
 
19
20
  if not (paths.configs_dir / "server.json").exists():
20
- logger.error("Configuration file for server does not exist, is server initialized?")
21
+ logger.error(
22
+ "Configuration file for server does not exist, is server initialized?"
23
+ )
21
24
 
22
- server_config = config.read_config("server", shared.default_configs["server"]["format_version"])
25
+ server_config = config.read_config(
26
+ "server", shared.default_configs["server"]["format_version"]
27
+ )
23
28
  game_version = server_config["game_version"]
24
29
  loader_name = server_config["loader"]["name"]
25
30
 
@@ -35,11 +40,12 @@ def add(args: Namespace) -> int:
35
40
  dependencies: list[Dependency] = []
36
41
  if project_records.record_exists(project_id):
37
42
  project_record = project_records.read_record(project_id)
38
- for dependency_id, dependency_type in project_record["dependencies"].items():
39
- dependencies.append({
40
- "project_id": dependency_id,
41
- "dependency_type": dependency_type
42
- })
43
+ for dependency_id, dependency_type in project_record[
44
+ "dependencies"
45
+ ].items():
46
+ dependencies.append(
47
+ {"project_id": dependency_id, "dependency_type": dependency_type}
48
+ )
43
49
 
44
50
  else:
45
51
  project_version = modrinth_apis.get_project_versions(
@@ -64,7 +70,9 @@ def add(args: Namespace) -> int:
64
70
 
65
71
  return human_to_resolver(dependencies)
66
72
 
67
- resolved_dependencies = resolve_dependencies(projects, get_dependencies, required_only)
73
+ resolved_dependencies = resolve_dependencies(
74
+ projects, get_dependencies, required_only
75
+ )
68
76
  print(resolved_dependencies)
69
77
  return 0
70
78
 
@@ -154,7 +162,6 @@ def add(args: Namespace) -> int:
154
162
  # ]
155
163
  # return a
156
164
 
157
-
158
165
  # server_config = config.read_config(
159
166
  # "server", shared.default_configs["server"]["format_version"]
160
167
  # )
@@ -1,7 +1,7 @@
1
1
  from argparse import Namespace
2
2
 
3
3
 
4
- def main(args: Namespace) -> int:
4
+ def run(args: Namespace) -> int:
5
5
  file: str = args.file
6
6
  import logging as log
7
7
 
@@ -1,7 +1,7 @@
1
1
  from argparse import Namespace
2
2
 
3
3
 
4
- def init(args: Namespace) -> int:
4
+ def run(args: Namespace) -> int:
5
5
  from ..modrinth.shared import SearchSortIndex
6
6
 
7
7
  # CLI Arguments
@@ -1,7 +1,7 @@
1
1
  from argparse import Namespace
2
2
 
3
3
 
4
- def main(args: Namespace) -> int:
4
+ def run(args: Namespace) -> int:
5
5
  import logging as log
6
6
 
7
7
  log.error("Command is not implemented yet.")
@@ -1,7 +1,7 @@
1
1
  from argparse import Namespace
2
2
 
3
3
 
4
- def main(args: Namespace) -> int:
4
+ def run(args: Namespace) -> int:
5
5
  players: list[str] = args.players
6
6
  import logging as log
7
7
 
@@ -1,7 +1,7 @@
1
1
  from argparse import Namespace
2
2
 
3
3
 
4
- def main(args: Namespace) -> int:
4
+ def run(args: Namespace) -> int:
5
5
  import logging as log
6
6
 
7
7
  from ..server_files import ops
@@ -1,7 +1,7 @@
1
1
  from argparse import Namespace
2
2
 
3
3
 
4
- def main(args: Namespace) -> int:
4
+ def run(args: Namespace) -> int:
5
5
  players: list[str] = args.players
6
6
  import logging as log
7
7
 
@@ -1,7 +1,7 @@
1
1
  import argparse
2
2
 
3
3
 
4
- def main(args: argparse.Namespace) -> int:
4
+ def run(args: argparse.Namespace) -> int:
5
5
  parser: argparse.ArgumentParser = args.parser
6
6
  parser.print_help()
7
7
  return 0
@@ -1,7 +1,7 @@
1
1
  from argparse import Namespace
2
2
 
3
3
 
4
- def main(args: Namespace) -> int:
4
+ def run(args: Namespace) -> int:
5
5
  import logging as log
6
6
 
7
7
  log.error("Command is not implemented yet.")
@@ -18,7 +18,7 @@ from ..shared import (
18
18
  logger = logging.getLogger(__name__)
19
19
 
20
20
 
21
- def search(args: Namespace) -> int:
21
+ def run(args: Namespace) -> int:
22
22
  search_query: list[str] = args.search_query
23
23
  search_limit: int | None = args.search_limit
24
24
  page_number: int = args.page_number
@@ -112,7 +112,7 @@ def search(args: Namespace) -> int:
112
112
  search_facets.append([f"project_type:{project_label}"])
113
113
  search_facets.append([f"categories:{loader_name}"])
114
114
  else:
115
- search_facets.append(["project_type:mod","project_type:plugin"])
115
+ search_facets.append(["project_type:mod", "project_type:plugin"])
116
116
 
117
117
  search_info = f"Searching {pluralize(project_label, search_limit)}"
118
118
  if search_query:
@@ -165,17 +165,13 @@ def search(args: Namespace) -> int:
165
165
  for environment in environments:
166
166
  readable_environments.append(project_environment_name(environment))
167
167
 
168
+ print(f"{hit['project_name']} ({slug_or_id}) {project_author}")
168
169
  print(
169
- f"{hit['project_name']} ({slug_or_id}) {project_author}"
170
- )
171
- print(f"> Downloads: {format_number(hit['download_count'])} | Follows: {format_number(hit['follower_count'])}")
172
- print(
173
- f"> {', '.join(readable_environments)}"
170
+ f"> Downloads: {format_number(hit['download_count'])} | Follows: {format_number(hit['follower_count'])}"
174
171
  )
172
+ print(f"> {', '.join(readable_environments)}")
175
173
  print(f"> https://modrinth.com/{hit['all_project_types'][0]}/{slug_or_id}")
176
- print(
177
- f" {hit['short_description']}"
178
- )
174
+ print(f" {hit['short_description']}")
179
175
 
180
176
  if (count + 1) < len(search_hits):
181
177
  print() # Print newline for readability
@@ -1,7 +1,7 @@
1
1
  from argparse import Namespace
2
2
 
3
3
 
4
- def main(args: Namespace) -> int:
4
+ def run(args: Namespace) -> int:
5
5
  import logging as log
6
6
 
7
7
  log.error("Command is not implemented yet.")
@@ -1,7 +1,7 @@
1
1
  from argparse import Namespace
2
2
 
3
3
 
4
- def show(args: Namespace) -> int:
4
+ def run(args: Namespace) -> int:
5
5
  projects: list[str] = args.projects
6
6
 
7
7
  import logging
@@ -1,7 +1,7 @@
1
1
  from argparse import Namespace
2
2
 
3
3
 
4
- def start(args: Namespace) -> int:
4
+ def run(args: Namespace) -> int:
5
5
  import logging as log
6
6
 
7
7
  from .. import state
@@ -1,7 +1,7 @@
1
1
  from argparse import Namespace
2
2
 
3
3
 
4
- def stop(args: Namespace) -> int:
4
+ def run(args: Namespace) -> int:
5
5
  import logging as log
6
6
  import os
7
7
  from signal import SIGTERM
@@ -1,7 +1,7 @@
1
1
  from argparse import Namespace
2
2
 
3
3
 
4
- def main(args: Namespace) -> int:
4
+ def run(args: Namespace) -> int:
5
5
  import logging as log
6
6
 
7
7
  log.error("Command is not implemented yet.")
@@ -1,7 +1,7 @@
1
1
  from argparse import Namespace
2
2
 
3
3
 
4
- def main(args: Namespace) -> int:
4
+ def run(args: Namespace) -> int:
5
5
  players: list[str] = args.players
6
6
  import logging as log
7
7
 
@@ -1,18 +1,19 @@
1
1
  import argparse
2
+ import logging
2
3
 
4
+ from ..server_files import whitelist
5
+ from ..shared import pluralize
3
6
 
4
- def main(args: argparse.Namespace) -> int:
5
- import logging as log
7
+ logger = logging.getLogger(__name__)
6
8
 
7
- from ..server_files import whitelist
8
- from ..shared import pluralize
9
9
 
10
- whitelist_file = whitelist.whitelist_file
10
+ def run(args: argparse.Namespace) -> int:
11
+ whitelist_file = whitelist.whitelist_file_path
11
12
  if not whitelist_file.exists():
12
- log.error(f"Whitelist file ({whitelist_file}) does not exist!")
13
+ logger.error(f"Whitelist file ({whitelist_file}) does not exist!")
13
14
  return 1
14
15
 
15
- whitelisted_players = whitelist.list_entries()
16
+ whitelisted_players = whitelist.list_players()
16
17
 
17
18
  player_list: list[str] = []
18
19
  for player in whitelisted_players:
@@ -20,10 +21,10 @@ def main(args: argparse.Namespace) -> int:
20
21
 
21
22
  player_count: int = len(player_list)
22
23
  if player_count == 0:
23
- log.info("There are no whitelisted players.")
24
+ logger.info("There are no whitelisted players.")
24
25
  return 0
25
26
  else:
26
- log.info(
27
+ logger.info(
27
28
  f"There {pluralize('is', player_count)} whitelisted {pluralize('player', player_count)}:"
28
29
  )
29
30
 
@@ -1,33 +1,39 @@
1
- from argparse import Namespace
1
+ import argparse
2
+ import logging
2
3
 
4
+ from ..server_files import whitelist
5
+ from ..shared import pluralize
3
6
 
4
- def main(args: Namespace) -> int:
5
- players: list[str] = args.players
6
- import logging as log
7
+ logger = logging.getLogger(__name__)
7
8
 
8
- # from uuid import UUID
9
- # from ..server_files.whitelist import remove_players
10
- # from ..minecraft.player_identity import PlayerID
9
+ def run(args: argparse.Namespace) -> int:
10
+ player_identifiers: list[str] = args.players
11
11
 
12
- log.error("Command is not implemented yet.")
13
- # player_ids: list[PlayerID] = []
14
- # for player in players:
15
- # try:
16
- # UUID(player)
17
- # log.debug(f"{player} is likely an UUID")
18
- # player_id: PlayerID = {"player_uuid": player}
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)
19
21
 
20
- # player_ids.append(player_id)
21
- # except ValueError:
22
- # log.debug(f"{player} is likely a name")
23
- # player_id: PlayerID = {"player_name": player}
22
+ removed_players = whitelist.remove_players(player_uuids, player_names)
24
23
 
25
- # player_ids.append(player_id)
24
+ player_count: int = len(removed_players)
25
+ if player_count == 0:
26
+ logger.info("No matching player found.")
27
+ return 0
26
28
 
27
- # try:
28
- # remove_players(player_ids)
29
- # except FileNotFoundError as error:
30
- # log.error(error)
31
- # return 1
29
+ player_list: list[str] = []
30
+ for player in removed_players:
31
+ player_list.append(f"{player['player_name']} ({player['player_uuid']})")
32
32
 
33
- return 1
33
+ logger.info(
34
+ f"There {pluralize('is', player_count)} {player_count} {pluralize('player', player_count)} that {pluralize('is', player_count)} removed:"
35
+ )
36
+
37
+ player_list.sort()
38
+ print("\n".join(player_list))
39
+ return 0
mcserver/config.py CHANGED
@@ -2,11 +2,14 @@
2
2
  # Standard
3
3
  import copy
4
4
  import json
5
+ import logging
5
6
  from typing import Any
6
7
 
7
8
  # MCServer
8
9
  from .paths import configs_dir
9
10
 
11
+ logger = logging.getLogger(__name__)
12
+
10
13
 
11
14
  class ConfigVersionError(Exception):
12
15
  pass
@@ -38,6 +41,8 @@ def write_config(
38
41
 
39
42
  configuration_data.update(copy.deepcopy(config_data))
40
43
  config_json = json.dumps(configuration_data, indent=2)
44
+
45
+ logger.debug(f"Writing configuration data for {config_name}")
41
46
  config_path.write_text(config_json)
42
47
 
43
48
 
@@ -60,6 +65,7 @@ def read_config(config_name: str, current_format_version: int) -> dict[str, Any]
60
65
  f"Configuration file for '{config_name}' does not exist"
61
66
  )
62
67
 
68
+ logger.debug(f"Reading configuration for {config_name}")
63
69
  config_json = config_path.read_text()
64
70
  config_data = json.loads(config_json)
65
71
 
mcserver/metadata.py CHANGED
@@ -8,7 +8,10 @@ from .paths import metadata_file
8
8
 
9
9
  metadata_format_version = 1
10
10
 
11
- class MetadataFormatVersionError(Exception): pass
11
+
12
+ class MetadataFormatVersionError(Exception):
13
+ pass
14
+
12
15
 
13
16
  class MCServerMetadata(TypedDict):
14
17
  version: str
@@ -21,7 +24,10 @@ class Metadata(TypedDict):
21
24
 
22
25
  # Functions
23
26
  def set_metadata(mcserver_version: str) -> None:
24
- metadata: Metadata = {"format_version": metadata_format_version,"mcserver": {"version": mcserver_version}}
27
+ metadata: Metadata = {
28
+ "format_version": metadata_format_version,
29
+ "mcserver": {"version": mcserver_version},
30
+ }
25
31
 
26
32
  metadata_data: str = json.dumps(metadata)
27
33
  metadata_file.write_text(metadata_data)
@@ -31,5 +37,7 @@ def get_metadata() -> Metadata:
31
37
  metadata_data = metadata_file.read_text()
32
38
  metadata: Metadata = json.loads(metadata_data)
33
39
  if metadata["format_version"] > metadata_format_version:
34
- raise MetadataFormatVersionError("Existing metadata format version is higher than current metadata format version")
40
+ raise MetadataFormatVersionError(
41
+ "Existing metadata format version is higher than current metadata format version"
42
+ )
35
43
  return metadata
@@ -1,5 +1,10 @@
1
+ import json
2
+ import logging
3
+
1
4
  from ..typings import ProjectInformation
2
5
 
6
+ logger = logging.getLogger(__name__)
7
+
3
8
 
4
9
  class GetProjectInformationsError(Exception):
5
10
  pass
@@ -17,9 +22,6 @@ def get_project_informations(project_ids: list[str] | str) -> list[ProjectInform
17
22
  if isinstance(project_ids, str):
18
23
  project_ids = [project_ids]
19
24
 
20
- import json
21
- import logging as log
22
-
23
25
  from ... import networking
24
26
  from .. import constants, shared
25
27
  from ..typings import (
@@ -49,35 +51,29 @@ def get_project_informations(project_ids: list[str] | str) -> list[ProjectInform
49
51
  # Checks
50
52
  project_status: ProjectStatus = information["status"]
51
53
  if project_status not in shared.PROJECT_STATUS:
52
- log.warning(f"Unknown project status: {project_status}")
54
+ logger.warning(f"Unknown project status: {project_status}")
53
55
 
54
56
  project_type: ProjectType = information["project_type"]
55
57
  if project_type not in shared.PROJECT_TYPE:
56
- log.warning(f"Unknown project type: {project_type}")
58
+ logger.warning(f"Unknown project type: {project_type}")
57
59
 
58
60
  monetization_status: MonetizationStatus = information["monetization_status"]
59
61
  if monetization_status not in shared.MONETIZATION_STATUS:
60
- log.warning(f"Unknown monetization status: {monetization_status}")
61
-
62
- requested_project_status: RequestedProjectStatus = information[
63
- "requested_status"
64
- ]
65
- if requested_project_status not in shared.REQUESTED_PROJECT_STATUS:
66
- log.warning(f"Unknown monetization status: {monetization_status}")
62
+ logger.warning(f"Unknown monetization status: {monetization_status}")
67
63
 
68
64
  client_side: EnvironmentSide = information["client_side"]
69
65
  if client_side not in shared.ENVIRONMENT_SIDE:
70
- log.warning(f"Unknown client side: {client_side}")
66
+ logger.warning(f"Unknown client side: {client_side}")
71
67
 
72
68
  server_side: EnvironmentSide = information["server_side"]
73
69
  if server_side not in shared.ENVIRONMENT_SIDE:
74
- log.warning(f"Unknown server side: {server_side}")
70
+ logger.warning(f"Unknown server side: {server_side}")
75
71
 
76
72
  # Lists
77
73
  environments: list[Environment] = information["environment"]
78
74
  for environment in environments:
79
75
  if environment not in shared.ENVIRONMENT:
80
- log.warning(f"Unknown environment: {environment}")
76
+ logger.warning(f"Unknown environment: {environment}")
81
77
 
82
78
  gallery: list[GalleryImage] = []
83
79
  for image in information["gallery"]:
@@ -159,6 +155,17 @@ def get_project_informations(project_ids: list[str] | str) -> list[ProjectInform
159
155
  project_information["organization_id"] = information["organization"]
160
156
 
161
157
  if "requested_status" in information:
158
+ requested_project_status: RequestedProjectStatus | None = information[
159
+ "requested_status"
160
+ ]
161
+ if (
162
+ requested_project_status is not None
163
+ and requested_project_status not in shared.REQUESTED_PROJECT_STATUS
164
+ ):
165
+ logger.warning(
166
+ f"Unknown requested_project_status status: {monetization_status}"
167
+ )
168
+
162
169
  project_information["requested_project_status"] = requested_project_status
163
170
 
164
171
  if "approved" in information:
@@ -158,7 +158,10 @@ def get_project_versions(
158
158
  requested_status_version: RequestedVersionStatus = version[
159
159
  "requested_status"
160
160
  ]
161
- if requested_status_version is not None and requested_status_version not in shared.REQUESTED_VERSION_STATUS:
161
+ if (
162
+ requested_status_version is not None
163
+ and requested_status_version not in shared.REQUESTED_VERSION_STATUS
164
+ ):
162
165
  logger.info(
163
166
  f"Unknown requested_status_version: {requested_status_version}"
164
167
  )
@@ -43,6 +43,7 @@ class ProjectRecordData(ProjectRecordPayload):
43
43
  def record_exists(project_id: str) -> bool:
44
44
  return (project_records_dir / f"{project_id}.json").exists()
45
45
 
46
+
46
47
  def write_record(project_id: str, record_payload: ProjectRecordPayload) -> None:
47
48
  """Write a record for a project record (create a new record or overwrite it)
48
49
  Args:
mcserver/resolver.py CHANGED
@@ -83,9 +83,7 @@ def resolver_to_human(dependency_graph: dict[str, Project]) -> list[ProjectData]
83
83
  }
84
84
 
85
85
  if "highest_type" in project:
86
- project_data["highest_type"] = dependency_types2[
87
- project["highest_type"]
88
- ]
86
+ project_data["highest_type"] = dependency_types2[project["highest_type"]]
89
87
 
90
88
  projects.append(project_data)
91
89
 
@@ -0,0 +1,3 @@
1
+ from ..paths import current_dir
2
+
3
+ whitelist_file_path = current_dir / "whitelist.json"
@@ -1,184 +1,138 @@
1
- # Modules
2
- # Standard
3
1
  import json
4
- import logging as log
5
- from pathlib import Path
2
+ import logging
6
3
  from typing import TypedDict
7
- from uuid import UUID
8
4
 
9
- # MCServer
10
- from mcserver.minecraft.player_identity import (
11
- PlayerID,
12
- PlayerUUID,
13
- normalize_player_uuid,
14
- )
5
+ from ..minecraft.player_identity import PlayerUUID
6
+ from .paths import whitelist_file_path
15
7
 
16
- # Paths
17
- whitelist_file = Path("whitelist.json")
8
+ logger = logging.getLogger(__name__)
18
9
 
19
10
 
20
- # TypedDicts
21
- class WhitelistEntry(TypedDict):
11
+ class WhitelistedPlayer(TypedDict):
22
12
  player_uuid: PlayerUUID
23
13
  player_name: str
24
14
 
25
15
 
26
- class WhitelistFileEntry(TypedDict):
16
+ class WhitelistedFilePlayer(TypedDict):
27
17
  uuid: str
28
18
  name: str
29
19
 
30
-
31
- # Functions
32
- # Add Players
33
- def add_player(player_uuid: PlayerUUID, player_name: str) -> None:
34
- whitelist_entry: WhitelistEntry = {
35
- "player_uuid": player_uuid,
36
- "player_name": player_name,
37
- }
38
-
39
- add_players(whitelist_entry)
40
-
41
-
42
- def add_players(whitelist_entries: list[WhitelistEntry] | WhitelistEntry) -> None:
43
- """Add entries to the whitelist file
20
+ def remove_players(player_uuids: list[str] | str | None = None, player_names: list[str] | str | None = None) -> list[WhitelistedPlayer]:
21
+ """Remove players from the whitelist that matches either the UUIDs or names
22
+
44
23
  Args:
45
- whitelist_entries: List of or an entry of player to be whitelisted
46
-
24
+ player_uuids: List of player UUIDs to be removed
25
+ player_names: List of player names to be removed
26
+
47
27
  Raises:
48
- FileNotFoundError: Whitelist file does not exist
49
- json.JSONDecodeError: Cannot parse JSON of whitelist data
50
- """
51
- if not whitelist_file.exists():
52
- raise FileNotFoundError(f"Whitelist file ({whitelist_file}) does not exist")
53
-
54
- if not isinstance(whitelist_entries, list):
55
- whitelist_entries = [whitelist_entries]
56
-
57
- with open(whitelist_file, mode="r+") as file:
58
- whitelist_json: list[WhitelistFileEntry] = json.load(file)
59
-
60
- for entry in whitelist_entries:
61
- whitelist_entry: WhitelistFileEntry = {
62
- "uuid": str(normalize_player_uuid(entry["player_uuid"])),
63
- "name": entry.get("player_name", ""),
64
- }
65
-
66
- whitelist_json.append(whitelist_entry)
67
-
68
- file.seek(0)
69
- json.dump(whitelist_json, file, indent=2)
70
- file.truncate()
71
-
28
+ ValueError: Must provide at least a player UUID or player name
29
+
30
+ Returns:
31
+ List of whitelisted players that are removed"""
32
+ if player_uuids is None:
33
+ player_uuids = []
34
+
35
+ if player_names is None:
36
+ player_names = []
37
+
38
+ if isinstance(player_uuids, str):
39
+ player_uuids = [player_uuids]
40
+
41
+ if isinstance(player_names, str):
42
+ player_names = [player_names]
43
+
44
+ if not player_uuids and not player_names:
45
+ raise ValueError("Must provide at least a player UUID or player name")
46
+
47
+ uuids: set[str] = set(player_uuids)
48
+ names: set[str] = set(player_names)
49
+
50
+ removed_players: list[WhitelistedPlayer] = []
51
+ with open(whitelist_file_path, mode="r+") as whitelist_file:
52
+ whitelist_data: list[WhitelistedFilePlayer] = json.load(whitelist_file)
53
+
54
+ new_whitelist_data: list[WhitelistedFilePlayer] = []
55
+ for whitelisted_file_player in whitelist_data:
56
+ if whitelisted_file_player["uuid"] in uuids or whitelisted_file_player["name"] in names:
57
+ logger.debug(f"Whitelisted player {whitelisted_file_player['name']} ({whitelisted_file_player['uuid']}) is removed")
58
+ whitelisted_player: WhitelistedPlayer = {
59
+ "player_uuid": whitelisted_file_player["uuid"],
60
+ "player_name": whitelisted_file_player["name"]
61
+ }
62
+
63
+ removed_players.append(whitelisted_player)
64
+ continue
72
65
 
73
- # Remove Players
74
- def remove_player(
75
- player_uuid: PlayerUUID | None = None, player_name: str | None = None
76
- ) -> None:
77
- if player_uuid is None and player_name is None:
78
- raise ValueError(
79
- "At least one of 'player_uuid' or 'player_name' must be provided"
80
- )
66
+ new_whitelist_data.append(whitelisted_file_player)
67
+
68
+ whitelist_file.seek(0)
69
+ json.dump(new_whitelist_data, whitelist_file, indent=2)
70
+ whitelist_file.truncate()
81
71
 
82
- player_id: PlayerID = {}
83
- if player_uuid is not None:
84
- player_uuid = normalize_player_uuid(player_uuid)
85
- player_id["player_uuid"] = normalize_player_uuid(player_uuid)
72
+ return removed_players
86
73
 
87
- if player_name is not None:
88
- player_id["player_name"] = player_name
89
74
 
90
- remove_players(player_id)
91
75
 
76
+ # def remove_players(player_ids: list[PlayerID] | PlayerID) -> None:
77
+ # """Remove player entries matching the exact UUIDs or names
92
78
 
93
- def remove_players(player_ids: list[PlayerID] | PlayerID) -> None:
94
- """Remove player entries matching the exact UUIDs or names
79
+ # Args:
80
+ # player_ids: Player UUIDs and/or names object
95
81
 
96
- Args:
97
- player_ids: Player UUIDs and/or names object
82
+ # Returns:
83
+ # None: Returns nothing
98
84
 
99
- Returns:
100
- None: Returns nothing
85
+ # Raises:
86
+ # FileNotFoundError: The 'whitelist.json' file not found
87
+ # """
88
+ # if not isinstance(player_ids, list):
89
+ # player_ids = [player_ids]
101
90
 
102
- Raises:
103
- FileNotFoundError: The 'whitelist.json' file not found
104
- """
105
- if not isinstance(player_ids, list):
106
- player_ids = [player_ids]
107
-
108
- player_uuids: set[PlayerUUID | None] = set()
109
- player_names: set[str | None] = set()
110
- for player_id in player_ids:
111
- if "player_uuid" in player_id:
112
- player_uuids.add(player_id["player_uuid"])
113
-
114
- if "player_name" in player_id:
115
- player_names.add(player_id["player_name"])
116
-
117
- if not whitelist_file.exists():
118
- raise FileNotFoundError(f"File '{whitelist_file}' is not found.")
119
-
120
- with open(whitelist_file, mode="r+") as file:
121
- whitelist_data: list[WhitelistFileEntry] = json.load(file)
122
- new_whitelist_data: list[WhitelistFileEntry] = []
123
- for player in whitelist_data:
124
- player_uuid = player["uuid"]
125
- player_name = player["name"]
126
-
127
- if player_uuid in player_uuids or player_name in player_names:
128
- log.debug(
129
- f"Removed player '{player_name}' ({player_uuid}) from the whitelisted player list"
130
- )
131
- continue
91
+ # player_uuids: set[PlayerUUID | None] = set()
92
+ # player_names: set[str | None] = set()
93
+ # for player_id in player_ids:
94
+ # if "player_uuid" in player_id:
95
+ # player_uuids.add(player_id["player_uuid"])
132
96
 
133
- new_whitelist_data.append(player)
97
+ # if "player_name" in player_id:
98
+ # player_names.add(player_id["player_name"])
134
99
 
135
- file.seek(0)
136
- json.dump(new_whitelist_data, file, indent=2)
137
- file.truncate()
100
+ # if not whitelist_file.exists():
101
+ # raise FileNotFoundError(f"File '{whitelist_file}' is not found.")
138
102
 
103
+ # with open(whitelist_file, mode="r+") as file:
104
+ # whitelist_data: list[WhitelistFileEntry] = json.load(file)
105
+ # new_whitelist_data: list[WhitelistFileEntry] = []
106
+ # for player in whitelist_data:
107
+ # player_uuid = player["uuid"]
108
+ # player_name = player["name"]
139
109
 
140
- # TODO: add 'update_player' and 'update_players', just use plain dict.update() because it has no depth
141
-
142
-
143
- # List Entries
144
- def list_entries() -> list[WhitelistEntry]:
145
- """Return a list of whitelist entries from the whitelist file
146
- Raises:
147
- FileNotFoundError: Whitelist file does not exist
148
- json.JSONDecodeError: Cannot parse JSON of whitelist file
149
-
150
- Returns:
151
- List of whitelist entries
152
- """
153
- if not whitelist_file.exists():
154
- raise FileNotFoundError(f"Whitelist file ({whitelist_file}) does not exist")
110
+ # if player_uuid in player_uuids or player_name in player_names:
111
+ # log.debug(
112
+ # f"Removed player '{player_name}' ({player_uuid}) from the whitelisted player list"
113
+ # )
114
+ # continue
155
115
 
156
- whitelist_data: str = whitelist_file.read_text()
116
+ # new_whitelist_data.append(player)
157
117
 
158
- # NOTE: A custom TypedDict for entry from JSON with NotRequired so we can get notified for edge cases where the field does no exist
159
- whitelist_json: list[WhitelistFileEntry] = json.loads(whitelist_data)
118
+ # file.seek(0)
119
+ # json.dump(new_whitelist_data, file, indent=2)
120
+ # file.truncate()
160
121
 
161
- whitelist_entries: list[WhitelistEntry] = []
162
- for file_entry in whitelist_json:
163
- if "uuid" not in file_entry:
164
- log.warning("Invalid whitelist entry: missing 'uuid'")
165
- continue
166
122
 
167
- if "name" not in file_entry:
168
- log.warning("Invalid whitelist entry: missing 'name'")
169
- continue
170
123
 
171
- file_entry_uuid = file_entry["uuid"]
124
+ def list_players() -> list[WhitelistedPlayer]:
125
+ logger.debug(f"Reading whitelist file {whitelist_file_path}")
126
+ whitelist_json = whitelist_file_path.read_text()
127
+ whitelist_data: list[WhitelistedFilePlayer] = json.loads(whitelist_json)
172
128
 
173
- try:
174
- whitelist_entry: WhitelistEntry = {
175
- "player_uuid": UUID(file_entry_uuid),
176
- "player_name": file_entry["name"],
177
- }
178
- except ValueError:
179
- log.error(f"Invalid UUID in whitelist: '{file_entry_uuid}'")
180
- continue
129
+ whitelisted_players: list[WhitelistedPlayer] = []
130
+ for player in whitelist_data:
131
+ whitelisted_player: WhitelistedPlayer = {
132
+ "player_uuid": player["uuid"],
133
+ "player_name": player["name"],
134
+ }
181
135
 
182
- whitelist_entries.append(whitelist_entry)
136
+ whitelisted_players.append(whitelisted_player)
183
137
 
184
- return whitelist_entries
138
+ return whitelisted_players
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: mcserver-cli
3
- Version: 4.2.0
3
+ Version: 4.3.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
@@ -1,36 +1,36 @@
1
- mcserver/__init__.py,sha256=pU56ZDjCDnUbINe39hYuKXHy9UI9Tf4xjWgnxBlxEDk,22
1
+ mcserver/__init__.py,sha256=wPyEHmYopdmpH4340zhwFNBFQBGN743kwlSVDWO73rA,22
2
2
  mcserver/__main__.py,sha256=3-WYJCtLQ8TbzmLMYBiAsm9PC89DwjXc6s_J-izMEz8,30
3
3
  mcserver/app.py,sha256=giOF7rFvz9V1RG975l_nvFBMKebvzRsTUyq7wbz7HNU,777
4
4
  mcserver/caching.py,sha256=oLIQuiBqlJLxSTCVyrtHoYEZvmtnb3duxhhE-P5bOR8,411
5
- mcserver/cli.py,sha256=VHKxS3BGN_Gl_2BP1nqDJew7U6fR42VJz09JhNwwLp0,9587
6
- mcserver/config.py,sha256=OlSWod2QC0nZS88Dm5Sg2QTv-j8c57h86b98mJZiVT4,1955
5
+ mcserver/cli.py,sha256=Oh4YNfGe8IY_7ZYiFoqY5HwsVGL2XBI3NMMGNCQJJ5o,9817
6
+ mcserver/config.py,sha256=JlIATmTETwVTmXzrmONDBbYddj_aB4hcn8zYu5CQHTQ,2136
7
7
  mcserver/constants.py,sha256=ME5f4dv1PbqyQ6G1lQkKtvHQ4b722De4xu5B5Vp1Hw8,480
8
- mcserver/metadata.py,sha256=q0JSwKGc8NSRswNRniZPyWrWTpAnUS8fs4CJk160S8U,925
8
+ mcserver/metadata.py,sha256=sPstt7jrtPh1_kthje-loQ6UYB2c5m496IOJFYeGxjI,977
9
9
  mcserver/mysterious.py,sha256=giH_NRs7CuV51NACh3AUIIXKEKowHKb6DFGQQVPgtxE,642
10
10
  mcserver/networking.py,sha256=EdJE5pNL5e4wSitbXQtxMUkjiRT3w2nLkObDaZQnwCk,4865
11
11
  mcserver/paths.py,sha256=ZwCKOj4VdVgEzq30ZtnZyGjTgW5S3CiuX3Su-csgb2k,462
12
- mcserver/resolver.py,sha256=1MXeCZjk7gw-3fXGoR7HH2roR6FXFxCuAoi_2VtvDKA,7375
12
+ mcserver/resolver.py,sha256=28oO8HOr0JnU66KFSkP7mArmRAHPi13y3q92QpLEmqQ,7345
13
13
  mcserver/shared.py,sha256=_v8QAM3jpkUSHzWBjgLSKbnjh4M3bfRNUG2LKmGdUcE,7308
14
14
  mcserver/state.py,sha256=L0JUtKVZ6qWlpYqD42rnzbn65Qcaa1xKaBWmkIXVT-c,1992
15
- mcserver/commands/__init__.py,sha256=5axkZLKMUK0X0pLoTGalQLkW-2uJsInnSu3XslVQYpA,1038
16
- mcserver/commands/add.py,sha256=hy_gnsYbiscPMeiOenYlIFQ-GLl6C_APoRRx7HREK40,8612
17
- mcserver/commands/import_setup.py,sha256=VS0Uj1zUihOwqBfI2v2n24piDbsDtMcaFGbFq97Frqc,182
18
- mcserver/commands/init.py,sha256=xR8ZtMRhHcKx0eAv1EMcmEsmv2jqjndScZe0y38J2EQ,5740
19
- mcserver/commands/list_projects.py,sha256=TttnyAyy5v8Wmrf5T21E-Fqz5qmjSOYooL_w3kXxS4g,156
20
- mcserver/commands/op_grant.py,sha256=vAJ_i_YRYqvMfnphsTe7PEw5mFyoBB7vXJNv9JHxwKA,194
21
- mcserver/commands/op_list.py,sha256=IpojvVqFLd7zwVFm7NjC9dsIVyVVP1gVI0PoVs3aGXc,829
22
- mcserver/commands/op_revoke.py,sha256=vAJ_i_YRYqvMfnphsTe7PEw5mFyoBB7vXJNv9JHxwKA,194
23
- mcserver/commands/print_help.py,sha256=30nMXGL2epEGSOaavJWfspsc28iru-IGH43_NQiI8r8,148
24
- mcserver/commands/remove_projects.py,sha256=TttnyAyy5v8Wmrf5T21E-Fqz5qmjSOYooL_w3kXxS4g,156
25
- mcserver/commands/search.py,sha256=igU1bxw-oq-HyKl4b1f74lU_Ve7vS-yiK9rYeo6MWKE,6294
26
- mcserver/commands/server_status.py,sha256=TttnyAyy5v8Wmrf5T21E-Fqz5qmjSOYooL_w3kXxS4g,156
27
- mcserver/commands/show.py,sha256=MBtzFP4YPlSRzMyZ7yYThLUC6tT0tjskOutmbV8vlFc,4030
28
- mcserver/commands/start.py,sha256=8vgrmpSrz0Ev5S85jRimJ6HV6T-H8zMIf5HvBUJQfQ8,5766
29
- mcserver/commands/stop.py,sha256=nfu_-CtEm2J0heo2M9sKva_2taxxDS06wLHissXLdHc,556
30
- mcserver/commands/update_projects.py,sha256=TttnyAyy5v8Wmrf5T21E-Fqz5qmjSOYooL_w3kXxS4g,156
31
- mcserver/commands/whitelist_add.py,sha256=vAJ_i_YRYqvMfnphsTe7PEw5mFyoBB7vXJNv9JHxwKA,194
32
- mcserver/commands/whitelist_list.py,sha256=jOUf9_rh10gO9ocvpuFEY_xcIRQdA-Ig0GTicBi2LWM,891
33
- mcserver/commands/whitelist_remove.py,sha256=swnddGpaVD7-jDyrVAAjepW4C8RuGbdrWjJixX3BcNg,928
15
+ mcserver/commands/__init__.py,sha256=h-rdpn8r32rrHIZzs9fFu3pYWuc3KoRZIJO8IX0vU3U,1230
16
+ mcserver/commands/add_projects.py,sha256=ceEdcBrf7lcziRjNoPtLUJJ_UV3TLdMkSufCN_RaEVY,8660
17
+ mcserver/commands/import_setup.py,sha256=NbByM4seH0dAYo2QEj37VsL_J_Mtvg0S7NTsTFbcneA,181
18
+ mcserver/commands/initialize_server.py,sha256=sjNRNot01joQrC7wp064h-rIkMSxfs229Dhj5Xfh0Is,5739
19
+ mcserver/commands/list_projects.py,sha256=XG7U6oMVxQrTuV_GFCsp5aYZJphjyYwFDZiiURnjzNw,155
20
+ mcserver/commands/op_grant.py,sha256=eWiNmnGfCNAIXCHFcsbnbYdtwJKbHv-Xd2uOUNpyg8w,193
21
+ mcserver/commands/op_list.py,sha256=tsvIMYyDiZOgDtBMReEmxDO1j1a8x5EG0o_4qsoOSbM,828
22
+ mcserver/commands/op_revoke.py,sha256=eWiNmnGfCNAIXCHFcsbnbYdtwJKbHv-Xd2uOUNpyg8w,193
23
+ mcserver/commands/print_help.py,sha256=aOb20JvvfEteXDI9Q8fd-2vNCRXgxP6rFGLXfSGeP_Q,147
24
+ mcserver/commands/remove_projects.py,sha256=XG7U6oMVxQrTuV_GFCsp5aYZJphjyYwFDZiiURnjzNw,155
25
+ mcserver/commands/search_projects.py,sha256=rNNejVL5o00m6CzTO36acKdJeoKFZ8anYAHIM9VQsFc,6248
26
+ mcserver/commands/server_status.py,sha256=XG7U6oMVxQrTuV_GFCsp5aYZJphjyYwFDZiiURnjzNw,155
27
+ mcserver/commands/show_projects.py,sha256=2mnuV8z8Ws1GSX_iMGsI5lrdu32ZsvAHI11eq7NAdlc,4029
28
+ mcserver/commands/start_server.py,sha256=Sbu6JQ2gP0G7Taxz_rTw1FwQ2IT71Hx36_gq3ta2rps,5764
29
+ mcserver/commands/stop_server.py,sha256=l3-OiInwPlj1ApWQ8ZTqBsMKmkAPCh1MAjoqYLnHnO4,555
30
+ mcserver/commands/update_projects.py,sha256=XG7U6oMVxQrTuV_GFCsp5aYZJphjyYwFDZiiURnjzNw,155
31
+ mcserver/commands/whitelist_add.py,sha256=eWiNmnGfCNAIXCHFcsbnbYdtwJKbHv-Xd2uOUNpyg8w,193
32
+ mcserver/commands/whitelist_list.py,sha256=W1lFgGzd8mOhuwNIqklvqXQdQMXIfUpeXxF-HqSICM0,922
33
+ mcserver/commands/whitelist_remove.py,sha256=zXulEJziIxzWg6sPl96KtHxI3kQPNf-sgHtvI49eZkM,1177
34
34
  mcserver/fabricmc/meta.py,sha256=aQl_qPKLic0wM-CdhJimLvkP277nunD_kcZQQN0p9So,1113
35
35
  mcserver/legacy_fabric/meta.py,sha256=FRrPm4QZq3uuH7zscjyHPs-zoFW7uREIz3iWaX_Tqxs,911
36
36
  mcserver/minecraft/api.py,sha256=7twGWNv6UytlzJJ5kSCpVZzkXjBVDxTMY-t3VoKNAzA,2704
@@ -38,13 +38,13 @@ mcserver/minecraft/player_identity.py,sha256=LDvL5vFs5i-67nezUB4G12FrmQoZCT0ID94
38
38
  mcserver/modrinth/constants.py,sha256=5KqG45wBp7ZoRbf9tsFi_w1hSi-vxFEu6XE11MrAHF4,51
39
39
  mcserver/modrinth/modpack.py,sha256=uBx51G8sxQZEK127EMyXEZbyFMayps9pPGzTa49Vk6w,2957
40
40
  mcserver/modrinth/paths.py,sha256=wDoBiWkR-xZG3FCQdB1nct82kh5yksWunt98uwyAxLw,75
41
- mcserver/modrinth/project_records.py,sha256=0PYJ1tUR6TplaQNZapl9x28W-aEJM5IsTulDMRO1PfQ,3447
41
+ mcserver/modrinth/project_records.py,sha256=bDFlALFELhIrr4-elLkJk3YrCsvOJBr1u8QB5DqifOk,3448
42
42
  mcserver/modrinth/projects.py,sha256=86EksO7F1sQZvIqMWVH9g4FmU2xIFUGcmvqgT6ZQP-E,2342
43
43
  mcserver/modrinth/shared.py,sha256=-bVTwhYxif2jufZ_jcH5Gifa4d7uUtq_SGVgHfVXsyQ,3013
44
44
  mcserver/modrinth/slug_index.py,sha256=h3NxJQP_Rs8BsLm24w62n-ZoqaSvfImeLY0z7kMrulo,3331
45
45
  mcserver/modrinth/apis/__init__.py,sha256=gCQwcpU3Duj2AfVKtcnm8wb91EqiQT3nsLbABYa6JC0,261
46
- mcserver/modrinth/apis/get_project_informations.py,sha256=E3Nr7FIl91CbbP9ilZzh-Mus6s-Uv2Q10vjBt5ErJbE,8076
47
- mcserver/modrinth/apis/get_project_versions.py,sha256=t7KKPw6xbzhvudL8nf8Hq3Ka6YFV65bcGS5jfP39k_w,6052
46
+ mcserver/modrinth/apis/get_project_informations.py,sha256=C05s0PfUyLfc72bJlctDb4vTWpAS6tN-jWOjjNMLIB0,8286
47
+ mcserver/modrinth/apis/get_project_versions.py,sha256=DDWjufayTaaHXVGENtz8490yTTT6oSdb60Si4DMRsbM,6100
48
48
  mcserver/modrinth/apis/search_projects.py,sha256=bUDkbCPqukhLGBZhFyFvH_HxwoUDF2nt7U8ecZgPutA,5501
49
49
  mcserver/modrinth/typings/__init__.py,sha256=XJgVGGVRfD_xuB8ZHzaEsjolzrawgw_TmcZ0G5qFV_A,1082
50
50
  mcserver/modrinth/typings/project_information.py,sha256=1G1ID3zbXQr_ftZh9QAKZfPKTcgZAqbshRMeA16swuc,6101
@@ -59,11 +59,12 @@ mcserver/quiltmc/meta.py,sha256=BVbvGCfQ1_ft9i1KJFSFDnuvFoSoDz2lcWF-nr4nMdI,1385
59
59
  mcserver/server_files/banned_ips.py,sha256=3kfG9fck8JLvSnrfWl9eVj-ztClsld3Z9G4RxCyPtUw,3581
60
60
  mcserver/server_files/banned_players.py,sha256=qMSuwRdn_PzMCUD9CEOyy3plbfCmf_StauwbrgU5RXI,5050
61
61
  mcserver/server_files/ops.py,sha256=PFhR95aNTJ_sHorZct8hNQLV1OaSL9vOdxf6PqYaxKw,4032
62
+ mcserver/server_files/paths.py,sha256=RHCYfNKAh6fXjFuEfp-O5rgaM962astjdHSplGFug0g,86
62
63
  mcserver/server_files/properties.py,sha256=5WPigqET70Xh61NIIP0KRaTyir9qwjpjC-HmkKrB6j4,1119
63
64
  mcserver/server_files/usercaches.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
64
- mcserver/server_files/whitelist.py,sha256=ZROjMwTu-7MILA6W8dCgmyTnLyq-9d_tcHYkmBzq-Lo,5467
65
- mcserver_cli-4.2.0.dist-info/METADATA,sha256=ZBMiWhinCn3mRhO2vVOBeL9CxzEAIC0Yur17cEJ9SUU,2038
66
- mcserver_cli-4.2.0.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
67
- mcserver_cli-4.2.0.dist-info/entry_points.txt,sha256=p7uN6UdTzjea7nGIkhjiYDYd7wznkxz9amUPY_fpz24,47
68
- mcserver_cli-4.2.0.dist-info/licenses/LICENSE,sha256=OzeasqJgwxVpwtMkEYOLoDPUnIDSbVcW62rk-voA3eI,1076
69
- mcserver_cli-4.2.0.dist-info/RECORD,,
65
+ mcserver/server_files/whitelist.py,sha256=7POUqusctgntxehwU3w2ngVIzuTy6Wtze95bBLM6AhM,4556
66
+ mcserver_cli-4.3.0.dist-info/METADATA,sha256=ZjSrxoRsTx6tcXbDDMXSTyd5YkW9dzECWGLhEzCXSjM,2038
67
+ mcserver_cli-4.3.0.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
68
+ mcserver_cli-4.3.0.dist-info/entry_points.txt,sha256=p7uN6UdTzjea7nGIkhjiYDYd7wznkxz9amUPY_fpz24,47
69
+ mcserver_cli-4.3.0.dist-info/licenses/LICENSE,sha256=OzeasqJgwxVpwtMkEYOLoDPUnIDSbVcW62rk-voA3eI,1076
70
+ mcserver_cli-4.3.0.dist-info/RECORD,,