iT邦幫忙

2023 iThome 鐵人賽

DAY 13
0

今天來寫上Router層的部分,開始之前,剛剛發現line-bot-sdk-go 更新到了v7版本,那我們也來跟著更新,目前使用到的地方,沒有使用方式要跟著換的,所以我們就趁開發到功能之前先來升級一下~

go get -u github.com/line/line-bot-sdk-go/v7/linebot
// import github.com/line/line-bot-sdk-go/linebot
// 換成下面的
import github.com/line/line-bot-sdk-go/v7/linebot

go mod tidy一下之後,我們開始來實現Router層

  1. 依照習慣先建立v1的資料夾(雖然應該不會有v2 XD),然後新增callback.go和v1.go

    https://ithelp.ithome.com.tw/upload/images/20230928/20115990v155rSfi1h.png

  2. callback.go,這邊我們寫上Callback(),這是給Linebot Webhook調用的function,接受一個Application物件,並返回一個gin的Handler Function。

    // callback.go
    package v1
    
    import (
    	"log"
    	"net/http"
    
    	"github.com/gin-gonic/gin"
    	"github.com/line/line-bot-sdk-go/v7/linebot"
    	"github.com/onepiece010938/Line2GoogleDriveBot/internal/app"
    )
    
    func Callback(app *app.Application) gin.HandlerFunc {
    	return func(c *gin.Context) {
    		ctx := c.Request.Context()
    		events, err := app.LineBotClient.ParseRequest(c.Request)
    		if err != nil {
    			if err == linebot.ErrInvalidSignature {
    				log.Println(err)
    				c.JSON(http.StatusBadRequest, err)
    			} else {
    				log.Println(err)
    				c.JSON(http.StatusInternalServerError, err)
    			}
    			return
    		}
    
    		for _, event := range events {
    			if event.Type == linebot.EventTypeMessage {
    				switch message := event.Message.(type) {
    				case *linebot.TextMessage:
    					samplePK, err := app.SampleService.Sample(ctx, message.Text)
    					if err != nil {
    						log.Println(err)
    						return
    					}
    					if _, err = app.LineBotClient.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(samplePK)).Do(); err != nil {
    						log.Println(err)
    					}
    				}
    			}
    		}
    
    	}
    
    }
    

    我們可以透過app.LineBotClient來取得一開始放進來Application的LineBot Client連線,也可以直接透過app.SampleService.XXX 這樣的方式來調用向app註冊好的Services們,以上面這個例子我們會調用昨天寫好的SampleService.Sample,將使用者的輸入作為lineID去dynamodb查詢對應的PK值,也就是linebot上輸入 test1234 如果有該筆紀錄會回傳LINE#test1234

  3. 接著我們到v1.go,寫上RegisterRouter(),由這裡來註冊v1這個gin Group下的所有路由,並把收到的Application放進Callback中。

    // v1.go
    package v1
    
    import (
    	"github.com/onepiece010938/Line2GoogleDriveBot/internal/app"
    
    	"github.com/gin-gonic/gin"
    )
    
    func RegisterRouter(router *gin.RouterGroup, app *app.Application) {
    
    	v1 := router.Group("/v1")
    	{
    		// 將 /v1/callback 請求路由到 Callback 函數來處理
    		v1.POST("/callback", Callback(app))
    
    	}
    }
    
  4. 最後到最外層的router.go,用一個對外的RegisterHandlers來調用registerAPIHandlers,並在api group下調用v1的RegisterRouter來把/v1註冊進/api下,如果哪天要更改內部路由的實現方式,這樣的方式就不需要修改外部調用 RegisterHandlers 的部分。

    // router.go
    package router
    
    import (
    	"context"
    
    	"github.com/onepiece010938/Line2GoogleDriveBot/internal/app"
    	v1 "github.com/onepiece010938/Line2GoogleDriveBot/internal/router/api/v1"
    	"github.com/gin-gonic/gin"
    )
    
    func RegisterHandlers(router *gin.Engine, app *app.Application) {
    	registerAPIHandlers(router, app)
    }
    
    func registerAPIHandlers(router *gin.Engine, app *app.Application) {
    
    	api := router.Group("/api")
    	{
    		v1.RegisterRouter(api, app)
    	}
    
    }
    

    那Router層的部分就先到這,我們明天再把server的部分寫好,就可以整個拉起來跑跑看,那我們明天見~


上一篇
Day12 Sever"啟動" - Gin + ( Lambda or Ngrok ) 02
下一篇
Day14 Sever"啟動" - Gin + ( Lambda or Ngrok ) 04
系列文
Golang LineBot X GoogleDrive:LINE有各種限制!? 那就丟上Drive吧!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言