iT邦幫忙

2023 iThome 鐵人賽

DAY 17
0

今天我們把的範例整理一下,首先先把操作Google Cloud的部分移到adapter

  1. 首先,我們在adapter建立資料夾google,並建立oauth.go和drive.go

    https://ithelp.ithome.com.tw/upload/images/20231002/20115990uVB5E8b1lf.png

  2. 接著我們先定義一個結構體 GoogleOAuth,包含一個 oauth2.Config 指標。NewGoogleOAuth 用於創建並返回一個 GoogleOAuth 實例,初始化一個 oauth2.Config 並將其指標賦值給 GoogleOAuthConfig 字段。NewGoogleOAuth的參數會在server.go由NewGinLambda()StartNgrokServer() ,從AWS SSM或env代入。

    // oauth.go
    package google
    
    import (
    	"context"
    	"log"
    	"net/http"
    
    	"golang.org/x/oauth2"
    	"golang.org/x/oauth2/google"
    	"google.golang.org/api/drive/v3"
    )
    
    type GoogleOAuth struct {
    	Config *oauth2.Config
    }
    
    func NewGoogleOAuth(clientID string, clientSecret string, redirectURL string) *GoogleOAuth {
    	return &GoogleOAuth{
    		Config: &oauth2.Config{
    			ClientID:     clientID,
    			ClientSecret: clientSecret,
    			Endpoint:     google.Endpoint,
    			Scopes:       []string{drive.DriveScope},
    			RedirectURL:  redirectURL,
    		},
    	}
    }
    
  3. 把目前會用到的function封裝起來

    // oauth.go
    func (oa *GoogleOAuth) OAuthLoginURL() (oauthURL string) {
    	oauthURL = oa.Config.AuthCodeURL("state-token", oauth2.AccessTypeOffline)
    	return oauthURL
    }
    
    func (oa *GoogleOAuth) UserOAuthToken(authCode string) (*oauth2.Token, error) {
    	token, err := oa.Config.Exchange(context.TODO(), authCode)
    	if err != nil {
    		log.Printf("Unable to retrieve token from web %v", err)
    		return nil, err
    	}
    	return token, nil
    }
    
    func (oa *GoogleOAuth) NewClientByUserToken(tok *oauth2.Token) *http.Client {
    	return oa.Config.Client(context.Background(), tok)
    }
    
    • OAuthLoginURL 返回一個 Google OAuth 登入的 URL。
    • 使用 oa.Config.AuthCodeURL 生成授權 URL,其中包括一個隨機的 "state-token" 和 oauth2.AccessTypeOffline 參數,用於支援 "refresh_token"。
    • UserOAuthToken 用於交換授權碼(authCode)以獲取用戶的 OAuth 2.0 令牌。
    • 使用 oa.Config.Exchange 進行令牌的交換,如果交換失敗,輸出並返回錯誤信息。
    • NewClientByUserToken 根據給定的 OAuth 2.0 令牌創建一個新的 HTTP 客戶端。
  4. 接著到drive.go,定義一個結構體 GoogleDrive,包含一個 drive.Service 指標。

    // drive.go
    package google
    
    import (
    	"context"
    	"fmt"
    	"log"
    	"net/http"
    
    	"google.golang.org/api/drive/v3"
    	"google.golang.org/api/option"
    )
    
    type GoogleDrive struct {
    	Service *drive.Service
    }
    
    func NewGoogleDrive(ctx context.Context, client *http.Client) (*GoogleDrive, error) {
    	srv, err := drive.NewService(ctx, option.WithHTTPClient(client))
    	if err != nil {
    		log.Printf("Unable to retrieve Drive client: %v", err)
    		return nil, err
    	}
    	return &GoogleDrive{
    		Service: srv,
    	}, nil
    }
    
  5. 封裝ListFiles

    // drive.go
    func (d *GoogleDrive) ListFiles(pageSize int) (map[string]string, error) {
    	nameM := make(map[string]string)
    	r, err := d.Service.Files.List().PageSize(int64(pageSize)).
    		Fields("nextPageToken, 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:", nameM)
    	return nameM, nil
    }
    
    • ListFiles 用於列出 Google Drive 上的文件。
    • 使用 d.Service.Files.List() 來創建一個文件列表的查詢,設定頁面大小和要擷取的欄位。
    • 使用 Do 來發送查詢,並得到文件列表的回應(*drive.FileList)。
    • 遍歷回應中的文件,將文件的 ID 和名稱存儲在 nameM 中,最後印出後返回nameM

那今天就先寫到這裡,明天再繼續,我們明天見~


上一篇
Day16 GoogleDrive API 02
下一篇
Day18 GoogleDrive API 04
系列文
Golang LineBot X GoogleDrive:LINE有各種限制!? 那就丟上Drive吧!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言