aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--downloads.txt37
-rw-r--r--latest-urls.txt37
-rw-r--r--mods.txt4
-rwxr-xr-xupdate.py202
-rw-r--r--version.txt4
-rw-r--r--whitelist.txt1
6 files changed, 152 insertions, 133 deletions
diff --git a/downloads.txt b/downloads.txt
deleted file mode 100644
index 47ca892..0000000
--- a/downloads.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-# Format: <jarname> <hex digested sha1> <direct download url>
-jei-01.jar f7672ddb5b7ac55ce3b49b55ad39977092737469 https://media.forgecdn.net/files/2635/239/jei_1.12.2-4.13.1.222.jar
-projectredinteg-01.jar 851f7fdfaa8a545cbee59c61455a949049e12075 https://media.forgecdn.net/files/2572/427/ProjectRed-1.12.2-4.9.1.92-integration.jar
-forgemultipart-01.jar 7b67222f2a61bb8574250b37df933a2f3b9c39e2 https://media.forgecdn.net/files/2626/992/ForgeMultipart-1.12.2-2.6.0.79-universal.jar
-projectredcore-01.jar c9012fa49e8eb9150085b00395b3bf99cb0a2972 https://media.forgecdn.net/files/2572/409/MrTJPCore-1.12.2-2.1.3.35-universal.jar
-thermaldynamics-01.jar a41bc51c0b659f80c6e90a0d60cc02b3f84a7b6b https://media.forgecdn.net/files/2624/182/ThermalDynamics-1.12.2-2.5.3.16-universal.jar
-thermalfoundation-01.jar 4d7b2f42799e3dff84c7c517d3162e645863bb7d https://media.forgecdn.net/files/2623/991/ThermalFoundation-1.12.2-2.6.1.22-universal.jar
-thermalexpansion-01.jar 9c81d89d97cff26c09bae1146012e1873cb884ae https://media.forgecdn.net/files/2624/855/ThermalExpansion-1.12.2-5.5.2.39-universal.jar
-twilightforest-01.jar 418e55d39800696341d888dd9f407daee3748276 https://media.forgecdn.net/files/2618/264/twilightforest-1.12.2-3.8.689-universal.jar
-idklib-01.jar 34244f742099f077ec0519969b3989784343ae02 https://media.forgecdn.net/files/2626/982/mcjtylib-1.12-3.0.6.jar
-projectredmech-01.jar 6d491aeddba2c5c22596ecb65b3d5621edf419d8 https://media.forgecdn.net/files/2572/422/ProjectRed-1.12.2-4.9.1.92-mechanical.jar
-chickenchunks-01.jar 22646ea2acdad735b5e82d8b80e4e40ec27aa62b https://media.forgecdn.net/files/2594/241/ChickenChunks-1.12.2-2.4.1.73-universal.jar
-translocators-01.jar 455f6b3e51821ad70d37f51a7b0a1aae2a9cac6c https://media.forgecdn.net/files/2594/249/Translocators-1.12.2-2.5.1.77-universal.jar
-tinkers-01.jar 7d31986c8c714bb588a63e1c686f38abcedeb914 https://media.forgecdn.net/files/2571/785/TConstruct-1.12.2-2.10.1.87.jar
-imersiveengineering-01.jar dba5544ae411b9ed1165edde345bbab901f84096 https://media.forgecdn.net/files/2625/312/ImmersiveEngineering-0.12-86.jar
-baubles-01.jar cb13fcfb18a9cb0cbd825fd5fe8d813c77368549 https://media.forgecdn.net/files/2518/667/Baubles-1.12-1.5.2.jar
-cofhcore-01.jar a448365b93842d40f8d52e823fd7acc69263269c https://media.forgecdn.net/files/2623/990/CoFHCore-1.12.2-4.6.1.22-universal.jar
-projectredcompat-01.jar bcfa9a8198b6a0f14bb8a79df5d94a3d5aea9666 https://media.forgecdn.net/files/2572/420/ProjectRed-1.12.2-4.9.1.92-compat.jar
-cofhworld-01.jar df965eac4acfabc3874efe6517d032467313855c https://media.forgecdn.net/files/2623/91/CoFHWorld-1.12.2-1.3.0.6-universal.jar
-enderio-01.jar 7c84b758a309fabb2fcba69b658ab4e2bb5d0629 https://media.forgecdn.net/files/2632/831/EnderIO-1.12.2-5.0.37.jar
-projectred-01.jar 334d4d68ef71f6aedb0fc5855dc672f7b6ac2aec https://media.forgecdn.net/files/2572/421/ProjectRed-1.12.2-4.9.1.92-world.jar
-mantle-01.jar bb23a99220319ebd1e6452e7a7e973aca6b286b3 https://media.forgecdn.net/files/2630/843/Mantle-1.12-1.3.3.39.jar
-tech-reborn-01.jar 87c0e64c49ee066b85771cffc1bcd3b9defe326d https://media.forgecdn.net/files/2633/989/TechReborn-1.12.2-2.17.7.840-universal.jar
-passwordlib-01.jar 7dbb26e59a96db83f3e64b4078bfd6339e3055fc https://media.forgecdn.net/files/2616/338/p455w0rdslib-1.12-2.0.35.jar
-redstoneflux-01.jar ed67a4ce69c8831b7536b2623a857fefc8257e62 https://media.forgecdn.net/files/2623/90/RedstoneFlux-1.12-2.1.0.6-universal.jar
-projectredcore2-01.jar 89744b1a82275d12cd9cf95014544c0f79ba7467 https://media.forgecdn.net/files/2572/423/ProjectRed-1.12.2-4.9.1.92-Base.jar
-opencomputers-02.jar 70feadd549255477810dff7145cade9d507b2dec https://media.forgecdn.net/files/2638/675/OpenComputers-MC1.12.2-1.7.3.146.jar
-reborncore-01.jar c750c0eb1b31fa8c8ef6aedfc69ebe42a8d83d78 https://media.forgecdn.net/files/2634/706/RebornCore-1.12.2-3.10.4.348-universal.jar
-connectedtextures-01.jar 02c17c9af47b54439cb22b9c17f6c93a1fd3ffe5 https://media.forgecdn.net/files/2629/306/CTM-MC1.12.2-0.3.2.20.jar
-foamfix.jar 69a9086f2084d3cbc3a410ee64369d719a212330 https://media.forgecdn.net/files/2638/380/foamfix-0.10.3-1.12.2.jar
-thaumcraft-01.jar fe0899048f1796df04e9727bbf1898df30492a00 https://media.forgecdn.net/files/2629/23/Thaumcraft-1.12.2-6.1.BETA26.jar
-codechickenlib-01.jar 1ead040eeee13c474d448f976363778e2918a7d0 https://media.forgecdn.net/files/2618/630/CodeChickenLib-1.12.2-3.2.2.353-universal.jar
-endercore-01.jar cb35af97775e257eedb94e6f09e2d50606cdb9bd https://media.forgecdn.net/files/2632/476/EnderCore-1.12.2-0.5.43.jar
-rftools-01.jar 09dfed39207c757c7b8120673f98a00c3c83cca1 https://media.forgecdn.net/files/2616/385/rftools-1.12-7.56.jar
-wirelesscraftingterminal-02.jar 5d78cfb2bf3033950b76c499589148de20b70f14 https://media.forgecdn.net/files/2619/932/WirelessCraftingTerminal-1.12.2-3.10.82.jar
-ae2-01.jar a7dfa60f06388091f13a42f2025f9d96a4ea7e18 https://media.forgecdn.net/files/2630/108/appliedenergistics2-rv6-stable-3.jar
-enderstorage-01.jar 4b44e4b5d4aa7887e2f0969acc9cf7b83c8c81f5 https://media.forgecdn.net/files/2594/243/EnderStorage-1.12.2-2.4.5.135-universal.jar
diff --git a/latest-urls.txt b/latest-urls.txt
deleted file mode 100644
index 7309b64..0000000
--- a/latest-urls.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-thaumcraft-01.jar https://minecraft.curseforge.com/projects/thaumcraft/files/2629023/download
-baubles-01.jar https://minecraft.curseforge.com/projects/baubles/files/2518667/download
-ae2-01.jar https://media.forgecdn.net/files/2630/108/appliedenergistics2-rv6-stable-3.jar
-tech-reborn-01.jar https://media.forgecdn.net/files/2633/989/TechReborn-1.12.2-2.17.7.840-universal.jar
-rftools-01.jar https://media.forgecdn.net/files/2616/385/rftools-1.12-7.56.jar
-tinkers-01.jar https://media.forgecdn.net/files/2571/785/TConstruct-1.12.2-2.10.1.87.jar
-enderio-01.jar https://media.forgecdn.net/files/2632/831/EnderIO-1.12.2-5.0.37.jar
-imersiveengineering-01.jar https://media.forgecdn.net/files/2625/312/ImmersiveEngineering-0.12-86.jar
-thermalexpansion-01.jar https://media.forgecdn.net/files/2624/855/ThermalExpansion-1.12.2-5.5.2.39-universal.jar
-thermaldynamics-01.jar https://media.forgecdn.net/files/2624/182/ThermalDynamics-1.12.2-2.5.3.16-universal.jar
-wirelesscraftingterminal-02.jar https://media.forgecdn.net/files/2619/932/WirelessCraftingTerminal-1.12.2-3.10.82.jar
-projectredcore-01.jar https://media.forgecdn.net/files/2572/409/MrTJPCore-1.12.2-2.1.3.35-universal.jar
-projectred-01.jar https://media.forgecdn.net/files/2572/421/ProjectRed-1.12.2-4.9.1.92-world.jar
-projectredcompat-01.jar https://media.forgecdn.net/files/2572/420/ProjectRed-1.12.2-4.9.1.92-compat.jar
-projectredmech-01.jar https://media.forgecdn.net/files/2572/422/ProjectRed-1.12.2-4.9.1.92-mechanical.jar
-projectredinteg-01.jar https://media.forgecdn.net/files/2572/427/ProjectRed-1.12.2-4.9.1.92-integration.jar
-translocators-01.jar https://media.forgecdn.net/files/2594/249/Translocators-1.12.2-2.5.1.77-universal.jar
-opencomputers-02.jar https://minecraft.curseforge.com/projects/opencomputers/files/2638675/download
-jei-01.jar https://media.forgecdn.net/files/2635/239/jei_1.12.2-4.13.1.222.jar
-thermalfoundation-01.jar https://media.forgecdn.net/files/2623/991/ThermalFoundation-1.12.2-2.6.1.22-universal.jar
-chickenchunks-01.jar https://media.forgecdn.net/files/2594/241/ChickenChunks-1.12.2-2.4.1.73-universal.jar
-enderstorage-01.jar https://media.forgecdn.net/files/2594/243/EnderStorage-1.12.2-2.4.5.135-universal.jar
-codechickenlib-01.jar https://media.forgecdn.net/files/2618/630/CodeChickenLib-1.12.2-3.2.2.353-universal.jar
-endercore-01.jar https://media.forgecdn.net/files/2632/476/EnderCore-1.12.2-0.5.43.jar
-forgemultipart-01.jar https://media.forgecdn.net/files/2626/992/ForgeMultipart-1.12.2-2.6.0.79-universal.jar
-cofhcore-01.jar https://media.forgecdn.net/files/2623/990/CoFHCore-1.12.2-4.6.1.22-universal.jar
-mantle-01.jar https://media.forgecdn.net/files/2630/843/Mantle-1.12-1.3.3.39.jar
-passwordlib-01.jar https://media.forgecdn.net/files/2616/338/p455w0rdslib-1.12-2.0.35.jar
-cofhworld-01.jar https://media.forgecdn.net/files/2623/91/CoFHWorld-1.12.2-1.3.0.6-universal.jar
-redstoneflux-01.jar https://media.forgecdn.net/files/2623/90/RedstoneFlux-1.12-2.1.0.6-universal.jar
-projectredcore2-01.jar https://media.forgecdn.net/files/2572/423/ProjectRed-1.12.2-4.9.1.92-Base.jar
-idklib-01.jar https://media.forgecdn.net/files/2626/982/mcjtylib-1.12-3.0.6.jar
-reborncore-01.jar https://media.forgecdn.net/files/2634/706/RebornCore-1.12.2-3.10.4.348-universal.jar
-twilightforest-01.jar https://minecraft.curseforge.com/projects/the-twilight-forest/files/2618264/download
-connectedtextures-01.jar https://minecraft.curseforge.com/projects/ctm/files/2629306/download
-foamfix.jar https://minecraft.curseforge.com/projects/foamfix-for-minecraft/files/latest
-# planarartiface-01.jar https://minecraft.curseforge.com/projects/planarartifice/files/2624612/download
diff --git a/mods.txt b/mods.txt
new file mode 100644
index 0000000..e608825
--- /dev/null
+++ b/mods.txt
@@ -0,0 +1,4 @@
+# fill this file with the same as downloads.txt but with links to the latest urls instead
+# e.g.
+thaumcraft.jar https://minecraft.curseforge.com/projects/thaumcraft/files/latest
+baubles.jar https://minecraft.curseforge.com/projects/baubles/files/latest
diff --git a/update.py b/update.py
index 68e598a..3404175 100755
--- a/update.py
+++ b/update.py
@@ -1,90 +1,174 @@
#!/usr/bin/env python3
-import hashlib
-import requests
+
+import argparse
import os
-import shutil
import sys
+import hashlib
+import shutil
+
+import requests
-# Initalize from config
-INSTALL_DIR = ""
-with open("pack-location.txt", "r") as f:
- INSTALL_DIR = f.read().strip()
+parser = argparse.ArgumentParser(
+ description="A Simple Git-Based Modpack Manager",
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ epilog='''\
+Available commands:
+ install : Downloads mods listed in version.txt and populates the mods folder specified in pack-location.txt
+ apply_updates : Using the urls in mods.txt, repopulates version.txt to reflect the most recent mod versions
+ check_updates : Compares version.txt and mods.txt to see if any mods can be updated
+''')
+parser.add_argument('command',
+ nargs='?',
+ default='install',
+ help="The action to perform (default: install)")
+parser.add_argument('filename',
+ nargs='?',
+ default="mods.txt",
+ help="Optional filename to specify latest mods (default: mods.txt)")
+parser.add_argument('--version-file',
+ type=str,
+ default="version.txt",
+ help="Optional custom version file to download mods from (default: version.txt)")
+parser.add_argument('--pack-location',
+ type=str,
+ help="Optional custom modpack folder location (default: read from pack-location.txt)")
+parser.add_argument('--whitelist-file',
+ type=str,
+ default="whitelist.txt",
+ help="Optional custom whitelist file that tells 'install' which files not to remove (default: whitelist.txt)")
+
+## loaded from version.txt
+VERSION = 0
+
+def read_file(fil):
+ strings = []
+ with open(fil) as f:
+ for line in f:
+ string = line.strip().split()
+ if len(line) > 1 and line[0] != '#':
+ # run strip on each element
+ string = tuple(map(lambda x: x.strip(), string))
+ strings.append(string)
+
+ return strings
# Apply updates to the actual mod pack
-def install():
- print("Updating pack...")
+def install(args):
+ print("Updating pack with version " + str(VERSION) + "...")
+ print()
# (fname, checksum, url)
- mods = read_file("downloads.txt")
+ mods = read_file(args.version_file)
names = [mod[0] for mod in mods]
+ # whitelist client mods (e.g. optifine)
+ names += [line[0] for line in read_file(args.whitelist_file)]
+
for mod in mods:
- if mod[0] in os.listdir(INSTALL_DIR) and hashlib.sha1(open(os.path.join(INSTALL_DIR, mod[0]), 'rb').read()).hexdigest() == mod[1]:
- print("Skipping " + mod[0] + ", already up to date")
+ mod_path = os.path.join(args.pack_location, mod[0])
+ if os.path.exists(mod_path) and os.path.isfile(mod_path) and \
+ hashlib.sha1(open(mod_path, 'rb').read()).hexdigest() == mod[1]:
+ print("Skipping {mod[0]}, already up to date".format(mod=mod))
else:
- print(f'Installing {mod[0]} from {mod[2]}...')
+ print('Installing {mod[0]} from {mod[2]}...'.format(mod=mod))
download_obj = requests.get(mod[2], stream=True)
- with open(os.path.join(INSTALL_DIR, mod[0]), "wb") as write_file:
+ with open(mod_path, "wb") as write_file:
shutil.copyfileobj(download_obj.raw, write_file)
print("Done!")
- print("\nRemoving old versions...")
- for jar in os.listdir(INSTALL_DIR):
+ print()
+ print("Removing old mods...")
+ for jar in os.listdir(args.pack_location):
if jar not in names and os.path.splitext(jar)[1] == ".jar":
- os.remove(os.path.join(INSTALL_DIR, jar))
- print(f"Removing '{jar}'")
+ os.remove(os.path.join(args.pack_location, jar))
+ print("Removing '{jar}'".format(jar=jar))
- print("\nFinished updating pack!")
+ print()
+ print("Finished installing mods!")
-# Using the latest urls, update downloads.txt to match the urls and have the correct sha1
-def apply_updates():
- print("Reading update file...")
- mods = read_file("latest-urls.txt")
- print("Downloading new versions of all mods...")
- with open('downloads.txt', 'w') as f:
+# Using the latest urls, update downloads.txt to match and have the correct sha1
+def apply_updates(args):
+ print("Populating version File...")
+ mods = read_file(args.filename)
+ print("Getting new versions of all mods...")
+ with open(args.version_file, 'w') as f:
f.write('# Format: <jarname> <hex digested sha1> <direct download url>\n')
+ f.write("#VERSION " + str(VERSION + 1) + "\n")
for mod in mods:
- print(f"Downloading {mod[0]}...")
+ print("Fetching {mod[0]}...".format(mod=mod))
resp = requests.get(mod[1])
- hsh = hashlib.sha1(resp.content)
- f.write(f'{mod[0]} {hsh.hexdigest()} {resp.url}\n')
- print("\nDone downloading updates!")
+ hsh = hashlib.sha1(resp.content).hexdigest()
+ f.write('{mod[0]} {hsh} {resp.url}\n'.format(mod=mod, hsh=hsh, resp=resp))
+ print()
+ print("Done!")
+ print("Updates applied to {args.version_file}".format(args=args))
+ print("New pack version is " + str(VERSION + 1))
+ print("[!] No mods were installed. To update your mods folder, run 'update.py install'")
+
# Find if any updates are available
-def check_updates():
- print("Reading update files...")
- latest = read_file("latest-urls.txt")
- old = read_file("downloads.txt")
+def check_updates(args):
+ print("Checking for updates to version " + str(VERSION) + "...")
+ latest = read_file(args.filename)
+ old = read_file(args.version_file)
old_urls = [mod[2] for mod in old]
+ num_updates = 0
- print("Checking updates...\nThe following mods have updates available:\n")
+ print("Checking updates...")
for mod in latest:
+ print("Checking for updates to {mod[0]}...".format(mod=mod), end="")
+ sys.stdout.flush() # takes care of line-buffered terminals
resp = requests.get(mod[1])
- if not resp.url in old_urls:
- print(f" -> Found update for {mod[0]}: {resp.url.split('/')[-1]}")
- print("\nFinished checking for updates!")
+ if resp.url in old_urls:
+ print(" No updates")
+ else:
+ print(" Found update: " + resp.url.split('/')[-1])
+ num_updates += 1
+
+ print("Finished checking for updates. {num} mods can be updated".format(num=num_updates))
+ if num_updates >= 0:
+ print("Run 'python update.py apply_updates' to create a new version with these updates applied.")
-def read_file(fil):
- strings = set()
- with open(fil) as f:
- for line in f:
- string = line.strip().split()
- if len(line) >= 1 and line[0] != '#':
- # run strip on each element
- string = tuple(map(lambda x: x.strip(), string))
- strings.add(string)
- return strings
+COMMAND_MAP = {
+ 'install': install,
+ 'apply_updates': apply_updates,
+ 'check_updates': check_updates,
+}
+if __name__ == "__main__":
+ args = parser.parse_args()
+
+ if not args.pack_location:
+ # initialize from config
+ with open("pack-location.txt", "r") as f:
+ args.pack_location = f.read().strip()
-if len(sys.argv) < 2:
- print(f"Usage: {sys.argv[0]} <apply_updates|find_updates>")
- sys.exit(-1)
-elif sys.argv[1] == 'install':
- install()
-elif sys.argv[1] == 'apply_updates':
- apply_updates()
-elif sys.argv[1] == 'check_updates':
- check_updates()
-else:
- print(f"Usage: {sys.argv[0]} <install|apply_updates|check_updates>")
- sys.exit(-1)
+ if not os.path.exists(args.version_file):
+ print("Error: version file\"" + args.version_file + "\" does not exist.")
+ parser.print_help()
+ sys.exit(1)
+ if not os.path.exists(args.pack_location):
+ print("Error: mod folder \"" + args.pack_location + "\" does not exist.")
+ parser.print_help()
+ sys.exit(1)
+ elif not os.path.isdir(args.pack_location):
+ print("Error: mod folder \"" + args.pack_location + "\" is not actually a folder.")
+ parser.print_help()
+ sys.exit(1)
+ if not os.path.exists(args.whitelist_file):
+ print("Error: whitelist file \"" + args.whitelist_file + "\" does not exist.")
+ sys.exit(1)
+
+ if not (args.command in COMMAND_MAP):
+ print("Error: command \"" + args.command + "\" does not exist")
+ parser.print_help()
+ sys.exit(1)
+
+ # fetch version
+ with open(args.version_file) as f:
+ for line in f:
+ if line.strip().split()[0] == "#VERSION":
+ VERSION = int(line.strip().split()[1])
+ break
+ # run the command
+ COMMAND_MAP[args.command](args)
diff --git a/version.txt b/version.txt
new file mode 100644
index 0000000..eb901a8
--- /dev/null
+++ b/version.txt
@@ -0,0 +1,4 @@
+# Format: <jarname> <hex digested sha1> <direct download url>
+#VERSION 16
+thaumcraft.jar ef9f8aaf4a4bfe29afb9ebc0fb90b15f2a62a0fb https://minecraft.curseforge.com/projects/thaumcraft/files/latest
+baubles.jar 498452d113a210bda499c49b650b4eae57866a19 https://minecraft.curseforge.com/projects/baubles/files/latest
diff --git a/whitelist.txt b/whitelist.txt
new file mode 100644
index 0000000..76c8d1f
--- /dev/null
+++ b/whitelist.txt
@@ -0,0 +1 @@
+# file names in here are NOT removed from mods folder during 'install'