我們之前實現過ListFiles()
,會把所有雲端硬碟上的檔案列出來,我們也確定操作GoogleDrive這段沒有問題。但我們今天的需求是要把收到的檔案傳到Google Drive上,應該要讓使用者能選擇預設要儲存的資料夾,而不是統一存到根目錄下面。
所以我們需要能只取得資料夾的方法,而Google Drive又有分”我的雲端硬碟”&”與我共用”,今天也可能會要存到共用的資料夾內,那我們今天就來實現這段吧~
首先我們回到adapter,ListMyDriveFolders()
會撈出”我的雲端硬碟”裡的資料夾,我們可以看到主要不同的地方是Q("mimeType='application/vnd.google-apps.folder'and 'root' in parents")
,其餘的部分與ListFiles()
一樣。
// internal\adapter\google\drive.go
func (d *GoogleDrive) ListMyDriveFolders() (map[string]string, error) {
nameM := make(map[string]string)
r, err := d.Service.Files.List().Q("mimeType='application/vnd.google-apps.folder'and 'root' in parents").
Fields("files(id, name)").Do()
if err != nil {
log.Printf("Unable to retrieve files: %v", err)
return nil, err
}
fmt.Println("Files:")
if len(r.Files) == 0 {
fmt.Println("No files found.")
} else {
for _, i := range r.Files {
nameM[i.Id] = i.Name
fmt.Printf("%s (%s)\n", i.Name, i.Id)
}
}
fmt.Println("nameM 共:", len(nameM), "個資料夾")
return nameM, nil
}
我們需要透過Google提供的查詢字串”Q”代入條件來做查詢,而Google的MIME type可以參考這邊,我們找到代表資料夾的'application/vnd.google-apps.folder'
並與根目錄下的資料做AND,就可以撈出”我的雲端硬碟”裡的第一層資料夾了~
接著一樣我們改變查詢字串,sharedWithMe
代表”與我共用”的檔案,AND只取資料夾的'application/vnd.google-apps.folder'
,就可以把第一層資料夾撈出來了,這邊不用去filter root是因為”與我共用”只能取得當前目錄下的資料。(詳細查詢的一些用法&關鍵字可以參考這兒)
// internal\adapter\google\drive.go
func (d *GoogleDrive) ListSharedFolders() (map[string]string, error) {
nameM := make(map[string]string)
r, err := d.Service.Files.List().Q("sharedWithMe and mimeType='application/vnd.google-apps.folder'").
Fields("files(id, name)").Do()
if err != nil {
log.Printf("Unable to retrieve files: %v", err)
return nil, err
}
fmt.Println("Files:")
if len(r.Files) == 0 {
fmt.Println("No files found.")
} else {
for _, i := range r.Files {
nameM[i.Id] = i.Name
fmt.Printf("%s (%s)\n", i.Name, i.Id)
}
}
fmt.Println("nameM 共:", len(nameM), "個資料夾")
return nameM, nil
}
接著我們回到drive_service.go,補上ListMyDriveFolders()
和ListSharedFolders
來調用剛剛寫的方法。
// internal\app\service\drive\drive_service.go
func (dr *GoogleDriveService) ListMyDriveFolders(ctx context.Context, lineID string) (map[string]string, error) {
dToken, err := dr.driveServiceDynamodb.GetGoogleOAuthToken(lineID)
if err != nil {
log.Println(err)
return nil, err
}
tok := oauth2.Token{
AccessToken: dToken.AccessToken,
TokenType: dToken.TokenType,
RefreshToken: dToken.RefreshToken,
Expiry: dToken.Expiry,
}
d, err := dr.driveServiceGoogleOA.NewGoogleDrive(ctx, &tok)
if err != nil {
log.Println(err)
return nil, err
}
result, err := d.ListMyDriveFolders()
if err != nil {
log.Println(err)
return nil, err
}
return result, nil
}
func (dr *GoogleDriveService) ListSharedFolders(ctx context.Context, lineID string) (map[string]string, error) {
dToken, err := dr.driveServiceDynamodb.GetGoogleOAuthToken(lineID)
if err != nil {
log.Println(err)
return nil, err
}
tok := oauth2.Token{
AccessToken: dToken.AccessToken,
TokenType: dToken.TokenType,
RefreshToken: dToken.RefreshToken,
Expiry: dToken.Expiry,
}
d, err := dr.driveServiceGoogleOA.NewGoogleDrive(ctx, &tok)
if err != nil {
log.Println(err)
return nil, err
}
result, err := d.ListSharedFolders()
if err != nil {
log.Println(err)
return nil, err
}
return result, nil
}
最後我們回到callback.go,在case *linebot.TextMessage
下多加兩個條件來測試我們剛剛補上的service。
// internal\router\api\v1\callback.go
if message.Text == "list folder" {
lineID := event.Source.UserID
res, err := app.DriveService.ListMyDriveFolders(ctx, lineID)
if err != nil {
log.Println(err)
return
}
if _, err = app.LineBotClient.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(fmt.Sprintln(res))).Do(); err != nil {
log.Println(err)
}
return
}
if message.Text == "list shared" {
lineID := event.Source.UserID
res, err := app.DriveService.ListSharedFolders(ctx, lineID)
if err != nil {
log.Println(err)
return
}
if _, err = app.LineBotClient.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(fmt.Sprintln(res))).Do(); err != nil {
log.Println(err)
}
return
}
到這裡我們可以看到,能正確拿取到我們要的資料夾名稱還有ID了,之後只要記得資料夾ID,就可以把檔案直接傳到對應的資料夾內了。
那我們今天就先寫到這兒,明天再見~