feat: (WIP) Curse mod/modpack download
This commit is contained in:
@@ -0,0 +1,435 @@
|
||||
package org.jackhuang.hmcl.mod.curse;
|
||||
|
||||
import org.jackhuang.hmcl.util.Immutable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Immutable
|
||||
public class CurseAddon {
|
||||
private final int id;
|
||||
private final String name;
|
||||
private final List<Author> authors;
|
||||
private final String websiteUrl;
|
||||
private final int gameId;
|
||||
private final String summary;
|
||||
private final int defaultFileId;
|
||||
private final List<LatestFile> latestFiles;
|
||||
private final List<Category> categories;
|
||||
private final int status;
|
||||
private final int primaryCategoryId;
|
||||
private final String slug;
|
||||
private final List<GameVersionLatestFile> gameVersionLatestFiles;
|
||||
private final boolean isFeatured;
|
||||
private final double popularityScore;
|
||||
private final int gamePopularityRank;
|
||||
private final String primaryLanguage; // e.g. enUS
|
||||
private final List<String> modLoaders;
|
||||
private final boolean isAvailable;
|
||||
private final boolean isExperimental;
|
||||
|
||||
public CurseAddon(int id, String name, List<Author> authors, String websiteUrl, int gameId, String summary, int defaultFileId, List<LatestFile> latestFiles, List<Category> categories, int status, int primaryCategoryId, String slug, List<GameVersionLatestFile> gameVersionLatestFiles, boolean isFeatured, double popularityScore, int gamePopularityRank, String primaryLanguage, List<String> modLoaders, boolean isAvailable, boolean isExperimental) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.authors = authors;
|
||||
this.websiteUrl = websiteUrl;
|
||||
this.gameId = gameId;
|
||||
this.summary = summary;
|
||||
this.defaultFileId = defaultFileId;
|
||||
this.latestFiles = latestFiles;
|
||||
this.categories = categories;
|
||||
this.status = status;
|
||||
this.primaryCategoryId = primaryCategoryId;
|
||||
this.slug = slug;
|
||||
this.gameVersionLatestFiles = gameVersionLatestFiles;
|
||||
this.isFeatured = isFeatured;
|
||||
this.popularityScore = popularityScore;
|
||||
this.gamePopularityRank = gamePopularityRank;
|
||||
this.primaryLanguage = primaryLanguage;
|
||||
this.modLoaders = modLoaders;
|
||||
this.isAvailable = isAvailable;
|
||||
this.isExperimental = isExperimental;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public List<Author> getAuthors() {
|
||||
return authors;
|
||||
}
|
||||
|
||||
public String getWebsiteUrl() {
|
||||
return websiteUrl;
|
||||
}
|
||||
|
||||
public int getGameId() {
|
||||
return gameId;
|
||||
}
|
||||
|
||||
public String getSummary() {
|
||||
return summary;
|
||||
}
|
||||
|
||||
public int getDefaultFileId() {
|
||||
return defaultFileId;
|
||||
}
|
||||
|
||||
public List<LatestFile> getLatestFiles() {
|
||||
return latestFiles;
|
||||
}
|
||||
|
||||
public List<Category> getCategories() {
|
||||
return categories;
|
||||
}
|
||||
|
||||
public int getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public int getPrimaryCategoryId() {
|
||||
return primaryCategoryId;
|
||||
}
|
||||
|
||||
public String getSlug() {
|
||||
return slug;
|
||||
}
|
||||
|
||||
public List<GameVersionLatestFile> getGameVersionLatestFiles() {
|
||||
return gameVersionLatestFiles;
|
||||
}
|
||||
|
||||
public boolean isFeatured() {
|
||||
return isFeatured;
|
||||
}
|
||||
|
||||
public double getPopularityScore() {
|
||||
return popularityScore;
|
||||
}
|
||||
|
||||
public int getGamePopularityRank() {
|
||||
return gamePopularityRank;
|
||||
}
|
||||
|
||||
public String getPrimaryLanguage() {
|
||||
return primaryLanguage;
|
||||
}
|
||||
|
||||
public List<String> getModLoaders() {
|
||||
return modLoaders;
|
||||
}
|
||||
|
||||
public boolean isAvailable() {
|
||||
return isAvailable;
|
||||
}
|
||||
|
||||
public boolean isExperimental() {
|
||||
return isExperimental;
|
||||
}
|
||||
|
||||
@Immutable
|
||||
public static class Author {
|
||||
private final String name;
|
||||
private final String url;
|
||||
private final int projectId;
|
||||
private final int id;
|
||||
private final int userId;
|
||||
private final int twitchId;
|
||||
|
||||
public Author(String name, String url, int projectId, int id, int userId, int twitchId) {
|
||||
this.name = name;
|
||||
this.url = url;
|
||||
this.projectId = projectId;
|
||||
this.id = id;
|
||||
this.userId = userId;
|
||||
this.twitchId = twitchId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public int getProjectId() {
|
||||
return projectId;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public int getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public int getTwitchId() {
|
||||
return twitchId;
|
||||
}
|
||||
}
|
||||
|
||||
@Immutable
|
||||
public static class Dependency {
|
||||
private final int id;
|
||||
private final int addonId;
|
||||
private final int type;
|
||||
private final int fileId;
|
||||
|
||||
public Dependency() {
|
||||
this(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
public Dependency(int id, int addonId, int type, int fileId) {
|
||||
this.id = id;
|
||||
this.addonId = addonId;
|
||||
this.type = type;
|
||||
this.fileId = fileId;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public int getAddonId() {
|
||||
return addonId;
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public int getFileId() {
|
||||
return fileId;
|
||||
}
|
||||
}
|
||||
|
||||
@Immutable
|
||||
public static class LatestFile {
|
||||
private final int id;
|
||||
private final String displayName;
|
||||
private final String fileDate;
|
||||
private final int fileLength;
|
||||
private final int releaseType;
|
||||
private final int fileStatus;
|
||||
private final String downloadUrl;
|
||||
private final boolean isAlternate;
|
||||
private final int alternateFileId;
|
||||
private final List<Dependency> dependencies;
|
||||
private final boolean isAvailable;
|
||||
private final List<String> gameVersion;
|
||||
private final boolean hasInstallScript;
|
||||
private final boolean isCompatibleWIthClient;
|
||||
private final int categorySectionPackageType;
|
||||
private final int restrictProjectFileAccess;
|
||||
private final int projectStatus;
|
||||
private final int projectId;
|
||||
private final int isServerPack;
|
||||
private final int serverPackFileId;
|
||||
|
||||
public LatestFile(int id, String displayName, String fileDate, int fileLength, int releaseType, int fileStatus, String downloadUrl, boolean isAlternate, int alternateFileId, List<Dependency> dependencies, boolean isAvailable, List<String> gameVersion, boolean hasInstallScript, boolean isCompatibleWIthClient, int categorySectionPackageType, int restrictProjectFileAccess, int projectStatus, int projectId, int isServerPack, int serverPackFileId) {
|
||||
this.id = id;
|
||||
this.displayName = displayName;
|
||||
this.fileDate = fileDate;
|
||||
this.fileLength = fileLength;
|
||||
this.releaseType = releaseType;
|
||||
this.fileStatus = fileStatus;
|
||||
this.downloadUrl = downloadUrl;
|
||||
this.isAlternate = isAlternate;
|
||||
this.alternateFileId = alternateFileId;
|
||||
this.dependencies = dependencies;
|
||||
this.isAvailable = isAvailable;
|
||||
this.gameVersion = gameVersion;
|
||||
this.hasInstallScript = hasInstallScript;
|
||||
this.isCompatibleWIthClient = isCompatibleWIthClient;
|
||||
this.categorySectionPackageType = categorySectionPackageType;
|
||||
this.restrictProjectFileAccess = restrictProjectFileAccess;
|
||||
this.projectStatus = projectStatus;
|
||||
this.projectId = projectId;
|
||||
this.isServerPack = isServerPack;
|
||||
this.serverPackFileId = serverPackFileId;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public String getFileDate() {
|
||||
return fileDate;
|
||||
}
|
||||
|
||||
public int getFileLength() {
|
||||
return fileLength;
|
||||
}
|
||||
|
||||
public int getReleaseType() {
|
||||
return releaseType;
|
||||
}
|
||||
|
||||
public int getFileStatus() {
|
||||
return fileStatus;
|
||||
}
|
||||
|
||||
public String getDownloadUrl() {
|
||||
return downloadUrl;
|
||||
}
|
||||
|
||||
public boolean isAlternate() {
|
||||
return isAlternate;
|
||||
}
|
||||
|
||||
public int getAlternateFileId() {
|
||||
return alternateFileId;
|
||||
}
|
||||
|
||||
public List<Dependency> getDependencies() {
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
public boolean isAvailable() {
|
||||
return isAvailable;
|
||||
}
|
||||
|
||||
public List<String> getGameVersion() {
|
||||
return gameVersion;
|
||||
}
|
||||
|
||||
public boolean isHasInstallScript() {
|
||||
return hasInstallScript;
|
||||
}
|
||||
|
||||
public boolean isCompatibleWIthClient() {
|
||||
return isCompatibleWIthClient;
|
||||
}
|
||||
|
||||
public int getCategorySectionPackageType() {
|
||||
return categorySectionPackageType;
|
||||
}
|
||||
|
||||
public int getRestrictProjectFileAccess() {
|
||||
return restrictProjectFileAccess;
|
||||
}
|
||||
|
||||
public int getProjectStatus() {
|
||||
return projectStatus;
|
||||
}
|
||||
|
||||
public int getProjectId() {
|
||||
return projectId;
|
||||
}
|
||||
|
||||
public int getIsServerPack() {
|
||||
return isServerPack;
|
||||
}
|
||||
|
||||
public int getServerPackFileId() {
|
||||
return serverPackFileId;
|
||||
}
|
||||
}
|
||||
|
||||
@Immutable
|
||||
public static class Category {
|
||||
private final int categoryId;
|
||||
private final String name;
|
||||
private final String url;
|
||||
private final String avatarUrl;
|
||||
private final int parentId;
|
||||
private final int rootId;
|
||||
private final int projectId;
|
||||
private final int avatarId;
|
||||
private final int gameId;
|
||||
|
||||
public Category(int categoryId, String name, String url, String avatarUrl, int parentId, int rootId, int projectId, int avatarId, int gameId) {
|
||||
this.categoryId = categoryId;
|
||||
this.name = name;
|
||||
this.url = url;
|
||||
this.avatarUrl = avatarUrl;
|
||||
this.parentId = parentId;
|
||||
this.rootId = rootId;
|
||||
this.projectId = projectId;
|
||||
this.avatarId = avatarId;
|
||||
this.gameId = gameId;
|
||||
}
|
||||
|
||||
public int getCategoryId() {
|
||||
return categoryId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public String getAvatarUrl() {
|
||||
return avatarUrl;
|
||||
}
|
||||
|
||||
public int getParentId() {
|
||||
return parentId;
|
||||
}
|
||||
|
||||
public int getRootId() {
|
||||
return rootId;
|
||||
}
|
||||
|
||||
public int getProjectId() {
|
||||
return projectId;
|
||||
}
|
||||
|
||||
public int getAvatarId() {
|
||||
return avatarId;
|
||||
}
|
||||
|
||||
public int getGameId() {
|
||||
return gameId;
|
||||
}
|
||||
}
|
||||
|
||||
@Immutable
|
||||
public static class GameVersionLatestFile {
|
||||
private final String gameVersion;
|
||||
private final String projectFileId;
|
||||
private final String projectFileName;
|
||||
private final int fileType;
|
||||
private final Integer modLoader; // optional
|
||||
|
||||
public GameVersionLatestFile(String gameVersion, String projectFileId, String projectFileName, int fileType, Integer modLoader) {
|
||||
this.gameVersion = gameVersion;
|
||||
this.projectFileId = projectFileId;
|
||||
this.projectFileName = projectFileName;
|
||||
this.fileType = fileType;
|
||||
this.modLoader = modLoader;
|
||||
}
|
||||
|
||||
public String getGameVersion() {
|
||||
return gameVersion;
|
||||
}
|
||||
|
||||
public String getProjectFileId() {
|
||||
return projectFileId;
|
||||
}
|
||||
|
||||
public String getProjectFileName() {
|
||||
return projectFileName;
|
||||
}
|
||||
|
||||
public int getFileType() {
|
||||
return fileType;
|
||||
}
|
||||
|
||||
public Integer getModLoader() {
|
||||
return modLoader;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package org.jackhuang.hmcl.mod.curse;
|
||||
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
||||
import org.jackhuang.hmcl.util.io.NetworkUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.*;
|
||||
|
||||
import static org.jackhuang.hmcl.util.Lang.mapOf;
|
||||
import static org.jackhuang.hmcl.util.Pair.pair;
|
||||
|
||||
public class CurseModManager {
|
||||
|
||||
public static List<CurseAddon> searchPaginated(String gameVersion, int category, int section, int pageOffset, String searchFilter, int sort) throws IOException {
|
||||
String response = NetworkUtils.doGet(new URL(NetworkUtils.withQuery("https://addons-ecs.forgesvc.net/api/v2/addon/search", mapOf(
|
||||
pair("categoryId", Integer.toString(category)),
|
||||
pair("gameId", "432"),
|
||||
pair("gameVersion", gameVersion),
|
||||
pair("index", Integer.toString(pageOffset)),
|
||||
pair("pageSize", "25"),
|
||||
pair("searchFilter", searchFilter),
|
||||
pair("sectionId", Integer.toString(section)),
|
||||
pair("sort", Integer.toString(sort))
|
||||
))));
|
||||
return JsonUtils.fromNonNullJson(response, new TypeToken<List<CurseAddon>>() {
|
||||
}.getType());
|
||||
}
|
||||
|
||||
public static List<Category> getCategories(int section) throws IOException {
|
||||
String response = NetworkUtils.doGet(NetworkUtils.toURL("https://addons-ecs.forgesvc.net/api/v2/category/section/" + section));
|
||||
List<Category> categories = JsonUtils.fromNonNullJson(response, new TypeToken<List<Category>>() {
|
||||
}.getType());
|
||||
return reorganizeCategories(categories, section);
|
||||
}
|
||||
|
||||
private static List<Category> reorganizeCategories(List<Category> categories, int rootId) {
|
||||
List<Category> result = new ArrayList<>();
|
||||
|
||||
Map<Integer, Category> categoryMap = new HashMap<>();
|
||||
for (Category category : categories) {
|
||||
categoryMap.put(category.id, category);
|
||||
}
|
||||
for (Category category : categories) {
|
||||
if (category.parentGameCategoryId == rootId) {
|
||||
result.add(category);
|
||||
} else {
|
||||
Category parentCategory = categoryMap.get(category.parentGameCategoryId);
|
||||
if (parentCategory == null) {
|
||||
// Category list is not correct, so we ignore this item.
|
||||
continue;
|
||||
}
|
||||
parentCategory.subcategories.add(category);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static final int SECTION_MODPACK = 4471;
|
||||
public static final int SECTION_MOD = 6;
|
||||
|
||||
public static class Category {
|
||||
private final int id;
|
||||
private final String name;
|
||||
private final String slug;
|
||||
private final String avatarUrl;
|
||||
private final int parentGameCategoryId;
|
||||
private final int rootGameCategoryId;
|
||||
private final int gameId;
|
||||
|
||||
private final List<Category> subcategories;
|
||||
|
||||
public Category() {
|
||||
this(0, "", "", "", 0, 0, 0, new ArrayList<>());
|
||||
}
|
||||
|
||||
public Category(int id, String name, String slug, String avatarUrl, int parentGameCategoryId, int rootGameCategoryId, int gameId, List<Category> subcategories) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.slug = slug;
|
||||
this.avatarUrl = avatarUrl;
|
||||
this.parentGameCategoryId = parentGameCategoryId;
|
||||
this.rootGameCategoryId = rootGameCategoryId;
|
||||
this.gameId = gameId;
|
||||
this.subcategories = subcategories;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getSlug() {
|
||||
return slug;
|
||||
}
|
||||
|
||||
public String getAvatarUrl() {
|
||||
return avatarUrl;
|
||||
}
|
||||
|
||||
public int getParentGameCategoryId() {
|
||||
return parentGameCategoryId;
|
||||
}
|
||||
|
||||
public int getRootGameCategoryId() {
|
||||
return rootGameCategoryId;
|
||||
}
|
||||
|
||||
public int getGameId() {
|
||||
return gameId;
|
||||
}
|
||||
|
||||
public List<Category> getSubcategories() {
|
||||
return subcategories;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user