iT邦幫忙

2023 iThome 鐵人賽

DAY 23
0
SideProject30

Golang LineBot X GoogleDrive:LINE有各種限制!? 那就丟上Drive吧!系列 第 23

Day23 Drive Service - 撈出”我的雲端硬碟”&”與我共用”下的資料夾

  • 分享至 

  • xImage
  •  

我們之前實現過ListFiles(),會把所有雲端硬碟上的檔案列出來,我們也確定操作GoogleDrive這段沒有問題。但我們今天的需求是要把收到的檔案傳到Google Drive上,應該要讓使用者能選擇預設要儲存的資料夾,而不是統一存到根目錄下面。

所以我們需要能只取得資料夾的方法,而Google Drive又有分”我的雲端硬碟”&”與我共用”,今天也可能會要存到共用的資料夾內,那我們今天就來實現這段吧~

https://ithelp.ithome.com.tw/upload/images/20231008/20115990H0d8kYHwvv.png

首先我們回到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,就可以把檔案直接傳到對應的資料夾內了。

https://ithelp.ithome.com.tw/upload/images/20231008/20115990LQwMSEA2M9.png

那我們今天就先寫到這兒,明天再見~


上一篇
Day22 繞過 Google OAuth 在 User Agent 上的使用限制
下一篇
Day24 Drive Service - 上傳檔案01
系列文
Golang LineBot X GoogleDrive:LINE有各種限制!? 那就丟上Drive吧!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
MissterHao
iT邦新手 5 級 ‧ 2023-10-08 21:25:40

剩下七天!

謝謝你有在看,我努力寫完🤣

我要留言

立即登入留言