diff --git a/storage.go b/storage.go index 4659983..8468818 100644 --- a/storage.go +++ b/storage.go @@ -1,12 +1,11 @@ package deck import ( - "bufio" "bytes" "context" + "encoding/json" "fmt" "os" - "strings" "time" "github.com/k1LoW/deck/template" @@ -15,6 +14,12 @@ import ( "google.golang.org/api/drive/v3" ) +// uploadResult represents the JSON output from the external upload command. +type uploadResult struct { + URL string `json:"url"` + ID string `json:"id"` +} + // Storage is the interface for image upload/delete operations. type Storage interface { Upload(ctx context.Context, data []byte, mimeType string) (publicURL, uploadedID string, err error) @@ -111,7 +116,7 @@ func newExternalStorage(uploadCmd, deleteCmd string) *externalStorage { // Upload uploads an image using the external upload command. // It passes image data via stdin and sets the environment variable DECK_UPLOAD_MIME. // The command also supports template variables: {{mime}} and {{env.XXX}}. -// The command should output the public URL on the first line and uploaded ID on the second line. +// The command should output JSON: {"url":"...","id":"..."} func (u *externalStorage) Upload(ctx context.Context, data []byte, mimeType string) (publicURL, uploadedID string, err error) { const envUploadMIME = "DECK_UPLOAD_MIME" @@ -149,26 +154,20 @@ func (u *externalStorage) Upload(ctx context.Context, data []byte, mimeType stri return "", "", fmt.Errorf("failed to run upload command: %w\nstderr: %s", err, stderr.String()) } - // Parse stdout: first line is public URL, second line is uploaded ID - scanner := bufio.NewScanner(&stdout) - if !scanner.Scan() { - return "", "", fmt.Errorf("upload command did not output public URL") + // Parse JSON output + var result uploadResult + if err := json.Unmarshal(stdout.Bytes(), &result); err != nil { + return "", "", fmt.Errorf("failed to parse upload command output as JSON: %w\nstdout: %s", err, stdout.String()) } - publicURL = strings.TrimSpace(scanner.Text()) - if !scanner.Scan() { - return "", "", fmt.Errorf("upload command did not output uploaded ID") + if result.URL == "" { + return "", "", fmt.Errorf("upload command returned empty URL") } - uploadedID = strings.TrimSpace(scanner.Text()) - - if publicURL == "" { - return "", "", fmt.Errorf("upload command returned empty public URL") - } - if uploadedID == "" { - return "", "", fmt.Errorf("upload command returned empty uploaded ID") + if result.ID == "" { + return "", "", fmt.Errorf("upload command returned empty ID") } - return publicURL, uploadedID, nil + return result.URL, result.ID, nil } // Delete deletes an uploaded image using the external delete command.