mirror of
https://github.com/henrybear327/Proton-API-Bridge.git
synced 2025-12-23 23:57:47 -05:00
The Proton-API-Bridge should not be attempting to take over, nor re-define, the existing proton-go-api interfaces. This is known has an "unfriendly fork" and increases the overall complexity of maintaining the Proton-API-Bridge. All changes to the proton-go-api should be done as "friendly" as possible, and should be submitted back upstream for inclusion. This improves the functionality of the proton-go-api for more than just 1 project, and it reduces the long-term maintenance required for Proton-API-Bridge. To this end, Proton-API-Bridge should be written to always assume it is using github.com/ProtonMail/proton-go-api and leverage the `replace` operation in go.mod in order to leverage our "friendly fork" of proton-go-api. I.e. the long-term goal should be to _not_ maintain a fork of proton-go-api. > Anything else would be uncivilized.
116 lines
2.8 KiB
Go
116 lines
2.8 KiB
Go
package proton_api_bridge
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
"log"
|
|
"os"
|
|
|
|
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
|
"github.com/ProtonMail/go-proton-api"
|
|
)
|
|
|
|
func (protonDrive *ProtonDrive) listDirectoriesRecursively(
|
|
ctx context.Context,
|
|
parentNodeKR *crypto.KeyRing,
|
|
link *proton.Link,
|
|
download bool,
|
|
maxDepth, curDepth /* 0-based */ int,
|
|
excludeRoot bool,
|
|
pathSoFar string,
|
|
paths *[]string) error {
|
|
/*
|
|
Assumptions:
|
|
- we only care about the active ones
|
|
*/
|
|
if link.State != proton.LinkStateActive {
|
|
return nil
|
|
}
|
|
// log.Println("curDepth", curDepth, "pathSoFar", pathSoFar)
|
|
|
|
var currentPath = ""
|
|
|
|
if !(excludeRoot && curDepth == 0) {
|
|
signatureVerificationKR, err := protonDrive.getSignatureVerificationKeyring([]string{link.NameSignatureEmail, link.SignatureEmail})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
name, err := link.GetName(parentNodeKR, signatureVerificationKR)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
currentPath = pathSoFar + "/" + name
|
|
// log.Println("currentPath", currentPath)
|
|
if paths != nil {
|
|
*paths = append(*paths, currentPath)
|
|
}
|
|
}
|
|
|
|
if download {
|
|
if protonDrive.Config.DataFolderName == "" {
|
|
return ErrDataFolderNameIsEmpty
|
|
}
|
|
|
|
if link.Type == proton.LinkTypeFile {
|
|
log.Println("Downloading", currentPath)
|
|
defer log.Println("Completes downloading", currentPath)
|
|
|
|
reader, _, _, err := protonDrive.DownloadFile(ctx, link, 0)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
byteArray, err := io.ReadAll(reader)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = os.WriteFile("./"+protonDrive.Config.DataFolderName+"/"+currentPath, byteArray, 0777)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
} else /* folder */ {
|
|
if !(excludeRoot && curDepth == 0) {
|
|
// log.Println("Creating folder", currentPath)
|
|
// defer log.Println("Completes creating folder", currentPath)
|
|
|
|
err := os.Mkdir("./"+protonDrive.Config.DataFolderName+"/"+currentPath, 0777)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if maxDepth == -1 || curDepth < maxDepth {
|
|
if link.Type == proton.LinkTypeFolder {
|
|
childrenLinks, err := protonDrive.c.ListChildren(ctx, protonDrive.MainShare.ShareID, link.LinkID, true)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// log.Printf("childrenLinks len = %v, %#v", len(childrenLinks), childrenLinks)
|
|
|
|
if childrenLinks != nil {
|
|
// get current node's keyring
|
|
signatureVerificationKR, err := protonDrive.getSignatureVerificationKeyring([]string{link.SignatureEmail})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
linkKR, err := link.GetKeyRing(parentNodeKR, signatureVerificationKR)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, childLink := range childrenLinks {
|
|
err = protonDrive.listDirectoriesRecursively(ctx, linkKR, &childLink, download, maxDepth, curDepth+1, excludeRoot, currentPath, paths)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|