diff --git a/README.md b/README.md index bf901d3..d415418 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,18 @@ export TEEDY_PASSWORD=password teedy-cli restore --url http://destination.teedy.local:8080 --sourcepath ./backup ``` +#### `deletedocsfortag` + +Deletes all documents with a specific Tag ID. + +```bash +# Provide username and password via environment variables +export TEEDY_USERNAME=user +export TEEDY_PASSWORD=password + +teedy-cli deletedocsfortag --url http://teedy.local:8080 --tagid f3472d4e-ed47-414c-ad7a-be65ab54d107 +``` + #### `evernote` Import an Evernote `.enex` file into Teedy. diff --git a/backup/document.go b/backup/document.go index b7d7913..337ceaa 100644 --- a/backup/document.go +++ b/backup/document.go @@ -21,7 +21,7 @@ func (b *Client) Documents() error { return fmt.Errorf("cannot get tags: %w", err) } - for _, doc := range docs.Documents { + for _, doc := range docs { os.MkdirAll(b.DocumentBackupDirectory(doc.Id), 0700) err := dumpJson(doc, b.DocumentBackupJSONFilePath(doc.Id)) diff --git a/cmd/teedy-cli/main.go b/cmd/teedy-cli/main.go index e470eeb..c58418d 100644 --- a/cmd/teedy-cli/main.go +++ b/cmd/teedy-cli/main.go @@ -33,11 +33,16 @@ type EvernoteCmd struct { Language string `arg:"-l" placeholder:"LANGUAGE" default:"eng"` } +type DeleteDocumentsForTag struct { + TagId []string `arg:"-t,required" placeholder:"TAGID" help:"A tag ID which all documents will be deleted for"` +} + type args struct { - Backup *BackupCmd `arg:"subcommand:backup"` - Restore *RestoreCmd `arg:"subcommand:restore"` - Evernote *EvernoteCmd `arg:"subcommand:evernote"` - URL string `arg:"-u,required" help:"Teedy Server URL"` + Backup *BackupCmd `arg:"subcommand:backup"` + Restore *RestoreCmd `arg:"subcommand:restore"` + Evernote *EvernoteCmd `arg:"subcommand:evernote"` + DeleteDocumentsForTag *DeleteDocumentsForTag `arg:"subcommand:deletedocsfortag"` + URL string `arg:"-u,required" help:"Teedy Server URL"` } func (a *args) Description() string { @@ -118,6 +123,30 @@ func main() { if err != nil { log.Fatalf("unable to import from evernote enex: %v", err) } + case args.DeleteDocumentsForTag != nil: + fmt.Printf("Running Delete Document For Tag\n") + + var allDocs []*teedy.Document + + for _, tagid := range args.DeleteDocumentsForTag.TagId { + docs, err := client.Document.GetByTagId(tagid) + + if err != nil { + log.Fatalf("unable to import from evernote enex: %v", err) + } + + allDocs = append(docs) + } + + for _, d := range allDocs { + fmt.Printf("Deleting %s (%s)\n", d.Title, d.Id) + _, err := client.Document.Delete(d.Id) + + if err != nil { + log.Fatalf("unable to delete: %v", err) + } + } + } } diff --git a/teedy/document.go b/teedy/document.go index 65c01b1..62d5ec7 100644 --- a/teedy/document.go +++ b/teedy/document.go @@ -2,6 +2,7 @@ package teedy import ( "fmt" + "strconv" "github.com/go-resty/resty/v2" ) @@ -112,18 +113,32 @@ func NewDocument(title, language string) *Document { } } -func (d *DocumentService) GetAll() (*DocumentList, error) { - resp, err := d.client.R(). - SetResult(&DocumentList{}). - Get("api/document/list") +func (d *DocumentService) GetAll() ([]*Document, error) { + const PAGINATION_LIMIT = 10 + var docsToReturn []*Document - err = checkRequestError(resp, err, d.apiError.GetAll) + for { + resp, err := d.client.R(). + SetResult(&DocumentList{}). + SetQueryParam("limit", strconv.Itoa(PAGINATION_LIMIT)). + SetQueryParam("offset", strconv.Itoa(len(docsToReturn))). // offset at the amount of docs read + Get("api/document/list") - if err != nil { - return nil, err + err = checkRequestError(resp, err, d.apiError.GetAll) + + if err != nil { + return nil, err + } + + docList := resp.Result().(*DocumentList) + docsToReturn = append(docsToReturn, docList.Documents...) + + if len(docList.Documents) < PAGINATION_LIMIT { + break + } } - return resp.Result().(*DocumentList), nil + return docsToReturn, nil } func (d *DocumentService) Get(id string) (*Document, error) { @@ -147,7 +162,7 @@ func (d *DocumentService) GetByTitle(title string) (*Document, error) { return nil, err } - for _, doc := range docs.Documents { + for _, doc := range docs { if doc.Title == title { return doc, nil } @@ -156,6 +171,25 @@ func (d *DocumentService) GetByTitle(title string) (*Document, error) { return nil, nil } +func (d *DocumentService) GetByTagId(tagid string) ([]*Document, error) { + var docsToReturn []*Document + docs, err := d.GetAll() + + if err != nil { + return nil, err + } + + for _, doc := range docs { + for _, tag := range doc.Tags { + if tag.Id == tagid { + docsToReturn = append(docsToReturn, doc) + } + } + } + + return docsToReturn, nil +} + func (d *DocumentService) Add(doc *Document) (*Document, error) { // builds the form data for creating a document in the teedy api fv := NewFormValues() diff --git a/teedy/document_test.go b/teedy/document_test.go index aa77fd9..1347a76 100644 --- a/teedy/document_test.go +++ b/teedy/document_test.go @@ -64,9 +64,53 @@ func TestDocumentService_GetAll(t *testing.T) { docs, err := client.Document.GetAll() require.NoError(t, err, "getting documents should not error") - require.Len(t, docs.Documents, 2) + require.Len(t, docs, 2) expected := teedy.Timestamp{Time: time.Date(2021, 3, 15, 23, 00, 00, 00, time.UTC)} - assert.Equal(t, expected.String(), docs.Documents[0].CreateDate.String(), "timestamp does not match expected") + assert.Equal(t, expected.String(), docs[0].CreateDate.String(), "timestamp does not match expected") +} + +func TestDocumentService_GetByTag(t *testing.T) { + fixture := ` +{ + "total": 2, + "documents": [ + { + "id": "1", + "title": "Insurance", + "tags": [ + { + "id": "bcd8e09b-84bc-4926-afce-222b7c21d8eb", + "name": "baz", + "color": "#3a87ad" + } + ] + }, + { + "id": "2", + "title": "Baz", + "tags": [ + { + "id": "bcd8e09b-84bc-4926-afce-222b7c21d8eb", + "name": "baz", + "color": "#3a87ad" + } + ] + }, + { + "id": "3", + "title": "Blinds" + } + ], + "suggestions": [] +} +` + responder := teedytest.NewJsonResponder(200, fixture) + httpmock.RegisterResponder("GET", "http://fake/api/document/list", responder) + client := teedy.NewFakeClient() + + docs, err := client.Document.GetByTagId("bcd8e09b-84bc-4926-afce-222b7c21d8eb") + require.NoError(t, err, "getting documents by tag should not error") + require.Len(t, docs, 2) } func TestDocumentService_AddDocument_Integration(t *testing.T) {