feat: search modrinth
This commit is contained in:
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher
|
||||
* Copyright (C) 2021 huangyuhui <huanghongxun2008@126.com> and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.jackhuang.hmcl.mod;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public final class DownloadManager {
|
||||
private DownloadManager() {
|
||||
}
|
||||
|
||||
public interface IMod {
|
||||
Stream<Version> loadVersions() throws IOException;
|
||||
}
|
||||
|
||||
public static class Mod {
|
||||
private final String slug;
|
||||
private final String author;
|
||||
private final String title;
|
||||
private final String description;
|
||||
private final List<String> categories;
|
||||
private final String pageUrl;
|
||||
private final String iconUrl;
|
||||
private final IMod data;
|
||||
|
||||
public Mod(String slug, String author, String title, String description, List<String> categories, String pageUrl, String iconUrl, IMod data) {
|
||||
this.slug = slug;
|
||||
this.author = author;
|
||||
this.title = title;
|
||||
this.description = description;
|
||||
this.categories = categories;
|
||||
this.pageUrl = pageUrl;
|
||||
this.iconUrl = iconUrl;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public String getSlug() {
|
||||
return slug;
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public List<String> getCategories() {
|
||||
return categories;
|
||||
}
|
||||
|
||||
public String getPageUrl() {
|
||||
return pageUrl;
|
||||
}
|
||||
|
||||
public String getIconUrl() {
|
||||
return iconUrl;
|
||||
}
|
||||
|
||||
public IMod getData() {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
public enum VersionType {
|
||||
Release,
|
||||
Beta,
|
||||
Alpha
|
||||
}
|
||||
|
||||
public static class Version {
|
||||
private final Object self;
|
||||
private final String name;
|
||||
private final String version;
|
||||
private final String changelog;
|
||||
private final Instant datePublished;
|
||||
private final VersionType versionType;
|
||||
private final File file;
|
||||
private final List<String> dependencies;
|
||||
private final List<String> gameVersions;
|
||||
private final List<String> loaders;
|
||||
|
||||
public Version(Object self, String name, String version, String changelog, Instant datePublished, VersionType versionType, File file, List<String> dependencies, List<String> gameVersions, List<String> loaders) {
|
||||
this.self = self;
|
||||
this.name = name;
|
||||
this.version = version;
|
||||
this.changelog = changelog;
|
||||
this.datePublished = datePublished;
|
||||
this.versionType = versionType;
|
||||
this.file = file;
|
||||
this.dependencies = dependencies;
|
||||
this.gameVersions = gameVersions;
|
||||
this.loaders = loaders;
|
||||
}
|
||||
|
||||
public Object getSelf() {
|
||||
return self;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public String getChangelog() {
|
||||
return changelog;
|
||||
}
|
||||
|
||||
public Instant getDatePublished() {
|
||||
return datePublished;
|
||||
}
|
||||
|
||||
public VersionType getVersionType() {
|
||||
return versionType;
|
||||
}
|
||||
|
||||
public File getFile() {
|
||||
return file;
|
||||
}
|
||||
|
||||
public List<String> getDependencies() {
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
public List<String> getGameVersions() {
|
||||
return gameVersions;
|
||||
}
|
||||
|
||||
public List<String> getLoaders() {
|
||||
return loaders;
|
||||
}
|
||||
}
|
||||
|
||||
public static class File {
|
||||
private final Map<String, String> hashes;
|
||||
private final String url;
|
||||
private final String filename;
|
||||
|
||||
public File(Map<String, String> hashes, String url, String filename) {
|
||||
this.hashes = hashes;
|
||||
this.url = url;
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
public Map<String, String> getHashes() {
|
||||
return hashes;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public String getFilename() {
|
||||
return filename;
|
||||
}
|
||||
}
|
||||
|
||||
public static final String[] DEFAULT_GAME_VERSIONS = new String[]{
|
||||
"1.17.1", "1.17",
|
||||
"1.16.5", "1.16.4", "1.16.3", "1.16.2", "1.16.1", "1.16",
|
||||
"1.15.2", "1.15.1", "1.15",
|
||||
"1.14.4", "1.14.3", "1.14.2", "1.14.1", "1.14",
|
||||
"1.13.2", "1.13.1", "1.13",
|
||||
"1.12.2", "1.12.1", "1.12",
|
||||
"1.11.2", "1.11.1", "1.11",
|
||||
"1.10.2", "1.10.1", "1.10",
|
||||
"1.9.4", "1.9.3", "1.9.2", "1.9.1", "1.9",
|
||||
"1.8.9", "1.8.8", "1.8.7", "1.8.6", "1.8.5", "1.8.4", "1.8.3", "1.8.2", "1.8.1", "1.8",
|
||||
"1.7.10", "1.7.9", "1.7.8", "1.7.7", "1.7.6", "1.7.5", "1.7.4", "1.7.3", "1.7.2",
|
||||
"1.6.4", "1.6.2", "1.6.1",
|
||||
"1.5.2", "1.5.1",
|
||||
"1.4.7", "1.4.6", "1.4.5", "1.4.4", "1.4.2",
|
||||
"1.3.2", "1.3.1",
|
||||
"1.2.5", "1.2.4", "1.2.3", "1.2.2", "1.2.1",
|
||||
"1.1",
|
||||
"1.0"
|
||||
};
|
||||
}
|
||||
@@ -1,12 +1,34 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher
|
||||
* Copyright (C) 2021 huangyuhui <huanghongxun2008@126.com> and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.jackhuang.hmcl.mod.curse;
|
||||
|
||||
import org.jackhuang.hmcl.mod.DownloadManager;
|
||||
import org.jackhuang.hmcl.util.Immutable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Immutable
|
||||
public class CurseAddon {
|
||||
public class CurseAddon implements DownloadManager.IMod {
|
||||
private final int id;
|
||||
private final String name;
|
||||
private final List<Author> authors;
|
||||
@@ -137,6 +159,32 @@ public class CurseAddon {
|
||||
return isExperimental;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<DownloadManager.Version> loadVersions() throws IOException {
|
||||
return CurseModManager.getFiles(this).stream()
|
||||
.map(CurseAddon.LatestFile::toVersion);
|
||||
}
|
||||
|
||||
public DownloadManager.Mod toMod() {
|
||||
String iconUrl = null;
|
||||
for (CurseAddon.Attachment attachment : attachments) {
|
||||
if (attachment.isDefault()) {
|
||||
iconUrl = attachment.getThumbnailUrl();
|
||||
}
|
||||
}
|
||||
|
||||
return new DownloadManager.Mod(
|
||||
slug,
|
||||
"",
|
||||
name,
|
||||
summary,
|
||||
categories.stream().map(category -> Integer.toString(category.getCategoryId())).collect(Collectors.toList()),
|
||||
websiteUrl,
|
||||
iconUrl,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
@Immutable
|
||||
public static class Author {
|
||||
private final String name;
|
||||
@@ -410,6 +458,37 @@ public class CurseAddon {
|
||||
}
|
||||
return fileDataInstant;
|
||||
}
|
||||
|
||||
public DownloadManager.Version toVersion() {
|
||||
DownloadManager.VersionType versionType;
|
||||
switch (getReleaseType()) {
|
||||
case 1:
|
||||
versionType = DownloadManager.VersionType.Release;
|
||||
break;
|
||||
case 2:
|
||||
versionType = DownloadManager.VersionType.Beta;
|
||||
break;
|
||||
case 3:
|
||||
versionType = DownloadManager.VersionType.Alpha;
|
||||
break;
|
||||
default:
|
||||
versionType = DownloadManager.VersionType.Release;
|
||||
break;
|
||||
}
|
||||
|
||||
return new DownloadManager.Version(
|
||||
this,
|
||||
getDisplayName(),
|
||||
null,
|
||||
null,
|
||||
getParsedFileDate(),
|
||||
versionType,
|
||||
new DownloadManager.File(Collections.emptyMap(), getDownloadUrl(), getFileName()),
|
||||
Collections.emptyList(),
|
||||
gameVersion,
|
||||
Collections.emptyList()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Immutable
|
||||
|
||||
@@ -1,3 +1,20 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher
|
||||
* Copyright (C) 2021 huangyuhui <huanghongxun2008@126.com> and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.jackhuang.hmcl.mod.curse;
|
||||
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
@@ -0,0 +1,479 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher
|
||||
* Copyright (C) 2021 huangyuhui <huanghongxun2008@126.com> and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.jackhuang.hmcl.mod.modrinth;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import org.jackhuang.hmcl.mod.DownloadManager;
|
||||
import org.jackhuang.hmcl.util.Lang;
|
||||
import org.jackhuang.hmcl.util.StringUtils;
|
||||
import org.jackhuang.hmcl.util.io.HttpRequest;
|
||||
import org.jackhuang.hmcl.util.io.NetworkUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.jackhuang.hmcl.util.Lang.mapOf;
|
||||
import static org.jackhuang.hmcl.util.Pair.pair;
|
||||
|
||||
public final class Modrinth {
|
||||
private Modrinth() {
|
||||
}
|
||||
|
||||
public static List<ModResult> searchPaginated(String gameVersion, int pageOffset, String searchFilter) throws IOException {
|
||||
Map<String, String> query = mapOf(
|
||||
pair("query", searchFilter),
|
||||
pair("offset", Integer.toString(pageOffset)),
|
||||
pair("limit", "25")
|
||||
);
|
||||
if (StringUtils.isNotBlank(gameVersion)) {
|
||||
query.put("version", "versions=" + gameVersion);
|
||||
}
|
||||
Response<ModResult> response = HttpRequest.GET(NetworkUtils.withQuery("https://api.modrinth.com/api/v1/mod", query))
|
||||
.getJson(new TypeToken<Response<ModResult>>() {
|
||||
}.getType());
|
||||
return response.getHits();
|
||||
}
|
||||
|
||||
public static List<ModVersion> getFiles(ModResult mod) throws IOException {
|
||||
String id = StringUtils.removePrefix(mod.getModId(), "local-");
|
||||
List<ModVersion> versions = HttpRequest.GET("https://api.modrinth.com/api/v1/mod/" + id + "/version")
|
||||
.getJson(new TypeToken<List<ModVersion>>() {
|
||||
}.getType());
|
||||
return versions;
|
||||
}
|
||||
|
||||
public static List<String> getCategories() throws IOException {
|
||||
List<String> categories = HttpRequest.GET("https://api.modrinth.com/api/v1/tag/category").getJson(new TypeToken<List<String>>() {
|
||||
}.getType());
|
||||
return categories;
|
||||
}
|
||||
|
||||
public static class Mod {
|
||||
private final String id;
|
||||
|
||||
private final String slug;
|
||||
|
||||
private final String team;
|
||||
|
||||
private final String title;
|
||||
|
||||
private final String description;
|
||||
|
||||
private final Instant published;
|
||||
|
||||
private final Instant updated;
|
||||
|
||||
private final List<String> categories;
|
||||
|
||||
private final List<String> versions;
|
||||
|
||||
private final int downloads;
|
||||
|
||||
@SerializedName("icon_url")
|
||||
private final String iconUrl;
|
||||
|
||||
public Mod(String id, String slug, String team, String title, String description, Instant published, Instant updated, List<String> categories, List<String> versions, int downloads, String iconUrl) {
|
||||
this.id = id;
|
||||
this.slug = slug;
|
||||
this.team = team;
|
||||
this.title = title;
|
||||
this.description = description;
|
||||
this.published = published;
|
||||
this.updated = updated;
|
||||
this.categories = categories;
|
||||
this.versions = versions;
|
||||
this.downloads = downloads;
|
||||
this.iconUrl = iconUrl;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getSlug() {
|
||||
return slug;
|
||||
}
|
||||
|
||||
public String getTeam() {
|
||||
return team;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public Instant getPublished() {
|
||||
return published;
|
||||
}
|
||||
|
||||
public Instant getUpdated() {
|
||||
return updated;
|
||||
}
|
||||
|
||||
public List<String> getCategories() {
|
||||
return categories;
|
||||
}
|
||||
|
||||
public List<String> getVersions() {
|
||||
return versions;
|
||||
}
|
||||
|
||||
public int getDownloads() {
|
||||
return downloads;
|
||||
}
|
||||
|
||||
public String getIconUrl() {
|
||||
return iconUrl;
|
||||
}
|
||||
}
|
||||
|
||||
public static class ModVersion {
|
||||
private final String id;
|
||||
|
||||
@SerializedName("mod_id")
|
||||
private final String modId;
|
||||
|
||||
@SerializedName("author_id")
|
||||
private final String authorId;
|
||||
|
||||
private final String name;
|
||||
|
||||
@SerializedName("version_number")
|
||||
private final String versionNumber;
|
||||
|
||||
private final String changelog;
|
||||
|
||||
@SerializedName("date_published")
|
||||
private final Instant datePublished;
|
||||
|
||||
private final int downloads;
|
||||
|
||||
@SerializedName("version_type")
|
||||
private final String versionType;
|
||||
|
||||
private final List<ModVersionFile> files;
|
||||
|
||||
private final List<String> dependencies;
|
||||
|
||||
@SerializedName("game_versions")
|
||||
private final List<String> gameVersions;
|
||||
|
||||
private final List<String> loaders;
|
||||
|
||||
public ModVersion(String id, String modId, String authorId, String name, String versionNumber, String changelog, Instant datePublished, int downloads, String versionType, List<ModVersionFile> files, List<String> dependencies, List<String> gameVersions, List<String> loaders) {
|
||||
this.id = id;
|
||||
this.modId = modId;
|
||||
this.authorId = authorId;
|
||||
this.name = name;
|
||||
this.versionNumber = versionNumber;
|
||||
this.changelog = changelog;
|
||||
this.datePublished = datePublished;
|
||||
this.downloads = downloads;
|
||||
this.versionType = versionType;
|
||||
this.files = files;
|
||||
this.dependencies = dependencies;
|
||||
this.gameVersions = gameVersions;
|
||||
this.loaders = loaders;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getModId() {
|
||||
return modId;
|
||||
}
|
||||
|
||||
public String getAuthorId() {
|
||||
return authorId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getVersionNumber() {
|
||||
return versionNumber;
|
||||
}
|
||||
|
||||
public String getChangelog() {
|
||||
return changelog;
|
||||
}
|
||||
|
||||
public Instant getDatePublished() {
|
||||
return datePublished;
|
||||
}
|
||||
|
||||
public int getDownloads() {
|
||||
return downloads;
|
||||
}
|
||||
|
||||
public String getVersionType() {
|
||||
return versionType;
|
||||
}
|
||||
|
||||
public List<ModVersionFile> getFiles() {
|
||||
return files;
|
||||
}
|
||||
|
||||
public List<String> getDependencies() {
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
public List<String> getGameVersions() {
|
||||
return gameVersions;
|
||||
}
|
||||
|
||||
public List<String> getLoaders() {
|
||||
return loaders;
|
||||
}
|
||||
|
||||
public Optional<DownloadManager.Version> toVersion() {
|
||||
DownloadManager.VersionType type;
|
||||
if ("release".equals(versionType)) {
|
||||
type = DownloadManager.VersionType.Release;
|
||||
} else if ("beta".equals(versionType)) {
|
||||
type = DownloadManager.VersionType.Beta;
|
||||
} else if ("alpha".equals(versionType)) {
|
||||
type = DownloadManager.VersionType.Alpha;
|
||||
} else {
|
||||
type = DownloadManager.VersionType.Release;
|
||||
}
|
||||
|
||||
if (files.size() == 0) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
return Optional.of(new DownloadManager.Version(
|
||||
this,
|
||||
name,
|
||||
versionNumber,
|
||||
changelog,
|
||||
datePublished,
|
||||
type,
|
||||
files.get(0).toFile(),
|
||||
dependencies,
|
||||
gameVersions,
|
||||
loaders
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
public static class ModVersionFile {
|
||||
private final Map<String, String> hashes;
|
||||
private final String url;
|
||||
private final String filename;
|
||||
|
||||
public ModVersionFile(Map<String, String> hashes, String url, String filename) {
|
||||
this.hashes = hashes;
|
||||
this.url = url;
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
public Map<String, String> getHashes() {
|
||||
return hashes;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public String getFilename() {
|
||||
return filename;
|
||||
}
|
||||
|
||||
public DownloadManager.File toFile() {
|
||||
return new DownloadManager.File(hashes, url, filename);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ModResult implements DownloadManager.IMod {
|
||||
@SerializedName("mod_id")
|
||||
private final String modId;
|
||||
|
||||
private final String slug;
|
||||
|
||||
private final String author;
|
||||
|
||||
private final String title;
|
||||
|
||||
private final String description;
|
||||
|
||||
private final List<String> categories;
|
||||
|
||||
private final List<String> versions;
|
||||
|
||||
private final int downloads;
|
||||
|
||||
@SerializedName("page_url")
|
||||
private final String pageUrl;
|
||||
|
||||
@SerializedName("icon_url")
|
||||
private final String iconUrl;
|
||||
|
||||
@SerializedName("author_url")
|
||||
private final String authorUrl;
|
||||
|
||||
@SerializedName("date_created")
|
||||
private final Instant dateCreated;
|
||||
|
||||
@SerializedName("date_modified")
|
||||
private final Instant dateModified;
|
||||
|
||||
@SerializedName("latest_version")
|
||||
private final String latestVersion;
|
||||
|
||||
public ModResult(String modId, String slug, String author, String title, String description, List<String> categories, List<String> versions, int downloads, String pageUrl, String iconUrl, String authorUrl, Instant dateCreated, Instant dateModified, String latestVersion) {
|
||||
this.modId = modId;
|
||||
this.slug = slug;
|
||||
this.author = author;
|
||||
this.title = title;
|
||||
this.description = description;
|
||||
this.categories = categories;
|
||||
this.versions = versions;
|
||||
this.downloads = downloads;
|
||||
this.pageUrl = pageUrl;
|
||||
this.iconUrl = iconUrl;
|
||||
this.authorUrl = authorUrl;
|
||||
this.dateCreated = dateCreated;
|
||||
this.dateModified = dateModified;
|
||||
this.latestVersion = latestVersion;
|
||||
}
|
||||
|
||||
public String getModId() {
|
||||
return modId;
|
||||
}
|
||||
|
||||
public String getSlug() {
|
||||
return slug;
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public List<String> getCategories() {
|
||||
return categories;
|
||||
}
|
||||
|
||||
public List<String> getVersions() {
|
||||
return versions;
|
||||
}
|
||||
|
||||
public int getDownloads() {
|
||||
return downloads;
|
||||
}
|
||||
|
||||
public String getPageUrl() {
|
||||
return pageUrl;
|
||||
}
|
||||
|
||||
public String getIconUrl() {
|
||||
return iconUrl;
|
||||
}
|
||||
|
||||
public String getAuthorUrl() {
|
||||
return authorUrl;
|
||||
}
|
||||
|
||||
public Instant getDateCreated() {
|
||||
return dateCreated;
|
||||
}
|
||||
|
||||
public Instant getDateModified() {
|
||||
return dateModified;
|
||||
}
|
||||
|
||||
public String getLatestVersion() {
|
||||
return latestVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<DownloadManager.Version> loadVersions() throws IOException {
|
||||
return Modrinth.getFiles(this).stream()
|
||||
.map(ModVersion::toVersion)
|
||||
.flatMap(Lang::toStream);
|
||||
}
|
||||
|
||||
public DownloadManager.Mod toMod() {
|
||||
return new DownloadManager.Mod(
|
||||
slug,
|
||||
author,
|
||||
title,
|
||||
description,
|
||||
categories,
|
||||
pageUrl,
|
||||
iconUrl,
|
||||
this
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Response<T> {
|
||||
private final int offset;
|
||||
|
||||
private final int limit;
|
||||
|
||||
@SerializedName("total_hits")
|
||||
private final int totalHits;
|
||||
|
||||
private final List<T> hits;
|
||||
|
||||
public Response() {
|
||||
this(0, 0, Collections.emptyList());
|
||||
}
|
||||
|
||||
public Response(int offset, int limit, List<T> hits) {
|
||||
this.offset = offset;
|
||||
this.limit = limit;
|
||||
this.totalHits = hits.size();
|
||||
this.hits = hits;
|
||||
}
|
||||
|
||||
public int getOffset() {
|
||||
return offset;
|
||||
}
|
||||
|
||||
public int getLimit() {
|
||||
return limit;
|
||||
}
|
||||
|
||||
public int getTotalHits() {
|
||||
return totalHits;
|
||||
}
|
||||
|
||||
public List<T> getHits() {
|
||||
return hits;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.*;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -315,6 +316,10 @@ public final class Lang {
|
||||
};
|
||||
}
|
||||
|
||||
public static <T> Stream<T> toStream(Optional<T> optional) {
|
||||
return optional.map(Stream::of).orElseGet(Stream::empty);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a useful function to prevent exceptions being eaten when using CompletableFuture.
|
||||
* You can write:
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher
|
||||
* Copyright (C) 2021 huangyuhui <huanghongxun2008@126.com> and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.jackhuang.hmcl.util.gson;
|
||||
|
||||
import com.google.gson.*;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
public final class InstantTypeAdapter implements JsonSerializer<Instant>, JsonDeserializer<Instant> {
|
||||
public static final InstantTypeAdapter INSTANCE = new InstantTypeAdapter();
|
||||
|
||||
private InstantTypeAdapter() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instant deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
|
||||
if (!(json instanceof JsonPrimitive)) {
|
||||
throw new JsonParseException("The instant should be a string value");
|
||||
} else {
|
||||
Instant instant = Instant.parse(json.getAsString());
|
||||
if (typeOfT == Instant.class) {
|
||||
return instant;
|
||||
} else {
|
||||
throw new IllegalArgumentException(this.getClass() + " cannot be deserialized to " + typeOfT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonElement serialize(Instant src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
return new JsonPrimitive(DateTimeFormatter.ISO_DATE_TIME.withZone(ZoneId.systemDefault()).format(src));
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import com.google.gson.JsonSyntaxException;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Type;
|
||||
import java.time.Instant;
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -63,6 +64,7 @@ public final class JsonUtils {
|
||||
return new GsonBuilder()
|
||||
.enableComplexMapKeySerialization()
|
||||
.setPrettyPrinting()
|
||||
.registerTypeAdapter(Instant.class, InstantTypeAdapter.INSTANCE)
|
||||
.registerTypeAdapter(Date.class, DateTypeAdapter.INSTANCE)
|
||||
.registerTypeAdapter(UUID.class, UUIDTypeAdapter.INSTANCE)
|
||||
.registerTypeAdapter(File.class, FileTypeAdapter.INSTANCE)
|
||||
|
||||
@@ -87,8 +87,8 @@ public final class NetworkUtils {
|
||||
public static URLConnection createConnection(URL url) throws IOException {
|
||||
URLConnection connection = url.openConnection();
|
||||
connection.setUseCaches(false);
|
||||
connection.setConnectTimeout(15000);
|
||||
connection.setReadTimeout(15000);
|
||||
connection.setConnectTimeout(5000);
|
||||
connection.setReadTimeout(5000);
|
||||
connection.setRequestProperty("Accept-Language", Locale.getDefault().toString());
|
||||
return connection;
|
||||
}
|
||||
@@ -143,8 +143,8 @@ public final class NetworkUtils {
|
||||
while (true) {
|
||||
|
||||
conn.setUseCaches(false);
|
||||
conn.setConnectTimeout(15000);
|
||||
conn.setReadTimeout(15000);
|
||||
conn.setConnectTimeout(5000);
|
||||
conn.setReadTimeout(5000);
|
||||
conn.setInstanceFollowRedirects(false);
|
||||
Map<String, List<String>> properties = conn.getRequestProperties();
|
||||
String method = conn.getRequestMethod();
|
||||
|
||||
Reference in New Issue
Block a user