e4b02a792d
* chore: move mod downloading to cli/cache * feat: data providers, ficsit and local * feat: keep cache in memory, load on init * feat: log invalid cache files instead of returning error * chore: make linter happy * feat: fill cached mod Authors field from CreatedBy * chore: make linter happy again * feat: add icon and size to cached mods * feat: cache the cached file hashes * fix: change to new provider access style --------- Co-authored-by: Vilsol <me@vil.so>
289 lines
7.5 KiB
Go
289 lines
7.5 KiB
Go
package provider
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/Masterminds/semver/v3"
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/satisfactorymodding/ficsit-cli/cli/cache"
|
|
"github.com/satisfactorymodding/ficsit-cli/ficsit"
|
|
)
|
|
|
|
type localProvider struct{}
|
|
|
|
func initLocalProvider() localProvider {
|
|
return localProvider{}
|
|
}
|
|
|
|
func (p localProvider) Mods(_ context.Context, filter ficsit.ModFilter) (*ficsit.ModsResponse, error) {
|
|
cachedMods, err := cache.GetCache()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "failed to get cache")
|
|
}
|
|
|
|
mods := make([]ficsit.ModsModsGetModsModsMod, 0)
|
|
|
|
for modReference, files := range cachedMods {
|
|
if modReference == "SML" {
|
|
continue
|
|
}
|
|
|
|
if len(filter.References) > 0 {
|
|
skip := true
|
|
|
|
for _, a := range filter.References {
|
|
if a == modReference {
|
|
skip = false
|
|
break
|
|
}
|
|
}
|
|
|
|
if skip {
|
|
continue
|
|
}
|
|
}
|
|
|
|
mods = append(mods, ficsit.ModsModsGetModsModsMod{
|
|
Id: modReference,
|
|
Name: files[0].Plugin.FriendlyName,
|
|
Mod_reference: modReference,
|
|
Last_version_date: time.Now(),
|
|
Created_at: time.Now(),
|
|
Downloads: 0,
|
|
Popularity: 0,
|
|
Hotness: 0,
|
|
})
|
|
}
|
|
|
|
if filter.Limit == 0 {
|
|
filter.Limit = 25
|
|
}
|
|
|
|
low := filter.Offset
|
|
high := filter.Offset + filter.Limit
|
|
|
|
if low > len(mods) {
|
|
return &ficsit.ModsResponse{
|
|
Mods: ficsit.ModsModsGetMods{
|
|
Count: 0,
|
|
Mods: []ficsit.ModsModsGetModsModsMod{},
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
if high > len(mods) {
|
|
high = len(mods)
|
|
}
|
|
|
|
mods = mods[low:high]
|
|
|
|
return &ficsit.ModsResponse{
|
|
Mods: ficsit.ModsModsGetMods{
|
|
Count: len(mods),
|
|
Mods: mods,
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
func (p localProvider) GetMod(_ context.Context, modReference string) (*ficsit.GetModResponse, error) {
|
|
cachedModFiles, err := cache.GetCacheMod(modReference)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "failed to get cache")
|
|
}
|
|
|
|
if len(cachedModFiles) == 0 {
|
|
return nil, errors.New("mod not found")
|
|
}
|
|
|
|
authors := make([]ficsit.GetModModAuthorsUserMod, 0)
|
|
|
|
for _, author := range strings.Split(cachedModFiles[0].Plugin.CreatedBy, ",") {
|
|
authors = append(authors, ficsit.GetModModAuthorsUserMod{
|
|
Role: "Unknown",
|
|
User: ficsit.GetModModAuthorsUserModUser{
|
|
Username: author,
|
|
},
|
|
})
|
|
}
|
|
|
|
return &ficsit.GetModResponse{
|
|
Mod: ficsit.GetModMod{
|
|
Id: modReference,
|
|
Name: cachedModFiles[0].Plugin.FriendlyName,
|
|
Mod_reference: modReference,
|
|
Created_at: time.Now(),
|
|
Views: 0,
|
|
Downloads: 0,
|
|
Authors: authors,
|
|
Full_description: "",
|
|
Source_url: "",
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
func (p localProvider) ModVersions(_ context.Context, modReference string, filter ficsit.VersionFilter) (*ficsit.ModVersionsResponse, error) {
|
|
cachedModFiles, err := cache.GetCacheMod(modReference)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "failed to get cache")
|
|
}
|
|
|
|
if filter.Limit == 0 {
|
|
filter.Limit = 25
|
|
}
|
|
|
|
versions := make([]ficsit.ModVersionsModVersionsVersion, 0)
|
|
|
|
for _, modFile := range cachedModFiles[filter.Offset : filter.Offset+filter.Limit] {
|
|
versions = append(versions, ficsit.ModVersionsModVersionsVersion{
|
|
Id: modReference + ":" + modFile.Plugin.SemVersion,
|
|
Version: modFile.Plugin.SemVersion,
|
|
})
|
|
}
|
|
|
|
return &ficsit.ModVersionsResponse{
|
|
Mod: ficsit.ModVersionsMod{
|
|
Id: modReference,
|
|
Versions: versions,
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
func (p localProvider) SMLVersions(_ context.Context) (*ficsit.SMLVersionsResponse, error) {
|
|
cachedSMLFiles, err := cache.GetCacheMod("SML")
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "failed to get cache")
|
|
}
|
|
|
|
smlVersions := make([]ficsit.SMLVersionsSmlVersionsGetSMLVersionsSml_versionsSMLVersion, 0)
|
|
|
|
for _, smlFile := range cachedSMLFiles {
|
|
smlVersions = append(smlVersions, ficsit.SMLVersionsSmlVersionsGetSMLVersionsSml_versionsSMLVersion{
|
|
Id: "SML:" + smlFile.Plugin.SemVersion,
|
|
Version: smlFile.Plugin.SemVersion,
|
|
Satisfactory_version: 0, // TODO: where can this be obtained from?
|
|
})
|
|
}
|
|
|
|
return &ficsit.SMLVersionsResponse{
|
|
SmlVersions: ficsit.SMLVersionsSmlVersionsGetSMLVersions{
|
|
Count: len(smlVersions),
|
|
Sml_versions: smlVersions,
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
func (p localProvider) ResolveModDependencies(_ context.Context, filter []ficsit.ModVersionConstraint) (*ficsit.ResolveModDependenciesResponse, error) {
|
|
cachedMods, err := cache.GetCache()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "failed to get cache")
|
|
}
|
|
|
|
mods := make([]ficsit.ResolveModDependenciesModsModVersion, 0)
|
|
|
|
constraintMap := make(map[string]string)
|
|
|
|
for _, constraint := range filter {
|
|
constraintMap[constraint.ModIdOrReference] = constraint.Version
|
|
}
|
|
|
|
for modReference, modFiles := range cachedMods {
|
|
constraint, ok := constraintMap[modReference]
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
semverConstraint, err := semver.NewConstraint(constraint)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "failed to parse constraint for %s", modReference)
|
|
}
|
|
|
|
versions := make([]ficsit.ResolveModDependenciesModsModVersionVersionsVersion, 0)
|
|
|
|
for _, modFile := range modFiles {
|
|
semverVersion, err := semver.NewVersion(modFile.Plugin.SemVersion)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "failed to parse version for %s", modReference)
|
|
}
|
|
|
|
if !semverConstraint.Check(semverVersion) {
|
|
continue
|
|
}
|
|
|
|
dependencies := make([]ficsit.ResolveModDependenciesModsModVersionVersionsVersionDependenciesVersionDependency, 0)
|
|
|
|
for _, dependency := range modFile.Plugin.Plugins {
|
|
if dependency.BasePlugin {
|
|
continue
|
|
}
|
|
dependencies = append(dependencies, ficsit.ResolveModDependenciesModsModVersionVersionsVersionDependenciesVersionDependency{
|
|
Mod_id: dependency.Name,
|
|
Condition: dependency.SemVersion,
|
|
Optional: dependency.Optional,
|
|
})
|
|
}
|
|
|
|
versions = append(versions, ficsit.ResolveModDependenciesModsModVersionVersionsVersion{
|
|
Id: modReference + ":" + modFile.Plugin.SemVersion,
|
|
Version: modFile.Plugin.SemVersion,
|
|
Link: "",
|
|
Hash: modFile.Hash,
|
|
Dependencies: dependencies,
|
|
})
|
|
}
|
|
|
|
mods = append(mods, ficsit.ResolveModDependenciesModsModVersion{
|
|
Id: modReference,
|
|
Mod_reference: modReference,
|
|
Versions: versions,
|
|
})
|
|
}
|
|
|
|
return &ficsit.ResolveModDependenciesResponse{
|
|
Mods: mods,
|
|
}, nil
|
|
}
|
|
|
|
func (p localProvider) ModVersionsWithDependencies(_ context.Context, modID string) (*ficsit.ModVersionsWithDependenciesResponse, error) {
|
|
cachedModFiles, err := cache.GetCacheMod(modID)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "failed to get cache")
|
|
}
|
|
|
|
versions := make([]ficsit.ModVersionsWithDependenciesModVersionsVersion, 0)
|
|
|
|
for _, modFile := range cachedModFiles {
|
|
versions = append(versions, ficsit.ModVersionsWithDependenciesModVersionsVersion{
|
|
Id: modID + ":" + modFile.Plugin.SemVersion,
|
|
Version: modFile.Plugin.SemVersion,
|
|
})
|
|
}
|
|
|
|
return &ficsit.ModVersionsWithDependenciesResponse{
|
|
Mod: ficsit.ModVersionsWithDependenciesMod{
|
|
Id: modID,
|
|
Versions: versions,
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
func (p localProvider) GetModName(_ context.Context, modReference string) (*ficsit.GetModNameResponse, error) {
|
|
cachedModFiles, err := cache.GetCacheMod(modReference)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "failed to get cache")
|
|
}
|
|
|
|
if len(cachedModFiles) == 0 {
|
|
return nil, errors.New("mod not found")
|
|
}
|
|
|
|
return &ficsit.GetModNameResponse{
|
|
Mod: ficsit.GetModNameMod{
|
|
Id: modReference,
|
|
Name: cachedModFiles[0].Plugin.FriendlyName,
|
|
Mod_reference: modReference,
|
|
},
|
|
}, nil
|
|
}
|