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.
Files changed (42) hide show
  1. mcserver/__init__.py +1 -1
  2. mcserver/cli.py +25 -65
  3. mcserver/commands/__init__.py +12 -12
  4. mcserver/commands/add.py +232 -0
  5. mcserver/commands/{initialize_server.py → init.py} +39 -15
  6. mcserver/commands/search.py +183 -0
  7. mcserver/commands/show.py +105 -0
  8. mcserver/commands/{start_server.py → start.py} +26 -14
  9. mcserver/commands/{stop_server.py → stop.py} +2 -10
  10. mcserver/config.py +8 -3
  11. mcserver/fabricmc/meta.py +1 -1
  12. mcserver/metadata.py +8 -6
  13. mcserver/modrinth/apis/__init__.py +5 -5
  14. mcserver/modrinth/apis/get_project_informations.py +33 -35
  15. mcserver/modrinth/apis/get_project_versions.py +82 -40
  16. mcserver/modrinth/apis/search_projects.py +64 -27
  17. mcserver/modrinth/project_records.py +39 -28
  18. mcserver/modrinth/shared.py +22 -20
  19. mcserver/modrinth/slug_index.py +3 -7
  20. mcserver/modrinth/typings/__init__.py +26 -14
  21. mcserver/modrinth/typings/{project_informations.py → project_information.py} +5 -3
  22. mcserver/modrinth/typings/project_version.py +90 -0
  23. mcserver/mysterious.py +1 -1
  24. mcserver/networking.py +3 -0
  25. mcserver/paths.py +2 -1
  26. mcserver/resolver.py +49 -30
  27. mcserver/shared.py +29 -7
  28. {mcserver_cli-4.0.0.dev0.dist-info → mcserver_cli-4.2.0.dist-info}/METADATA +6 -5
  29. mcserver_cli-4.2.0.dist-info/RECORD +69 -0
  30. {mcserver_cli-4.0.0.dev0.dist-info → mcserver_cli-4.2.0.dist-info}/WHEEL +1 -1
  31. mcserver/commands/add_projects.py +0 -148
  32. mcserver/commands/search_projects.py +0 -109
  33. mcserver/commands/show_projects.py +0 -29
  34. mcserver/mcserver_v2.0.0.py +0 -1119
  35. mcserver/modrinth/api.py +0 -768
  36. mcserver/modrinth/project_records/metadata.py +0 -0
  37. mcserver/modrinth/project_records/relationships.py +0 -205
  38. mcserver/modrinth/project_records/shared.py +0 -8
  39. mcserver_cli-4.0.0.dev0.dist-info/RECORD +0 -73
  40. /mcserver/{legacyfabric → legacy_fabric}/meta.py +0 -0
  41. {mcserver_cli-4.0.0.dev0.dist-info → mcserver_cli-4.2.0.dist-info}/entry_points.txt +0 -0
  42. {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 main(args: Namespace) -> int:
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
- log.error(
17
- f"There's another active MCServer process ({current_state['action']}) running with process ID: {current_state['process_id']}"
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.load_config("launcher")
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.load_config("server")
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.0.1"),
75
+ fabricmc_meta.download_url(game_version, loader_version, "1.1.2"),
65
76
  jarfile,
66
77
  )
67
78
 
68
- # case "quilt":
69
- # log.info(f"Downloading Quilt loader {loader_version} for Minecraft version {game_version}...")
70
- # networking.download(f"https://")
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
- # case "legacy-fabric":
73
- # pass
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 main(args: Namespace) -> int:
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
- try:
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
- config_json = json.dumps(config_data)
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/{loader_version}/{game_version}/{installer_version}/server/jar"
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 .shared import mcserver_dir
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
- # from .get_project_versions import main as get_project_versions
2
- # from .search_projects import main as search_projects
3
- from .get_project_informations import main as get_project_informations
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
- # "search_projects",
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 GetProjectInformationError(Exception):
4
+ class GetProjectInformationsError(Exception):
5
5
  pass
6
6
 
7
7
 
8
- def main(project_ids: list[str] | str) -> list[ProjectInformation]:
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 project informations
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 GetProjectInformationError("Cannot load JSON response")
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
- categories: list[str] = []
70
- for category in information["categories"]:
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": loader_names,
156
- "version_ids": 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["requested_status"] = information["requested_status"]
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
- project_information["moderator_message"] = information["moderator_message"]
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