mirror of
https://github.com/henrybear327/Proton-API-Bridge.git
synced 2026-05-19 12:26:01 -04:00
All large file download and upload testing
This commit is contained in:
@@ -55,8 +55,9 @@ Currently, the development are split into 2 versions. V1 supports the features [
|
||||
- [ ] File actions
|
||||
- [x] Download
|
||||
- [x] Download empty file
|
||||
- [ ] Properly handle large files and empty files (check iOS codebase)
|
||||
- [x] Properly handle large files and empty files (check iOS codebase)
|
||||
- esp. large files, where buffering in-memory will screw up the runtime
|
||||
- [ ] Improve large file handling
|
||||
- [ ] Check signature and hash
|
||||
- [x] Delete
|
||||
- [x] Upload
|
||||
@@ -64,8 +65,7 @@ Currently, the development are split into 2 versions. V1 supports the features [
|
||||
- [x] Parse mime type
|
||||
- [x] Add revision
|
||||
- [x] Modified time
|
||||
- [ ] Improve to handle large files
|
||||
- [ ] Upload verification
|
||||
- [ ] Improve large file handling
|
||||
- [ ] Handle failed / interrupted upload
|
||||
- [ ] List file metadata
|
||||
- [x] Duplicated file name handling: 422: A file or folder with that name already exists (Code=2500, Status=422)
|
||||
@@ -107,7 +107,6 @@ Currently, the development are split into 2 versions. V1 supports the features [
|
||||
- [x] Remove delete all's hardcoded string
|
||||
- [ ] Address TODO and FIXME
|
||||
- [ ] Use CI to run integration tests
|
||||
- [ ] Figure out the bottleneck by doing some profiling
|
||||
- [ ] Some error handling from [here](https://github.com/ProtonMail/WebClients/blob/main/packages/shared/lib/drive/constants.ts) MAX_NAME_LENGTH, TIMEOUT
|
||||
- [x] Point to the right proton-go-api branch
|
||||
- [x] Run `go get github.com/henrybear327/go-proton-api@dev` to update go mod
|
||||
@@ -125,6 +124,7 @@ Currently, the development are split into 2 versions. V1 supports the features [
|
||||
|
||||
Moving files and folders are [features](https://github.com/rclone/rclone/blob/51a468b2bae4ca8e21760435211623a8199a9167/fs/features.go#L25)
|
||||
|
||||
- [ ] Figure out the bottleneck by doing some profiling
|
||||
- [ ] Folder
|
||||
- [ ] (Feature) Update (force overwrite)
|
||||
- [ ] (Feature) Move
|
||||
|
||||
107
drive_test.go
107
drive_test.go
@@ -3,6 +3,7 @@ package proton_api_bridge
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/henrybear327/Proton-API-Bridge/common"
|
||||
@@ -78,15 +79,15 @@ func TestUploadAndDownloadAndDeleteAFile(t *testing.T) {
|
||||
})
|
||||
|
||||
log.Println("Upload integrationTestImage.png")
|
||||
uploadFile(t, ctx, protonDrive, "", "integrationTestImage.png", "testcase/integrationTestImage.png")
|
||||
uploadFileByFilepath(t, ctx, protonDrive, "", "integrationTestImage.png", "testcase/integrationTestImage.png")
|
||||
checkRevisions(protonDrive, ctx, t, "integrationTestImage.png", 1)
|
||||
checkFileListing(t, ctx, protonDrive, []string{"/integrationTestImage.png"})
|
||||
downloadFile(t, ctx, protonDrive, "", "integrationTestImage.png", "testcase/integrationTestImage.png")
|
||||
downloadFile(t, ctx, protonDrive, "", "integrationTestImage.png", "testcase/integrationTestImage.png", "")
|
||||
|
||||
log.Println("Upload a new revision to replace integrationTestImage.png")
|
||||
uploadFile(t, ctx, protonDrive, "", "integrationTestImage.png", "testcase/integrationTestImage2.png") /* Add a revision */
|
||||
uploadFileByFilepath(t, ctx, protonDrive, "", "integrationTestImage.png", "testcase/integrationTestImage2.png") /* Add a revision */
|
||||
checkRevisions(protonDrive, ctx, t, "integrationTestImage.png", 2)
|
||||
downloadFile(t, ctx, protonDrive, "", "integrationTestImage.png", "testcase/integrationTestImage2.png")
|
||||
downloadFile(t, ctx, protonDrive, "", "integrationTestImage.png", "testcase/integrationTestImage2.png", "")
|
||||
checkFileListing(t, ctx, protonDrive, []string{"/integrationTestImage.png"})
|
||||
|
||||
log.Println("Delete file integrationTestImage.png")
|
||||
@@ -102,15 +103,15 @@ func TestUploadAndDeleteAnEmptyFileAtRoot(t *testing.T) {
|
||||
})
|
||||
|
||||
log.Println("Upload empty.txt")
|
||||
uploadFile(t, ctx, protonDrive, "", "empty.txt", "testcase/empty.txt")
|
||||
uploadFileByFilepath(t, ctx, protonDrive, "", "empty.txt", "testcase/empty.txt")
|
||||
checkRevisions(protonDrive, ctx, t, "empty.txt", 1)
|
||||
checkFileListing(t, ctx, protonDrive, []string{"/empty.txt"})
|
||||
downloadFile(t, ctx, protonDrive, "", "empty.txt", "testcase/empty.txt")
|
||||
downloadFile(t, ctx, protonDrive, "", "empty.txt", "testcase/empty.txt", "")
|
||||
|
||||
log.Println("Upload a new revision to replace empty.txt")
|
||||
uploadFile(t, ctx, protonDrive, "", "empty.txt", "testcase/empty.txt") /* Add a revision */
|
||||
uploadFileByFilepath(t, ctx, protonDrive, "", "empty.txt", "testcase/empty.txt") /* Add a revision */
|
||||
checkRevisions(protonDrive, ctx, t, "empty.txt", 2)
|
||||
downloadFile(t, ctx, protonDrive, "", "empty.txt", "testcase/empty.txt")
|
||||
downloadFile(t, ctx, protonDrive, "", "empty.txt", "testcase/empty.txt", "")
|
||||
checkFileListing(t, ctx, protonDrive, []string{"/empty.txt"})
|
||||
|
||||
log.Println("Delete file empty.txt")
|
||||
@@ -130,15 +131,15 @@ func TestUploadAndDownloadAndDeleteAFileAtAFolderOneLevelFromRoot(t *testing.T)
|
||||
checkFileListing(t, ctx, protonDrive, []string{"/level1"})
|
||||
|
||||
log.Println("Upload integrationTestImage.png to level1")
|
||||
uploadFile(t, ctx, protonDrive, "level1", "integrationTestImage.png", "testcase/integrationTestImage.png")
|
||||
uploadFileByFilepath(t, ctx, protonDrive, "level1", "integrationTestImage.png", "testcase/integrationTestImage.png")
|
||||
checkRevisions(protonDrive, ctx, t, "integrationTestImage.png", 1)
|
||||
checkFileListing(t, ctx, protonDrive, []string{"/level1", "/level1/integrationTestImage.png"})
|
||||
downloadFile(t, ctx, protonDrive, "level1", "integrationTestImage.png", "testcase/integrationTestImage.png")
|
||||
downloadFile(t, ctx, protonDrive, "level1", "integrationTestImage.png", "testcase/integrationTestImage.png", "")
|
||||
|
||||
log.Println("Upload a new revision to replace integrationTestImage.png in level1")
|
||||
uploadFile(t, ctx, protonDrive, "level1", "integrationTestImage.png", "testcase/integrationTestImage2.png") /* Add a revision */
|
||||
uploadFileByFilepath(t, ctx, protonDrive, "level1", "integrationTestImage.png", "testcase/integrationTestImage2.png") /* Add a revision */
|
||||
checkRevisions(protonDrive, ctx, t, "integrationTestImage.png", 2)
|
||||
downloadFile(t, ctx, protonDrive, "level1", "integrationTestImage.png", "testcase/integrationTestImage2.png")
|
||||
downloadFile(t, ctx, protonDrive, "level1", "integrationTestImage.png", "testcase/integrationTestImage2.png", "")
|
||||
|
||||
log.Println("Delete folder level1")
|
||||
deleteBySearchingFromRoot(t, ctx, protonDrive, "level1", true)
|
||||
@@ -181,19 +182,19 @@ func TestCreateAndMoveAndDeleteFolderWithAFile(t *testing.T) {
|
||||
checkFileListing(t, ctx, protonDrive, []string{"/src"})
|
||||
|
||||
log.Println("Upload integrationTestImage.png to src")
|
||||
uploadFile(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage.png")
|
||||
uploadFileByFilepath(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage.png")
|
||||
checkRevisions(protonDrive, ctx, t, "integrationTestImage.png", 1)
|
||||
checkFileListing(t, ctx, protonDrive, []string{"/src", "/src/integrationTestImage.png"})
|
||||
downloadFile(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage.png")
|
||||
downloadFile(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage.png", "")
|
||||
|
||||
log.Println("Create a folder dst at root")
|
||||
createFolder(t, ctx, protonDrive, "", "dst")
|
||||
checkFileListing(t, ctx, protonDrive, []string{"/src", "/src/integrationTestImage.png", "/dst"})
|
||||
|
||||
log.Println("Upload a new revision to replace integrationTestImage.png in src")
|
||||
uploadFile(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage2.png") /* Add a revision */
|
||||
uploadFileByFilepath(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage2.png") /* Add a revision */
|
||||
checkRevisions(protonDrive, ctx, t, "integrationTestImage.png", 2)
|
||||
downloadFile(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage2.png")
|
||||
downloadFile(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage2.png", "")
|
||||
checkFileListing(t, ctx, protonDrive, []string{"/src", "/src/integrationTestImage.png", "/dst"})
|
||||
|
||||
log.Println("Move folder src to under folder dst")
|
||||
@@ -217,19 +218,19 @@ func TestCreateAndMoveAndDeleteAFileOneLevelFromRoot(t *testing.T) {
|
||||
checkFileListing(t, ctx, protonDrive, []string{"/src"})
|
||||
|
||||
log.Println("Upload integrationTestImage.png to src")
|
||||
uploadFile(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage.png")
|
||||
uploadFileByFilepath(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage.png")
|
||||
checkRevisions(protonDrive, ctx, t, "integrationTestImage.png", 1)
|
||||
checkFileListing(t, ctx, protonDrive, []string{"/src", "/src/integrationTestImage.png"})
|
||||
downloadFile(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage.png")
|
||||
downloadFile(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage.png", "")
|
||||
|
||||
log.Println("Create a folder dst at root")
|
||||
createFolder(t, ctx, protonDrive, "", "dst")
|
||||
checkFileListing(t, ctx, protonDrive, []string{"/src", "/src/integrationTestImage.png", "/dst"})
|
||||
|
||||
log.Println("Upload a new revision to replace integrationTestImage.png in src")
|
||||
uploadFile(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage2.png") /* Add a revision */
|
||||
uploadFileByFilepath(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage2.png") /* Add a revision */
|
||||
checkRevisions(protonDrive, ctx, t, "integrationTestImage.png", 2)
|
||||
downloadFile(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage2.png")
|
||||
downloadFile(t, ctx, protonDrive, "src", "integrationTestImage.png", "testcase/integrationTestImage2.png", "")
|
||||
checkFileListing(t, ctx, protonDrive, []string{"/src", "/src/integrationTestImage.png", "/dst"})
|
||||
|
||||
log.Println("Move folder src to under folder dst")
|
||||
@@ -241,39 +242,43 @@ func TestCreateAndMoveAndDeleteAFileOneLevelFromRoot(t *testing.T) {
|
||||
checkFileListing(t, ctx, protonDrive, []string{"/src"})
|
||||
}
|
||||
|
||||
// func TestUploadLargeNumberOfBlocks(t *testing.T) {
|
||||
// ctx, cancel, protonDrive := setup(t)
|
||||
// t.Cleanup(func() {
|
||||
// defer cancel()
|
||||
// defer tearDown(t, ctx, protonDrive)
|
||||
// })
|
||||
func TestUploadLargeNumberOfBlocks(t *testing.T) {
|
||||
ctx, cancel, protonDrive := setup(t)
|
||||
t.Cleanup(func() {
|
||||
defer cancel()
|
||||
defer tearDown(t, ctx, protonDrive)
|
||||
})
|
||||
|
||||
// // in order to simulate uploading large files
|
||||
// // we use 1KB for the UPLOAD_BLOCK_SIZE
|
||||
// // so a 1000KB file will generate 1000 blocks to test the uploading mechanism
|
||||
// // and also testing the downloading mechanism
|
||||
// ORIGINAL_UPLOAD_BLOCK_SIZE := UPLOAD_BLOCK_SIZE
|
||||
// defer func() {
|
||||
// UPLOAD_BLOCK_SIZE = ORIGINAL_UPLOAD_BLOCK_SIZE
|
||||
// }()
|
||||
// blocks := 500
|
||||
// UPLOAD_BLOCK_SIZE = 1000
|
||||
// in order to simulate uploading large files
|
||||
// we use 1KB for the UPLOAD_BLOCK_SIZE
|
||||
// so a 1000KB file will generate 1000 blocks to test the uploading mechanism
|
||||
// and also testing the downloading mechanism
|
||||
ORIGINAL_UPLOAD_BLOCK_SIZE := UPLOAD_BLOCK_SIZE
|
||||
defer func() {
|
||||
UPLOAD_BLOCK_SIZE = ORIGINAL_UPLOAD_BLOCK_SIZE
|
||||
}()
|
||||
blocks := 100
|
||||
UPLOAD_BLOCK_SIZE = 10
|
||||
|
||||
// file1Content := RandomString(UPLOAD_BLOCK_SIZE * blocks)
|
||||
filename := "fileContent.txt"
|
||||
file1Content := RandomString(UPLOAD_BLOCK_SIZE * blocks)
|
||||
file1ContentReader := strings.NewReader(file1Content)
|
||||
file2Content := RandomString(UPLOAD_BLOCK_SIZE * blocks)
|
||||
file2ContentReader := strings.NewReader(file2Content)
|
||||
|
||||
// log.Println("Upload file1Content")
|
||||
// uploadFile(t, ctx, protonDrive, "", "integrationTestImage.png", "testcase/integrationTestImage.png")
|
||||
// checkRevisions(protonDrive, ctx, t, "integrationTestImage.png", 1)
|
||||
// checkFileListing(t, ctx, protonDrive, []string{"/integrationTestImage.png"})
|
||||
// downloadFile(t, ctx, protonDrive, "", "integrationTestImage.png", "testcase/integrationTestImage.png")
|
||||
log.Println("Upload fileContent.txt")
|
||||
uploadFileByReader(t, ctx, protonDrive, "", filename, file1ContentReader)
|
||||
checkRevisions(protonDrive, ctx, t, filename, 1)
|
||||
checkFileListing(t, ctx, protonDrive, []string{"/" + filename})
|
||||
downloadFile(t, ctx, protonDrive, "", filename, "", file1Content)
|
||||
|
||||
// log.Println("Upload a new revision to replace integrationTestImage.png")
|
||||
// uploadFile(t, ctx, protonDrive, "", "integrationTestImage.png", "testcase/integrationTestImage2.png") /* Add a revision */
|
||||
// checkRevisions(protonDrive, ctx, t, "integrationTestImage.png", 2)
|
||||
// downloadFile(t, ctx, protonDrive, "", "integrationTestImage.png", "testcase/integrationTestImage2.png")
|
||||
// checkFileListing(t, ctx, protonDrive, []string{"/integrationTestImage.png"})
|
||||
log.Println("Upload a new revision to replace fileContent.txt")
|
||||
uploadFileByReader(t, ctx, protonDrive, "", filename, file2ContentReader)
|
||||
checkRevisions(protonDrive, ctx, t, filename, 2)
|
||||
checkFileListing(t, ctx, protonDrive, []string{"/" + filename})
|
||||
downloadFile(t, ctx, protonDrive, "", filename, "", file2Content)
|
||||
|
||||
// log.Println("Delete file integrationTestImage.png")
|
||||
// deleteBySearchingFromRoot(t, ctx, protonDrive, "integrationTestImage.png", false)
|
||||
// checkFileListing(t, ctx, protonDrive, []string{})
|
||||
// }
|
||||
log.Println("Delete file fileContent.txt")
|
||||
deleteBySearchingFromRoot(t, ctx, protonDrive, filename, false)
|
||||
checkFileListing(t, ctx, protonDrive, []string{})
|
||||
}
|
||||
|
||||
@@ -4,8 +4,10 @@ import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/henrybear327/go-proton-api"
|
||||
|
||||
@@ -66,7 +68,29 @@ func createFolder(t *testing.T, ctx context.Context, protonDrive *ProtonDrive, p
|
||||
}
|
||||
}
|
||||
|
||||
func uploadFile(t *testing.T, ctx context.Context, protonDrive *ProtonDrive, parent, name string, filepath string) {
|
||||
func uploadFileByReader(t *testing.T, ctx context.Context, protonDrive *ProtonDrive, parent, name string, in io.Reader) {
|
||||
parentLink := protonDrive.RootLink
|
||||
if parent != "" {
|
||||
targetFolderLink, err := protonDrive.SearchByNameRecursivelyFromRoot(ctx, parent, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if targetFolderLink == nil {
|
||||
t.Fatalf("Folder %v not found", parent)
|
||||
}
|
||||
parentLink = targetFolderLink
|
||||
}
|
||||
if parentLink.Type != proton.LinkTypeFolder {
|
||||
t.Fatalf("parentLink is not of folder type")
|
||||
}
|
||||
|
||||
_, _, err := protonDrive.UploadFileByReader(ctx, parentLink.LinkID, name, time.Now(), in)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func uploadFileByFilepath(t *testing.T, ctx context.Context, protonDrive *ProtonDrive, parent, name string, filepath string) {
|
||||
parentLink := protonDrive.RootLink
|
||||
if parent != "" {
|
||||
targetFolderLink, err := protonDrive.SearchByNameRecursivelyFromRoot(ctx, parent, true)
|
||||
@@ -101,7 +125,7 @@ func uploadFile(t *testing.T, ctx context.Context, protonDrive *ProtonDrive, par
|
||||
}
|
||||
}
|
||||
|
||||
func downloadFile(t *testing.T, ctx context.Context, protonDrive *ProtonDrive, parent, name string, filepath string) {
|
||||
func downloadFile(t *testing.T, ctx context.Context, protonDrive *ProtonDrive, parent, name string, filepath string, data string) {
|
||||
parentLink := protonDrive.RootLink
|
||||
if parent != "" {
|
||||
targetFolderLink, err := protonDrive.SearchByNameRecursivelyFromRoot(ctx, parent, true)
|
||||
@@ -135,17 +159,25 @@ func downloadFile(t *testing.T, ctx context.Context, protonDrive *ProtonDrive, p
|
||||
t.Fatalf("FileSystemAttr should not be nil")
|
||||
} else {
|
||||
if len(downloadedData) != int(fileSystemAttr.Size) {
|
||||
t.Fatalf("Downloaded file size != uploaded file size: %#v", fileSystemAttr)
|
||||
t.Fatalf("Downloaded file size != uploaded file size: %#v vs %#v", len(downloadedData), int(fileSystemAttr.Size))
|
||||
}
|
||||
}
|
||||
|
||||
originalData, err := os.ReadFile(filepath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if filepath != "" {
|
||||
originalData, err := os.ReadFile(filepath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !bytes.Equal(downloadedData, originalData) {
|
||||
t.Fatalf("Downloaded content is different from the original content")
|
||||
if !bytes.Equal(downloadedData, originalData) {
|
||||
t.Fatalf("Downloaded content is different from the original content")
|
||||
}
|
||||
} else if data != "" {
|
||||
if !bytes.Equal(downloadedData, []byte(data)) {
|
||||
t.Fatalf("Downloaded content is different from the original content")
|
||||
}
|
||||
} else {
|
||||
t.Fatalf("Nothing to verify against")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
6
file.go
6
file.go
@@ -47,13 +47,11 @@ func (protonDrive *ProtonDrive) GetActiveRevision(ctx context.Context, link *pro
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: compute total blocks required
|
||||
// TODO: handle large file downloading
|
||||
// FIXME: total block calculation: how?
|
||||
revision, err := protonDrive.c.GetRevision(ctx, protonDrive.MainShare.ShareID, link.LinkID, revisions[activeRevision].ID, 1, 50)
|
||||
revision, err := protonDrive.c.GetRevisionAllBlocks(ctx, protonDrive.MainShare.ShareID, link.LinkID, revisions[activeRevision].ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// log.Println("Total blocks", len(revision.Blocks))
|
||||
|
||||
return &revision, nil
|
||||
}
|
||||
|
||||
6
go.mod
6
go.mod
@@ -5,7 +5,7 @@ go 1.18
|
||||
require (
|
||||
github.com/ProtonMail/gopenpgp/v2 v2.7.1
|
||||
github.com/gabriel-vasile/mimetype v1.4.2
|
||||
github.com/henrybear327/go-proton-api v0.0.0-20230626095836-c05921e07e64
|
||||
github.com/henrybear327/go-proton-api v0.0.0-20230626213659-c3c0905ee910
|
||||
github.com/relvacode/iso8601 v1.3.0
|
||||
)
|
||||
|
||||
@@ -22,13 +22,13 @@ require (
|
||||
github.com/cronokirby/saferith v0.33.0 // indirect
|
||||
github.com/emersion/go-message v0.16.0 // indirect
|
||||
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594 // indirect
|
||||
github.com/emersion/go-vcard v0.0.0-20230331202150-f3d26859ccd3 // indirect
|
||||
github.com/emersion/go-vcard v0.0.0-20230626131229-38c18b295bbd // indirect
|
||||
github.com/go-resty/resty/v2 v2.7.0 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
golang.org/x/crypto v0.10.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect
|
||||
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect
|
||||
golang.org/x/net v0.11.0 // indirect
|
||||
golang.org/x/sync v0.3.0 // indirect
|
||||
golang.org/x/sys v0.9.0 // indirect
|
||||
|
||||
12
go.sum
12
go.sum
@@ -36,8 +36,8 @@ github.com/emersion/go-message v0.16.0 h1:uZLz8ClLv3V5fSFF/fFdW9jXjrZkXIpE1Fn8fK
|
||||
github.com/emersion/go-message v0.16.0/go.mod h1:pDJDgf/xeUIF+eicT6B/hPX/ZbEorKkUMPOxrPVG2eQ=
|
||||
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594 h1:IbFBtwoTQyw0fIM5xv1HF+Y+3ZijDR839WMulgxCcUY=
|
||||
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U=
|
||||
github.com/emersion/go-vcard v0.0.0-20230331202150-f3d26859ccd3 h1:hQ1wTMaKcGfobYRT88RM8NFNyX+IQHvagkm/tqViU98=
|
||||
github.com/emersion/go-vcard v0.0.0-20230331202150-f3d26859ccd3/go.mod h1:HMJKR5wlh/ziNp+sHEDV2ltblO4JD2+IdDOWtGcQBTM=
|
||||
github.com/emersion/go-vcard v0.0.0-20230626131229-38c18b295bbd h1:n1kH4lDJLDgO8sqkt0QgeQXKims1L8khdgilk9G5lm8=
|
||||
github.com/emersion/go-vcard v0.0.0-20230626131229-38c18b295bbd/go.mod h1:HMJKR5wlh/ziNp+sHEDV2ltblO4JD2+IdDOWtGcQBTM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
||||
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
@@ -50,8 +50,8 @@ github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSM
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/henrybear327/go-proton-api v0.0.0-20230626095836-c05921e07e64 h1:23dMmB9tttnzpli/aswiujO+/uj8Uuxh9jRSenOnQnE=
|
||||
github.com/henrybear327/go-proton-api v0.0.0-20230626095836-c05921e07e64/go.mod h1:l42xBSOrCmkAxzWUHcoUsG/cP8m1hMhV72GoChOX3bg=
|
||||
github.com/henrybear327/go-proton-api v0.0.0-20230626213659-c3c0905ee910 h1:FZIVc2R3G2dY+c1u2KYiXaBx1IiLfmp6ir5cm9ityPs=
|
||||
github.com/henrybear327/go-proton-api v0.0.0-20230626213659-c3c0905ee910/go.mod h1:l42xBSOrCmkAxzWUHcoUsG/cP8m1hMhV72GoChOX3bg=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
|
||||
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
|
||||
@@ -81,8 +81,8 @@ golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2Uz
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
|
||||
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
|
||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc=
|
||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
|
||||
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME=
|
||||
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
|
||||
Reference in New Issue
Block a user