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/__init__.py ADDED
@@ -0,0 +1 @@
1
+ __version__ = "3.0.0"
mcserver/__main__.py ADDED
@@ -0,0 +1,3 @@
1
+ from . import app
2
+
3
+ app.main()
mcserver/app.py ADDED
@@ -0,0 +1,24 @@
1
+ def main() -> None:
2
+ import sys
3
+
4
+ if (sys.argv[1] if len(sys.argv) > 1 else "") == "cake":
5
+ from .mysterious import nothing_to_see_here_move_along
6
+
7
+ nothing_to_see_here_move_along()
8
+
9
+ MIN_PYTHON_VERSION: tuple[int, int] = (3, 14)
10
+ if sys.version_info < MIN_PYTHON_VERSION:
11
+ sys.exit(
12
+ f"MCServer requires Python {'.'.join(map(str, MIN_PYTHON_VERSION))} or newer."
13
+ )
14
+
15
+ import logging as log
16
+ import os
17
+
18
+ from . import cli
19
+
20
+ debug_mode = os.getenv("MCSERVER_DEBUG") == "1"
21
+ log_level = log.DEBUG if debug_mode else log.INFO
22
+ log.basicConfig(level=log_level, format="[%(levelname)s]: %(message)s")
23
+
24
+ sys.exit(cli.main())
mcserver/caching.py ADDED
File without changes
mcserver/cli.py ADDED
@@ -0,0 +1,326 @@
1
+ def main() -> int:
2
+ import argparse
3
+
4
+ from . import __version__
5
+ from .shared import loader_list
6
+
7
+ def command_function(args: argparse.Namespace) -> int:
8
+ command_name: str = args.command_name
9
+
10
+ match command_name:
11
+ case "add":
12
+ from .commands import add_projects
13
+
14
+ return add_projects(args)
15
+ case "import":
16
+ from .commands import import_setup
17
+
18
+ return import_setup(args)
19
+ case "help":
20
+ from .commands import print_help
21
+
22
+ return print_help(args)
23
+ case "init":
24
+ from .commands import initialize_server
25
+
26
+ return initialize_server(args)
27
+ case "list":
28
+ from .commands import list_projects
29
+
30
+ return list_projects(args)
31
+ case "op_grant":
32
+ from .commands import op_grant
33
+
34
+ return op_grant(args)
35
+ case "op_list":
36
+ from .commands import op_list
37
+
38
+ return op_list(args)
39
+ case "op_revoke":
40
+ from .commands import op_revoke
41
+
42
+ return op_revoke(args)
43
+ case "remove":
44
+ from .commands import remove_projects
45
+
46
+ return remove_projects(args)
47
+ case "search":
48
+ from .commands import search_projects
49
+
50
+ return search_projects(args)
51
+ case "show":
52
+ from .commands import show_projects
53
+
54
+ return show_projects(args)
55
+ case "start":
56
+ from .commands import start_server
57
+
58
+ return start_server(args)
59
+ case "status":
60
+ from .commands import server_status
61
+
62
+ return server_status(args)
63
+ case "stop":
64
+ from .commands import stop_server
65
+
66
+ return stop_server(args)
67
+ case "update":
68
+ from .commands import update_projects
69
+
70
+ return update_projects(args)
71
+ case "whitelist_add":
72
+ from .commands import whitelist_add
73
+
74
+ return whitelist_add(args)
75
+ case "whitelist_list":
76
+ from .commands import whitelist_list
77
+
78
+ return whitelist_list(args)
79
+ case "whitelist_remove":
80
+ from .commands import whitelist_remove
81
+
82
+ return whitelist_remove(args)
83
+ case _:
84
+ import logging as log
85
+
86
+ log.error(f"Unknown command: {command_name}")
87
+ return 1
88
+
89
+ parser = argparse.ArgumentParser(
90
+ prog="mcserver",
91
+ description="A CLI tool for managing Minecraft: Java Edition servers.",
92
+ epilog="Created for Linux and Termux only.",
93
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter,
94
+ prefix_chars="-",
95
+ add_help=True,
96
+ allow_abbrev=False,
97
+ exit_on_error=True,
98
+ suggest_on_error=True,
99
+ color=True,
100
+ )
101
+
102
+ parser.set_defaults(func=command_function, command_name="help", parser=parser)
103
+ parser.add_argument(
104
+ "-v",
105
+ "--version",
106
+ action="version",
107
+ version="%(prog)s " + __version__,
108
+ )
109
+
110
+ commands = parser.add_subparsers(title="Commands")
111
+
112
+ # 'add' command
113
+ add_command = commands.add_parser(
114
+ "add",
115
+ help="Add mods/projects",
116
+ description="Add mods/plugins and their dependencies.",
117
+ )
118
+
119
+ add_command.set_defaults(command_name="add")
120
+ add_command.add_argument(
121
+ "projects", nargs="+", type=str, help="Project slugs or IDs"
122
+ )
123
+
124
+ # 'import' command
125
+ import_command = commands.add_parser(
126
+ "import",
127
+ help="Import a Modrinth modpack",
128
+ description="Import a Modrinth modpack from a file.",
129
+ )
130
+
131
+ import_command.set_defaults(command_name="import")
132
+ import_command.add_argument("modpack", type=str, help="The Modrinth modpack file")
133
+
134
+ # 'init' command
135
+ init_command = commands.add_parser(
136
+ "init",
137
+ help="Initialize server configurations",
138
+ description="Initialize the server configurations.",
139
+ )
140
+
141
+ init_command.set_defaults(command_name="init")
142
+ init_command.add_argument(
143
+ "--mc-version",
144
+ default="latest-release",
145
+ type=str,
146
+ help="Minecraft version of the server",
147
+ metavar="Version",
148
+ dest="game_version",
149
+ )
150
+
151
+ init_command.add_argument(
152
+ "--loader",
153
+ default="vanilla",
154
+ type=str,
155
+ choices=loader_list,
156
+ help="Loader for the server",
157
+ metavar="Loader",
158
+ dest="loader_name",
159
+ )
160
+
161
+ init_command.add_argument(
162
+ "--loader-version",
163
+ default="latest",
164
+ type=str,
165
+ help="Version of the loader",
166
+ metavar="Version",
167
+ )
168
+
169
+ init_command.add_argument(
170
+ "--min-ram",
171
+ default=512,
172
+ type=int,
173
+ help="Minimum RAM for the server (in MebiBytes)",
174
+ metavar="Size",
175
+ )
176
+
177
+ init_command.add_argument(
178
+ "--max-ram",
179
+ default=2048,
180
+ type=int,
181
+ help="Maximum RAM for the server (in MebiBytes)",
182
+ metavar="Size",
183
+ )
184
+
185
+ # 'list' command
186
+ list_command = commands.add_parser(
187
+ "list", help="List all added projects", description="List all added projects."
188
+ )
189
+
190
+ list_command.set_defaults(command_name="list")
191
+
192
+ # 'op' command
193
+ op_command = commands.add_parser(
194
+ "op", help="Manage operator players", description="Manage the operator status."
195
+ )
196
+
197
+ op_command.set_defaults(parser=op_command)
198
+ op_subcommands = op_command.add_subparsers(title="Subcommands")
199
+
200
+ # 'op grant'
201
+ op_grant_command = op_subcommands.add_parser(
202
+ "grant",
203
+ help="Grant operator to players",
204
+ description="Grant operator status to players.",
205
+ )
206
+
207
+ op_grant_command.set_defaults(command_name="op_grant")
208
+ op_grant_command.add_argument(
209
+ "players", nargs="+", type=str, help="Player names or UUIDs"
210
+ )
211
+
212
+ # 'op list'
213
+ op_list_command = op_subcommands.add_parser(
214
+ "list", help="List operator players", description="List all operator players."
215
+ )
216
+
217
+ op_list_command.set_defaults(command_name="op_list")
218
+
219
+ # 'op revoke'
220
+ op_revoke_command = op_subcommands.add_parser(
221
+ "revoke",
222
+ help="Revoke operator from players",
223
+ description="Revoke operator status from players.",
224
+ )
225
+
226
+ op_revoke_command.set_defaults(command_name="op_revoke")
227
+ op_revoke_command.add_argument(
228
+ "players", nargs="+", type=str, help="Player names or UUIDs"
229
+ )
230
+
231
+ # 'remove' command
232
+ remove_command = commands.add_parser(
233
+ "remove", help="Remove projects", description="Remove projects"
234
+ )
235
+
236
+ # 'search' command
237
+ search_command = commands.add_parser(
238
+ "search",
239
+ help="Search Modrinth projects",
240
+ description="Search projects from Modrinth.",
241
+ )
242
+
243
+ search_command.set_defaults(command_name="search")
244
+ search_command.add_argument("query", nargs="*", type=str, help="Query to search")
245
+
246
+ # 'show' command
247
+ show_command = commands.add_parser(
248
+ "show",
249
+ help="Show Modrinth project information",
250
+ description="Show information about Modrinth projects.",
251
+ )
252
+
253
+ show_command.set_defaults(command_name="show")
254
+ show_command.add_argument(
255
+ "projects", nargs="+", type=str, help="Project slugs or IDs"
256
+ )
257
+
258
+ # 'start' command
259
+ start_command = commands.add_parser(
260
+ "start", help="Start the server", description="Install and start the server."
261
+ )
262
+
263
+ start_command.set_defaults(command_name="start")
264
+
265
+ # "stop" command
266
+ stop_command = commands.add_parser(
267
+ "stop", help="Stop the server", description="Stop the running server"
268
+ )
269
+
270
+ stop_command.set_defaults(command_name="stop")
271
+ stop_command.add_argument(
272
+ "--force-stop", action="store_true", help="Force stop the server"
273
+ )
274
+
275
+ # "update" command
276
+ update_command = commands.add_parser(
277
+ "update",
278
+ help="Update projects from Modrinth",
279
+ description="Update projects from Modrinth",
280
+ )
281
+
282
+ # 'whitelist' command
283
+ whitelist_command = commands.add_parser(
284
+ "whitelist",
285
+ help="Manage whitelisted players",
286
+ description="Manage the player whitelist.",
287
+ )
288
+
289
+ whitelist_command.set_defaults(parser=whitelist_command)
290
+ whitelist_subcommands = whitelist_command.add_subparsers(title="Subcommands")
291
+
292
+ # 'whitelist add'
293
+ whitelist_add_command = whitelist_subcommands.add_parser(
294
+ "add",
295
+ help="Add players to whitelist",
296
+ description="Add players to the whitelist.",
297
+ )
298
+
299
+ whitelist_add_command.set_defaults(command_name="whitelist_add")
300
+ whitelist_add_command.add_argument(
301
+ "players", nargs="+", type=str, help="Player names or UUIDs"
302
+ )
303
+
304
+ # 'whitelist list'
305
+ whitelist_list_command = whitelist_subcommands.add_parser(
306
+ "list",
307
+ help="List whitelisted players",
308
+ description="List all whitelisted players.",
309
+ )
310
+
311
+ whitelist_list_command.set_defaults(command_name="whitelist_list")
312
+
313
+ # 'whitelist remove'
314
+ whitelist_remove_command = whitelist_subcommands.add_parser(
315
+ "remove",
316
+ help="Remove players from whitelist",
317
+ description="Remove players from the whitelist.",
318
+ )
319
+
320
+ whitelist_remove_command.set_defaults(command_name="whitelist_remove")
321
+ whitelist_remove_command.add_argument(
322
+ "players", nargs="+", type=str, help="Player names or UUIDs"
323
+ )
324
+
325
+ args = parser.parse_args()
326
+ return args.func(args)
@@ -0,0 +1,39 @@
1
+ from .add_projects import main as add_projects
2
+ from .import_setup import main as import_setup
3
+ from .initialize_server import main as initialize_server
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_projects import main as search_projects
11
+ from .show_projects import main as show_projects
12
+ from .server_status import main as server_status
13
+ from .start_server import main as start_server
14
+ from .stop_server import main as stop_server
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
19
+
20
+ __all__ = [
21
+ "add_projects",
22
+ "import_setup",
23
+ "initialize_server",
24
+ "list_projects",
25
+ "op_grant",
26
+ "op_list",
27
+ "op_revoke",
28
+ "print_help",
29
+ "remove_projects",
30
+ "search_projects",
31
+ "server_status",
32
+ "show_projects",
33
+ "start_server",
34
+ "stop_server",
35
+ "update_projects",
36
+ "whitelist_add",
37
+ "whitelist_list",
38
+ "whitelist_remove",
39
+ ]
@@ -0,0 +1,7 @@
1
+ import argparse
2
+
3
+
4
+ def main(args: argparse.Namespace) -> int:
5
+ projects: list[str] = args.projects
6
+ print(args)
7
+ return 0
@@ -0,0 +1,6 @@
1
+ import argparse
2
+
3
+
4
+ def main(args: argparse.Namespace) -> int:
5
+ print(args)
6
+ return 0
@@ -0,0 +1,119 @@
1
+ import argparse
2
+
3
+
4
+ def main(args: argparse.Namespace) -> int:
5
+ # CLI Arguments
6
+ game_version: str = args.game_version
7
+
8
+ loader_name: str = args.loader_name
9
+ loader_version: str | None = args.loader_version
10
+
11
+ min_ram: int = args.min_ram
12
+ max_ram: int = args.max_ram
13
+
14
+ # Imports
15
+ import copy
16
+ import logging as log
17
+
18
+ from .. import __version__, config, shared, state
19
+ from ..metadata import metadata_file, set_metadata
20
+
21
+ # Special loader version
22
+ if loader_name == "vanilla":
23
+ loader_version = None
24
+
25
+ # Special latest game_version
26
+ if game_version in ["latest", "latest-release", "latest-snapshot"]:
27
+ from ..mojang import manifest as mojang_manifest
28
+
29
+ match game_version:
30
+ case "latest" | "latest-release":
31
+ game_version = mojang_manifest.get_latest_release_version()
32
+ log.info(f"Latest Minecraft release version is: {game_version}")
33
+ case "latest-snapshot":
34
+ game_version = mojang_manifest.get_latest_snapshot_version()
35
+ log.info(f"Latest Minecraft snapshot version is: {game_version}")
36
+
37
+ # Special latest loader_version
38
+ if loader_version == "latest":
39
+ match loader_name:
40
+ # Mod Loaders
41
+ case "fabric":
42
+ from ..fabricmc import meta as fabricmc_meta
43
+
44
+ loader_versions = fabricmc_meta.get_loader_versions()
45
+ for version in loader_versions:
46
+ if version["is_stable"]:
47
+ loader_version = version["loader_version"]
48
+ break
49
+
50
+ log.info(f"Latest Fabric loader version is {loader_version}")
51
+ case "quilt":
52
+ from ..quiltmc import meta as quiltmc_meta
53
+
54
+ loader_versions = quiltmc_meta.get_loader_versions()
55
+ latest_quilt_version = loader_versions[0]
56
+ loader_version = str(latest_quilt_version["loader_version"])
57
+ log.info(f"Latest Quilt loader version is {loader_version}")
58
+ # Plugin Loader
59
+ case "paper":
60
+ from ..papermc import api as papermc_api
61
+
62
+ latest_paper_version = papermc_api.get_latest_project_build(
63
+ "paper", game_version
64
+ )
65
+ loader_version = str(latest_paper_version["build_id"])
66
+ log.info(f"Latest Paper build version is: {loader_version}")
67
+ case "purpur":
68
+ from ..purpurmc import api as purpurmc_api
69
+
70
+ latest_purpur_version = purpurmc_api.get_latest_project_build(
71
+ "purpur", game_version
72
+ )
73
+ loader_version = str(latest_purpur_version["build_id"])
74
+ log.info(f"Latest Purpur build version is: {loader_version}")
75
+
76
+ case _:
77
+ log.error(f"Unknown loader: {loader_name}")
78
+ return 1
79
+
80
+ # Is first initializing
81
+ is_first_initialize = not metadata_file.exists()
82
+ shared.set_loader_context(loader_name)
83
+
84
+ shared.mcserver_dir.mkdir(exist_ok=True)
85
+ state.set_state("initializing_server")
86
+
87
+ config.configs_dir.mkdir(exist_ok=True)
88
+ shared.tempfiles_dir.mkdir(exist_ok=True)
89
+ if shared.loader_context["project_directory"] is not None:
90
+ shared.loader_context["project_directory"].mkdir(exist_ok=True)
91
+
92
+ # Write configuration to file
93
+ for config_name in shared.default_configs.keys():
94
+ default_config = copy.deepcopy(shared.default_configs[config_name])
95
+
96
+ config_override: dict = {}
97
+ match config_name:
98
+ case "launcher":
99
+ config_override = {"ram": {"min": min_ram, "max": max_ram}}
100
+
101
+ case "server":
102
+ config_override = {
103
+ "game_version": game_version,
104
+ "loader": {"name": loader_name, "version": loader_version},
105
+ }
106
+
107
+ config_data = shared.merge_dict(default_config, config_override)
108
+ try:
109
+ config.generate_config(config_name, config_data)
110
+ except FileExistsError:
111
+ log.debug(f"Configuration file {config_name} already exists")
112
+
113
+ if is_first_initialize:
114
+ set_metadata(__version__)
115
+ log.info("Initialized server configurations.")
116
+ else:
117
+ log.info("Reinitialized server configurations.")
118
+
119
+ return 0
@@ -0,0 +1,6 @@
1
+ import argparse
2
+
3
+
4
+ def main(args: argparse.Namespace) -> int:
5
+ print(args)
6
+ return 0
@@ -0,0 +1,7 @@
1
+ import argparse
2
+
3
+
4
+ def main(args: argparse.Namespace) -> int:
5
+ players: list[str] = args.players
6
+ print(args)
7
+ return 0
@@ -0,0 +1,32 @@
1
+ import argparse
2
+
3
+
4
+ def main(args: argparse.Namespace) -> int:
5
+ import logging as log
6
+
7
+ from ..server_files import ops
8
+ from ..shared import pluralize
9
+
10
+ if not ops.ops_file.exists():
11
+ log.error(f"File '{ops.ops_file}' not found.")
12
+ return 1
13
+
14
+ operator_players = ops.list_players()
15
+
16
+ players: list[str] = []
17
+ for player in operator_players:
18
+ players.append(
19
+ f"{player['player_name']} ({player['player_uuid']}) Level: {player["permission_level"]}"
20
+ )
21
+
22
+ players.sort()
23
+ sorted_players = "\n".join(players)
24
+
25
+ player_count = len(operator_players)
26
+ if player_count == 0:
27
+ log.info("There's no operator player.")
28
+ return 0
29
+
30
+ log.info(f"All {player_count} operator {pluralize("player", player_count)}:")
31
+ print(sorted_players)
32
+ return 0
@@ -0,0 +1,7 @@
1
+ import argparse
2
+
3
+
4
+ def main(args: argparse.Namespace) -> int:
5
+ players: list[str] = args.players
6
+ print(args)
7
+ return 0
@@ -0,0 +1,7 @@
1
+ import argparse
2
+
3
+
4
+ def main(args: argparse.Namespace) -> int:
5
+ parser: argparse.ArgumentParser = args.parser
6
+ parser.print_help()
7
+ return 0
@@ -0,0 +1,6 @@
1
+ import argparse
2
+
3
+
4
+ def main(args: argparse.Namespace) -> int:
5
+ print(args)
6
+ return 0
@@ -0,0 +1,7 @@
1
+ import argparse
2
+
3
+
4
+ def main(args: argparse.Namespace) -> int:
5
+ query: list[str] = args.query
6
+ print(args)
7
+ return 0
@@ -0,0 +1,6 @@
1
+ import argparse
2
+
3
+
4
+ def main(args: argparse.Namespace) -> int:
5
+ print(args)
6
+ return 0
@@ -0,0 +1,26 @@
1
+ import argparse
2
+
3
+
4
+ def main(args: argparse.Namespace) -> int:
5
+ projects: list[str] = args.projects
6
+
7
+ from ..modrinth import api as modrinth_api
8
+ from ..shared import format_number
9
+
10
+ project_information = modrinth_api.get_project_information(projects)
11
+ for project in project_information:
12
+ if "project_title" in project and "project_slug" in project:
13
+ print(f"Name: {project['project_title']} ({project['project_slug']})")
14
+
15
+ if "download_count" in project:
16
+ print(f"Downloads: {format_number(project['download_count'])}")
17
+
18
+ if "follower_count" in project:
19
+ print(f"Followers: {format_number(project["follower_count"])}")
20
+
21
+ if "project_slug" in project:
22
+ print(
23
+ f"Homepage: https://modrinth.com/{project['project_type']}/{project['project_slug']}"
24
+ )
25
+
26
+ return 0