昨天我們完成了組成一個Bubble需要的4個區塊,今天我們透過這4個區塊把Bubble組起來,然後再用Bubble把Carousel組合起來,就可以回傳給Drive Service使用了。
首先,我們假設最小製作的單位就是Bubble,也就是一開始資料會從Bubble做輸入,那我們就可以寫一個newFolderBubble()以及定義輸入資料的NewFolderBubbleParam。
在newFolderBubble()中,我們先宣告一個allFlexComponents,把4個區塊拿到的linebot.FlexComponent在這裡一一展開組合進allFlexComponents,然後塞進BubbleContainer的Contents裡回傳。
// internal\domain\drive\flex.go
type NewFolderBubbleParam struct {
	Type          string
	Name          string
	Path          string
	ID            string
	InsideFolderM map[string]string
	FileM         map[string]string
}
func newFolderBubble(param NewFolderBubbleParam) *linebot.BubbleContainer {
	var allFlexComponents []linebot.FlexComponent
	title := folderTitleFlexComponents(param.Type, param.Name, param.Path)
	allFlexComponents = append(allFlexComponents, title...)
	folder := folderFlexComponents(param.InsideFolderM)
	allFlexComponents = append(allFlexComponents, folder...)
	file := fileFlexComponents(param.FileM)
	allFlexComponents = append(allFlexComponents, file...)
	button := buttonFlexComponents(param.ID)
	allFlexComponents = append(allFlexComponents, button...)
	// Single Bubble
	bubble := linebot.BubbleContainer{
		Type: linebot.FlexContainerTypeBubble,
		Body: &linebot.BoxComponent{
			Type:   linebot.FlexComponentTypeBox,
			Layout: linebot.FlexBoxLayoutTypeVertical,
			// Insert Components
			Contents: allFlexComponents,
		},
		Styles: &linebot.BubbleStyle{
			Footer: &linebot.BlockStyle{
				Separator: true,
			},
		},
	}
	return &bubble
}
接著,有了Bubble之後就可以來組Carousel了。
我們先定義一個對外的NewFolderCarousel(),會回傳我們定義的FolderCarousel,裡面存放linebot最終需要的CarouselContainer,然後NewFolderCarouselParam做為外部輸入的參數,要提供[]NewFolderBubbleParam。
NewFolderCarousel()會根據有多少個NewFolderBubbleParam被傳進來,調用newFolderBubble製作對應的Bubble,最後組合成FolderCarousel後回傳。
// internal\domain\drive\flex.go
type FolderCarousel struct {
	CarouselContainer *linebot.CarouselContainer
}
type NewFolderCarouselParam struct {
	BubbleParams []NewFolderBubbleParam
}
func NewFolderCarousel(carouselParams NewFolderCarouselParam) FolderCarousel {
	var bubbles []*linebot.BubbleContainer
	for _, v := range carouselParams.BubbleParams {
		bubble := newFolderBubble(v)
		bubbles = append(bubbles, bubble)
	}
	return FolderCarousel{
		CarouselContainer: &linebot.CarouselContainer{
			Type: linebot.FlexContainerTypeCarousel,
			// Insert bubbles
			Contents: bubbles,
		},
	}
}
接著我們回Service層,寫一個TestFolderCarousel來調用domainDrive.NewFolderCarousel組出我們的Carousel,首先寫定義兩個map,分別代表資料夾內的子資料夾和檔案,接著我們填充params.BubbleParams把每一個Bubble要顯示的參數代入,最後把*domainDrive.FolderCarousel回傳出去。
P.S. 不在這邊回傳*linebotXXX這種類型,是為了保持Service層的乾淨,讓Service層只會去碰到Domain跟Adapter。
// internal\app\service\drive\drive_service.go
func (dr *GoogleDriveService) TestFolderCarousel(ctx context.Context, lineID string) (*domainDrive.FolderCarousel, error) {
	insideFolderM := map[string]string{
		"001": "F1",
		"002": "F2",
	}
	fileM := map[string]string{
		"001": "file1",
		"002": "file2",
	}
	var params domainDrive.NewFolderCarouselParam
	params.BubbleParams = append(params.BubbleParams,
		domainDrive.NewFolderBubbleParam{
			Type:          "我的雲端硬碟",
			Name:          "Folder1",
			Path:          "/xx/xx",
			ID:            "123",
			InsideFolderM: insideFolderM,
			FileM:         fileM,
		},
		domainDrive.NewFolderBubbleParam{
			Type:          "我的雲端硬碟",
			Name:          "Folder2",
			Path:          "/yy/yy",
			ID:            "1234",
			InsideFolderM: insideFolderM,
			FileM:         fileM,
		},
	)
	carousel := domainDrive.NewFolderCarousel(params)
	return &carousel, nil
}
最後我們去Callback()來測試一下效果,從res取出CarouselContainer放入NewFlexMessage中。
//internal\router\api\v1\callback.go
if message.Text == "test" {
		lineID := event.Source.UserID
		res, err := app.DriveService.TestFolderCarousel(ctx, lineID)
		if err != nil {
			log.Println(err)
			return
		}
		if _, err := app.LineBotClient.ReplyMessage(
			event.ReplyToken,
			linebot.NewFlexMessage("測試Flex Carousel", res.CarouselContainer),
		).Do(); err != nil {
			log.Println(err)
			return
		}
}

可以看到,我們已經能依照我們給定的資料去動態組合出需要的Carousel,這樣Flex Message的部分就沒問題了。
那我們今天就先到這裡,明天我們只要把資料一一替換成從GoogleDrive取得的就沒問題了,那我們明天見囉。