From 6e46f52b52e0620d37665866bba93cd77a7cdb11 Mon Sep 17 00:00:00 2001 From: Niklas Kapelle Date: Wed, 29 Oct 2025 15:54:02 +0100 Subject: [PATCH] implemented album for uploads --- cmd/steamimmich.go | 2 ++ internal/immich.go | 49 ++++++++++++++++++++++++++++++++++++----- internal/steamimmich.go | 12 +++++++++- 3 files changed, 57 insertions(+), 6 deletions(-) diff --git a/cmd/steamimmich.go b/cmd/steamimmich.go index 63b8462..018a591 100644 --- a/cmd/steamimmich.go +++ b/cmd/steamimmich.go @@ -12,6 +12,7 @@ type args struct { APIKey string `arg:"--api-key,required,env:API_KEY" placeholder:"API_KEY"` UserdataDir string `arg:"--steam-userdata-dir,env:USERDATA_DIR" default:"$HOME/.var/app/com.valvesoftware.Steam/.local/share/Steam/userdata"` DeviceID string `arg:"--device-id,env:DEVICE_ID" default:"steam-immich"` + Album string `arg:"--album,env:ALBUM"` } func main() { @@ -23,5 +24,6 @@ func main() { BaseURL: args.BaseURL, UserdataDir: os.ExpandEnv(args.UserdataDir), DeiveID: args.DeviceID, + Album: args.Album, }) } diff --git a/internal/immich.go b/internal/immich.go index 3c42f17..ad99d38 100644 --- a/internal/immich.go +++ b/internal/immich.go @@ -12,17 +12,23 @@ import ( "time" ) -type ImmichAPIUploadResponse struct { +type uploadResponse struct { ID string `json:"id"` Status string `json:"status"` } -type ImmichAPIAssetPutRequest struct { +type assetPutRequest struct { Ids []string `json:"ids"` Description string `json:"description,omitempty"` } -func uploadToImmich(filePath, appID, baseURL, apiKey, deviceID string) (*ImmichAPIUploadResponse, error) { +type bulkIdResponseDto struct { + Error string `json:"error"` + Id string `json:"id"` + Success bool `json:"success"` +} + +func uploadToImmich(filePath, appID, baseURL, apiKey, deviceID string) (*uploadResponse, error) { file, err := os.Open(filePath) if err != nil { return nil, fmt.Errorf("open file: %w", err) @@ -80,7 +86,7 @@ func uploadToImmich(filePath, appID, baseURL, apiKey, deviceID string) (*ImmichA return nil, fmt.Errorf("Immich upload failed (%d): %s", resp.StatusCode, string(respBody)) } - var result ImmichAPIUploadResponse + var result uploadResponse if err := json.Unmarshal(respBody, &result); err != nil { return nil, fmt.Errorf("Failed to parse immich response: %s", err) } @@ -89,7 +95,7 @@ func uploadToImmich(filePath, appID, baseURL, apiKey, deviceID string) (*ImmichA } func setAssetMetadata(assets []string, description, baseURL, apiKey string) error { - body, _ := json.Marshal(ImmichAPIAssetPutRequest{ + body, _ := json.Marshal(assetPutRequest{ Ids: assets, Description: description, }) @@ -111,3 +117,36 @@ func setAssetMetadata(assets []string, description, baseURL, apiKey string) erro return nil } +func addAssetsToAlbum(assets []string, album, baseURL, apiKey string) error { + body, _ := json.Marshal(struct { + IDs []string `json:"ids"` + }{IDs: assets}) + + req, err := http.NewRequest("PUT", fmt.Sprintf("%s/api/albums/%s/assets", baseURL, album), bytes.NewBuffer(body)) + if err != nil { + return err + } + + req.Header.Set("x-api-key", apiKey) + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Accept", "application/json") + + res, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + + defer res.Body.Close() + + respBody, _ := io.ReadAll(res.Body) + if res.StatusCode >= 300 { + return fmt.Errorf("Failed to add assets to album (%d): %s", res.StatusCode, string(respBody)) + } + + var result []bulkIdResponseDto + if err := json.Unmarshal(respBody, &result); err != nil { + return fmt.Errorf("Failed to parse immich response: %s", err) + } + + return nil +} diff --git a/internal/steamimmich.go b/internal/steamimmich.go index b34a269..a7f7fef 100644 --- a/internal/steamimmich.go +++ b/internal/steamimmich.go @@ -48,7 +48,17 @@ func Run(config Config) { assetsInGame = append(assetsInGame, res.ID) } - setAssetMetadata(assetsInGame, fmt.Sprintf("Game: %s", gameName), config.BaseURL, config.APIKey) + err := setAssetMetadata(assetsInGame, fmt.Sprintf("Game: %s", gameName), config.BaseURL, config.APIKey) + if err != nil { + fmt.Printf("Stopped: %s", err) + } + + if config.Album != "" { + err = addAssetsToAlbum(assetsInGame, config.Album, config.BaseURL, config.APIKey) + if err != nil { + fmt.Printf("Stopped: %s", err) + } + } fmt.Println() }