Skip to content

Commit

Permalink
Merge pull request #8 from kkdai/support_linebot_v8
Browse files Browse the repository at this point in the history
chore: update line-bot-sdk-go version and refactor main.go
  • Loading branch information
kkdai committed Jan 5, 2024
2 parents 461370b + db55e0b commit 645b1db
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 30 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.21.1

require (
github.com/google/generative-ai-go v0.5.0
github.com/line/line-bot-sdk-go/v7 v7.21.0
github.com/line/line-bot-sdk-go/v8 v8.2.0
google.golang.org/api v0.154.0
)

Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfF
github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas=
github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU=
github.com/line/line-bot-sdk-go/v7 v7.21.0 h1:eeYMuAwaDV5DZNTRqDipNhzjT51HwEcM1PRPG+cqh4Y=
github.com/line/line-bot-sdk-go/v7 v7.21.0/go.mod h1:idpoxOZgtSd8JyhctMMpwg5LNgRAIL/QIxa5S0DXcMg=
github.com/line/line-bot-sdk-go/v8 v8.2.0 h1:IFqwd3pKbA+o3pwV3nzamtWHt7n+ijSH3t/D8Q/vVQ0=
github.com/line/line-bot-sdk-go/v8 v8.2.0/go.mod h1:n9Ly8OHM6xCeQktLzRpQHe/yBda95kFgmQUefUQeFCs=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
Expand Down
104 changes: 77 additions & 27 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,32 +20,57 @@ import (
"os"

"github.com/google/generative-ai-go/genai"
"github.com/line/line-bot-sdk-go/v7/linebot"
"github.com/line/line-bot-sdk-go/v8/linebot"
"github.com/line/line-bot-sdk-go/v8/linebot/messaging_api"
"github.com/line/line-bot-sdk-go/v8/linebot/webhook"
)

var bot *linebot.Client

var bot *messaging_api.MessagingApiAPI
var blob *messaging_api.MessagingApiBlobAPI
var geminiKey string
var channelToken string

// 建立一個 map 來儲存每個用戶的 ChatSession
var userSessions = make(map[string]*genai.ChatSession)

func main() {
var err error
geminiKey = os.Getenv("GOOGLE_GEMINI_API_KEY")
bot, err = linebot.New(os.Getenv("ChannelSecret"), os.Getenv("ChannelAccessToken"))
channelToken = os.Getenv("ChannelAccessToken")
bot, err = messaging_api.NewMessagingApiAPI(channelToken)
if err != nil {
log.Fatal(err)
}

blob, err = messaging_api.NewMessagingApiBlobAPI(channelToken)
if err != nil {
log.Println("Bot:", bot, " err:", err)
log.Fatal(err)
}

http.HandleFunc("/callback", callbackHandler)
port := os.Getenv("PORT")
addr := fmt.Sprintf(":%s", port)
http.ListenAndServe(addr, nil)
}

func callbackHandler(w http.ResponseWriter, r *http.Request) {
events, err := bot.ParseRequest(r)
func replyText(replyToken, text string) error {
if _, err := bot.ReplyMessage(
&messaging_api.ReplyMessageRequest{
ReplyToken: replyToken,
Messages: []messaging_api.MessageInterface{
&messaging_api.TextMessage{
Text: text,
},
},
},
); err != nil {
return err
}
return nil
}

func callbackHandler(w http.ResponseWriter, r *http.Request) {
cb, err := webhook.ParseRequest(os.Getenv("ChannelSecret"), r)
if err != nil {
if err == linebot.ErrInvalidSignature {
w.WriteHeader(400)
Expand All @@ -55,72 +80,97 @@ func callbackHandler(w http.ResponseWriter, r *http.Request) {
return
}

for _, event := range events {
if event.Type == linebot.EventTypeMessage {
switch message := event.Message.(type) {
for _, event := range cb.Events {
log.Printf("Got event %v", event)
switch e := event.(type) {
case webhook.MessageEvent:
switch message := e.Message.(type) {
// Handle only on text message
case *linebot.TextMessage:
case webhook.TextMessageContent:
req := message.Text
// 檢查是否已經有這個用戶的 ChatSession or req == "reset"
cs, ok := userSessions[event.Source.UserID]

// 取得用戶 ID
var uID string
switch source := e.Source.(type) {
case *webhook.UserSource:
uID = source.UserId
case *webhook.GroupSource:
uID = source.UserId
case *webhook.RoomSource:
uID = source.UserId
}

// 檢查是否已經有這個用戶的 ChatSession
cs, ok := userSessions[uID]
if !ok {
// 如果沒有,則創建一個新的 ChatSession
cs = startNewChatSession()
userSessions[event.Source.UserID] = cs
userSessions[uID] = cs
}
if req == "reset" {
// 如果需要重置記憶,創建一個新的 ChatSession
cs = startNewChatSession()
userSessions[event.Source.UserID] = cs
if _, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage("很高興初次見到你,請問有什麼想了解的嗎?")).Do(); err != nil {
userSessions[uID] = cs
if err := replyText(e.ReplyToken, "很高興初次見到你,請問有什麼想了解的嗎?"); err != nil {
log.Print(err)
}
continue
}
// 使用這個 ChatSession 來處理訊息 & Reply with Gemini result
res := send(cs, req)
ret := printResponse(res)
if _, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(ret)).Do(); err != nil {
if err := replyText(e.ReplyToken, ret); err != nil {
log.Print(err)
}
// Handle only on Sticker message
case *linebot.StickerMessage:
case webhook.StickerMessageContent:
var kw string
for _, k := range message.Keywords {
kw = kw + "," + k
}

outStickerResult := fmt.Sprintf("收到貼圖訊息: %s, pkg: %s kw: %s text: %s", message.StickerID, message.PackageID, kw, message.Text)
if _, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(outStickerResult)).Do(); err != nil {
outStickerResult := fmt.Sprintf("收到貼圖訊息: %s, pkg: %s kw: %s text: %s", message.StickerId, message.PackageId, kw, message.Text)
if err := replyText(e.ReplyToken, outStickerResult); err != nil {
log.Print(err)
}

// Handle only image message
case *linebot.ImageMessage:
log.Println("Got img msg ID:", message.ID)
case webhook.ImageMessageContent:
log.Println("Got img msg ID:", message.Id)

//Get image binary from LINE server based on message ID.
content, err := bot.GetMessageContent(message.ID).Do()
content, err := blob.GetMessageContent(message.Id)
if err != nil {
log.Println("Got GetMessageContent err:", err)
}
defer content.Content.Close()
data, err := io.ReadAll(content.Content)
defer content.Body.Close()
data, err := io.ReadAll(content.Body)
if err != nil {
log.Fatal(err)
}
ret, err := GeminiImage(data)
if err != nil {
ret = "無法辨識圖片內容,請重新輸入:" + err.Error()
}
if _, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(ret)).Do(); err != nil {
if err := replyText(e.ReplyToken, ret); err != nil {
log.Print(err)
}

// Handle only video message
case *linebot.VideoMessage:
log.Println("Got video msg ID:", message.ID)
case webhook.VideoMessageContent:
log.Println("Got video msg ID:", message.Id)

default:
log.Printf("Unknown message: %v", message)
}
case webhook.FollowEvent:
log.Printf("message: Got followed event")
case webhook.PostbackEvent:
data := e.Postback.Data
log.Printf("Unknown message: Got postback: " + data)
case webhook.BeaconEvent:
log.Printf("Got beacon: " + e.Beacon.Hwid)
}
}
}

0 comments on commit 645b1db

Please sign in to comment.