diff --git a/README.md b/README.md index 6d414d6..7352cc6 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,7 @@ Flags: The command checks every Pad if the last edited date is older than the defined limit. Older Pads will be deleted. +Pads without any changes (revisions) will be deleted. Pads without a suffix will be deleted after 30 days of inactivity. Pads with the suffix "-temp" will be deleted after 24 hours of inactivity. Pads with the suffix "-keep" will be deleted after 365 days of inactivity. diff --git a/cmd/purge.go b/cmd/purge.go index 59fb1e1..3240460 100644 --- a/cmd/purge.go +++ b/cmd/purge.go @@ -15,6 +15,7 @@ var ( longDescription = ` The command checks every Pad if the last edited date is older than the defined limit. Older Pads will be deleted. +Pads without any changes (revisions) will be deleted. Pads without a suffix will be deleted after 30 days of inactivity. Pads with the suffix "-temp" will be deleted after 24 hours of inactivity. Pads with the suffix "-keep" will be deleted after 365 days of inactivity. diff --git a/pkg/api.go b/pkg/api.go index 34f0048..084eb7a 100644 --- a/pkg/api.go +++ b/pkg/api.go @@ -159,6 +159,34 @@ func (ep *Etherpad) CopyPad(sourceID, destinationID string, force bool) error { return nil } +// GetRevisionsCount returns the number of revisions of this pad. +// See: https://etherpad.org/doc/v1.8.4/#index_getrevisionscount_padid +func (ep *Etherpad) GetRevisionsCount(padID string) (int, error) { + params := map[string]interface{}{"padID": padID} + res, err := ep.sendRequest("getRevisionsCount", params) + if err != nil { + return 0, err + } + defer res.Body.Close() + + var body struct { + Code int `json:"code"` + Message string `json:"message"` + Data struct { + Revisions int `json:"revisions"` + } + } + if err = json.NewDecoder(res.Body).Decode(&body); err != nil { + return 0, err + } + + if body.Code != 0 { + return 0, fmt.Errorf("error: %s (code: %d)", body.Message, body.Code) + } + + return body.Data.Revisions, nil +} + func (ep *Etherpad) sendRequest(path string, params map[string]interface{}) (*http.Response, error) { uri, err := url.Parse(fmt.Sprintf("%s/api/%s/%s", ep.url, ep.apiVersion, path)) if err != nil { diff --git a/pkg/api_test.go b/pkg/api_test.go index ba57a3a..86486dd 100644 --- a/pkg/api_test.go +++ b/pkg/api_test.go @@ -165,3 +165,35 @@ func TestEtherpad_CopyPad_NotFound(t *testing.T) { err := etherpad.CopyPad("pad1", "pad2", false) assert.NotNil(t, err) } + +func TestEtherpad_GetRevisionsCount_Successful(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(`{"code": 0, "message":"ok", "data": {"revisions": 31}}`)) + })) + defer ts.Close() + + etherpad := NewEtherpadClient(ts.URL, etherpadApiKey) + etherpad.Client = ts.Client() + + rev, err := etherpad.GetRevisionsCount("pad") + assert.Nil(t, err) + assert.Equal(t, 31, rev) +} + +func TestEtherpad_GetRevisionsCount_NotFound(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(`{"code": 1, "message":"padID does not exist", "data": null}`)) + })) + defer ts.Close() + + etherpad := NewEtherpadClient(ts.URL, etherpadApiKey) + etherpad.Client = ts.Client() + + rev, err := etherpad.GetRevisionsCount("pad") + assert.NotNil(t, err) + assert.Equal(t, 0, rev) +} diff --git a/pkg/purge/purger.go b/pkg/purge/purger.go index 6f6aa42..e7189dd 100644 --- a/pkg/purge/purger.go +++ b/pkg/purge/purger.go @@ -66,18 +66,24 @@ func (p *Purger) worker(pads chan string, out chan int) { for pad := range pads { log.WithField("pad", pad).Debug("Process Pad") + revisions, err := p.Etherpad.GetRevisionsCount(pad) + if err != nil { + log.WithError(err).WithField("pad", pad).Error("failed to get last edited time") + continue + } + lastEdited, err := p.Etherpad.GetLastEdited(pad) if err != nil { log.WithError(err).Error("") - return + continue } - deletable := lastEdited.Before(time.Now().Add(padDuration(pad))) + deletable := lastEdited.Before(time.Now().Add(padDuration(pad))) || revisions == 0 if !deletable { continue } - log.WithField("pad", pad).WithField("lastEdited", lastEdited).Info("Delete Pad") + log.WithFields(log.Fields{"pad": pad, "lastEdited": lastEdited, "revisions": revisions}).Info("Delete Pad") if p.DryRun { continue }