From f4c24e1a042d63a9ef32218bc9784b8de4ff599e Mon Sep 17 00:00:00 2001 From: #MDanial <48054961+mdanialr@users.noreply.github.com> Date: Sun, 8 May 2022 16:59:58 +0700 Subject: [PATCH] fix: issue#17 (#18) * add service to check whether a filename exist in array of filenames * feat: only upload files that do not exist yet in the cloud --- internal/provider/gdrive/gdrive.go | 40 ++++++++++++++++++------- internal/service/contain_string.go | 11 +++++++ internal/service/contain_string_test.go | 36 ++++++++++++++++++++++ 3 files changed, 76 insertions(+), 11 deletions(-) create mode 100644 internal/service/contain_string.go create mode 100644 internal/service/contain_string_test.go diff --git a/internal/provider/gdrive/gdrive.go b/internal/provider/gdrive/gdrive.go index f52dcc6..b8e7963 100644 --- a/internal/provider/gdrive/gdrive.go +++ b/internal/provider/gdrive/gdrive.go @@ -14,6 +14,7 @@ import ( "github.com/mdanialr/cron-upload/internal/config" "github.com/mdanialr/cron-upload/internal/provider/gdrive/token" "github.com/mdanialr/cron-upload/internal/scan" + "github.com/mdanialr/cron-upload/internal/service" "golang.org/x/oauth2" "google.golang.org/api/drive/v3" "google.golang.org/api/option" @@ -175,6 +176,17 @@ func GoogleDrive(conf *config.Model) error { } } + // 9. Index all files in Google Drive then compare it to soon to be uploaded files, ONLY upload + // files that do not exist yet. + var listOfFilesInCloud []string + query := fmt.Sprintf("'%s' in parents and %s != '%s'", + currentParentIdFolder, FieldMIME, MIMEFolder, + ) + list, _ := dr.Files.List().Q(query).Fields("files(name)").Do() + for _, fl := range list.Files { + listOfFilesInCloud = append(listOfFilesInCloud, fl.Name) + } + // Then we are ready to upload the files to Google Drive's folder for _, fl := range allFiles { flInstance, err := os.Open(fl) @@ -182,20 +194,26 @@ func GoogleDrive(conf *config.Model) error { return fmt.Errorf("failed to open file: %s with error: %s\n", fl, err) } defer flInstance.Close() - fl := &drive.File{ - Parents: []string{currentParentIdFolder}, - Name: filepath.Base(flInstance.Name()), - } - uploadFl, err := dr.Files.Create(fl).Media(flInstance).Fields( - FieldId, FieldMIME, - FieldName, FieldParents, - ).Do() - if err != nil { - return fmt.Errorf("failed to upload file: %s with error: %s\n", uploadFl.Name, err) + + // If this filename already exist in cloud then do not upload this file. ONLY upload filename + // that does not exist in the cloud yet. + fileName := filepath.Base(flInstance.Name()) + if !service.Contains(listOfFilesInCloud, fileName) { + fl := &drive.File{ + Parents: []string{currentParentIdFolder}, + Name: fileName, + } + uploadFl, err := dr.Files.Create(fl).Media(flInstance).Fields( + FieldId, FieldMIME, + FieldName, FieldParents, + ).Do() + if err != nil { + return fmt.Errorf("failed to upload file: %s with error: %s\n", uploadFl.Name, err) + } } } - // 9. Lastly, delete all soon to be deleted files using their id + // 10. Lastly, delete all soon to be deleted files using their id for _, filesToDelete := range soonToBeDeletedFiles { if err := dr.Files.Delete(filesToDelete).Do(); err != nil { return fmt.Errorf("failed to delete a file or a folder with id: %s and error: %s\n", filesToDelete, err) diff --git a/internal/service/contain_string.go b/internal/service/contain_string.go new file mode 100644 index 0000000..4f3a022 --- /dev/null +++ b/internal/service/contain_string.go @@ -0,0 +1,11 @@ +package service + +// Contains tells whether b exist in a. +func Contains(a []string, b string) bool { + for _, n := range a { + if b == n { + return true + } + } + return false +} diff --git a/internal/service/contain_string_test.go b/internal/service/contain_string_test.go new file mode 100644 index 0000000..4108d40 --- /dev/null +++ b/internal/service/contain_string_test.go @@ -0,0 +1,36 @@ +package service + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestContains(t *testing.T) { + testCases := []struct { + name string + sample []string + check string + expect bool + }{ + { + name: "Should true if `sample` contains string `check`", + sample: []string{"one.zip", "two.txt", "three.mp4"}, + check: "two.txt", + expect: true, + }, + { + name: "Should false if `sample` does not contains string `check`", + sample: []string{"one.zip", "two.txt", "three.mp4"}, + check: "one.txt", + expect: false, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + out := Contains(tc.sample, tc.check) + assert.Equal(t, tc.expect, out) + }) + } +}