2626import java .sql .ResultSet ;
2727import java .sql .SQLException ;
2828import java .time .ZonedDateTime ;
29- import java .util . List ;
30- import java .util .Locale ;
31- import java .util .Optional ;
32- import java .util .Set ;
29+ import java .time . temporal . ChronoField ;
30+ import java .util .* ;
31+ import java .util .stream . Collectors ;
32+ import java .util .stream . Stream ;
3333
3434// TODO: Rewrite to use a faster deserialization library than GSON.
3535public class DiscordBotSubmissionHandler {
@@ -461,11 +461,6 @@ private static boolean hasModrinthAttribution(Context ctx,
461461
462462 @ Nullable
463463 private static ModrinthVersion getModrinthVersion (OAuthClient modrinthClient , ModrinthProject modrinthProject , String minecraftVersion , String loader , @ Nullable String versionString ) throws IOException , InterruptedException {
464- ModrinthVersion modrinthVersion = null ;
465- ZonedDateTime latestVersionTime = null ;
466- boolean isNative = false ; // Used within NeoForge events to make sure that Modrinth will prioritise NeoForge projects over Connector-ran Fabric projects.
467-
468-
469464 if (versionString != null ) {
470465 var versionStream = modrinthClient .get ("v2/project/" + modrinthProject .id + "/version/" + versionString , HttpResponse .BodyHandlers .ofInputStream ());
471466 if (versionStream .statusCode () == 200 ) {
@@ -475,40 +470,53 @@ private static ModrinthVersion getModrinthVersion(OAuthClient modrinthClient, Mo
475470
476471 if (versionString .equals (potentialVersion .id ) || versionString .equals (potentialVersion .versionNumber )) {
477472 if (potentialVersion .loaders .contains (loader ) || loader .equals ("neoforge" ) && potentialVersion .loaders .contains ("fabric" )) {
478- modrinthVersion = potentialVersion ;
473+ return potentialVersion ;
479474 }
480475 }
481476 }
482477 }
483- return modrinthVersion ;
478+ return null ;
484479 }
485480
486- for (String versionId : modrinthProject .versions ) {
487- var versionStream = modrinthClient .get ("v2/version/" + versionId , HttpResponse .BodyHandlers .ofInputStream ());
488- if (versionStream .statusCode () != 200 )
489- continue ;
490-
491- try (InputStreamReader versionReader = new InputStreamReader (versionStream .body ())) {
492- JsonElement versionJson = JsonParser .parseReader (versionReader );
493- ModrinthVersion potentialVersion = ModrinthVersion .CODEC .parse (JsonOps .INSTANCE , versionJson ).getOrThrow ();
494-
495- if (!potentialVersion .gameVersions .contains (minecraftVersion ))
496- continue ;
497-
498- // Handle natively supported mods for the event's loader.
499- if (potentialVersion .loaders .contains (loader ) && (latestVersionTime == null || potentialVersion .datePublished .isAfter (latestVersionTime ))) {
500- modrinthVersion = potentialVersion ;
501- latestVersionTime = potentialVersion .datePublished ;
502- isNative = true ;
503- // Handle Fabric mods loaded via Connector on NeoForge.
504- } else if (!isNative && loader .equals ("neoforge" ) && potentialVersion .loaders .contains ("fabric" ) && (latestVersionTime == null || potentialVersion .datePublished .isAfter (latestVersionTime ))) {
505- modrinthVersion = potentialVersion ;
506- latestVersionTime = potentialVersion .datePublished ;
481+ ModrinthVersion modrinthVersion = null ;
482+ ZonedDateTime latestVersionTime = null ;
483+
484+ List <ModrinthVersion > modrinthVersions = modrinthProject .versions .parallelStream ().map (versionId -> {
485+ try {
486+ var versionStream = modrinthClient .get ("v2/version/" + versionId , HttpResponse .BodyHandlers .ofInputStream ());
487+ if (versionStream .statusCode () != 200 )
488+ return null ;
489+
490+ try (InputStreamReader versionReader = new InputStreamReader (versionStream .body ())) {
491+ JsonElement versionJson = JsonParser .parseReader (versionReader );
492+ ModrinthVersion potentialVersion = ModrinthVersion .CODEC .parse (JsonOps .INSTANCE , versionJson ).getOrThrow ();
493+
494+ if (!potentialVersion .gameVersions .contains (minecraftVersion ))
495+ return null ;
496+
497+ // Handle natively supported mods for the event's loader.
498+ if (potentialVersion .loaders .contains (loader )) {
499+ return potentialVersion ;
500+ // Handle Fabric mods loaded via Connector on NeoForge.
501+ } else if (loader .equals ("neoforge" ) && potentialVersion .loaders .contains ("fabric" )) {
502+ return potentialVersion ;
503+ }
507504 }
505+ } catch (Exception ex ) {
506+ ModGardenBackend .LOG .error ("Failed to read Modrinth version." , ex );
508507 }
508+ return null ;
509+ }).filter (Objects ::nonNull ).collect (Collectors .toCollection (ArrayList ::new ));
510+
511+ // Filter out non-native options if the mod has a native version.
512+ // Handles cases like Sinytra Connector.
513+ if (modrinthVersions .stream ().anyMatch (v -> v .loaders .contains (loader ))) {
514+ modrinthVersions .removeIf (v -> !v .loaders .contains (loader ));
509515 }
510516
511- return modrinthVersion ;
517+ return modrinthVersions .stream ()
518+ .max (Comparator .comparingLong (value -> value .datePublished .getLong (ChronoField .INSTANT_SECONDS )))
519+ .orElse (null );
512520 }
513521
514522 private static Event getCurrentEvent (Connection connection ) throws SQLException {
0 commit comments