package ami import ( "pbx-api-gin/internal/app/ami/model" "pbx-api-gin/internal/app/mysql" "pbx-api-gin/internal/pkg/configs" "pbx-api-gin/pkg/lfshook" "strings" "github.com/mitchellh/mapstructure" "github.com/sirupsen/logrus" "github.com/tqcenglish/amigo-go" "github.com/tqcenglish/amigo-go/pkg" ) var AminInstance *amigo.Amigo func StartAMI(connectOKCallBack func(), handleEvents []func(event map[string]string)) { lfshook.NewLogger().Info("Start AMI") settings := &amigo.Settings{ Host: configs.ConfigGlobal.AsteriskAMIHost, Port: configs.ConfigGlobal.AsteriskAMIPort, Username: configs.ConfigGlobal.AsteriskAMIUser, Password: configs.ConfigGlobal.AsteriskAMISecret, LogLevel: logrus.ErrorLevel} lfshook.NewLogger().Infof("ami setting: %+v", settings) AminInstance = amigo.New(settings, lfshook.NewLogger()) AminInstance.EventOn(func(payload ...interface{}) { // lfshook.NewLogger().Infof("ami event on %+v", payload[0]) event := payload[0].(map[string]string) handleAMIBridge(event) handleAMI(event) //handleSocketIO(event) for _, handle := range handleEvents { go handle(event) } }) AminInstance.ConnectOn(func(payload ...interface{}) { lfshook.NewLogger().Infof("ami connect on %+v", payload[0]) if payload[0] == pkg.Connect_OK { ClearBridge() connectOKCallBack() } else { lfshook.NewLogger().Errorf("ami connect failure %+v", payload) } }) AminInstance.Connect() } func handleAMI(event map[string]string) { switch event["Event"] { case "ContactStatus": /* endpointName := event["EndpointName"] contactStatus := event["ContactStatus"] // 中继变化也会触发此事件, 需要忽略 switch contactStatus { case "Reachable": //add contact uri := event["URI"] data := strings.Split(uri, "@") if len(data) < 2 { lfshook.NewLogger().Debugf("split URI by @ error URI: %s event:%+v", uri, event) return } first := data[1] redis.ExtensionSet(endpointName, event["URI"], strings.Split(first, ":")[0], event["RoundtripUsec"])*/ case "Removed": //remove contact //redis.ExtensionDel(endpointName) case "ExtensionStatus": status := &model.Extension{ Extension: event["Exten"], Status: event["StatusText"], } _, err := mysql.DBOrmInstance.Where("exten = ?", status.Extension).Cols("status").Update(status) if err != nil { lfshook.NewLogger().Infof("update extension status err : %+v", err.Error()) } } } func handleSocketIO(event map[string]string) { var data interface{} switch event["Event"] { case "ExtensionStatus": lfshook.NewLogger().Tracef("ExtensionStatus %+v", event) status := &model.ExtensionStatus{} mapstructure.Decode(event, status) data = status case "QueueMemberStatus": lfshook.NewLogger().Tracef("QueueMemberStatus %+v", event) status := &model.QueueMember{} mapstructure.Decode(event, status) data = status case "QueueCallerJoin": status := &model.QueueCallerJoin{} lfshook.NewLogger().Infof("status %+v", event) mapstructure.Decode(event, status) data = status case "QueueCallerLeave": status := &model.QueueCallerLeave{} mapstructure.Decode(event, status) data = status case "QueueCallerAbandon": status := &model.QueueCallerAbandon{} mapstructure.Decode(event, status) data = status case "ParkedCall": status := &model.ParkedCall{} mapstructure.Decode(event, status) data = status case "ParkedCallTimeOut": status := &model.ParkedCallTimeOut{} mapstructure.Decode(event, status) data = status case "ParkedCallGiveUp": status := &model.ParkedCallGiveUp{} mapstructure.Decode(event, status) data = status case "UnParkedCall": status := &model.UnParkedCall{} mapstructure.Decode(event, status) data = status case "MeetmeEnd": status := &model.MeetmeEnd{} mapstructure.Decode(event, status) data = status case "MeetmeJoin": fallthrough case "MeetmeLeave": fallthrough case "MeetmeMute": fallthrough case "MeetmeTalking": fallthrough case "MeetmeTalkRequest": status := &model.Meetme{} mapstructure.Decode(event, status) data = status case "PresenceStateChange": status := &model.PresenceStateChange{} mapstructure.Decode(event, status) if status.Presentity != "" { data := strings.Split(status.Presentity, ":") if len(data) == 2 { status.Extension = data[1] } } if status.Status == "dnd" { status.DndStatus = "yes" } else { status.DndStatus = "" } data = status case "DialBegin": fallthrough case "DialEnd": fallthrough case "DialState": status := &model.Dial{} mapstructure.Decode(event, status) data = status case "Newstate": status := &model.Newstate{} mapstructure.Decode(event, status) data = status case "Hangup": status := &model.Hangup{} mapstructure.Decode(event, status) data = status case "UserEvent": switch event["UserEvent"] { case "SetDND": status := &model.SetDND{} mapstructure.Decode(event, status) data = status event["Event"] = event["UserEvent"] case "WakeUpStatus": status := &model.WakeUpStatus{} mapstructure.Decode(event, status) data = status event["Event"] = event["UserEvent"] default: data = event } case "SuccessfulAuth": // 获取上线 IP 地址 status := &model.SuccessfulAuth{} mapstructure.Decode(event, status) status.GetAddress() data = status case "MessageWaiting": status := &model.MessageWaiting{} mapstructure.Decode(event, status) status.GetExtension() data = status if status.Extension == "" { lfshook.NewLogger().Warnf("MessageWaiting error %+v", event) return } default: // if !strings.Contains(event["Event"], "RTP") && // !strings.Contains(event["Event"], "RTCP") && // !strings.Contains(event["Event"], "VarSet") && // !strings.Contains(event["Event"], "Bridge") && // !strings.Contains(event["Event"], "New") && // !strings.Contains(event["Event"], "SuccessfulAuth") && // !strings.Contains(event["Event"], "ChallengeSent") { // lfshook.NewLogger().Info(event) // } } if data != nil { //socketio.SocketIOServer.BroadcastToNamespace("", event["Event"], data) } } func Connected() bool { if AminInstance != nil { return AminInstance.Connected() } return false }