Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ plugins {
}

repositories {
mavenCentral()
gradlePluginPortal()
}

Expand Down
8 changes: 8 additions & 0 deletions eternalcode-commons-updater-example/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
plugins {
`commons-java-17`
`commons-repositories`
}

dependencies {
implementation(project(":eternalcode-commons-updater"))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.eternalcode.commons.updater.example;

import com.eternalcode.commons.updater.UpdateResult;

public class ExampleChecker {

private static final String OLD_ETERNALCOMBAT_VERSION = "1.3.3";

public static void main(String[] args) {
ExampleUpdateService updateService = new ExampleUpdateService();

UpdateResult modrinthResult = updateService.checkModrinth("EternalCombat", OLD_ETERNALCOMBAT_VERSION);
System.out.println("Modrinth update available: " + modrinthResult.isUpdateAvailable());
if (modrinthResult.isUpdateAvailable()) {
System.out.println("Latest: " + modrinthResult.latestVersion());
System.out.println("Download: " + modrinthResult.downloadUrl());
System.out.println("Release page: " + modrinthResult.releaseUrl());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.eternalcode.commons.updater.example;

import com.eternalcode.commons.updater.UpdateResult;
import com.eternalcode.commons.updater.Version;
import com.eternalcode.commons.updater.impl.ModrinthUpdateChecker;

public final class ExampleUpdateService {
private final ModrinthUpdateChecker modrinthChecker = new ModrinthUpdateChecker();

public UpdateResult checkModrinth(String projectId, String currentVersion) {
return modrinthChecker.check(projectId, new Version(currentVersion));
}
}
10 changes: 10 additions & 0 deletions eternalcode-commons-updater/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
plugins {
`commons-java-17`
`commons-publish`
`commons-repositories`
}

dependencies {
api("org.json:json:20240303")
api(project(":eternalcode-commons-shared"))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.eternalcode.commons.updater;

public interface UpdateChecker {

UpdateResult check(String projectId, Version currentVersion);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.eternalcode.commons.updater;

public record UpdateResult(Version currentVersion, Version latestVersion, String downloadUrl, String releaseUrl) {

public boolean isUpdateAvailable() {
return this.latestVersion.isNewerThan(this.currentVersion);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.eternalcode.commons.updater;

public class Version implements Comparable<Version> {

private final String value;

public Version(String version) {
this.value = version.trim();
}

@Override
public int compareTo(Version version) {
return this.value.compareTo(version.value);
}

public boolean isNewerThan(Version version) {
return this.value.compareTo(version.value) > 0;
}

@Override
public boolean equals(Object object) {
return object instanceof Version other && value.equals(other.value);
}

@Override
public int hashCode() {
return value.hashCode();
}

@Override
public String toString() {
return this.value;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package com.eternalcode.commons.updater.impl;

import com.eternalcode.commons.Lazy;
import com.eternalcode.commons.updater.UpdateChecker;
import com.eternalcode.commons.updater.UpdateResult;
import com.eternalcode.commons.updater.Version;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public final class ModrinthUpdateChecker implements UpdateChecker {

private static final String API_BASE_URL = "https://api.modrinth.com/v2";
private static final String MODRINTH_BASE_URL = "https://modrinth.com/plugin";
private static final String USER_AGENT = "UpdateChecker/1.0";
private static final Duration TIMEOUT = Duration.ofSeconds(10);

private final Lazy<HttpClient> client = new Lazy<>(() -> HttpClient.newBuilder().connectTimeout(TIMEOUT).build());

@Override
public UpdateResult check(String projectId, Version currentVersion) {
if (projectId == null || projectId.trim().isEmpty()) {
throw new IllegalArgumentException("Project ID cannot be null or empty");
}

try {
String url = API_BASE_URL + "/project/" + projectId + "/version";

HttpRequest request =
HttpRequest.newBuilder().uri(URI.create(url)).header("User-Agent", USER_AGENT).timeout(TIMEOUT).build();

HttpResponse<String> response = this.client.get().send(request, HttpResponse.BodyHandlers.ofString());

if (response.statusCode() != 200) {
return createEmptyResult(currentVersion);
}

String json = response.body();
if (json == null || json.trim().isEmpty()) {
return createEmptyResult(currentVersion);
}

return parseVersionResponse(json, currentVersion, projectId);
}
catch (Exception exception) {
throw new RuntimeException("Failed to check Modrinth updates for project: " + projectId, exception);
}
}

private UpdateResult parseVersionResponse(String json, Version currentVersion, String projectId) {
try {
JSONArray versions = new JSONArray(json);

if (versions.isEmpty()) {
return createEmptyResult(currentVersion);
}

JSONObject latestVersionObj = versions.getJSONObject(0);

String versionNumber = latestVersionObj.optString("version_number", null);
if (versionNumber == null || versionNumber.trim().isEmpty()) {
return createEmptyResult(currentVersion);
}

String downloadUrl = null;
if (latestVersionObj.has("files")) {
JSONArray files = latestVersionObj.getJSONArray("files");
if (!files.isEmpty()) {
JSONObject firstFile = files.getJSONObject(0);
downloadUrl = firstFile.optString("url", null);
}
}

String releaseUrl = MODRINTH_BASE_URL + "/" + projectId + "/version/" + versionNumber;
Version latestVersion = new Version(versionNumber);

return new UpdateResult(currentVersion, latestVersion, downloadUrl, releaseUrl);
}
catch (JSONException exception) {
return createEmptyResult(currentVersion);
}
}

private UpdateResult createEmptyResult(Version currentVersion) {
return new UpdateResult(currentVersion, currentVersion, null, null);
}
}
2 changes: 2 additions & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ include(":eternalcode-commons-bukkit")
include(":eternalcode-commons-adventure")
include(":eternalcode-commons-shared")
include("eternalcode-commons-folia")
include("eternalcode-commons-updater")
include("eternalcode-commons-updater-example")