Skip to content

Commit

Permalink
Merge pull request #15 from a-company-jp/new-phone-call-integration
Browse files Browse the repository at this point in the history
new phone call integration
  • Loading branch information
Shion1305 authored Oct 11, 2024
2 parents 5a01deb + 6e0b4cf commit 32ae510
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 9 deletions.
17 changes: 15 additions & 2 deletions pkg/handler/invoke.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package handler
import (
"cloud.google.com/go/firestore"
"fmt"
"github.com/a-company/yoriai-backend/pkg/model"
"github.com/a-company/yoriai-backend/pkg/service/vonage"
"github.com/gin-gonic/gin"
"log/slog"
"time"
Expand All @@ -22,21 +24,32 @@ func NewInvokeHandler(

func (h *CallInvoke) Handle(c *gin.Context) {
// get time
timeVal := fmt.Sprintf("%2d:%2d", time.Now().Hour(), 0)
timeVal := fmt.Sprintf("%02d:%02d", time.Now().Hour(), 0)
slog.Info("invoke call", slog.String("time", timeVal))
res := h.fs.Collection("users").Where("call_time", "==", timeVal).Documents(c)
if res == nil {
c.JSON(400, gin.H{"error": "no data"})
return
}

v := vonage.NewVonage()
for {
doc, err := res.Next()
if err != nil {
break
}
userdata := doc.Data()
userdata := model.User{}
doc.DataTo(&userdata)
slog.Info("invoke call on user", slog.Any("data", userdata))

// vonage callを発火
v.CallPhoneAPI(
vonage.PhoneAPIInput{
PhoneNumber: string(userdata.Phone),
ReceiverName: userdata.Nickname,
CallerName: "Yoriai",
RemindMessage: "今日の通話の時間です",
})
}
c.JSON(200, gin.H{
"message": "success",
Expand Down
33 changes: 30 additions & 3 deletions pkg/handler/line.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ func (l *LINEWebhookHandler) HandleFollowEvent(event webhook.FollowEvent) {
l.lineBotSvc.ReplyTextMessage(event.ReplyToken, "Failed to add you as a friend. Please try again later.")
return
}
l.lineBotSvc.ReplyTextMessage(event.ReplyToken, "友達登録ありがとうございます!\n\nまずは電話対象者のニックネームを入力してください")
l.lineBotSvc.ReplyTextMessage(event.ReplyToken, "友達登録ありがとうございます!\n\nまずはあなたのニックネームを入力してください")
}

func (l *LINEWebhookHandler) HandleUnfollowEvent(event webhook.UnfollowEvent) {
Expand Down Expand Up @@ -125,13 +125,22 @@ func (l *LINEWebhookHandler) HandleMessageEvent(event webhook.MessageEvent) {
doc.DataTo(&userdata)

if userdata.Target.Nickname == "" {
event.Message.GetType()
userdata.Target.Nickname = txtMsg.Text
_, err := ref.Set(ctx, userdata)
if err != nil {
slog.Error("failed to set user", err)
return
}
l.lineBotSvc.ReplyTextMessage(event.ReplyToken, "次に相手のニックネームを入力してください")
return
}
if userdata.Target.RecipientNickname == "" {
userdata.Target.RecipientNickname = txtMsg.Text
_, err := ref.Set(ctx, userdata)
if err != nil {
slog.Error("failed to set user", err)
return
}
l.lineBotSvc.ReplyTextMessage(event.ReplyToken, "次に電話番号を入力してください (例: 09012345678)")
return
}
Expand All @@ -143,6 +152,8 @@ func (l *LINEWebhookHandler) HandleMessageEvent(event webhook.MessageEvent) {
l.lineBotSvc.ReplyTextMessage(event.ReplyToken, "電話番号の形式が正しくありません。もう一度入力してください。(例: 09012345678)")
return
}
// 先頭の0を81に変換
userdata.Target.Phone = model.PhoneNumber("81" + string(userdata.Target.Phone)[1:])
_, err := ref.Set(ctx, userdata)
if err != nil {
slog.Error("failed to set user", err)
Expand All @@ -164,8 +175,24 @@ func (l *LINEWebhookHandler) HandleMessageEvent(event webhook.MessageEvent) {
slog.Error("failed to set user", err)
return
}
l.lineBotSvc.ReplyTextMessage(event.ReplyToken, "登録が完了しました!")
l.lineBotSvc.ReplyTextMessage(event.ReplyToken, "最後にリマインドメッセージがある場合は入力してください。ない場合は「なし」と入力してください")
return
}
if userdata.Target.RemindMessage == "" && !userdata.Target.Confirm {
if txtMsg.Text == "なし" {
userdata.Target.Confirm = true
} else {
userdata.Target.RemindMessage = txtMsg.Text
}
_, err := ref.Set(ctx, userdata)
if err != nil {
slog.Error("failed to set user", err)
return
}
l.lineBotSvc.ReplyTextMessage(event.ReplyToken, "登録完了しました!")
return
}
l.lineBotSvc.ReplyTextMessage(event.ReplyToken, "登録が完了しています!")
}

func (l *LINEWebhookHandler) HandleLeaveEvent(event webhook.UnfollowEvent) {
Expand Down
10 changes: 6 additions & 4 deletions pkg/model/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ type User struct {
type PhoneNumber string

type Target struct {
Nickname string `firestore:"nickname"`
Phone PhoneNumber `firestore:"phone_number"`
CallTime string `firestore:"call_time"` // 12:00
Confirm bool `firestore:"confirm"`
Nickname string `firestore:"nickname"`
RecipientNickname string `firestore:"r_nickname"`
Phone PhoneNumber `firestore:"phone_number"`
CallTime string `firestore:"call_time"` // 12:00
RemindMessage string `firestore:"remind_message"`
Confirm bool `firestore:"confirm"`
}
102 changes: 102 additions & 0 deletions pkg/service/vonage/vonage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package vonage

import (
"bytes"
"encoding/json"
"fmt"
"github.com/a-company/yoriai-backend/pkg/config"
"io"
"log/slog"
"net/http"
)

const (
API_URL = "https://studio-api-us.ai.vonage.com/telephony/make-call"
)

type VonageService struct {
conf config.VonageConfig
}

func NewVonage() *VonageService {
return &VonageService{
conf: config.Config.VonageConfig,
}
}

type PhoneAPIInput struct {
PhoneNumber string
ReceiverName string
CallerName string
RemindMessage string
}

func (s VonageService) CallPhoneAPI(input PhoneAPIInput) error {
slog.Info("CallPhoneAPI", slog.Any("input", input))
requestBody, err := createRequestBody(s.conf.AgentID, input)
if err != nil {
return err
}

responseBody, err := sendApiRequest(requestBody, s.conf.VgaiKey)
if err != nil {
return err
}

slog.Info("Response Body:", slog.String("response", responseBody))
return nil
}

func createRequestBody(agentId string, input PhoneAPIInput) ([]byte, error) {
requestBody, err := json.Marshal(map[string]interface{}{
"agent_id": agentId,
"to": input.PhoneNumber,
"session_parameters": []map[string]string{
{
"name": "RECEIVER_NAME",
"value": input.ReceiverName,
},
{
"name": "CALLER_NAME",
"value": input.CallerName,
},
{
"name": "REMIND_MESSAGE",
"value": input.RemindMessage,
},
},
})

if err != nil {
fmt.Println("Error marshalling JSON:", err)
return nil, err
}
return requestBody, nil
}

func sendApiRequest(requestBody []byte, XKey string) (string, error) {
req, err := http.NewRequest("POST", API_URL, bytes.NewBuffer(requestBody))
if err != nil {
slog.Error("Error creating request:", err)
return "", err
}

req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Vgai-Key", XKey)

client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
slog.Error("Error sending request:", err)
return "", err
}
defer resp.Body.Close()

body, err := io.ReadAll(resp.Body)
if err != nil {
slog.Error("Error reading response body", err)
return "", err
}

return string(body), nil
}

0 comments on commit 32ae510

Please sign in to comment.