diff --git a/.gitignore b/.gitignore index edd1254..f6c18f3 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ .idea/ /mark.test /profile.cov +.vscode diff --git a/main.go b/main.go index 03bd170..7f373b4 100644 --- a/main.go +++ b/main.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "path/filepath" + "slices" "strings" "time" @@ -522,6 +523,8 @@ func processFile( log.Fatal(err) } + updateLabels(err, api, target, meta) + if cCtx.Bool("edit-lock") { log.Infof( nil, @@ -539,6 +542,68 @@ func processFile( return target } +func updateLabels(api *confluence.API, target *confluence.PageInfo, meta *mark.Meta) { + + labelInfo, err := api.GetPageLabels(target, "global") + if err != nil { + log.Fatal(err) + } + + log.Debug("Page Labels:") + log.Debug(labelInfo.Labels) + + log.Debug("Meta Labels:") + log.Debug(meta.Labels) + + delLabels := determineLabelsToRemove(labelInfo, meta) + log.Debug("Del Labels:") + log.Debug(delLabels) + + addLabels := determineLabelsToAdd(meta, labelInfo) + log.Debug("Add Labels:") + log.Debug(addLabels) + + if len(addLabels) > 0 { + _, err = api.AddPageLabels(target, addLabels) + if err != nil { + log.Fatal(err) + } + } + + for _, label := range delLabels { + _, err = api.DeletePageLabel(target, label) + if err != nil { + log.Fatal(err) + } + } +} + +// Page has label but label not in Metadata +func determineLabelsToRemove(labelInfo *confluence.LabelInfo, meta *mark.Meta) []string { + var labels []string + for _, label := range labelInfo.Labels { + if !slices.ContainsFunc(meta.Labels, func(metaLabel string) bool { + return strings.ToLower(metaLabel) == strings.ToLower(label.Name) + }) { + labels = append(labels, label.Name) + } + } + return labels +} + +// Metadata has label but Page does not have it +func determineLabelsToAdd(meta *mark.Meta, labelInfo *confluence.LabelInfo) []string { + var labels []string + for _, metaLabel := range meta.Labels { + if !slices.ContainsFunc(labelInfo.Labels, func(label confluence.Label) bool { + return strings.ToLower(label.Name) == strings.ToLower(metaLabel) + }) { + labels = append(labels, metaLabel) + } + } + return labels +} + func configFilePath() string { fp, err := os.UserConfigDir() if err != nil { diff --git a/pkg/confluence/api.go b/pkg/confluence/api.go index 31be7f2..6ede89e 100644 --- a/pkg/confluence/api.go +++ b/pkg/confluence/api.go @@ -73,6 +73,15 @@ type AttachmentInfo struct { } `json:"_links"` } +type Label struct { + ID string `json:"id"` + Prefix string `json:"prefix"` + Name string `json:"name"` +} +type LabelInfo struct { + Labels []Label `json:"results"` + Size int `json:"number"` +} type form struct { buffer io.Reader writer *multipart.Writer @@ -514,17 +523,6 @@ func (api *API) UpdatePage(page *PageInfo, newContent string, minorEdit bool, ve } } - labels := []map[string]interface{}{} - for _, label := range newLabels { - if label != "" { - item := map[string]interface{}{ - "prexix": "global", - "name": label, - } - labels = append(labels, item) - } - } - payload := map[string]interface{}{ "id": page.ID, "type": page.Type, @@ -542,7 +540,6 @@ func (api *API) UpdatePage(page *PageInfo, newContent string, minorEdit bool, ve }, }, "metadata": map[string]interface{}{ - "labels": labels, // Fix to set full-width as has changed on Confluence APIs again. // https://jira.atlassian.com/browse/CONFCLOUD-65447 // @@ -570,6 +567,66 @@ func (api *API) UpdatePage(page *PageInfo, newContent string, minorEdit bool, ve return nil } +func (api *API) AddPageLabels(page *PageInfo, newLabels []string) (*LabelInfo, error) { + + labels := []map[string]interface{}{} + for _, label := range newLabels { + if label != "" { + item := map[string]interface{}{ + "prefix": "global", + "name": label, + } + labels = append(labels, item) + } + } + + payload := labels + + request, err := api.rest.Res( + "content/"+page.ID+"/label", &LabelInfo{}, + ).Post(payload) + if err != nil { + return nil, err + } + + if request.Raw.StatusCode != http.StatusOK { + return nil, newErrorStatusNotOK(request) + } + + return request.Response.(*LabelInfo), nil +} + +func (api *API) DeletePageLabel(page *PageInfo, label string) (*LabelInfo, error) { + + request, err := api.rest.Res( + "content/"+page.ID+"/label/"+label, &LabelInfo{}, + ).Delete() + if err != nil { + return nil, err + } + + if request.Raw.StatusCode != http.StatusOK { + return nil, newErrorStatusNotOK(request) + } + + return request.Response.(*LabelInfo), nil +} + +func (api *API) GetPageLabels(page *PageInfo, prefix string) (*LabelInfo, error) { + + request, err := api.rest.Res( + "content/"+page.ID+"/label", &LabelInfo{}, + ).Get(map[string]string{"prefix": prefix}) + if err != nil { + return nil, err + } + + if request.Raw.StatusCode != http.StatusOK { + return nil, newErrorStatusNotOK(request) + } + return request.Response.(*LabelInfo), nil +} + func (api *API) GetUserByName(name string) (*User, error) { var response struct { Results []struct {