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.
- mcserver/__init__.py +1 -0
- mcserver/__main__.py +3 -0
- mcserver/app.py +24 -0
- mcserver/caching.py +0 -0
- mcserver/cli.py +326 -0
- mcserver/commands/__init__.py +39 -0
- mcserver/commands/add_projects.py +7 -0
- mcserver/commands/import_setup.py +6 -0
- mcserver/commands/initialize_server.py +119 -0
- mcserver/commands/list_projects.py +6 -0
- mcserver/commands/op_grant.py +7 -0
- mcserver/commands/op_list.py +32 -0
- mcserver/commands/op_revoke.py +7 -0
- mcserver/commands/print_help.py +7 -0
- mcserver/commands/remove_projects.py +6 -0
- mcserver/commands/search_projects.py +7 -0
- mcserver/commands/server_status.py +6 -0
- mcserver/commands/show_projects.py +26 -0
- mcserver/commands/start_server.py +150 -0
- mcserver/commands/stop_server.py +46 -0
- mcserver/commands/update_projects.py +6 -0
- mcserver/commands/whitelist_add.py +7 -0
- mcserver/commands/whitelist_list.py +31 -0
- mcserver/commands/whitelist_remove.py +31 -0
- mcserver/commandsa.py +1297 -0
- mcserver/config.py +37 -0
- mcserver/constants.py +14 -0
- mcserver/fabricmc/meta.py +41 -0
- mcserver/legacyfabric/meta.py +37 -0
- mcserver/metadata.py +33 -0
- mcserver/minecraft/api.py +94 -0
- mcserver/minecraft/player_identity.py +21 -0
- mcserver/modrinth/api.py +657 -0
- mcserver/modrinth/modpack.py +101 -0
- mcserver/modrinth/project_records/metadata.py +0 -0
- mcserver/modrinth/project_records/relationships.py +203 -0
- mcserver/modrinth/project_records/shared.py +9 -0
- mcserver/modrinth/projects.py +80 -0
- mcserver/modrinth/shared.py +13 -0
- mcserver/modrinth/slug_index.py +36 -0
- mcserver/mojang/eula.py +28 -0
- mcserver/mojang/manifest.py +69 -0
- mcserver/mysterious.py +5 -0
- mcserver/networking.py +152 -0
- mcserver/papermc/api.py +81 -0
- mcserver/purpurmc/api.py +81 -0
- mcserver/quiltmc/meta.py +54 -0
- mcserver/resolver.py +164 -0
- mcserver/server_files/banned_ips.py +120 -0
- mcserver/server_files/banned_players.py +166 -0
- mcserver/server_files/ops.py +143 -0
- mcserver/server_files/properties.py +41 -0
- mcserver/server_files/usercaches.py +0 -0
- mcserver/server_files/whitelist.py +163 -0
- mcserver/shared.py +198 -0
- mcserver/state.py +77 -0
- mcserver_cli-3.0.0.dist-info/METADATA +63 -0
- mcserver_cli-3.0.0.dist-info/RECORD +61 -0
- mcserver_cli-3.0.0.dist-info/WHEEL +4 -0
- mcserver_cli-3.0.0.dist-info/entry_points.txt +2 -0
- 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
|