mcserver-cli 4.0.0.dev0__py3-none-any.whl → 4.2.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 -1
- mcserver/cli.py +25 -65
- mcserver/commands/__init__.py +12 -12
- mcserver/commands/add.py +232 -0
- mcserver/commands/{initialize_server.py → init.py} +39 -15
- mcserver/commands/search.py +183 -0
- mcserver/commands/show.py +105 -0
- mcserver/commands/{start_server.py → start.py} +26 -14
- mcserver/commands/{stop_server.py → stop.py} +2 -10
- mcserver/config.py +8 -3
- mcserver/fabricmc/meta.py +1 -1
- mcserver/metadata.py +8 -6
- mcserver/modrinth/apis/__init__.py +5 -5
- mcserver/modrinth/apis/get_project_informations.py +33 -35
- mcserver/modrinth/apis/get_project_versions.py +82 -40
- mcserver/modrinth/apis/search_projects.py +64 -27
- mcserver/modrinth/project_records.py +39 -28
- mcserver/modrinth/shared.py +22 -20
- mcserver/modrinth/slug_index.py +3 -7
- mcserver/modrinth/typings/__init__.py +26 -14
- mcserver/modrinth/typings/{project_informations.py → project_information.py} +5 -3
- mcserver/modrinth/typings/project_version.py +90 -0
- mcserver/mysterious.py +1 -1
- mcserver/networking.py +3 -0
- mcserver/paths.py +2 -1
- mcserver/resolver.py +49 -30
- mcserver/shared.py +29 -7
- {mcserver_cli-4.0.0.dev0.dist-info → mcserver_cli-4.2.0.dist-info}/METADATA +6 -5
- mcserver_cli-4.2.0.dist-info/RECORD +69 -0
- {mcserver_cli-4.0.0.dev0.dist-info → mcserver_cli-4.2.0.dist-info}/WHEEL +1 -1
- mcserver/commands/add_projects.py +0 -148
- mcserver/commands/search_projects.py +0 -109
- mcserver/commands/show_projects.py +0 -29
- mcserver/mcserver_v2.0.0.py +0 -1119
- mcserver/modrinth/api.py +0 -768
- mcserver/modrinth/project_records/metadata.py +0 -0
- mcserver/modrinth/project_records/relationships.py +0 -205
- mcserver/modrinth/project_records/shared.py +0 -8
- mcserver_cli-4.0.0.dev0.dist-info/RECORD +0 -73
- /mcserver/{legacyfabric → legacy_fabric}/meta.py +0 -0
- {mcserver_cli-4.0.0.dev0.dist-info → mcserver_cli-4.2.0.dist-info}/entry_points.txt +0 -0
- {mcserver_cli-4.0.0.dev0.dist-info → mcserver_cli-4.2.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import math
|
|
3
|
+
from argparse import Namespace
|
|
4
|
+
|
|
5
|
+
from mcserver import paths
|
|
6
|
+
|
|
7
|
+
from .. import config
|
|
8
|
+
from ..modrinth import apis as modrinth_apis
|
|
9
|
+
from ..modrinth.shared import SearchSortIndex
|
|
10
|
+
from ..shared import (
|
|
11
|
+
default_configs,
|
|
12
|
+
format_number,
|
|
13
|
+
get_loader_context,
|
|
14
|
+
pluralize,
|
|
15
|
+
project_environment_name,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
logger = logging.getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def search(args: Namespace) -> int:
|
|
22
|
+
search_query: list[str] = args.search_query
|
|
23
|
+
search_limit: int | None = args.search_limit
|
|
24
|
+
page_number: int = args.page_number
|
|
25
|
+
sort_index: SearchSortIndex | None = args.sort_index
|
|
26
|
+
game_version: str | None = args.game_version
|
|
27
|
+
no_version: str = args.no_version
|
|
28
|
+
loader_name: str | None = args.loader_name
|
|
29
|
+
|
|
30
|
+
if search_limit is None or sort_index is None:
|
|
31
|
+
modrinth_default_config = default_configs["modrinth"]
|
|
32
|
+
modrinth_config_path = paths.configs_dir / "modrinth.json"
|
|
33
|
+
|
|
34
|
+
if search_limit is None:
|
|
35
|
+
search_limit = modrinth_default_config["config_data"]["search_limit"]
|
|
36
|
+
logger.debug(
|
|
37
|
+
f"search_limit is set to default modrinth configuration: {search_limit}"
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
if sort_index is None:
|
|
41
|
+
sort_index = modrinth_default_config["config_data"]["sort_index"]
|
|
42
|
+
logger.debug(
|
|
43
|
+
f"sort_index is set to default modrinth configuration: {sort_index}"
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
if modrinth_config_path.exists():
|
|
47
|
+
modrinth_config = config.read_config(
|
|
48
|
+
"modrinth", modrinth_default_config["format_version"]
|
|
49
|
+
)
|
|
50
|
+
if search_limit is None and "search_limit" in modrinth_config:
|
|
51
|
+
search_limit = modrinth_config["search_limit"]
|
|
52
|
+
logger.debug(
|
|
53
|
+
f"search_limit is set to modrinth configuration file: {search_limit}"
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
if sort_index is None and "sort_index" in modrinth_config:
|
|
57
|
+
sort_index = modrinth_config["sort_index"]
|
|
58
|
+
logger.debug(
|
|
59
|
+
f"sort_index is set to modrinth configuration file: {sort_index}"
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
if game_version is None or loader_name is None:
|
|
63
|
+
server_config_path = paths.configs_dir / "server.json"
|
|
64
|
+
|
|
65
|
+
if server_config_path.exists():
|
|
66
|
+
server_config = config.read_config(
|
|
67
|
+
"server", default_configs["server"]["format_version"]
|
|
68
|
+
)
|
|
69
|
+
if game_version is None and "game_version" in server_config:
|
|
70
|
+
game_version = server_config["game_version"]
|
|
71
|
+
logger.debug(
|
|
72
|
+
f"game_version is set to server configuration file: {game_version}"
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
if (
|
|
76
|
+
loader_name is None
|
|
77
|
+
and "loader" in server_config
|
|
78
|
+
and "name" in server_config["loader"]
|
|
79
|
+
):
|
|
80
|
+
loader_name = server_config["loader"]["name"]
|
|
81
|
+
logger.debug(
|
|
82
|
+
f"loader_name is set to server configuration file: {loader_name}"
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
if no_version:
|
|
86
|
+
game_version = None
|
|
87
|
+
logger.debug("game_version is set to None because of no_version")
|
|
88
|
+
|
|
89
|
+
if search_limit is None:
|
|
90
|
+
logger.error("search_limit is None (somehow, really!)")
|
|
91
|
+
return 1
|
|
92
|
+
|
|
93
|
+
if sort_index is None:
|
|
94
|
+
logger.error("sort_index is None (somehow, really!)")
|
|
95
|
+
return 1
|
|
96
|
+
|
|
97
|
+
if loader_name == "vanilla":
|
|
98
|
+
logger.error("Vanilla does not support mods or plugin.")
|
|
99
|
+
return 1
|
|
100
|
+
|
|
101
|
+
project_label, _ = get_loader_context(loader_name)
|
|
102
|
+
|
|
103
|
+
search_offset = search_limit * (page_number - 1)
|
|
104
|
+
search_facets = [
|
|
105
|
+
["environment!=singleplayer_only"],
|
|
106
|
+
]
|
|
107
|
+
|
|
108
|
+
if game_version is not None:
|
|
109
|
+
search_facets.append([f"versions:{game_version}"])
|
|
110
|
+
|
|
111
|
+
if loader_name is not None:
|
|
112
|
+
search_facets.append([f"project_type:{project_label}"])
|
|
113
|
+
search_facets.append([f"categories:{loader_name}"])
|
|
114
|
+
else:
|
|
115
|
+
search_facets.append(["project_type:mod","project_type:plugin"])
|
|
116
|
+
|
|
117
|
+
search_info = f"Searching {pluralize(project_label, search_limit)}"
|
|
118
|
+
if search_query:
|
|
119
|
+
search_info += f" with '{' '.join(search_query)}'"
|
|
120
|
+
|
|
121
|
+
if game_version or loader_name:
|
|
122
|
+
search_info += " for"
|
|
123
|
+
|
|
124
|
+
if game_version:
|
|
125
|
+
search_info += f" Minecraft {game_version},"
|
|
126
|
+
|
|
127
|
+
if loader_name:
|
|
128
|
+
search_info += f" {loader_name.capitalize()}"
|
|
129
|
+
|
|
130
|
+
search_info += f" sorted by {sort_index}..."
|
|
131
|
+
|
|
132
|
+
logger.info(search_info)
|
|
133
|
+
search_result = modrinth_apis.search_projects(
|
|
134
|
+
search_query, search_facets, sort_index, search_offset, search_limit
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
total_hits = search_result["total_hits"]
|
|
138
|
+
total_pages = math.ceil(total_hits / search_limit)
|
|
139
|
+
|
|
140
|
+
search_hits = search_result["search_hits"]
|
|
141
|
+
|
|
142
|
+
if search_result["total_hits"] == 0:
|
|
143
|
+
logger.error(f"No {project_label} found.")
|
|
144
|
+
return 1
|
|
145
|
+
|
|
146
|
+
if page_number > total_pages:
|
|
147
|
+
logger.error(
|
|
148
|
+
f"Page number is larger than total pages of {total_pages} available"
|
|
149
|
+
)
|
|
150
|
+
return 1
|
|
151
|
+
|
|
152
|
+
logger.info(
|
|
153
|
+
f"Showing {len(search_hits)} {pluralize(project_label, len(search_hits))} out of {total_hits:,} {pluralize(project_label, total_hits)} (Page {page_number} out of {total_pages})"
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
for count, hit in enumerate(search_hits):
|
|
157
|
+
slug_or_id = hit["project_slug"] if "project_slug" in hit else hit["project_id"]
|
|
158
|
+
project_author = f"by {hit['author_username']}"
|
|
159
|
+
|
|
160
|
+
environments: list[Environment] = hit["environments"]
|
|
161
|
+
if len(environments) == 0:
|
|
162
|
+
environments.append("No environment")
|
|
163
|
+
|
|
164
|
+
readable_environments: list[str] = []
|
|
165
|
+
for environment in environments:
|
|
166
|
+
readable_environments.append(project_environment_name(environment))
|
|
167
|
+
|
|
168
|
+
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)}"
|
|
174
|
+
)
|
|
175
|
+
print(f"> https://modrinth.com/{hit['all_project_types'][0]}/{slug_or_id}")
|
|
176
|
+
print(
|
|
177
|
+
f" {hit['short_description']}"
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
if (count + 1) < len(search_hits):
|
|
181
|
+
print() # Print newline for readability
|
|
182
|
+
|
|
183
|
+
return 0
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
from argparse import Namespace
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def show(args: Namespace) -> int:
|
|
5
|
+
projects: list[str] = args.projects
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
|
|
9
|
+
from .. import shared
|
|
10
|
+
from ..modrinth import apis as modrinth_api
|
|
11
|
+
from ..shared import format_number, pluralize
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
logger.info(f"Getting {pluralize('project', len(projects))} informations...")
|
|
16
|
+
project_informations = modrinth_api.get_project_informations(projects)
|
|
17
|
+
|
|
18
|
+
logger.info(
|
|
19
|
+
f"Showing {len(project_informations)} out of {len(projects)} {pluralize('project', len(project_informations))}."
|
|
20
|
+
)
|
|
21
|
+
for project_information in project_informations:
|
|
22
|
+
slug_or_id = project_information.get(
|
|
23
|
+
"project_slug", project_information["project_id"]
|
|
24
|
+
)
|
|
25
|
+
print(f"Name: {project_information['project_name']} ({slug_or_id})")
|
|
26
|
+
|
|
27
|
+
download_count = project_information["download_count"]
|
|
28
|
+
print(
|
|
29
|
+
f"{pluralize('Download', download_count)}: {format_number(download_count)}"
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
follower_count = project_information["follower_count"]
|
|
33
|
+
print(
|
|
34
|
+
f"{pluralize('Follower', follower_count)}: {format_number(follower_count)}"
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
categories = project_information["categories"]
|
|
38
|
+
readable_categories: list[str] = []
|
|
39
|
+
for category in categories:
|
|
40
|
+
readable_categories.append(category.replace("-", " ").title())
|
|
41
|
+
print(
|
|
42
|
+
f"{pluralize('Category', len(categories))}: {', '.join(readable_categories)}"
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
if "additional_categories" in project_information:
|
|
46
|
+
additional_categories = project_information["additional_categories"]
|
|
47
|
+
readable_additional_categories: list[str] = []
|
|
48
|
+
for additional_category in additional_categories:
|
|
49
|
+
readable_additional_categories.append(
|
|
50
|
+
additional_category.replace("-", " ").title()
|
|
51
|
+
)
|
|
52
|
+
print(
|
|
53
|
+
f"Additional {pluralize('Category', len(additional_categories))}: {', '.join(readable_additional_categories)}"
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
loader_names = project_information["loader_names"]
|
|
57
|
+
loaders: list[str] = []
|
|
58
|
+
for loader in loader_names:
|
|
59
|
+
loaders.append(loader.title())
|
|
60
|
+
print(f"{pluralize('Loader', len(loader_names))}: {', '.join(loaders)}")
|
|
61
|
+
|
|
62
|
+
game_versions = project_information["game_versions"]
|
|
63
|
+
print(
|
|
64
|
+
f"Minecraft {pluralize('Version', len(game_versions))}: {', '.join(game_versions)}"
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
environments = project_information["environments"]
|
|
68
|
+
readable_environments: list[str] = []
|
|
69
|
+
for environment in environments:
|
|
70
|
+
readable_environments.append(shared.project_environment_name(environment))
|
|
71
|
+
print(
|
|
72
|
+
f"{pluralize('Environment', len(environments))}: {', '.join(readable_environments)}"
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
project_license = project_information["project_license"]
|
|
76
|
+
license_string = ""
|
|
77
|
+
if "license_name" in project_license:
|
|
78
|
+
license_string = project_license["license_name"]
|
|
79
|
+
|
|
80
|
+
if "license_id" in project_license:
|
|
81
|
+
if license_string != "":
|
|
82
|
+
license_string += f"({project_license['license_id']})"
|
|
83
|
+
else:
|
|
84
|
+
license_string = project_license["license_id"]
|
|
85
|
+
print(f"License: {license_string}")
|
|
86
|
+
|
|
87
|
+
print(
|
|
88
|
+
f"Homepage: https://modrinth.com/{project_information['project_type']}/{slug_or_id}"
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
if "source_url" in project_information:
|
|
92
|
+
print(f"Source Code: {project_information['source_url']}")
|
|
93
|
+
|
|
94
|
+
if "issues_url" in project_information:
|
|
95
|
+
print(f"Issues: {project_information['issues_url']}")
|
|
96
|
+
|
|
97
|
+
if "wiki_url" in project_information:
|
|
98
|
+
print(f"Wiki: {project_information['wiki_url']}")
|
|
99
|
+
|
|
100
|
+
if "discord_url" in project_information:
|
|
101
|
+
print(f"Discord: {project_information['discord_url']}")
|
|
102
|
+
|
|
103
|
+
print(f"Description: {project_information['short_description']}")
|
|
104
|
+
|
|
105
|
+
return 0
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from argparse import Namespace
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
def
|
|
4
|
+
def start(args: Namespace) -> int:
|
|
5
5
|
import logging as log
|
|
6
6
|
|
|
7
7
|
from .. import state
|
|
@@ -13,9 +13,16 @@ def main(args: Namespace) -> int:
|
|
|
13
13
|
|
|
14
14
|
current_state = state.get_state()
|
|
15
15
|
if current_state["is_active"]:
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
error_message = "There's another active MCServer process"
|
|
17
|
+
if "action" in current_state:
|
|
18
|
+
error_message += f" ({current_state['action']})"
|
|
19
|
+
error_message += " running"
|
|
20
|
+
|
|
21
|
+
if "process_id" in current_state:
|
|
22
|
+
error_message += f" with process ID: {current_state['process_id']}"
|
|
23
|
+
error_message += "."
|
|
24
|
+
|
|
25
|
+
log.error(error_message)
|
|
19
26
|
return 1
|
|
20
27
|
|
|
21
28
|
# Set state
|
|
@@ -25,10 +32,12 @@ def main(args: Namespace) -> int:
|
|
|
25
32
|
import shutil
|
|
26
33
|
from pathlib import Path
|
|
27
34
|
|
|
28
|
-
from .. import config
|
|
35
|
+
from .. import config, shared
|
|
29
36
|
|
|
30
37
|
# Load configs
|
|
31
|
-
launcher_config = config.
|
|
38
|
+
launcher_config = config.read_config(
|
|
39
|
+
"launcher", shared.default_configs["launcher"]["format_version"]
|
|
40
|
+
)
|
|
32
41
|
|
|
33
42
|
jarfile = Path(launcher_config["jarfile"])
|
|
34
43
|
memory_config = launcher_config["ram"]
|
|
@@ -41,7 +50,9 @@ def main(args: Namespace) -> int:
|
|
|
41
50
|
|
|
42
51
|
state.set_state("downloading_server")
|
|
43
52
|
|
|
44
|
-
server_config = config.
|
|
53
|
+
server_config = config.read_config(
|
|
54
|
+
"server", shared.default_configs["server"]["format_version"]
|
|
55
|
+
)
|
|
45
56
|
game_version = server_config["game_version"]
|
|
46
57
|
server_loader = server_config["loader"]
|
|
47
58
|
|
|
@@ -61,16 +72,17 @@ def main(args: Namespace) -> int:
|
|
|
61
72
|
f"Downloading Fabric loader {loader_version} for Minecraft version {game_version}..."
|
|
62
73
|
)
|
|
63
74
|
networking.download(
|
|
64
|
-
fabricmc_meta.download_url(game_version, loader_version, "1.
|
|
75
|
+
fabricmc_meta.download_url(game_version, loader_version, "1.1.2"),
|
|
65
76
|
jarfile,
|
|
66
77
|
)
|
|
67
78
|
|
|
68
|
-
#
|
|
69
|
-
#
|
|
70
|
-
#
|
|
79
|
+
# case "quilt":
|
|
80
|
+
# from ..quiltmc import meta
|
|
81
|
+
# log.info(f"Downloading Quilt loader {loader_version} for Minecraft version {game_version}...")
|
|
82
|
+
# networking.download(meta., jarfile)
|
|
71
83
|
|
|
72
|
-
#
|
|
73
|
-
#
|
|
84
|
+
# case "legacy-fabric":
|
|
85
|
+
# pass
|
|
74
86
|
|
|
75
87
|
# Plugin loaders
|
|
76
88
|
case "paper":
|
|
@@ -86,7 +98,7 @@ def main(args: Namespace) -> int:
|
|
|
86
98
|
networking.download(
|
|
87
99
|
download_prop["download_url"],
|
|
88
100
|
jarfile,
|
|
89
|
-
hashes=download_prop["file_hashes"],
|
|
101
|
+
hashes={"sha256": download_prop["file_hashes"]["sha256"]},
|
|
90
102
|
)
|
|
91
103
|
case "purpur":
|
|
92
104
|
from ..purpurmc import api as purpurmc_api
|
|
@@ -1,22 +1,14 @@
|
|
|
1
1
|
from argparse import Namespace
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
def
|
|
5
|
-
# CLI arguments
|
|
6
|
-
force_stop: bool = args.force_stop
|
|
7
|
-
|
|
4
|
+
def stop(args: Namespace) -> int:
|
|
8
5
|
import logging as log
|
|
9
6
|
import os
|
|
10
7
|
from signal import SIGTERM
|
|
11
8
|
|
|
12
9
|
from .. import state
|
|
13
10
|
|
|
14
|
-
|
|
15
|
-
current_state = state.get_state()
|
|
16
|
-
except FileNotFoundError:
|
|
17
|
-
log.error(f"File '{state.state_file}' not found; MCServer not initialized.")
|
|
18
|
-
return 1
|
|
19
|
-
|
|
11
|
+
current_state = state.get_state()
|
|
20
12
|
if not current_state["is_active"]:
|
|
21
13
|
log.error("Server is not running.")
|
|
22
14
|
return 1
|
mcserver/config.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# Modules
|
|
2
2
|
# Standard
|
|
3
|
+
import copy
|
|
3
4
|
import json
|
|
4
5
|
from typing import Any
|
|
5
6
|
|
|
@@ -32,9 +33,11 @@ def write_config(
|
|
|
32
33
|
|
|
33
34
|
config_filename = f"{config_name}.json"
|
|
34
35
|
config_path = configs_dir / config_filename
|
|
35
|
-
config_data["format_version"] = format_version
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
configuration_data = {"format_version": format_version}
|
|
38
|
+
|
|
39
|
+
configuration_data.update(copy.deepcopy(config_data))
|
|
40
|
+
config_json = json.dumps(configuration_data, indent=2)
|
|
38
41
|
config_path.write_text(config_json)
|
|
39
42
|
|
|
40
43
|
|
|
@@ -61,6 +64,8 @@ def read_config(config_name: str, current_format_version: int) -> dict[str, Any]
|
|
|
61
64
|
config_data = json.loads(config_json)
|
|
62
65
|
|
|
63
66
|
if config_data["format_version"] > current_format_version:
|
|
64
|
-
raise ConfigVersionError(
|
|
67
|
+
raise ConfigVersionError(
|
|
68
|
+
f"The configuration for {config_name}'s format version is higher than this version of MCServer."
|
|
69
|
+
)
|
|
65
70
|
|
|
66
71
|
return config_data
|
mcserver/fabricmc/meta.py
CHANGED
|
@@ -38,4 +38,4 @@ def get_loader_versions() -> list[LoaderVersion]:
|
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
def download_url(game_version: str, loader_version: str, installer_version) -> str:
|
|
41
|
-
return f"{fabricmc_meta_url}/v2/versions/loader/{
|
|
41
|
+
return f"{fabricmc_meta_url}/v2/versions/loader/{game_version}/{loader_version}/{installer_version}/server/jar"
|
mcserver/metadata.py
CHANGED
|
@@ -4,24 +4,24 @@ import json
|
|
|
4
4
|
from typing import TypedDict
|
|
5
5
|
|
|
6
6
|
# MCServer
|
|
7
|
-
from .
|
|
7
|
+
from .paths import metadata_file
|
|
8
8
|
|
|
9
|
+
metadata_format_version = 1
|
|
10
|
+
|
|
11
|
+
class MetadataFormatVersionError(Exception): pass
|
|
9
12
|
|
|
10
13
|
class MCServerMetadata(TypedDict):
|
|
11
14
|
version: str
|
|
12
15
|
|
|
13
16
|
|
|
14
17
|
class Metadata(TypedDict):
|
|
18
|
+
format_version: int
|
|
15
19
|
mcserver: MCServerMetadata
|
|
16
20
|
|
|
17
21
|
|
|
18
|
-
# Paths
|
|
19
|
-
metadata_file = mcserver_dir / "metadata.json"
|
|
20
|
-
|
|
21
|
-
|
|
22
22
|
# Functions
|
|
23
23
|
def set_metadata(mcserver_version: str) -> None:
|
|
24
|
-
metadata: Metadata = {"mcserver": {"version": mcserver_version}}
|
|
24
|
+
metadata: Metadata = {"format_version": metadata_format_version,"mcserver": {"version": mcserver_version}}
|
|
25
25
|
|
|
26
26
|
metadata_data: str = json.dumps(metadata)
|
|
27
27
|
metadata_file.write_text(metadata_data)
|
|
@@ -30,4 +30,6 @@ def set_metadata(mcserver_version: str) -> None:
|
|
|
30
30
|
def get_metadata() -> Metadata:
|
|
31
31
|
metadata_data = metadata_file.read_text()
|
|
32
32
|
metadata: Metadata = json.loads(metadata_data)
|
|
33
|
+
if metadata["format_version"] > metadata_format_version:
|
|
34
|
+
raise MetadataFormatVersionError("Existing metadata format version is higher than current metadata format version")
|
|
33
35
|
return metadata
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
from .
|
|
1
|
+
from .get_project_informations import get_project_informations
|
|
2
|
+
from .get_project_versions import get_project_versions
|
|
3
|
+
from .search_projects import search_projects
|
|
4
4
|
|
|
5
5
|
__all__ = [
|
|
6
|
-
# "get_project_versions",
|
|
7
6
|
"get_project_informations",
|
|
8
|
-
|
|
7
|
+
"get_project_versions",
|
|
8
|
+
"search_projects",
|
|
9
9
|
]
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
from ..typings import ProjectInformation
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
class
|
|
4
|
+
class GetProjectInformationsError(Exception):
|
|
5
5
|
pass
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
def
|
|
8
|
+
def get_project_informations(project_ids: list[str] | str) -> list[ProjectInformation]:
|
|
9
9
|
"""Get information about Modrinth projects
|
|
10
10
|
|
|
11
11
|
Args:
|
|
12
12
|
project_ids: The ID of the projects
|
|
13
13
|
|
|
14
14
|
Returns:
|
|
15
|
-
List of
|
|
15
|
+
List of information for the projects
|
|
16
16
|
"""
|
|
17
17
|
if isinstance(project_ids, str):
|
|
18
18
|
project_ids = [project_ids]
|
|
@@ -27,10 +27,12 @@ def main(project_ids: list[str] | str) -> list[ProjectInformation]:
|
|
|
27
27
|
Environment,
|
|
28
28
|
EnvironmentSide,
|
|
29
29
|
GalleryImage,
|
|
30
|
+
ModeratorMessage,
|
|
30
31
|
MonetizationStatus,
|
|
31
32
|
ProjectLicense,
|
|
32
33
|
ProjectStatus,
|
|
33
34
|
ProjectType,
|
|
35
|
+
RequestedProjectStatus,
|
|
34
36
|
)
|
|
35
37
|
|
|
36
38
|
query_parameters = {"ids": json.dumps(project_ids)}
|
|
@@ -40,7 +42,7 @@ def main(project_ids: list[str] | str) -> list[ProjectInformation]:
|
|
|
40
42
|
)
|
|
41
43
|
|
|
42
44
|
if "json" not in response:
|
|
43
|
-
raise
|
|
45
|
+
raise GetProjectInformationsError("Cannot load JSON response")
|
|
44
46
|
|
|
45
47
|
project_informations: list[ProjectInformation] = []
|
|
46
48
|
for information in response["json"]:
|
|
@@ -57,6 +59,12 @@ def main(project_ids: list[str] | str) -> list[ProjectInformation]:
|
|
|
57
59
|
if monetization_status not in shared.MONETIZATION_STATUS:
|
|
58
60
|
log.warning(f"Unknown monetization status: {monetization_status}")
|
|
59
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}")
|
|
67
|
+
|
|
60
68
|
client_side: EnvironmentSide = information["client_side"]
|
|
61
69
|
if client_side not in shared.ENVIRONMENT_SIDE:
|
|
62
70
|
log.warning(f"Unknown client side: {client_side}")
|
|
@@ -66,33 +74,11 @@ def main(project_ids: list[str] | str) -> list[ProjectInformation]:
|
|
|
66
74
|
log.warning(f"Unknown server side: {server_side}")
|
|
67
75
|
|
|
68
76
|
# Lists
|
|
69
|
-
|
|
70
|
-
for
|
|
71
|
-
categories.append(category)
|
|
72
|
-
|
|
73
|
-
additional_categories: list[str] = []
|
|
74
|
-
for additional_category in information["additional_categories"]:
|
|
75
|
-
additional_categories.append(additional_category)
|
|
76
|
-
|
|
77
|
-
environments: list[Environment] = []
|
|
78
|
-
for environment in information["environment"]:
|
|
77
|
+
environments: list[Environment] = information["environment"]
|
|
78
|
+
for environment in environments:
|
|
79
79
|
if environment not in shared.ENVIRONMENT:
|
|
80
80
|
log.warning(f"Unknown environment: {environment}")
|
|
81
81
|
|
|
82
|
-
environments.append(environment)
|
|
83
|
-
|
|
84
|
-
game_versions: list[str] = []
|
|
85
|
-
for game_version in information["game_versions"]:
|
|
86
|
-
game_versions.append(game_version)
|
|
87
|
-
|
|
88
|
-
loader_names: list[str] = []
|
|
89
|
-
for loader_name in information["loaders"]:
|
|
90
|
-
loader_names.append(loader_name)
|
|
91
|
-
|
|
92
|
-
version_ids: list[str] = []
|
|
93
|
-
for version_id in information["versions"]:
|
|
94
|
-
version_ids.append(version_id)
|
|
95
|
-
|
|
96
82
|
gallery: list[GalleryImage] = []
|
|
97
83
|
for image in information["gallery"]:
|
|
98
84
|
gallery_image: GalleryImage = {
|
|
@@ -148,12 +134,12 @@ def main(project_ids: list[str] | str) -> list[ProjectInformation]:
|
|
|
148
134
|
"description": information["body"],
|
|
149
135
|
"project_status": project_status,
|
|
150
136
|
"project_type": project_type,
|
|
151
|
-
"categories": categories,
|
|
152
|
-
"additional_categories": additional_categories,
|
|
137
|
+
"categories": information["categories"],
|
|
138
|
+
"additional_categories": information["additional_categories"],
|
|
153
139
|
"environments": environments,
|
|
154
|
-
"game_versions": game_versions,
|
|
155
|
-
"loader_names":
|
|
156
|
-
"version_ids":
|
|
140
|
+
"game_versions": information["game_versions"],
|
|
141
|
+
"loader_names": information["loaders"],
|
|
142
|
+
"version_ids": information["versions"],
|
|
157
143
|
"project_license": project_license,
|
|
158
144
|
"published_time": information["published"],
|
|
159
145
|
"updated_time": information["updated"],
|
|
@@ -173,7 +159,7 @@ def main(project_ids: list[str] | str) -> list[ProjectInformation]:
|
|
|
173
159
|
project_information["organization_id"] = information["organization"]
|
|
174
160
|
|
|
175
161
|
if "requested_status" in information:
|
|
176
|
-
project_information["
|
|
162
|
+
project_information["requested_project_status"] = requested_project_status
|
|
177
163
|
|
|
178
164
|
if "approved" in information:
|
|
179
165
|
project_information["approved_time"] = information["approved"]
|
|
@@ -209,7 +195,19 @@ def main(project_ids: list[str] | str) -> list[ProjectInformation]:
|
|
|
209
195
|
project_information["body_url"] = information["body_url"]
|
|
210
196
|
|
|
211
197
|
if "moderator_message" in information:
|
|
212
|
-
|
|
198
|
+
moderator_message: ModeratorMessage | None = None
|
|
199
|
+
if information["moderator_message"] is not None:
|
|
200
|
+
moderator_message = {}
|
|
201
|
+
information_moderator_message = information["moderator_message"]
|
|
202
|
+
if "message" in information_moderator_message:
|
|
203
|
+
moderator_message["message"] = information_moderator_message[
|
|
204
|
+
"message"
|
|
205
|
+
]
|
|
206
|
+
|
|
207
|
+
if "body" in information_moderator_message:
|
|
208
|
+
moderator_message["body"] = information_moderator_message["body"]
|
|
209
|
+
|
|
210
|
+
project_information["moderator_message"] = moderator_message
|
|
213
211
|
|
|
214
212
|
project_informations.append(project_information)
|
|
215
213
|
|