mcserver-cli 3.0.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 (61) hide show
  1. mcserver/__init__.py +1 -0
  2. mcserver/__main__.py +3 -0
  3. mcserver/app.py +24 -0
  4. mcserver/caching.py +0 -0
  5. mcserver/cli.py +326 -0
  6. mcserver/commands/__init__.py +39 -0
  7. mcserver/commands/add_projects.py +7 -0
  8. mcserver/commands/import_setup.py +6 -0
  9. mcserver/commands/initialize_server.py +119 -0
  10. mcserver/commands/list_projects.py +6 -0
  11. mcserver/commands/op_grant.py +7 -0
  12. mcserver/commands/op_list.py +32 -0
  13. mcserver/commands/op_revoke.py +7 -0
  14. mcserver/commands/print_help.py +7 -0
  15. mcserver/commands/remove_projects.py +6 -0
  16. mcserver/commands/search_projects.py +7 -0
  17. mcserver/commands/server_status.py +6 -0
  18. mcserver/commands/show_projects.py +26 -0
  19. mcserver/commands/start_server.py +150 -0
  20. mcserver/commands/stop_server.py +46 -0
  21. mcserver/commands/update_projects.py +6 -0
  22. mcserver/commands/whitelist_add.py +7 -0
  23. mcserver/commands/whitelist_list.py +31 -0
  24. mcserver/commands/whitelist_remove.py +31 -0
  25. mcserver/commandsa.py +1297 -0
  26. mcserver/config.py +37 -0
  27. mcserver/constants.py +14 -0
  28. mcserver/fabricmc/meta.py +41 -0
  29. mcserver/legacyfabric/meta.py +37 -0
  30. mcserver/metadata.py +33 -0
  31. mcserver/minecraft/api.py +94 -0
  32. mcserver/minecraft/player_identity.py +21 -0
  33. mcserver/modrinth/api.py +657 -0
  34. mcserver/modrinth/modpack.py +101 -0
  35. mcserver/modrinth/project_records/metadata.py +0 -0
  36. mcserver/modrinth/project_records/relationships.py +203 -0
  37. mcserver/modrinth/project_records/shared.py +9 -0
  38. mcserver/modrinth/projects.py +80 -0
  39. mcserver/modrinth/shared.py +13 -0
  40. mcserver/modrinth/slug_index.py +36 -0
  41. mcserver/mojang/eula.py +28 -0
  42. mcserver/mojang/manifest.py +69 -0
  43. mcserver/mysterious.py +5 -0
  44. mcserver/networking.py +152 -0
  45. mcserver/papermc/api.py +81 -0
  46. mcserver/purpurmc/api.py +81 -0
  47. mcserver/quiltmc/meta.py +54 -0
  48. mcserver/resolver.py +164 -0
  49. mcserver/server_files/banned_ips.py +120 -0
  50. mcserver/server_files/banned_players.py +166 -0
  51. mcserver/server_files/ops.py +143 -0
  52. mcserver/server_files/properties.py +41 -0
  53. mcserver/server_files/usercaches.py +0 -0
  54. mcserver/server_files/whitelist.py +163 -0
  55. mcserver/shared.py +198 -0
  56. mcserver/state.py +77 -0
  57. mcserver_cli-3.0.0.dist-info/METADATA +63 -0
  58. mcserver_cli-3.0.0.dist-info/RECORD +61 -0
  59. mcserver_cli-3.0.0.dist-info/WHEEL +4 -0
  60. mcserver_cli-3.0.0.dist-info/entry_points.txt +2 -0
  61. mcserver_cli-3.0.0.dist-info/licenses/LICENSE +9 -0
mcserver/config.py ADDED
@@ -0,0 +1,37 @@
1
+ # Modules
2
+ # Standard
3
+ import json
4
+ from typing import Any
5
+
6
+ # MCServer
7
+ from .shared import mcserver_dir, merge_dict
8
+
9
+ # Paths
10
+ configs_dir = mcserver_dir / "configs"
11
+
12
+
13
+ # Functions
14
+ def generate_config(config_name: str, config_data: dict[str, Any]) -> None:
15
+ config_filename = f"{config_name}.json"
16
+ config_path = configs_dir / config_filename
17
+
18
+ with open(config_path, mode="xt") as config_file:
19
+ json.dump(config_data, config_file, indent=2)
20
+
21
+
22
+ def load_config(config_name: str) -> dict[str, Any]:
23
+ config_filename = f"{config_name}.json"
24
+ config_path = configs_dir / config_filename
25
+
26
+ with open(config_path, mode="rt") as config_file:
27
+ return json.load(config_file)
28
+
29
+
30
+ def update_config(config_name: str, new_data: dict[str, Any]) -> None:
31
+ config_filename = f"{config_name}.json"
32
+ config_path = configs_dir / config_filename
33
+
34
+ with open(config_path, mode="r+") as file:
35
+ config_data = json.load(file)
36
+ merge_dict(config_data, new_data)
37
+ json.dump(config_data, file, indent=2)
mcserver/constants.py ADDED
@@ -0,0 +1,14 @@
1
+ __version__: str = "2.0.0"
2
+
3
+ mojang_manifest_url: str = "https://launchermeta.mojang.com"
4
+
5
+ minecraft_api_url: str = "https://api.minecraftservices.com"
6
+ modrinth_api_url: str = "https://api.modrinth.com"
7
+ papermc_api_url: str = "https://fill.papermc.io"
8
+ purpurmc_api_url: str = "https://api.purpurmc.org"
9
+
10
+ fabricmc_meta_url: str = "https://meta.fabricmc.net"
11
+ quiltmc_meta_url: str = "https://meta.quiltmc.org"
12
+
13
+ si_prefixes: list = ["", "K", "M", "B", "T"]
14
+ iec_prefixes: list = ["B", "KiB", "MiB", "GiB", "TiB"]
@@ -0,0 +1,41 @@
1
+ # Modules
2
+ # Standard
3
+ import json
4
+ from typing import TypedDict
5
+
6
+ # MCServer
7
+ from .. import networking
8
+ from ..constants import fabricmc_meta_url
9
+
10
+
11
+ # TypedDict
12
+ class LoaderVersion(TypedDict):
13
+ separator: str
14
+ build_id: int
15
+ maven_id: str
16
+ loader_version: str
17
+ is_stable: bool
18
+
19
+
20
+ # Functions
21
+ def get_loader_versions() -> list[LoaderVersion]:
22
+ response = networking.request(f"{fabricmc_meta_url}/v2/versions/loader")
23
+ response_json = json.loads(response["text"])
24
+
25
+ loader_versions: list[LoaderVersion] = []
26
+ for version in response_json:
27
+ loader_version: LoaderVersion = {
28
+ "separator": version["separator"],
29
+ "build_id": version["build"],
30
+ "maven_id": version["maven"],
31
+ "loader_version": version["version"],
32
+ "is_stable": version["stable"],
33
+ }
34
+
35
+ loader_versions.append(loader_version)
36
+
37
+ return loader_versions
38
+
39
+
40
+ def download_url(game_version: str, loader_version: str, installer_version) -> str:
41
+ return f"{fabricmc_meta_url}/v2/versions/loader/{loader_version}/{game_version}/{installer_version}/server/jar"
@@ -0,0 +1,37 @@
1
+ # Modules
2
+ # Standard
3
+ import json
4
+ from typing import TypedDict
5
+
6
+ # MCServer
7
+ from .. import networking
8
+ from ..constants import fabricmc_meta_url
9
+
10
+
11
+ # TypedDict
12
+ class LoaderVersion(TypedDict):
13
+ separator: str
14
+ build_id: int
15
+ maven_id: str
16
+ loader_version: str
17
+ is_stable: bool
18
+
19
+
20
+ # Functions
21
+ def get_loader_versions() -> list[LoaderVersion]:
22
+ response = networking.request(f"{fabricmc_meta_url}/v2/versions/loader")
23
+ response_json = json.loads(response["text"])
24
+
25
+ loader_versions: list[LoaderVersion] = []
26
+ for version in response_json:
27
+ loader_version: LoaderVersion = {
28
+ "separator": version["separator"],
29
+ "build_id": version["build"],
30
+ "maven_id": version["maven"],
31
+ "loader_version": version["version"],
32
+ "is_stable": version["stable"],
33
+ }
34
+
35
+ loader_versions.append(loader_version)
36
+
37
+ return loader_versions
mcserver/metadata.py ADDED
@@ -0,0 +1,33 @@
1
+ # Modules
2
+ # Standard
3
+ import json
4
+ from typing import TypedDict
5
+
6
+ # MCServer
7
+ from .shared import mcserver_dir
8
+
9
+
10
+ class MCServerMetadata(TypedDict):
11
+ version: tuple[int, int, int]
12
+
13
+
14
+ class Metadata(TypedDict):
15
+ mcserver: MCServerMetadata
16
+
17
+
18
+ # Paths
19
+ metadata_file = mcserver_dir / "metadata.json"
20
+
21
+
22
+ # Functions
23
+ def set_metadata(mcserver_version: tuple[int, int, int]) -> None:
24
+ metadata: Metadata = {"mcserver": {"version": mcserver_version}}
25
+
26
+ metadata_data: str = json.dumps(metadata)
27
+ metadata_file.write_text(metadata_data)
28
+
29
+
30
+ def get_metadata() -> Metadata:
31
+ metadata_data = metadata_file.read_text()
32
+ metadata: Metadata = json.loads(metadata_data)
33
+ return metadata
@@ -0,0 +1,94 @@
1
+ # Modules
2
+ # Standard
3
+ import json
4
+ from typing import NotRequired, TypedDict
5
+
6
+ from .. import networking
7
+ from ..constants import minecraft_api_url
8
+
9
+ # MCSe.rver
10
+ from .player_identity import PlayerUUID, normalize_player_uuid
11
+
12
+
13
+ # TypedDict
14
+ class PlayerIdentity(TypedDict):
15
+ player_uuid: PlayerUUID
16
+ player_name: str
17
+ is_legacy: NotRequired[bool]
18
+ is_demo: NotRequired[bool]
19
+
20
+
21
+ # Functions
22
+ def get_player_from_name(player_name: str) -> PlayerIdentity:
23
+ response = networking.request(
24
+ f"{minecraft_api_url}/minecraft/profile/lookup/name/{player_name}"
25
+ )
26
+ response_json = json.loads(response["text"])
27
+
28
+ player_identity: PlayerIdentity = {
29
+ "player_uuid": normalize_player_uuid(response_json["id"]),
30
+ "player_name": response_json["name"],
31
+ }
32
+
33
+ if "legacy" in response_json:
34
+ player_identity["is_legacy"] = response_json["legacy"]
35
+
36
+ if "demo" in response_json:
37
+ player_identity["is_demo"] = response_json["demo"]
38
+
39
+ return player_identity
40
+
41
+
42
+ def get_players_from_names(player_names: list[str] | str) -> list[PlayerIdentity]:
43
+ if isinstance(player_names, str):
44
+ player_names = [player_names]
45
+
46
+ if len(player_names) > 10:
47
+ raise ValueError("Cannot query more than 10 player names at once")
48
+
49
+ data_payload = json.dumps(player_names).encode("utf-8")
50
+ response = networking.request(
51
+ f"{minecraft_api_url}/minecraft/profile/lookup/bulk/byname",
52
+ data=data_payload,
53
+ headers={"Content-Type": "application/json"},
54
+ method="POST",
55
+ )
56
+
57
+ response_json = json.loads(response["text"])
58
+
59
+ player_identities: list[PlayerIdentity] = []
60
+ for player in response_json:
61
+ player_identity: PlayerIdentity = {
62
+ "player_uuid": normalize_player_uuid(player["id"]),
63
+ "player_name": player["name"],
64
+ }
65
+
66
+ if "legacy" in player:
67
+ player_identity["is_legacy"] = player["legacy"]
68
+
69
+ if "demo" in player:
70
+ player_identity["is_demo"] = player["demo"]
71
+
72
+ player_identities.append(player_identity)
73
+
74
+ return player_identities
75
+
76
+
77
+ def get_player_from_uuid(player_uuid: PlayerUUID) -> PlayerIdentity:
78
+ response = networking.request(
79
+ f"{minecraft_api_url}/minecraft/profile/lookup/{player_uuid}"
80
+ )
81
+ response_json = json.loads(response["text"])
82
+
83
+ player_identity: PlayerIdentity = {
84
+ "player_uuid": normalize_player_uuid(response_json["id"]),
85
+ "player_name": response_json["name"],
86
+ }
87
+
88
+ if "legacy" in response_json:
89
+ player_identity["is_legacy"] = response_json["legacy"]
90
+
91
+ if "demo" in response_json:
92
+ player_identity["is_demo"] = response_json["demo"]
93
+
94
+ return player_identity
@@ -0,0 +1,21 @@
1
+ # Modules
2
+ from typing import NotRequired, TypedDict
3
+ from uuid import UUID
4
+
5
+ # Type Aliases
6
+ type PlayerUUID = UUID | str
7
+
8
+
9
+ # TypedDicts
10
+ class PlayerID(TypedDict):
11
+ # Used for providing either player UUID and/or name
12
+ player_uuid: NotRequired[PlayerUUID]
13
+ player_name: NotRequired[str]
14
+
15
+
16
+ # Functions
17
+ def normalize_player_uuid(player_uuid: PlayerUUID) -> UUID:
18
+ if isinstance(player_uuid, str):
19
+ player_uuid = UUID(player_uuid)
20
+
21
+ return player_uuid