Files
steam-immich/internal/steamimmich.go

172 lines
4.3 KiB
Go

package steamimmich
import (
"fmt"
"log"
"slices"
"sort"
"strconv"
)
type Config struct {
BaseURL string
APIKey string
UserdataDir string
DeiveID string
Album string
CacheFile string
}
func Run(config Config) {
screenshotFiles, err := listScreenshots(config.UserdataDir)
if err != nil {
log.Fatalf("Failed to scan for screenshots: %s", err)
return
}
if len(screenshotFiles) == 0 {
log.Println("No screenshots found.")
return
}
immichClient := newImmichHttpClient(config.APIKey)
localState, err := loadLocalState(config.CacheFile)
if err != nil {
log.Fatalf("Failed to load local state: %s", err)
}
for appid, files := range screenshotFiles {
gameName := getGameName(appid, localState.GameIDs)
assetsInGame := make([]string, 0)
for _, filepath := range files {
idx := slices.IndexFunc(localState.Assets, func(e assetState) bool { return e.FilePath == filepath })
if idx != -1 {
log.Printf("Asset already uploaded: %s", filepath)
continue
}
res, err := uploadToImmich(filepath, appid, config.BaseURL, config.DeiveID, &immichClient)
if err != nil {
log.Fatalf("Failed to upload to immich: %s", err)
return
}
log.Printf("Assest uploaded: %s (%s) %s with ID: %s", gameName, appid, filepath, res.ID)
localState.Assets = append(localState.Assets, assetState{FilePath: filepath, ImmichID: res.ID})
assetsInGame = append(assetsInGame, res.ID)
}
err := setAssetMetadata(assetsInGame, fmt.Sprintf("Game: %s", gameName), config.BaseURL, immichClient)
if err != nil {
log.Fatalf("Failed to set asset metadata: %s", err)
return
}
if config.Album != "" {
err = addAssetsToAlbum(assetsInGame, config.Album, config.BaseURL, immichClient)
if err != nil {
log.Fatalf("Failed to add assets to album: %s", err)
return
}
log.Printf("Added %d assets to album %s", len(assetsInGame), config.Album)
}
}
log.Println("Finished uploading screenshots")
err = saveLocalState(config.CacheFile, *localState)
if err != nil {
log.Fatalf("Failed to save local cache: %s", err)
return
}
}
func Revalidate(config Config) {
immichClient := newImmichHttpClient(config.APIKey)
localState, err := loadLocalState(config.CacheFile)
if err != nil {
log.Fatalf("Failed to load local state: %s", err)
return
}
hashes, err := hashFiles(localState.Assets)
if err != nil {
log.Fatalf("Failed to generate hashes: %s", err)
return
}
idxToRemoveFromCache := []int{}
rejected := 0
updated := 0
missingFromImmich := 0
missingFile := 0
// Prepare payload
var idsToCheck = []assetBulkUploadCheckItem{}
for i := range localState.Assets {
hash := hashes[i]
if hash == "" {
idxToRemoveFromCache = append(idxToRemoveFromCache, i)
missingFile += 1
} else {
idsToCheck = append(idsToCheck, assetBulkUploadCheckItem{Checksum: hashes[i], Id: strconv.Itoa(i)})
}
}
results, err := bulkCheckAssets(idsToCheck, config.BaseURL, immichClient)
if err != nil {
log.Fatalf("Failed to bulk check hashes: %s", err)
}
for _, result := range results {
i, err := strconv.Atoi(result.Id)
if err != nil {
log.Fatalf("What ?: %s", err)
return
}
asset := localState.Assets[i]
if asset.ImmichID != result.AssetId {
log.Printf("Asset %s had the wrong Immich ID. New %s", asset.FilePath, result.AssetId)
localState.Assets[i].ImmichID = result.AssetId
updated += 1
}
if result.Action == "reject" {
rejected += 1
} else {
idxToRemoveFromCache = append(idxToRemoveFromCache, i)
missingFromImmich += 1
}
}
sort.Sort(sort.Reverse(sort.IntSlice(idxToRemoveFromCache)))
for _, idx := range idxToRemoveFromCache {
localState.Assets[idx] = localState.Assets[len(localState.Assets)-1]
localState.Assets = localState.Assets[:len(localState.Assets)-1]
}
saveLocalState(config.CacheFile, *localState)
log.Printf("Revalidated %d assets", len(results))
log.Printf("Assets present on Immich: %d", rejected)
log.Printf("Wrong metadata on cache: %d", updated)
log.Printf("Missing on Immich: %d", missingFromImmich)
log.Printf("Missing on local storage: %d", missingFile)
if (updated + missingFromImmich + missingFromImmich) > 0 {
log.Printf("Fixed cache. Run the normal upload command again. If error persists try removing cache file at: %s", config.CacheFile)
}
}