Skip to content

Commit

Permalink
chore: follow immich 1.95.0 API changes (#170)
Browse files Browse the repository at this point in the history
  • Loading branch information
simulot committed Feb 27, 2024
1 parent 935e0a4 commit 362d82b
Show file tree
Hide file tree
Showing 12 changed files with 255 additions and 155 deletions.
2 changes: 1 addition & 1 deletion cmd/duplicate/duplicate.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func DuplicateCommand(ctx context.Context, common *cmd.SharedFlags, args []strin

dupCount := 0
app.Jnl.Log.MessageContinue(logger.OK, "Get server's assets...")
err = app.Immich.GetAllAssetsWithFilter(ctx, nil, func(a *immich.Asset) {
err = app.Immich.GetAllAssetsWithFilter(ctx, func(a *immich.Asset) {
if a.IsTrashed {
return
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/metadata/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func MetadataCommand(ctx context.Context, common *cmd.SharedFlags, args []string
}

app.Jnl.Log.MessageContinue(logger.OK, "Get server's assets...")
list, err := app.Immich.GetAllAssets(ctx, nil)
list, err := app.Immich.GetAllAssets(ctx)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/stack/stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func NewStackCommand(ctx context.Context, common *cmd.SharedFlags, args []string
app.Jnl.Log.MessageContinue(logger.OK, "Get server's assets...")
assetCount := 0

err = app.Immich.GetAllAssetsWithFilter(ctx, nil, func(a *immich.Asset) {
err = app.Immich.GetAllAssetsWithFilter(ctx, func(a *immich.Asset) {
if a.IsTrashed {
return
}
Expand Down
4 changes: 2 additions & 2 deletions cmd/upload/e2e_upload_folder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ func resetImmich(ic *immich.ImmichClient, user string) error {
}
}

assets, err := ic.GetAllAssets(context.Background(), nil)
assets, err := ic.GetAllAssets(context.Background())
if err != nil {
return err
}
Expand All @@ -405,7 +405,7 @@ func resetImmich(ic *immich.ImmichClient, user string) error {

attempts := 5
for attempts > 0 {
assets, err := ic.GetAllAssets(context.Background(), nil)
assets, err := ic.GetAllAssets(context.Background())
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/upload/upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ func NewUpCmd(ctx context.Context, common *cmd.SharedFlags, args []string) (*UpC
}
app.Jnl.Log.OK("Ask for server's assets...")
var list []*immich.Asset
err = app.Immich.GetAllAssetsWithFilter(ctx, nil, func(a *immich.Asset) {
err = app.Immich.GetAllAssetsWithFilter(ctx, func(a *immich.Asset) {
if a.IsTrashed {
return
}
Expand Down
4 changes: 2 additions & 2 deletions cmd/upload/upload_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import (

type stubIC struct{}

func (c *stubIC) GetAllAssetsWithFilter(context.Context, *immich.GetAssetOptions, func(*immich.Asset)) error {
func (c *stubIC) GetAllAssetsWithFilter(context.Context, func(*immich.Asset)) error {
return nil
}

Expand Down Expand Up @@ -77,7 +77,7 @@ func (c *stubIC) GetAssetAlbums(ctx context.Context, id string) ([]immich.AlbumS
return nil, nil
}

func (c *stubIC) GetAllAssets(ctx context.Context, opt *immich.GetAssetOptions) ([]*immich.Asset, error) {
func (c *stubIC) GetAllAssets(ctx context.Context) ([]*immich.Asset, error) {
return nil, nil
}

Expand Down
58 changes: 6 additions & 52 deletions immich/asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,57 +174,6 @@ func (o *GetAssetOptions) Values() url.Values {
return v
}

// GetAllAssets get all user's assets using the paged API searchAssets
//
// It calls the server for IMAGE, VIDEO, normal item, trashed Items

func (ic *ImmichClient) GetAllAssets(ctx context.Context, opt *GetAssetOptions) ([]*Asset, error) {
var r []*Asset

for _, t := range []string{"IMAGE", "VIDEO", "AUDIO", "OTHER"} {
values := opt.Values()
values.Set("type", t)
values.Set("withExif", "true")
values.Set("isVisible", "true")
values.Del("trashedBefore")
err := ic.newServerCall(ctx, "GetAllAssets", setPaginator()).do(get("/assets", setURLValues(values), setAcceptJSON()), responseAccumulateJSON(&r))
if err != nil {
return r, err
}
values.Set("trashedBefore", "9999-01-01")
err = ic.newServerCall(ctx, "GetAllAssets", setPaginator()).do(get("/assets", setURLValues(values), setAcceptJSON()), responseAccumulateJSON(&r))
if err != nil {
return r, err
}
}
return r, nil
}

// GetAllAssetsWithFilter get all user's assets using the paged API searchAssets and apply a filter
// TODO: rename this function, it's not a filter, it uses a callback function for each item
//
// It calls the server for IMAGE, VIDEO, normal item, trashed Items
func (ic *ImmichClient) GetAllAssetsWithFilter(ctx context.Context, opt *GetAssetOptions, filter func(*Asset)) error {
for _, t := range []string{"IMAGE", "VIDEO", "AUDIO", "OTHER"} {
values := opt.Values()
values.Set("type", t)
values.Set("withExif", "true")
values.Set("isVisible", "true")
values.Del("trashedBefore")
err := ic.newServerCall(ctx, "GetAllAssets", setPaginator()).do(get("/assets", setURLValues(values), setAcceptJSON()), responseJSONWithFilter(filter))
if err != nil {
return err
}
values.Set("trashedBefore", "9999-01-01")
err = ic.newServerCall(ctx, "GetAllAssets", setPaginator()).do(get("/assets", setURLValues(values), setAcceptJSON()), responseJSONWithFilter(filter))
if err != nil {
return err
}
}

return nil
}

func (ic *ImmichClient) DeleteAssets(ctx context.Context, id []string, forceDelete bool) error {
req := struct {
Force bool `json:"force"`
Expand All @@ -238,8 +187,13 @@ func (ic *ImmichClient) DeleteAssets(ctx context.Context, id []string, forceDele
}

func (ic *ImmichClient) GetAssetByID(ctx context.Context, id string) (*Asset, error) {
body := struct {
WithExif bool `json:"withExif,omitempty"`
IsVisible bool `json:"isVisible,omitempty"`
ID string `json:"id"`
}{WithExif: true, IsVisible: true, ID: id}
r := Asset{}
err := ic.newServerCall(ctx, "GetAssetByID").do(get("/asset/assetById/"+id, setAcceptJSON()), responseJSON(&r))
err := ic.newServerCall(ctx, "GetAssetByID").do(post("/search/metadata", "application/json", setAcceptJSON(), setJSONBody(body)), responseJSON(&r))
return &r, err
}

Expand Down
100 changes: 15 additions & 85 deletions immich/call.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ import (
"fmt"
"io"
"net/http"
"net/url"
"strconv"
"strings"
)

Expand All @@ -28,11 +26,8 @@ type serverCall struct {
ic *ImmichClient
err error
ctx context.Context
p *paginator
}

type serverCallOption func(sc *serverCall) error

// callError represents errors returned by the server
type callError struct {
endPoint string
Expand Down Expand Up @@ -85,17 +80,12 @@ func (ce callError) Error() string {
return b.String()
}

func (ic *ImmichClient) newServerCall(ctx context.Context, api string, opts ...serverCallOption) *serverCall {
func (ic *ImmichClient) newServerCall(ctx context.Context, api string) *serverCall {
sc := &serverCall{
endPoint: api,
ic: ic,
ctx: ctx,
}
if sc.err == nil {
for _, opt := range opts {
_ = sc.joinError(opt(sc))
}
}
return sc
}

Expand All @@ -120,32 +110,6 @@ func (sc *serverCall) joinError(err error) error {
return err
}

// paginator controls the paged API calls
type paginator struct {
pageNumber int // current page
pageParameter string // page parameter name on the URL
EOF bool // true when the last page was empty
}

func (p paginator) setPage(v url.Values) {
v.Set(p.pageParameter, strconv.Itoa(p.pageNumber))
}

func (p *paginator) nextPage() {
p.pageNumber++
}

func setPaginator() serverCallOption {
return func(sc *serverCall) error {
p := paginator{
pageParameter: "page",
pageNumber: 1,
}
sc.p = &p
return nil
}
}

type requestFunction func(sc *serverCall) *http.Request

func (sc *serverCall) request(method string, url string, opts ...serverRequestOption) *http.Request {
Expand Down Expand Up @@ -199,25 +163,6 @@ func put(url string, opts ...serverRequestOption) requestFunction {
}

func (sc *serverCall) do(fnRequest requestFunction, opts ...serverResponseOption) error {
if sc.err != nil || fnRequest == nil {
return sc.Err(nil, nil, nil)
}

if sc.p == nil {
return sc._callDo(fnRequest, opts...)
}

for !sc.p.EOF {
err := sc._callDo(fnRequest, opts...)
if err != nil {
return err
}
sc.p.nextPage()
}
return nil
}

func (sc *serverCall) _callDo(fnRequest requestFunction, opts ...serverResponseOption) error {
var (
resp *http.Response
err error
Expand All @@ -228,11 +173,6 @@ func (sc *serverCall) _callDo(fnRequest requestFunction, opts ...serverResponseO
return sc.Err(req, nil, nil)
}

if sc.p != nil {
v := req.URL.Query()
sc.p.setPage(v)
req.URL.RawQuery = v.Encode()
}
if sc.ic.APITrace /* && req.Header.Get("Content-Type") == "application/json"*/ {
_ = sc.joinError(setTraceJSONRequest()(sc, req))
}
Expand Down Expand Up @@ -316,21 +256,6 @@ func setContentType(cType string) serverRequestOption {
}
}

func setURLValues(values url.Values) serverRequestOption {
return func(sc *serverCall, req *http.Request) error {
if values != nil {
rValues := req.URL.Query()
for k, v := range values {
for _, s := range v {
rValues.Set(k, s)
}
}
req.URL.RawQuery = rValues.Encode()
}
return nil
}
}

type serverResponseOption func(sc *serverCall, resp *http.Response) error

func responseJSON[T any](object *T) serverResponseOption {
Expand All @@ -349,11 +274,10 @@ func responseJSON[T any](object *T) serverResponseOption {
}
}

/*
func responseAccumulateJSON[T any](acc *[]T) serverResponseOption {
return func(sc *serverCall, resp *http.Response) error {
if sc.p != nil {
sc.p.EOF = true
}
eof := true
if resp != nil {
if resp.Body != nil {
defer resp.Body.Close()
Expand All @@ -366,21 +290,23 @@ func responseAccumulateJSON[T any](acc *[]T) serverResponseOption {
return err
}
if len(arr) > 0 && sc.p != nil {
sc.p.EOF = false
eof = false
}
(*acc) = append((*acc), arr...)
if eof {
sc.p.setEOF()
}
return nil
}
}
return errors.New("can't decode nil response")
}
}

*/
/*
func responseJSONWithFilter[T any](filter func(*T)) serverResponseOption {
return func(sc *serverCall, resp *http.Response) error {
if sc.p != nil {
sc.p.EOF = true
}
eof := true
if resp != nil {
if resp.Body != nil {
defer resp.Body.Close()
Expand All @@ -403,15 +329,19 @@ func responseJSONWithFilter[T any](filter func(*T)) serverResponseOption {
return err
}
if sc.p != nil {
sc.p.EOF = false
eof = false
}
filter(&o)
}
// read closing bracket "]"
_, err = dec.Token()
if eof {
sc.p.setEOF()
}
return err
}
}
return errors.New("can't decode nil response")
}
}
*/

0 comments on commit 362d82b

Please sign in to comment.