mirror of
https://github.com/packwiz/packwiz.git
synced 2025-04-19 21:16:30 +02:00
155 lines
3.8 KiB
Go
155 lines
3.8 KiB
Go
package modrinth
|
|
|
|
import (
|
|
modrinthApi "codeberg.org/jmansfield/go-modrinth/modrinth"
|
|
"errors"
|
|
"github.com/packwiz/packwiz/cmd"
|
|
"github.com/packwiz/packwiz/core"
|
|
"github.com/spf13/cobra"
|
|
"github.com/spf13/viper"
|
|
"github.com/unascribed/FlexVer/go/flexver"
|
|
"golang.org/x/exp/slices"
|
|
"net/http"
|
|
)
|
|
|
|
var modrinthCmd = &cobra.Command{
|
|
Use: "modrinth",
|
|
Aliases: []string{"mr"},
|
|
Short: "Manage modrinth-based mods",
|
|
}
|
|
|
|
var mrDefaultClient = modrinthApi.NewClient(&http.Client{})
|
|
|
|
func init() {
|
|
cmd.Add(modrinthCmd)
|
|
core.Updaters["modrinth"] = mrUpdater{}
|
|
|
|
mrDefaultClient.UserAgent = core.UserAgent
|
|
}
|
|
|
|
func getModIdsViaSearch(query string, versions []string) ([]*modrinthApi.SearchResult, error) {
|
|
facets := make([]string, 0)
|
|
for _, v := range versions {
|
|
facets = append(facets, "versions:"+v)
|
|
}
|
|
|
|
res, err := mrDefaultClient.Projects.Search(&modrinthApi.SearchOptions{
|
|
Limit: 5,
|
|
Index: "relevance",
|
|
// Filters by mod since currently only mods and modpacks are supported by Modrinth
|
|
Facets: [][]string{facets, {"project_type:mod"}},
|
|
Query: query,
|
|
})
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return res.Hits, nil
|
|
}
|
|
|
|
func getLatestVersion(modID string, pack core.Pack) (*modrinthApi.Version, error) {
|
|
mcVersion, err := pack.GetMCVersion()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
gameVersions := append([]string{mcVersion}, viper.GetStringSlice("acceptable-game-versions")...)
|
|
|
|
result, err := mrDefaultClient.Versions.ListVersions(modID, modrinthApi.ListVersionsOptions{
|
|
GameVersions: gameVersions,
|
|
Loaders: pack.GetLoaders(),
|
|
})
|
|
|
|
if len(result) == 0 {
|
|
return nil, errors.New("no valid versions found")
|
|
}
|
|
|
|
latestValidVersion := result[0]
|
|
for _, v := range result[1:] {
|
|
// Use FlexVer to compare versions
|
|
compare := flexver.Compare(*v.VersionNumber, *latestValidVersion.VersionNumber)
|
|
|
|
if compare == 0 {
|
|
// Prefer Quilt over Fabric (Modrinth backend handles filtering)
|
|
if slices.Contains(v.Loaders, "quilt") && !slices.Contains(latestValidVersion.Loaders, "quilt") {
|
|
latestValidVersion = v
|
|
continue
|
|
}
|
|
|
|
//Semver is equal, compare date instead
|
|
if v.DatePublished.After(*latestValidVersion.DatePublished) {
|
|
latestValidVersion = v
|
|
}
|
|
} else if compare > 0 {
|
|
latestValidVersion = v
|
|
}
|
|
}
|
|
|
|
return latestValidVersion, nil
|
|
}
|
|
|
|
func getSide(mod *modrinthApi.Project) string {
|
|
server := shouldDownloadOnSide(*mod.ServerSide)
|
|
client := shouldDownloadOnSide(*mod.ClientSide)
|
|
|
|
if server && client {
|
|
return core.UniversalSide
|
|
} else if server {
|
|
return core.ServerSide
|
|
} else if client {
|
|
return core.ClientSide
|
|
} else {
|
|
return ""
|
|
}
|
|
}
|
|
|
|
func shouldDownloadOnSide(side string) bool {
|
|
return side == "required" || side == "optional"
|
|
}
|
|
|
|
func getBestHash(v *modrinthApi.File) (string, string) {
|
|
// Try preferred hashes first; SHA1 is first as it is required for Modrinth pack exporting
|
|
val, exists := v.Hashes["sha1"]
|
|
if exists {
|
|
return "sha1", val
|
|
}
|
|
val, exists = v.Hashes["sha512"]
|
|
if exists {
|
|
return "sha512", val
|
|
}
|
|
val, exists = v.Hashes["sha256"]
|
|
if exists {
|
|
return "sha256", val
|
|
}
|
|
val, exists = v.Hashes["murmur2"] // (not defined in Modrinth pack spec, use with caution)
|
|
if exists {
|
|
return "murmur2", val
|
|
}
|
|
|
|
//none of the preferred hashes are present, just get the first one
|
|
for key, val := range v.Hashes {
|
|
return key, val
|
|
}
|
|
|
|
//No hashes were present
|
|
return "", ""
|
|
}
|
|
|
|
func getInstalledProjectIDs(index *core.Index) []string {
|
|
var installedProjects []string
|
|
for _, modPath := range index.GetAllMods() {
|
|
mod, err := core.LoadMod(modPath)
|
|
if err == nil {
|
|
data, ok := mod.GetParsedUpdateData("modrinth")
|
|
if ok {
|
|
updateData, ok := data.(mrUpdateData)
|
|
if ok {
|
|
if len(updateData.ModID) > 0 {
|
|
installedProjects = append(installedProjects, updateData.ModID)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return installedProjects
|
|
}
|