Inceptum/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/api/CurseforgeApi.java

91 lines
4.4 KiB
Java

package io.gitlab.jfronny.inceptum.launcher.api;
import gsoncompile.extensions.io.gitlab.jfronny.inceptum.launcher.model.curseforge.response.FingerprintMatchesResponse.GC_FingerprintMatchesResponse;
import gsoncompile.extensions.io.gitlab.jfronny.inceptum.launcher.model.curseforge.response.GetModFileResponse.GC_GetModFileResponse;
import gsoncompile.extensions.io.gitlab.jfronny.inceptum.launcher.model.curseforge.response.GetModResponse.GC_GetModResponse;
import gsoncompile.extensions.io.gitlab.jfronny.inceptum.launcher.model.curseforge.response.SearchResponse.GC_SearchResponse;
import io.gitlab.jfronny.commons.HttpUtils;
import io.gitlab.jfronny.inceptum.common.Net;
import io.gitlab.jfronny.inceptum.launcher.model.curseforge.CurseforgeFile;
import io.gitlab.jfronny.inceptum.launcher.model.curseforge.CurseforgeMod;
import io.gitlab.jfronny.inceptum.launcher.model.curseforge.response.*;
import java.io.*;
import java.net.URISyntaxException;
import java.util.*;
public class CurseforgeApi {
// So you found the API key.
// Please be aware that CurseForge requires you to change this if you make any kind of derivative work
// Creating your own API key is relatively simple, so please don't abuse this
private static final String API_KEY = new String(unsalt(new byte[]{
-30, 50, -60, -121, 62, -31, 35, 17, 16, -53,
-53, -88, 21, -21, 15, -105, -115, -108, 114, -50,
-49, -4, 56, -65, -70, 108, -65, -3, -55, -4,
36, -86, -40, 116, 71, -5, 75, -9, -43, 4,
91, -91, -29, 40, 66, 87, -80, -74, 71, 41,
76, -96, 108, -61, -113, 118, 7, -39, -116, -120
}, 1024));
private static final String API_URL = "https://api.curseforge.com/v1/";
private static final int pageSize = 20;
public static List<CurseforgeMod> search(String gameVersion, String query, int page, String sort) throws IOException {
return Net.downloadObject(Net.buildUrl(API_URL, "mods/search", Map.of(
"gameId", "432", // minecraft
"modLoaderType", "4", // fabric
"classId", "6", // mods
// "categoryId", ""
"searchFilter", query,
"sortField", sort,
"sortOrder", "desc",
"gameVersion", gameVersion,
"pageSize", Integer.toString(pageSize),
"index", Integer.toString(page * pageSize)
)), GC_SearchResponse::read, API_KEY).data;
}
public static CurseforgeMod getMod(String slug) throws IOException {
SearchResponse response = Net.downloadObject(Net.buildUrl(API_URL, "mods/search", Map.of(
"gameId", "432",
"classId", "6",
"slug", slug
)), GC_SearchResponse::read, API_KEY);
if (response.pagination.totalCount != 1) {
throw new FileNotFoundException("Could not find mod with slug \"" + slug + "\"");
}
return checkDistribution(response.data[0]);
}
public static CurseforgeMod getMod(int id) throws IOException {
return checkDistribution(Net.downloadObject(API_URL + "mods/" + id, GC_GetModResponse::read, API_KEY).data);
}
private static CurseforgeMod checkDistribution(CurseforgeMod mod) {
if (!mod.allowModDistribution) {
throw new IllegalArgumentException("The author of the mod \"" + mod.slug + "\" has chosen to deliberately break your ability of downloading it.\n"
+ "Please let them know that disabling third party downloads does nothing but make the users life harder for no reason.");
}
return mod;
}
public static CurseforgeFile getFile(int modId, int fileId) throws IOException {
return Net.downloadObject(API_URL + "mods/" + modId + "/files/" + fileId, GC_GetModFileResponse::read, API_KEY).data;
}
public static FingerprintMatchesResponse.Result checkFingerprint(long hash) throws IOException, URISyntaxException {
try (Reader r = HttpUtils.post(API_URL + "fingerprints").bodyJson("{\"fingerprints\":[" + hash + "]}").sendReader()) {
return GC_FingerprintMatchesResponse.read(r).data;
}
}
private static byte[] unsalt(byte[] data, int salt) {
byte[] result = new byte[data.length];
new Random(salt).nextBytes(result);
for (int i = 0; i < data.length; i++) {
result[i] ^= data[i];
}
return result;
}
}