Skip to content

Commit

Permalink
rework metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
maradotwebp committed Apr 17, 2022
1 parent 88162af commit 9a83f5a
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 68 deletions.
48 changes: 26 additions & 22 deletions src/api/metadata.nim
Original file line number Diff line number Diff line change
@@ -1,54 +1,58 @@
## Provides `getModLoaderId` which retrieves the modloader id (a string specifying
## the type & version of the modloader) given a minecraft version and modloader.
## the type & version of the modloader) given a minecraft version and type of modloader.
##
## Pax currently has support for the Forge & Fabric modloader. The information about
## what loader version corresponds to what minecraft version is retrieved online
## and should be generally up-to-date 99% of the time.

import asyncdispatch, json, options, strutils, sugar
import std/[asyncdispatch, json, strutils]
import http
import ../modpack/version, ../modpack/loader

const
## base url of the fabric metadata endpoint
fabricBaseUrl = "https://meta.fabricmc.net/v2/versions/loader/"
## base url of the curse metadata api endpoint
forgeBaseUrl = "http://raw.githubusercontent.com/MultiMC/meta-upstream/master/forge/derived_index.json"
forgeBaseUrl = "https://cfproxy.fly.dev/v1/minecraft/modloader"

proc getFabricLoaderVersion(mcVersion: Version): Future[Option[string]] {.async.} =
type
MetadataClientError* = object of HttpRequestError

proc getFabricLoaderVersion(mcVersion: Version): Future[string] {.async.} =
## get the fabric loader version fitting for the given minecraft version
let url = fabricBaseUrl & $mcVersion
var json: JsonNode
try:
json = get(url.Url).await.parseJson
let json: JsonNode = try:
get(url.Url).await.parseJson
except HttpRequestError:
return none[string]()
raise newException(MetadataClientError, "'" & $mcVersion & "' is not a valid mc version.")
let loaderElems = json.getElems()
if loaderElems.len == 0:
return none[string]()
raise newException(MetadataClientError, "'" & $mcVersion & "' is not a valid mc version.")
let ver = loaderElems[0]["loader"]["version"].getStr()
return some(ver)
return ver

proc getForgeLoaderVersion(mcVersion: Version, latest: bool): Future[Option[string]] {.async.} =
proc getForgeLoaderVersion(mcVersion: Version, latest: bool): Future[string] {.async.} =
## get the forge loader version fitting for the given minecraft version
let json = get(forgeBaseUrl.Url).await.parseJson
let recommendedVersion = json{"by_mcversion", $mcVersion, "recommended"}.getStr()
let latestVersion = json{"by_mcversion", $mcVersion, "latest"}.getStr()
let forgeVersion = if latest:
latestVersion
else:
if $recommendedVersion != "": recommendedVersion else: latestVersion
return if forgeVersion != "": some(forgeVersion) else: none[string]()
let url = forgeBaseUrl & "?version=" & $mcVersion
let json: JsonNode = try:
get(url.Url).await.parseJson
except HttpRequestError:
raise newException(MetadataClientError, "'" & $mcVersion & "' is not a valid mc version.")
let searchKey = if latest: "latest" else: "recommended"
for item in json["data"].items():
if item[searchKey].getBool():
return item["name"].getStr()
raise newException(MetadataClientError, "'" & $mcVersion & "' is not a valid mc version.")

proc toModloaderId(loaderVersion: string, loader: Loader): string =
## get the modloader id fitting for the given loader version and loader
return case loader:
of Loader.Forge: "forge-" & loaderVersion.split("-")[1]
of Loader.Fabric: "fabric-" & loaderVersion

proc getModloaderId*(mcVersion: Version, loader: Loader, latest: bool = false): Future[Option[string]] {.async.} =
proc getModloaderId*(mcVersion: Version, loader: Loader, latest: bool = false): Future[string] {.async.} =
## get the modloader id fitting for the given minecraft version and loader
let loaderVersion = case loader:
of Loader.Forge: await mcVersion.getForgeLoaderVersion(latest)
of Loader.Fabric: await mcVersion.getFabricLoaderVersion()
return loaderVersion.map((x) => toModloaderId(x, loader))
of Loader.Fabric: mcVersion.getFabricLoaderVersion().await.toModloaderId(loader)
return loaderVersion
91 changes: 45 additions & 46 deletions tests/api/tmetadata.nim
Original file line number Diff line number Diff line change
@@ -1,54 +1,53 @@
discard """
cmd: "nim $target --hints:on -d:testing -d:ssl --nimblePath:tests/deps $options $file"
"""

import asyncdispatch, sequtils, strutils, sugar, options
import std/[asyncdispatch, sequtils, strutils, sugar, options]
import api/metadata
import modpack/loader, modpack/version
import ../tutils

block: # getModloaderId - Fabric
let id1 = getModloaderId("1.10.2".Version, Loader.Fabric)
let id2 = getModloaderId("1.128.0".Version, Loader.Fabric)
let id3 = getModloaderId("0.0.0".Version, Loader.Fabric)
let id4 = getModloaderId("1.16.3".Version, Loader.Fabric)
let id5 = getModloaderId("1.17".Version, Loader.Fabric)
let id6 = getModloaderId("1.14.4".Version, Loader.Fabric)
let id7 = getModloaderId("1.16.1".Version, Loader.Fabric)
asyncBlock: # getModLoaderId on Fabric for versions
let id = await getModloaderId("1.16.3".Version, Loader.Fabric)
doAssert id != ""
asyncBlock:
let id = await getModloaderId("1.17".Version, Loader.Fabric)
doAssert id != ""
asyncBlock:
let id = await getModloaderId("1.14.4".Version, Loader.Fabric)
doAssert id != ""

let allIdPromises = @[id1, id2, id3, id4, id5, id6, id7]
let allIds = waitFor(all(allIdPromises))
asyncBlock: # getModLoaderId on Fabric for non-existing versions
doAssertRaises(MetadataClientError):
discard await getModloaderId("1.10.2".Version, Loader.Fabric)
asyncBlock:
doAssertRaises(MetadataClientError):
discard await getModloaderId("1.128.0".Version, Loader.Fabric)
asyncBlock:
doAssertRaises(MetadataClientError):
discard await getModloaderId("0.0.0".Version, Loader.Fabric)

doAssert id1.read().isNone()
doAssert id2.read().isNone()
doAssert id3.read().isNone()
doAssert id4.read().isSome()
doAssert id5.read().isSome()
doAssert id6.read().isSome()
doAssert id7.read().isSome()
doAssert allIds.filter((x) => x.isSome()).all((x) => x.get().startsWith("fabric-"))
asyncBlock: # getModLoaderId on Forge for versions
let id = await getModloaderId("1.12.2".Version, Loader.Forge)
doAssert id == "forge-14.23.5.2859"
asyncBlock:
let id = await getModloaderId("1.12".Version, Loader.Forge)
doAssert id == "forge-14.21.1.2387"
asyncBlock:
let id = await getModloaderId("1.16.1".Version, Loader.Forge)
doAssert id == "forge-32.0.108"

block: # getModloaderId - Forge
let id1 = getModloaderId("1.128.0".Version, Loader.Forge)
let id2 = getModloaderId("0.0.0".Version, Loader.Forge)
let id3 = getModloaderId("1.1.0".Version, Loader.Forge)
let id4 = getModloaderId("1.12.2".Version, Loader.Forge)
let id5 = getModloaderId("1.12".Version, Loader.Forge)
let id6 = getModloaderId("1.16.1".Version, Loader.Forge)
let id7 = getModloaderId("1.16.3".Version, Loader.Forge)
let id8 = getModloaderId("1.12".Version, Loader.Forge, latest=true)
let id9 = getModloaderId("1.16.1".Version, Loader.Forge, latest=true)
let id10 = getModloaderId("1.16.3".Version, Loader.Forge, latest=true)
asyncBlock: # getModLoaderId on Forge for latest versions
let id = await getModloaderId("1.12".Version, Loader.Forge, latest = true)
doAssert id == "forge-14.21.1.2443"
asyncBlock:
let id = await getModloaderId("1.16.1".Version, Loader.Forge, latest = true)
doAssert id == "forge-32.0.108"

let allIdPromises = @[id1, id2, id3, id4, id5, id6, id7, id8, id9, id10]
discard waitFor(all(allIdPromises))
asyncBlock: # getModLoaderId on Forge for non-existing versions
doAssertRaises(MetadataClientError):
discard await getModloaderId("1.1.0".Version, Loader.Forge)
asyncBlock:
doAssertRaises(MetadataClientError):
discard await getModloaderId("1.128.0".Version, Loader.Forge)
asyncBlock:
doAssertRaises(MetadataClientError):
discard await getModloaderId("0.0.0".Version, Loader.Forge)

doAssert id1.read().isNone()
doAssert id2.read().isNone()
doAssert id3.read().isNone()
doAssert id4.read().get() == "forge-14.23.5.2859"
doAssert id5.read().get() == "forge-14.21.1.2387"
doAssert id6.read().get() == "forge-32.0.108"
doAssert id7.read().get() == "forge-34.1.0"
doAssert id8.read().get() == "forge-14.21.1.2443"
doAssert id9.read().get() == "forge-32.0.108"
doAssert id10.read().get() == "forge-34.1.42"
runTests()

0 comments on commit 9a83f5a

Please sign in to comment.