mcmu 2.0.0.dev2__tar.gz → 2.0.0.dev3__tar.gz
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.
- {mcmu-2.0.0.dev2 → mcmu-2.0.0.dev3}/CHANGELOG.md +10 -0
- {mcmu-2.0.0.dev2 → mcmu-2.0.0.dev3}/PKG-INFO +2 -2
- {mcmu-2.0.0.dev2 → mcmu-2.0.0.dev3}/TODO.md +2 -3
- {mcmu-2.0.0.dev2 → mcmu-2.0.0.dev3}/pyproject.toml +1 -1
- {mcmu-2.0.0.dev2 → mcmu-2.0.0.dev3}/src/mcmu/__main__.py +66 -28
- {mcmu-2.0.0.dev2 → mcmu-2.0.0.dev3}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {mcmu-2.0.0.dev2 → mcmu-2.0.0.dev3}/.github/ISSUE_TEMPLATE/custom.md +0 -0
- {mcmu-2.0.0.dev2 → mcmu-2.0.0.dev3}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {mcmu-2.0.0.dev2 → mcmu-2.0.0.dev3}/.github/pull_request_template.md +0 -0
- {mcmu-2.0.0.dev2 → mcmu-2.0.0.dev3}/.gitignore +0 -0
- {mcmu-2.0.0.dev2 → mcmu-2.0.0.dev3}/CODE_OF_CONDUCT.md +0 -0
- {mcmu-2.0.0.dev2 → mcmu-2.0.0.dev3}/CONTRIBUTING.md +0 -0
- {mcmu-2.0.0.dev2 → mcmu-2.0.0.dev3}/LICENSE +0 -0
- {mcmu-2.0.0.dev2 → mcmu-2.0.0.dev3}/Makefile +0 -0
- {mcmu-2.0.0.dev2 → mcmu-2.0.0.dev3}/README.md +0 -0
- {mcmu-2.0.0.dev2 → mcmu-2.0.0.dev3}/SECURITY.md +0 -0
- {mcmu-2.0.0.dev2 → mcmu-2.0.0.dev3}/UPGRADING.md +0 -0
- {mcmu-2.0.0.dev2 → mcmu-2.0.0.dev3}/requirements.txt +0 -0
- {mcmu-2.0.0.dev2 → mcmu-2.0.0.dev3}/src/mcmu/ModrinthAPI.py +0 -0
- {mcmu-2.0.0.dev2 → mcmu-2.0.0.dev3}/src/mcmu/__init__.py +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mcmu
|
|
3
|
-
Version: 2.0.0.
|
|
3
|
+
Version: 2.0.0.dev3
|
|
4
4
|
Summary: A utility to update Minecraft java edition mods from Modrinth
|
|
5
5
|
Project-URL: homepage, https://github.com/Josiah-Jarvis/MCMU
|
|
6
6
|
Project-URL: source, https://github.com/Josiah-Jarvis/MCMU/
|
|
7
7
|
Project-URL: download, https://pypi.org/project/mcmu/#files
|
|
8
8
|
Project-URL: changelog, https://github.com/Josiah-Jarvis/MCMU/blob/master/CHANGELOG.md
|
|
9
|
-
Project-URL: releasenotes, https://github.com/Josiah-Jarvis/MCMU/compare/v2.0.0.
|
|
9
|
+
Project-URL: releasenotes, https://github.com/Josiah-Jarvis/MCMU/compare/v2.0.0.dev2...v2.0.0.dev3
|
|
10
10
|
Project-URL: documentation, https://github.com/Josiah-Jarvis/MCMU/blob/master/README.md
|
|
11
11
|
Project-URL: issues, https://github.com/Josiah-Jarvis/MCMU/issues
|
|
12
12
|
Author: Josiah Jarvis
|
|
@@ -4,11 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
## In Progress
|
|
6
6
|
|
|
7
|
-
[ ] Install mod dependencies
|
|
8
|
-
[ ] Get rid of the config file (might have found a solution!)
|
|
9
|
-
|
|
10
7
|
## Completed
|
|
11
8
|
|
|
9
|
+
[x] Install mod dependencies - 2026-03-18
|
|
10
|
+
[x] Get rid of the config file (might have found a solution!) - 2026-03-17
|
|
12
11
|
[x] Add comments to the code - 2026-03-16
|
|
13
12
|
[x] Search mods from Modrinth - 2026-03-15
|
|
14
13
|
[x] Add logging - 2026-03-11
|
|
@@ -51,7 +51,7 @@ homepage = "https://github.com/Josiah-Jarvis/MCMU"
|
|
|
51
51
|
source = "https://github.com/Josiah-Jarvis/MCMU/"
|
|
52
52
|
download = "https://pypi.org/project/mcmu/#files"
|
|
53
53
|
changelog = "https://github.com/Josiah-Jarvis/MCMU/blob/master/CHANGELOG.md"
|
|
54
|
-
releasenotes = "https://github.com/Josiah-Jarvis/MCMU/compare/v2.0.0.
|
|
54
|
+
releasenotes = "https://github.com/Josiah-Jarvis/MCMU/compare/v2.0.0.dev2...v2.0.0.dev3" # Change before every release
|
|
55
55
|
documentation = "https://github.com/Josiah-Jarvis/MCMU/blob/master/README.md"
|
|
56
56
|
issues = "https://github.com/Josiah-Jarvis/MCMU/issues"
|
|
57
57
|
|
|
@@ -10,13 +10,17 @@ from requests import get # Get files from the CDN
|
|
|
10
10
|
from argparse import ArgumentParser # Command line arguments class
|
|
11
11
|
from .ModrinthAPI import ModrinthAPI # Modrinth API code (Local import)
|
|
12
12
|
|
|
13
|
-
__version__ = "2.0.0.
|
|
13
|
+
__version__ = "2.0.0.dev3"
|
|
14
14
|
__author__ = "Josiah Jarvis"
|
|
15
15
|
|
|
16
16
|
logger = getLogger(__name__)
|
|
17
|
-
basicConfig(format="%(levelname)s: %(message)s") # Set logging
|
|
17
|
+
basicConfig(format="%(levelname)s: %(message)s") # Set logging format
|
|
18
18
|
|
|
19
|
-
parser = ArgumentParser(
|
|
19
|
+
parser = ArgumentParser(
|
|
20
|
+
prog="mcmu",
|
|
21
|
+
epilog=f"Version: {__version__}",
|
|
22
|
+
description="Downloads Minecraft mods from Modrinth"
|
|
23
|
+
)
|
|
20
24
|
group = parser.add_mutually_exclusive_group() # Get mutually exclusive group set up
|
|
21
25
|
group.add_argument("-u", "--update", help="Updates installed mods", action="store_true")
|
|
22
26
|
group.add_argument("-r", "--remove", help="Removes an installed mod")
|
|
@@ -76,12 +80,23 @@ def list_mods(mod_path: Path):
|
|
|
76
80
|
return mods
|
|
77
81
|
|
|
78
82
|
|
|
83
|
+
def install_mod(file: str, path: Path):
|
|
84
|
+
response = get(file, stream=True) # Get mod jar file
|
|
85
|
+
if response.status_code != 200:
|
|
86
|
+
return False
|
|
87
|
+
with open(path, 'wb') as file: # Write to the jar file
|
|
88
|
+
for chunk in response.iter_content(chunk_size=1024):
|
|
89
|
+
if chunk:
|
|
90
|
+
file.write(chunk)
|
|
91
|
+
return True
|
|
92
|
+
|
|
93
|
+
|
|
79
94
|
def main():
|
|
80
95
|
"""Main function
|
|
81
96
|
|
|
82
97
|
Returns:
|
|
83
|
-
1: Failure
|
|
84
98
|
0: Success
|
|
99
|
+
1: Failure
|
|
85
100
|
"""
|
|
86
101
|
mod_path = Path(args.minecraft_dir, "mods/") # Path to folder where the mod jar's are stored
|
|
87
102
|
mods = list_mods(mod_path)
|
|
@@ -92,25 +107,37 @@ def main():
|
|
|
92
107
|
for mod_name in mods:
|
|
93
108
|
latest_version = check_update(mod_name, mods[mod_name]['version']) # Check for update
|
|
94
109
|
if latest_version == 404: # Thats weird
|
|
95
|
-
print("Mod does not exist on Modrinth.")
|
|
96
|
-
sys.exit(1)
|
|
110
|
+
print(f"Mod: {mod_name}does not exist on Modrinth.")
|
|
97
111
|
elif latest_version is None: # If latest version is None no newer version was found
|
|
98
112
|
print("No version found for the specified game version and loader.")
|
|
99
|
-
return 1
|
|
100
113
|
elif latest_version: # If latest version is a dict it should return True
|
|
101
114
|
old_file = Path(mod_path, mods[mod_name]['file']) # Path to the old mod file
|
|
102
115
|
additional_storage = latest_version['files'][0]['size'] - old_file.stat().st_size # Calculate how much more storage will be taken up
|
|
103
116
|
if input(f"{mods[mod_name]['name']} will take up: {additional_storage} additional bytes, would you like to install? [Y/n]: ") is ("" or "Y"): # Ask them if they want to install it
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
117
|
+
for dependency in latest_version['dependencies']:
|
|
118
|
+
mod_data = ModAPI.project(dependency['project_id'])
|
|
119
|
+
if (not mod_data['slug'] in mods) and (dependency['dependency_type'] == "required"):
|
|
120
|
+
dependency_latest_version = check_update(mod_data['slug'], 0)
|
|
121
|
+
mod_jar_file = Path(mod_path, f"{mod_data['slug']}_version_{dependency_latest_version['version_number']}.jar")
|
|
122
|
+
if install_mod(dependency_latest_version['files'][0]['url'], mod_jar_file):
|
|
123
|
+
print(f"\tDownloaded required dependency at {mod_jar_file} successfully.") # Print the success
|
|
124
|
+
else:
|
|
125
|
+
print("Failed to download required dependency.")
|
|
126
|
+
return 1
|
|
127
|
+
elif (not mod_data['slug'] in mods) and (dependency['dependency_type'] == "optional"):
|
|
128
|
+
dependency_latest_version = check_update(mod_data['slug'], 0)
|
|
129
|
+
print(f"Optional dependency: {mod_data['slug']} not installed")
|
|
130
|
+
elif (mod_data['slug'] in mods) and (dependency['dependency_type'] == "incompatible"):
|
|
131
|
+
print(f"Incompatible dependency: {mod_data['slug']} installed, please remove.")
|
|
132
|
+
return 1
|
|
133
|
+
mod_jar_file = Path(mod_path, f"{args.install}_version_{latest_version['version_number']}.jar")
|
|
134
|
+
if install_mod(latest_version['files'][0]['url'], mod_jar_file):
|
|
135
|
+
print(f"Downloaded mod at {mod_jar_file} successfully.") # Print the success
|
|
136
|
+
print(f"Deleting old file: {old_file}")
|
|
137
|
+
old_file.unlink() # Delete old file
|
|
138
|
+
else:
|
|
139
|
+
print("Failed to download the mod.")
|
|
108
140
|
return 1
|
|
109
|
-
with open(f"{mod_path}/{args.install}_version_{latest_version['version_number']}.jar", 'wb') as file: # IF everything good write to the file
|
|
110
|
-
for chunk in response.iter_content(chunk_size=1024):
|
|
111
|
-
if chunk:
|
|
112
|
-
file.write(chunk)
|
|
113
|
-
print(f"Downloaded mod at {mod_path}/{args.install}_version_{latest_version['version_number']}.jar successfully.") # Print the success
|
|
114
141
|
else:
|
|
115
142
|
print("Canceling.")
|
|
116
143
|
return 0
|
|
@@ -126,15 +153,28 @@ def main():
|
|
|
126
153
|
return 1
|
|
127
154
|
if latest_version: # Should be True if it is a dict
|
|
128
155
|
if input(f"{args.install} will take up: {latest_version['files'][0]['size']} bytes, would you like to install? [Y/n]: ") is ("" or "Y"): # Ask if the want to install it
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
156
|
+
for dependency in latest_version['dependencies']:
|
|
157
|
+
mod_data = ModAPI.project(dependency['project_id'])
|
|
158
|
+
if (not mod_data['slug'] in mods) and (dependency['dependency_type'] == "required"):
|
|
159
|
+
dependency_latest_version = check_update(mod_data['slug'], 0)
|
|
160
|
+
mod_jar_file = Path(mod_path, f"{mod_data['slug']}_version_{dependency_latest_version['version_number']}.jar")
|
|
161
|
+
if install_mod(dependency_latest_version['files'][0]['url'], mod_jar_file):
|
|
162
|
+
print(f"\tDownloaded required dependency at {mod_jar_file} successfully.") # Print the success
|
|
163
|
+
else:
|
|
164
|
+
print("Failed to download required dependency.")
|
|
165
|
+
return 1
|
|
166
|
+
elif (not mod_data['slug'] in mods) and (dependency['dependency_type'] == "optional"):
|
|
167
|
+
dependency_latest_version = check_update(mod_data['slug'], 0)
|
|
168
|
+
print(f"Optional dependency: {mod_data['slug']} not installed")
|
|
169
|
+
elif (mod_data['slug'] in mods) and (dependency['dependency_type'] == "incompatible"):
|
|
170
|
+
print(f"Incompatible dependency: {mod_data['slug']} installed, please remove.")
|
|
171
|
+
return 1
|
|
172
|
+
mod_jar_file = Path(mod_path, f"{args.install}_version_{latest_version['version_number']}.jar")
|
|
173
|
+
if install_mod(latest_version['files'][0]['url'], mod_jar_file):
|
|
174
|
+
print(f"Downloaded mod at {mod_jar_file} successfully.") # Print the success
|
|
175
|
+
else:
|
|
176
|
+
print("Failed to download the mod.")
|
|
177
|
+
return 1
|
|
138
178
|
else:
|
|
139
179
|
print("Canceling.")
|
|
140
180
|
return 0
|
|
@@ -152,8 +192,6 @@ def main():
|
|
|
152
192
|
else:
|
|
153
193
|
print("Canceling.")
|
|
154
194
|
return 0
|
|
155
|
-
except FileNotFoundError: # Oops file not found must already be deleted
|
|
156
|
-
logger.warn("Mod's file already deleted.")
|
|
157
195
|
except PermissionError: # No permission to delete the file
|
|
158
196
|
logger.critical("No permission to delete mod file.")
|
|
159
197
|
return 1
|
|
@@ -165,7 +203,7 @@ def main():
|
|
|
165
203
|
elif args.search: # If we are searching for a mod
|
|
166
204
|
response = ModAPI.search(args.search, '[["categories:fabric"],["project_type:mod"]]')
|
|
167
205
|
if response == 410: # That means the API is deprecated: https://docs.modrinth.com/api/
|
|
168
|
-
logger.critical("API is deprecated,
|
|
206
|
+
logger.critical("API is deprecated, try updating MCMU")
|
|
169
207
|
elif response == 400: # Response of 400 means request was invalid: https://docs.modrinth.com/api/operations/searchprojects/
|
|
170
208
|
logger.error("Request invalid") # Print error
|
|
171
209
|
else:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|