diff --git a/internal/piwigo/categories.go b/internal/piwigo/categories.go index ad73380..0c7cba3 100644 --- a/internal/piwigo/categories.go +++ b/internal/piwigo/categories.go @@ -1,10 +1,10 @@ package piwigo -import "net/url" +import ( + "net/url" +) -type Categories struct { - Categories []Category `json:"categories"` -} +type Categories []Category type Category struct { Id int `json:"id"` @@ -14,7 +14,9 @@ type Category struct { } func (p *Piwigo) Categories() (map[int]Category, error) { - var categories Categories + var categories struct { + Categories `json:"categories"` + } err := p.Post("pwg.categories.getList", &url.Values{ "fullname": []string{"true"}, @@ -31,3 +33,11 @@ func (p *Piwigo) Categories() (map[int]Category, error) { } return result, nil } + +func (c Categories) Names() []string { + names := []string{} + for _, category := range c { + names = append(names, category.Name) + } + return names +} diff --git a/internal/piwigo/tags.go b/internal/piwigo/tags.go new file mode 100644 index 0000000..4410a96 --- /dev/null +++ b/internal/piwigo/tags.go @@ -0,0 +1,30 @@ +package piwigo + +import ( + "fmt" +) + +type Tags []Tag + +type Tag struct { + Id int `json:"id"` + Name string `json:"name"` + LastModified TimeResult `json:"lastmodified"` + Birthdate TimeResult `json:"birthdate"` + Url string `json:"url"` + UrlName string `json:"url_name"` + ImageUrl string `json:"page_url"` +} + +func (c Tags) NamesWithAgeAt(createdAt TimeResult) []string { + names := []string{} + for _, category := range c { + bd := category.Birthdate.AgeAt(createdAt) + if bd != "" { + names = append(names, fmt.Sprintf("%s (%s)", category.Name, bd)) + } else { + names = append(names, category.Name) + } + } + return names +} diff --git a/internal/piwigo/time.go b/internal/piwigo/time.go index 48c1f5f..e175d19 100644 --- a/internal/piwigo/time.go +++ b/internal/piwigo/time.go @@ -1,6 +1,7 @@ package piwigo import ( + "fmt" "strings" "time" ) @@ -22,5 +23,93 @@ func (c *TimeResult) UnmarshalJSON(b []byte) error { } func (c TimeResult) MarshalJSON() ([]byte, error) { - return []byte(`"` + time.Time(c).Format(time.RFC3339) + `"`), nil + switch s := c.String(); s { + case "": + return []byte("null"), nil + default: + return []byte(`"` + s + `"`), nil + } +} + +func (c TimeResult) String() string { + t := c.toTime() + if t.IsZero() { + return "" + } else { + return t.Format(time.RFC3339) + } +} + +func (c TimeResult) toTime() time.Time { + return time.Time(c) +} + +func (c TimeResult) AgeAt(createdAt TimeResult) string { + var year, month, day, hour, min, sec int + a := c.toTime() + if a.IsZero() { + return "" + } + b := createdAt.toTime() + if b.IsZero() { + return "" + } + + if a.Location() != b.Location() { + b = b.In(a.Location()) + } + if a.After(b) { + a, b = b, a + } + y1, M1, d1 := a.Date() + y2, M2, d2 := b.Date() + + h1, m1, s1 := a.Clock() + h2, m2, s2 := b.Clock() + + year = int(y2 - y1) + month = int(M2 - M1) + day = int(d2 - d1) + hour = int(h2 - h1) + min = int(m2 - m1) + sec = int(s2 - s1) + + // Normalize negative values + if sec < 0 { + sec += 60 + min-- + } + if min < 0 { + min += 60 + hour-- + } + if hour < 0 { + hour += 24 + day-- + } + if day < 0 { + // days in month: + t := time.Date(y1, M1, 32, 0, 0, 0, 0, time.UTC) + day += 32 - t.Day() + month-- + } + if month < 0 { + month += 12 + year-- + } + + switch { + case year == 1: + return fmt.Sprintf("%d months old", 12+month) + case year > 1: + return fmt.Sprintf("%d years old", year) + case month == 1: + return fmt.Sprintf("%d month old", month) + case month > 1: + return fmt.Sprintf("%d months old", month) + case day > 1: + return fmt.Sprintf("%d days old", day) + default: + return fmt.Sprintf("%d day, %d hour", day, hour) + } } diff --git a/internal/piwigocli/images_details.go b/internal/piwigocli/images_details.go index 1d78ad6..6bf2298 100644 --- a/internal/piwigocli/images_details.go +++ b/internal/piwigocli/images_details.go @@ -1,19 +1,41 @@ package piwigocli import ( + "fmt" "net/url" + "os" + "strings" "github.com/celogeek/piwigo-cli/internal/piwigo" + "github.com/jedib0t/go-pretty/v6/table" ) type ImagesDetailsCommand struct { Id string `short:"i" long:"id" description:"ID of the images" required:"true"` } +type Derivative struct { + Height int `json:"height"` + Width int `json:"width"` + Url string `json:"url"` +} + type GetImagesDetailsResponse struct { - Categories []piwigo.Category `json:"categories"` - DateAvailable piwigo.TimeResult `json:"date_available"` - DateCreation piwigo.TimeResult `json:"date_creation"` + Id int `json:"id"` + Md5 string `json:"md5sum"` + Name string `json:"name"` + DateAvailable piwigo.TimeResult `json:"date_available"` + DateCreation piwigo.TimeResult `json:"date_creation"` + LastModified piwigo.TimeResult `json:"lastmodified"` + Width int `json:"width"` + Height int `json:"height"` + Url string `json:"page_url"` + ImageUrl string `json:"element_url"` + Filename string `json:"file"` + Filesize int64 `json:"filesize"` + Categories piwigo.Categories `json:"categories"` + Tags piwigo.Tags `json:"tags"` + Derivatives map[string]Derivative `json:"derivatives"` } func (c *ImagesDetailsCommand) Execute(args []string) error { @@ -43,6 +65,42 @@ func (c *ImagesDetailsCommand) Execute(args []string) error { resp.Categories[i] = categories[category.Id] } - piwigo.DumpResponse(resp) + t := table.NewWriter() + t.AppendHeader(table.Row{"Key", "Value"}) + t.AppendRows([]table.Row{ + {"Id", resp.Id}, + {"Md5", resp.Md5}, + {"Name", resp.Name}, + {"DateAvailable", resp.DateAvailable}, + {"DateCreation", resp.DateCreation}, + {"LastModified", resp.LastModified}, + {"Width", resp.Width}, + {"Height", resp.Height}, + {"Url", resp.Url}, + {"ImageUrl", resp.ImageUrl}, + {"Filename", resp.Filename}, + {"Filesize", resp.Filesize}, + {"Categories", strings.Join(resp.Categories.Names(), "\n")}, + {"Tags", strings.Join(resp.Tags.NamesWithAgeAt(resp.DateCreation), "\n")}, + // {"Derivatives", resp.Derivatives}, + }) + t.SetOutputMirror(os.Stdout) + t.SetStyle(table.StyleLight) + t.Render() + + fmt.Println("Derivatives:") + t = table.NewWriter() + t.AppendHeader(table.Row{"Name", "Width", "Height", "Url"}) + for k, v := range resp.Derivatives { + t.AppendRow(table.Row{ + k, + v.Width, + v.Height, + v.Url, + }) + } + t.SetOutputMirror(os.Stdout) + t.SetStyle(table.StyleLight) + t.Render() return nil }