Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: update line-bot-sdk-go version and refactor main.go #8

Merged
merged 1 commit into from
Jan 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
}
}
}