昨天我們完成了組成一個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取得的就沒問題了,那我們明天見囉。