11package com .eternalcode .commons .updater .impl ;
22
3- import com .eternalcode .commons .Lazy ;
43import com .eternalcode .commons .updater .UpdateChecker ;
54import com .eternalcode .commons .updater .UpdateResult ;
65import com .eternalcode .commons .updater .Version ;
6+ import com .google .gson .Gson ;
7+ import com .google .gson .JsonParseException ;
8+ import com .google .gson .annotations .SerializedName ;
9+ import com .google .gson .reflect .TypeToken ;
710import java .net .URI ;
811import java .net .http .HttpClient ;
912import java .net .http .HttpRequest ;
1013import java .net .http .HttpResponse ;
1114import java .time .Duration ;
12- import org .json .JSONArray ;
13- import org .json .JSONException ;
14- import org .json .JSONObject ;
15+ import java .util .List ;
16+ import java .util .Objects ;
1517
1618public final class ModrinthUpdateChecker implements UpdateChecker {
1719
1820 private static final String API_BASE_URL = "https://api.modrinth.com/v2" ;
1921 private static final String MODRINTH_BASE_URL = "https://modrinth.com/plugin" ;
2022 private static final String USER_AGENT = "UpdateChecker/1.0" ;
21- private static final Duration TIMEOUT = Duration .ofSeconds (10 );
2223
23- private final Lazy <HttpClient > client = new Lazy <>(() -> HttpClient .newBuilder ().connectTimeout (TIMEOUT ).build ());
24+ private static final Gson GSON = new Gson ();
25+
26+ private final HttpClient client = HttpClient .newBuilder ()
27+ .connectTimeout (Duration .ofSeconds (60 ))
28+ .build ();
2429
2530 @ Override
2631 public UpdateResult check (String projectId , Version currentVersion ) {
27- if (projectId == null || projectId .trim (). isEmpty ()) {
32+ if (projectId == null || projectId .isBlank ()) {
2833 throw new IllegalArgumentException ("Project ID cannot be null or empty" );
2934 }
3035
3136 try {
32- String url = API_BASE_URL + "/project/" + projectId + "/version" ;
33-
34- HttpRequest request =
35- HttpRequest .newBuilder ().uri (URI .create (url )).header ("User-Agent" , USER_AGENT ).timeout (TIMEOUT ).build ();
36-
37- HttpResponse <String > response = this .client .get ().send (request , HttpResponse .BodyHandlers .ofString ());
37+ HttpRequest request = HttpRequest .newBuilder ()
38+ .uri (URI .create (API_BASE_URL + "/project/" + projectId + "/version" ))
39+ .header ("User-Agent" , USER_AGENT )
40+ .timeout (Duration .ofSeconds (30 ))
41+ .build ();
3842
43+ HttpResponse <String > response = this .client .send (request , HttpResponse .BodyHandlers .ofString ());
3944 if (response .statusCode () != 200 ) {
40- return createEmptyResult (currentVersion );
45+ return UpdateResult . empty (currentVersion );
4146 }
4247
43- String json = response .body ();
44- if (json == null || json .trim ().isEmpty ()) {
45- return createEmptyResult (currentVersion );
46- }
47-
48- return parseVersionResponse (json , currentVersion , projectId );
48+ return this .parseVersionResponse (response .body (), currentVersion , projectId );
4949 }
5050 catch (Exception exception ) {
5151 throw new RuntimeException ("Failed to check Modrinth updates for project: " + projectId , exception );
@@ -54,39 +54,35 @@ public UpdateResult check(String projectId, Version currentVersion) {
5454
5555 private UpdateResult parseVersionResponse (String json , Version currentVersion , String projectId ) {
5656 try {
57- JSONArray versions = new JSONArray (json );
58-
59- if (versions .isEmpty ()) {
60- return createEmptyResult (currentVersion );
57+ List <ModrinthVersion > versions = GSON .fromJson (json , new TypeToken <>(){});
58+ if (versions == null || versions .isEmpty ()) {
59+ return UpdateResult .empty (currentVersion );
6160 }
6261
63- JSONObject latestVersionObj = versions .getJSONObject (0 );
64-
65- String versionNumber = latestVersionObj .optString ("version_number" , null );
62+ ModrinthVersion latestVersionData = versions .get (0 );
63+ String versionNumber = latestVersionData .versionNumber ();
6664 if (versionNumber == null || versionNumber .trim ().isEmpty ()) {
67- return createEmptyResult (currentVersion );
68- }
69-
70- String downloadUrl = null ;
71- if (latestVersionObj .has ("files" )) {
72- JSONArray files = latestVersionObj .getJSONArray ("files" );
73- if (!files .isEmpty ()) {
74- JSONObject firstFile = files .getJSONObject (0 );
75- downloadUrl = firstFile .optString ("url" , null );
76- }
65+ return UpdateResult .empty (currentVersion );
7766 }
7867
7968 String releaseUrl = MODRINTH_BASE_URL + "/" + projectId + "/version/" + versionNumber ;
80- Version latestVersion = new Version (versionNumber );
69+ String downloadUrl = latestVersionData .files ().stream ()
70+ .map (modrinthFile -> modrinthFile .url ())
71+ .filter (obj -> Objects .nonNull (obj ))
72+ .findFirst ()
73+ .orElse (releaseUrl );
8174
75+ Version latestVersion = new Version (versionNumber );
8276 return new UpdateResult (currentVersion , latestVersion , downloadUrl , releaseUrl );
8377 }
84- catch (JSONException exception ) {
85- return createEmptyResult (currentVersion );
78+ catch (JsonParseException exception ) {
79+ return UpdateResult . empty (currentVersion );
8680 }
8781 }
8882
89- private UpdateResult createEmptyResult (Version currentVersion ) {
90- return new UpdateResult (currentVersion , currentVersion , null , null );
83+ private record ModrinthVersion (@ SerializedName ("version_number" ) String versionNumber , List <ModrinthFile > files ) {
84+ }
85+
86+ private record ModrinthFile (String url ) {
9187 }
9288}
0 commit comments