iT邦幫忙

2023 iThome 鐵人賽

DAY 30
1

最後一天,我們來為Button增加對應的功能,目前有的按鈕有兩種,一種是[進入資料夾],一種是[設為上傳路徑]。

那我們就先從[進入資料夾]開始,我們要製作進入子資料夾之後呈現的畫面,我們寫一個 ListSelectedFolderCarousel,跟昨天的 ListFolderCarousel很像,差別在我們透過floderID去取得內容d.ListFolderByID(folderID),還有我們在Carousel的最前面會插入顯示自己當前的目錄還有檔案的bubble。

這樣如果當前目錄裡面沒有其他子資料夾要展開的話,至少還有一個bubble顯示,並且能設定他為上傳路徑。

// internal\app\service\drive\drive_service.go
func (dr *GoogleDriveService) ListSelectedFolderCarousel(ctx context.Context, lineID string, folderID string) (*domainDrive.FolderCarousel, 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
	}

	var params domainDrive.NewFolderCarouselParam

	// 當前目錄下的自己,才能看到資料夾下的檔案
	folderList, err := d.ListFolderByID(folderID)
	if err != nil {
		log.Println(err)
		return nil, err
	}
	currentPath, err := d.FindFolderPathByID(folderID)
	if err != nil {
		log.Println(err)
		return nil, err
	}
	currentFile, err := d.ListFilesByID(folderID)
	if err != nil {
		log.Println(err)
		return nil, err
	}
	segments := strings.Split(currentPath, "/")
	currentName := segments[len(segments)-2]

	params.BubbleParams = append(params.BubbleParams, domainDrive.NewFolderBubbleParam{
		Type:          "打開資料夾",
		Name:          currentName,
		Path:          currentPath,
		ID:            folderID,
		InsideFolderM: folderList,
		FileM:         currentFile,
	})

	for folderID, name := range folderList {
		path, err := d.FindFolderPathByID(folderID)
		if err != nil {
			log.Println(err)
			return nil, err
		}
		insideFolderM, err := d.ListFolderByID(folderID)
		if err != nil {
			log.Println(err)
			return nil, err
		}
		fileM, err := d.ListFilesByID(folderID)
		if err != nil {
			log.Println(err)
			return nil, err
		}
		param := domainDrive.NewFolderBubbleParam{
			Type:          "子資料夾",
			Name:          name,
			Path:          path,
			ID:            folderID,
			InsideFolderM: insideFolderM,
			FileM:         fileM,
		}
		params.BubbleParams = append(params.BubbleParams, param)
	}

	carousel := domainDrive.NewFolderCarousel(params)

	return &carousel, err
}

接著是[設為上傳路徑]的按鈕,我們寫上SetUploadPath,把輸入的folderID代到dToken.Info的"upload_folder_id"裡面,然後再更新回Dynamodb。

// internal\app\service\drive\drive_service.go
func (dr *GoogleDriveService) SetUploadPath(ctx context.Context, lineID string, folderID string) error {
	dToken, err := dr.driveServiceDynamodb.GetGoogleOAuthToken(lineID)
	if err != nil {
		log.Println(err)
		return err
	}
	dToken.PK = lineID
	dToken.Info = map[string]interface{}{
		"upload_folder_id": folderID,
	}

	_, err = dr.driveServiceDynamodb.TxUpdateGoogleOAuthToken(dToken)
	if err != nil {
		log.Println(err)
		return err
	}
	return nil
}

這樣兩個按鈕需要的service就完成了,但是寫了設定上傳路徑之後,我想有時候也會想看一下當前的上傳路徑在哪裡,所以我們順手寫上GetUploadPath,來從Dynamodb取得folderID,再透過FindFolderPathByID去查詢上傳的路徑。

//  internal\app\service\drive\drive_service.go
func (dr *GoogleDriveService) GetUploadPath(ctx context.Context, lineID string) (string, error) {
	dToken, err := dr.driveServiceDynamodb.GetGoogleOAuthToken(lineID)
	if err != nil {
		log.Println(err)
		return "", err
	}
	folderID := dToken.Info["upload_folder_id"]

	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 "", err
	}
	path, err := d.FindFolderPathByID(folderID.(string))
	if err != nil {
		log.Println(err)
		return "", err
	}
	return path, nil
}

接著我們在callback處理message.Text的地方先多加一條判斷來調用GetUploadPath

// internal\router\api\v1\callback.go
if message.Text == "[上傳路徑]" {
	lineID := event.Source.UserID
	path, err := app.DriveService.GetUploadPath(ctx, lineID)
	if err != nil {
		log.Println(err)
		return
	}
	if _, err = app.LineBotClient.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(path)).Do(); err != nil {
		log.Println(err)
	}
	return
}

再來,我們在最上面loop events的地方,來處理Button的Postback。當按鈕被按下的時候就會觸發Postback,我們透過event.Postback.Data可以取得我們當初在按鈕裡面的data埋下的資訊("action=setFolder&folderID=XXX"),並透過url.ParseQuery將data解析出來,我們再根據action代的是setFolder還是openFolder來呼叫對應的service來操作,這樣就沒問題哩。

// internal\router\api\v1\callback.go
for _, event := range events {
	// Handle Button Postback
	if event.Type == linebot.EventTypePostback {
		// 如果是 Postback 事件,取得 postback 資料
		postbackData := event.Postback.Data
		log.Printf("Postback data: %s", postbackData)
		// 解析 postback 資料
		values, err := url.ParseQuery(postbackData)
		if err != nil {
			log.Printf("Error parsing postback data: %v", err)
			return
		}
		// 取得特定參數的值,setFolder || openFolder
		action := values.Get("action")
		folderID := values.Get("folderID")

		lineID := event.Source.UserID

		// 在這裡可以根據 action 和 FolderID 做相應的處理
		log.Printf("Action: %s, FolderID: %s", action, folderID)
		if action == "openFolder" {
			res, err := app.DriveService.ListSelectedFolderCarousel(ctx, lineID, folderID)
			if err != nil {
				log.Println(err)
				return
			}
			if _, err := app.LineBotClient.ReplyMessage(
				event.ReplyToken,
				linebot.NewFlexMessage("打開資料夾", res.CarouselContainer),
			).Do(); err != nil {
				log.Println(err)
				return
			}
		}
		if action == "setFolder" {
			err := app.DriveService.SetUploadPath(ctx, lineID, folderID)
			if err != nil {
				log.Println(err)
				return
			}
			if _, err = app.LineBotClient.ReplyMessage(event.ReplyToken, linebot.NewTextMessage("成功設定上傳路徑")).Do(); err != nil {
				log.Println(err)
			}
			return

		}
	}
	if event.Type == linebot.EventTypeMessage {
...

最後,為了操作方便,我們進到LineOA(不是Line developers),到圖文選單的地方
https://ithelp.ithome.com.tw/upload/images/20231015/20115990wu6MKIZXJ6.png

我們選好自己想要的版型之後,可以上傳自己做的圖片當背景,依照他給定的A,B,C…區塊設定動作,我們類型選擇回傳文字,內容用[]包起來,這樣在按下圖片區塊的時候,我們就可以讓使用者傳送對應的文字訊息了。

https://ithelp.ithome.com.tw/upload/images/20231015/20115990hOpz75egNO.png

在手機上的效果會像這樣
https://ithelp.ithome.com.tw/upload/images/20231015/20115990n7KZ1twguf.jpg

最後的最後,我們走一遍流程再來測試一次。

  1. 列出我的雲端硬碟

    https://ithelp.ithome.com.tw/upload/images/20231015/20115990hiD3HC7Qef.png

  2. 進入子資料夾

    https://ithelp.ithome.com.tw/upload/images/20231015/201159903H59wCDJZ8.png

  3. 設為上傳路徑&上傳檔案

    https://ithelp.ithome.com.tw/upload/images/20231015/20115990pWol1XGp2g.png

  4. 確認上傳路徑
    https://ithelp.ithome.com.tw/upload/images/20231015/20115990uYog2GWxK7.png

  5. 對照GoogleDrive

    https://ithelp.ithome.com.tw/upload/images/20231015/201159907L7NHxQC9W.png

終於完賽了~ 謝謝有看過我其中任何一篇文章的每一個人,可能目前還有些地方沒有寫得很好,有時間應該會整理整理再放上來,真的是參與過才懂那種連續30天,每天都要擠出時間寫code+寫文章的感覺,真的沒有一開始想像的容易XDD,不過好在還是成功完賽了,再次感謝各位!!


上一篇
Day29 Drive Service - 用Google Drive API取資料建立Carousel
系列文
Golang LineBot X GoogleDrive:LINE有各種限制!? 那就丟上Drive吧!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言