From cab294c9f611637a0562463a7201df27cea5e365 Mon Sep 17 00:00:00 2001 From: Geoff Bourne Date: Sun, 30 Jul 2023 08:55:11 -0500 Subject: [PATCH] cf: added support for ModLoaderType=6 for NeoForge --- dev/.gitignore | 1 + dev/curseforge.http | 34 +++++++++++++ dev/purpur.http | 21 ++++++++ .../curseforge/CurseForgeApiClient.java | 9 ++-- .../curseforge/CurseForgeInstaller.java | 51 ++++++++++++------- .../curseforge/InstallCurseForgeCommand.java | 25 +++++---- .../curseforge/model/ModLoaderType.java | 4 +- 7 files changed, 108 insertions(+), 37 deletions(-) create mode 100644 dev/.gitignore create mode 100644 dev/curseforge.http create mode 100644 dev/purpur.http diff --git a/dev/.gitignore b/dev/.gitignore new file mode 100644 index 00000000..42c7d2cd --- /dev/null +++ b/dev/.gitignore @@ -0,0 +1 @@ +http-client.private.env.json \ No newline at end of file diff --git a/dev/curseforge.http b/dev/curseforge.http new file mode 100644 index 00000000..ff24ff7e --- /dev/null +++ b/dev/curseforge.http @@ -0,0 +1,34 @@ +### +GET https://api.curseforge.com/v1/categories?gameId=432&classesOnly=true +x-api-key: {{cfApiKey}} + +<> 2023-04-01T131517.200.json +<> 2023-03-30T083426.200.json + +### +GET https://api.curseforge.com/v1/mods/350464 +x-api-key: {{cfApiKey}} + +### +GET https://api.curseforge.com/v1/mods/694605/files/4098018/download-url +x-api-key: {{cfApiKey}} + +### +GET https://api.curseforge.com/v1/mods/369096/files/4560441 +x-api-key: {{cfApiKey}} + +<> 2023-04-01T192357.200.json + +### +GET https://api.curseforge.com/v1/mods/622737/files/4560441 +x-api-key: {{cfApiKey}} + +<> 2023-03-30T081023.200.json +<> 2023-03-30T075419.200.json +<> 2023-03-30T074422.200.json + +### +GET https://api.curseforge.com/v1/mods/707734/files/4415193 +x-api-key: {{cfApiKey}} + +<> 2023-03-30T080528.403.html \ No newline at end of file diff --git a/dev/purpur.http b/dev/purpur.http new file mode 100644 index 00000000..f05e18ac --- /dev/null +++ b/dev/purpur.http @@ -0,0 +1,21 @@ +### +GET https://api.purpurmc.org/v2/purpur/1.20 +User-Agent: mc-image-helper + +<> f-3.txt +<> f-2.txt + +### +GET https://api.purpurmc.org/v2/purpur/1.19.4/1985 +User-Agent: mc-image-helper + +<> 2023-06-13T204234.200.json + +### +GET https://api.purpurmc.org/v2/purpur/1.19.4/1985/download +User-Agent: mc-image-helper + +<> purpur-1.19.4-1985.jar +<> 2023-06-13T170922.200.json +<> f-1.txt +<> f.txt \ No newline at end of file diff --git a/src/main/java/me/itzg/helpers/curseforge/CurseForgeApiClient.java b/src/main/java/me/itzg/helpers/curseforge/CurseForgeApiClient.java index 3888f362..8b700796 100644 --- a/src/main/java/me/itzg/helpers/curseforge/CurseForgeApiClient.java +++ b/src/main/java/me/itzg/helpers/curseforge/CurseForgeApiClient.java @@ -53,7 +53,7 @@ public void close() { preparedFetch.close(); } - public CategoryInfo loadCategoryInfo(Set applicableClassIdSlugs, String categorySlug) { + CategoryInfo loadModpacksCategoryInfo(Set applicableClassIdSlugs) { return preparedFetch // get only categories that are classes, like mc-mods .fetch(uriBuilder.resolve("/categories?gameId={gameId}&classesOnly=true", gameId)) @@ -67,7 +67,7 @@ public CategoryInfo loadCategoryInfo(Set applicableClassIdSlugs, String if (applicableClassIdSlugs.contains(category.getSlug())) { contentClassIds.put(category.getId(), category); } - if (category.getSlug().equals(categorySlug)) { + if (category.getSlug().equals(CurseForgeInstaller.CATEGORY_SLUG_MODPACKS)) { modpackClassId = category.getId(); } } @@ -82,7 +82,7 @@ public CategoryInfo loadCategoryInfo(Set applicableClassIdSlugs, String .block(); } - public CurseForgeMod searchMod(String slug, CategoryInfo categoryInfo) { + CurseForgeMod searchMod(String slug, CategoryInfo categoryInfo) { final ModsSearchResponse searchResponse = preparedFetch.fetch( uriBuilder.resolve("/mods/search?gameId={gameId}&slug={slug}&classId={classId}", gameId, slug, categoryInfo.modpackClassId @@ -130,7 +130,7 @@ public CurseForgeFile resolveModpackFile( }); } - public Mono slugToId(CategoryInfo categoryInfo, + Mono slugToId(CategoryInfo categoryInfo, String slug ) { return preparedFetch @@ -158,6 +158,7 @@ public Mono getModInfo( ) .toObject(GetModResponse.class) .assemble() + .checkpoint("Getting mod info for " + projectID) .map(GetModResponse::getData); } diff --git a/src/main/java/me/itzg/helpers/curseforge/CurseForgeInstaller.java b/src/main/java/me/itzg/helpers/curseforge/CurseForgeInstaller.java index 595189ce..e21941b9 100644 --- a/src/main/java/me/itzg/helpers/curseforge/CurseForgeInstaller.java +++ b/src/main/java/me/itzg/helpers/curseforge/CurseForgeInstaller.java @@ -1,12 +1,41 @@ package me.itzg.helpers.curseforge; +import static java.util.Collections.emptySet; +import static java.util.Objects.requireNonNull; +import static java.util.Optional.ofNullable; +import static me.itzg.helpers.singles.MoreCollections.safeStreamFrom; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.Setter; import lombok.extern.slf4j.Slf4j; import me.itzg.helpers.curseforge.ExcludeIncludesContent.ExcludeIncludes; -import me.itzg.helpers.curseforge.model.*; +import me.itzg.helpers.curseforge.model.Category; +import me.itzg.helpers.curseforge.model.CurseForgeFile; +import me.itzg.helpers.curseforge.model.CurseForgeMod; +import me.itzg.helpers.curseforge.model.ManifestFileRef; +import me.itzg.helpers.curseforge.model.ManifestType; +import me.itzg.helpers.curseforge.model.MinecraftModpackManifest; +import me.itzg.helpers.curseforge.model.ModLoader; import me.itzg.helpers.errors.GenericException; import me.itzg.helpers.errors.InvalidParameterException; import me.itzg.helpers.fabric.FabricLauncherInstaller; @@ -20,22 +49,6 @@ import reactor.core.publisher.Mono; import reactor.core.scheduler.Schedulers; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardCopyOption; -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - -import static java.util.Collections.emptySet; -import static java.util.Objects.requireNonNull; -import static java.util.Optional.ofNullable; -import static me.itzg.helpers.singles.MoreCollections.safeStreamFrom; - @RequiredArgsConstructor @Slf4j public class CurseForgeInstaller { @@ -131,7 +144,7 @@ public void install(String slug, String fileMatcher, Integer fileId) throws IOEx ); } - protected void install(String slug, InstallationEntryPoint entryPoint) throws IOException { + void install(String slug, InstallationEntryPoint entryPoint) throws IOException { requireNonNull(outputDir, "outputDir is required"); requireNonNull(slug); requireNonNull(entryPoint); @@ -160,7 +173,7 @@ protected void install(String slug, InstallationEntryPoint entryPoint) throws IO MINECRAFT_GAME_ID ) ) { - final CategoryInfo categoryInfo = cfApi.loadCategoryInfo(applicableClassIdSlugs, CATEGORY_SLUG_MODPACKS); + final CategoryInfo categoryInfo = cfApi.loadModpacksCategoryInfo(applicableClassIdSlugs); entryPoint.install( new InstallContext(slug, cfApi, categoryInfo, manifest) diff --git a/src/main/java/me/itzg/helpers/curseforge/InstallCurseForgeCommand.java b/src/main/java/me/itzg/helpers/curseforge/InstallCurseForgeCommand.java index 11ee6cc8..59aea6db 100644 --- a/src/main/java/me/itzg/helpers/curseforge/InstallCurseForgeCommand.java +++ b/src/main/java/me/itzg/helpers/curseforge/InstallCurseForgeCommand.java @@ -1,15 +1,6 @@ package me.itzg.helpers.curseforge; -import me.itzg.helpers.files.ResultsFileWriter; -import me.itzg.helpers.files.TabularOutput; -import me.itzg.helpers.http.PathOrUri; -import me.itzg.helpers.http.PathOrUriConverter; -import me.itzg.helpers.http.SharedFetchArgs; -import me.itzg.helpers.json.ObjectMappers; -import picocli.CommandLine.ArgGroup; -import picocli.CommandLine.Command; -import picocli.CommandLine.ExitCode; -import picocli.CommandLine.Option; +import static me.itzg.helpers.http.Fetch.fetch; import java.io.BufferedWriter; import java.io.IOException; @@ -22,8 +13,16 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; - -import static me.itzg.helpers.http.Fetch.fetch; +import me.itzg.helpers.files.ResultsFileWriter; +import me.itzg.helpers.files.TabularOutput; +import me.itzg.helpers.http.PathOrUri; +import me.itzg.helpers.http.PathOrUriConverter; +import me.itzg.helpers.http.SharedFetchArgs; +import me.itzg.helpers.json.ObjectMappers; +import picocli.CommandLine.ArgGroup; +import picocli.CommandLine.Command; +import picocli.CommandLine.ExitCode; +import picocli.CommandLine.Option; @Command(name = "install-curseforge", subcommands = { SchemasCommand.class @@ -228,7 +227,7 @@ public Integer call() throws Exception { System.err.println("Some mod authors disallow automated downloads."); System.err.println("The following need to be manually downloaded into the repo or excluded:"); if (needsDownloadFile != null) { - System.err.printf("(Also written to %s%n", needsDownloadFile); + System.err.printf("(Also written to %s)%n", needsDownloadFile); } System.err.println(); final PrintWriter out = new PrintWriter(System.err); diff --git a/src/main/java/me/itzg/helpers/curseforge/model/ModLoaderType.java b/src/main/java/me/itzg/helpers/curseforge/model/ModLoaderType.java index 736c83c6..c9e7559a 100644 --- a/src/main/java/me/itzg/helpers/curseforge/model/ModLoaderType.java +++ b/src/main/java/me/itzg/helpers/curseforge/model/ModLoaderType.java @@ -8,7 +8,9 @@ public enum ModLoaderType { Cauldron, LiteLoader, Fabric, - Quilt; + Quilt, + // undocumented as of 2023-07-23 but referenced in https://www.curseforge.com/minecraft/mc-mods/chimes/files/4671986 + NeoForge; @JsonValue public int toValue() {