initial commit
This commit is contained in:
113
internal/immich.go
Normal file
113
internal/immich.go
Normal file
@@ -0,0 +1,113 @@
|
||||
package steamimmich
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ImmichAPIUploadResponse struct {
|
||||
ID string `json:"id"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
type ImmichAPIAssetPutRequest struct {
|
||||
Ids []string `json:"ids"`
|
||||
Description string `json:"description,omitempty"`
|
||||
}
|
||||
|
||||
func uploadToImmich(filePath, appID, baseURL, apiKey, deviceID string) (*ImmichAPIUploadResponse, error) {
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("open file: %w", err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
fileInfo, err := file.Stat()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("stat file: %w", err)
|
||||
}
|
||||
|
||||
// Create multipart form
|
||||
var body bytes.Buffer
|
||||
writer := multipart.NewWriter(&body)
|
||||
|
||||
// Attach the image file
|
||||
part, err := writer.CreateFormFile("assetData", filepath.Base(filePath))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create form file: %w", err)
|
||||
}
|
||||
if _, err := io.Copy(part, file); err != nil {
|
||||
return nil, fmt.Errorf("copy file data: %w", err)
|
||||
}
|
||||
|
||||
modTime := fileInfo.ModTime().UTC().Format(time.RFC3339)
|
||||
createTime := modTime // If you don't have a separate created time
|
||||
|
||||
// Required metadata fields
|
||||
writer.WriteField("deviceAssetId", fmt.Sprintf("%s-%s", appID, filepath.Base(filePath)))
|
||||
writer.WriteField("deviceId", deviceID)
|
||||
writer.WriteField("fileCreatedAt", createTime)
|
||||
writer.WriteField("fileModifiedAt", modTime)
|
||||
writer.WriteField("isFavorite", "false")
|
||||
|
||||
writer.Close()
|
||||
|
||||
// Build request
|
||||
req, err := http.NewRequest("POST", fmt.Sprintf("%s/api/assets", baseURL), &body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create request: %w", err)
|
||||
}
|
||||
req.Header.Set("x-api-key", apiKey)
|
||||
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||||
req.Header.Set("Accept", "application/json")
|
||||
|
||||
client := &http.Client{Timeout: 60 * time.Second}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("POST to Immich: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
respBody, _ := io.ReadAll(resp.Body)
|
||||
if resp.StatusCode >= 300 {
|
||||
return nil, fmt.Errorf("Immich upload failed (%d): %s", resp.StatusCode, string(respBody))
|
||||
}
|
||||
|
||||
var result ImmichAPIUploadResponse
|
||||
if err := json.Unmarshal(respBody, &result); err != nil {
|
||||
return nil, fmt.Errorf("Failed to parse immich response: %s", err)
|
||||
}
|
||||
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
func setAssetMetadata(assets []string, description, baseURL, apiKey string) error {
|
||||
body, _ := json.Marshal(ImmichAPIAssetPutRequest{
|
||||
Ids: assets,
|
||||
Description: description,
|
||||
})
|
||||
|
||||
req, err := http.NewRequest("PUT", fmt.Sprintf("%s/api/assets", baseURL), 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")
|
||||
|
||||
_, err = http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user