index.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. package ami
  2. import (
  3. "pbx-api-gin/internal/app/ami/model"
  4. "pbx-api-gin/internal/app/mysql"
  5. "pbx-api-gin/internal/pkg/configs"
  6. "pbx-api-gin/pkg/lfshook"
  7. "strings"
  8. "github.com/mitchellh/mapstructure"
  9. "github.com/sirupsen/logrus"
  10. "github.com/tqcenglish/amigo-go"
  11. "github.com/tqcenglish/amigo-go/pkg"
  12. )
  13. var AminInstance *amigo.Amigo
  14. func StartAMI(connectOKCallBack func(), handleEvents []func(event map[string]string)) {
  15. lfshook.NewLogger().Info("Start AMI")
  16. settings := &amigo.Settings{
  17. Host: configs.ConfigGlobal.AsteriskAMIHost,
  18. Port: configs.ConfigGlobal.AsteriskAMIPort,
  19. Username: configs.ConfigGlobal.AsteriskAMIUser,
  20. Password: configs.ConfigGlobal.AsteriskAMISecret,
  21. LogLevel: logrus.ErrorLevel}
  22. lfshook.NewLogger().Infof("ami setting: %+v", settings)
  23. AminInstance = amigo.New(settings, lfshook.NewLogger())
  24. AminInstance.EventOn(func(payload ...interface{}) {
  25. // lfshook.NewLogger().Infof("ami event on %+v", payload[0])
  26. event := payload[0].(map[string]string)
  27. handleAMIBridge(event)
  28. handleAMI(event)
  29. //handleSocketIO(event)
  30. for _, handle := range handleEvents {
  31. go handle(event)
  32. }
  33. })
  34. AminInstance.ConnectOn(func(payload ...interface{}) {
  35. lfshook.NewLogger().Infof("ami connect on %+v", payload[0])
  36. if payload[0] == pkg.Connect_OK {
  37. ClearBridge()
  38. connectOKCallBack()
  39. } else {
  40. lfshook.NewLogger().Errorf("ami connect failure %+v", payload)
  41. }
  42. })
  43. AminInstance.Connect()
  44. }
  45. func handleAMI(event map[string]string) {
  46. switch event["Event"] {
  47. case "ContactStatus": /*
  48. endpointName := event["EndpointName"]
  49. contactStatus := event["ContactStatus"]
  50. // 中继变化也会触发此事件, 需要忽略
  51. switch contactStatus {
  52. case "Reachable":
  53. //add contact
  54. uri := event["URI"]
  55. data := strings.Split(uri, "@")
  56. if len(data) < 2 {
  57. lfshook.NewLogger().Debugf("split URI by @ error URI: %s event:%+v", uri, event)
  58. return
  59. }
  60. first := data[1]
  61. redis.ExtensionSet(endpointName, event["URI"], strings.Split(first, ":")[0], event["RoundtripUsec"])*/
  62. case "Removed":
  63. //remove contact
  64. //redis.ExtensionDel(endpointName)
  65. case "ExtensionStatus":
  66. status := &model.Extension{
  67. Extension: event["Exten"],
  68. Status: event["StatusText"],
  69. }
  70. _, err := mysql.DBOrmInstance.Where("exten = ?", status.Extension).Cols("status").Update(status)
  71. if err != nil {
  72. lfshook.NewLogger().Infof("update extension status err : %+v", err.Error())
  73. }
  74. }
  75. }
  76. func handleSocketIO(event map[string]string) {
  77. var data interface{}
  78. switch event["Event"] {
  79. case "ExtensionStatus":
  80. lfshook.NewLogger().Tracef("ExtensionStatus %+v", event)
  81. status := &model.ExtensionStatus{}
  82. mapstructure.Decode(event, status)
  83. data = status
  84. case "QueueMemberStatus":
  85. lfshook.NewLogger().Tracef("QueueMemberStatus %+v", event)
  86. status := &model.QueueMember{}
  87. mapstructure.Decode(event, status)
  88. data = status
  89. case "QueueCallerJoin":
  90. status := &model.QueueCallerJoin{}
  91. lfshook.NewLogger().Infof("status %+v", event)
  92. mapstructure.Decode(event, status)
  93. data = status
  94. case "QueueCallerLeave":
  95. status := &model.QueueCallerLeave{}
  96. mapstructure.Decode(event, status)
  97. data = status
  98. case "QueueCallerAbandon":
  99. status := &model.QueueCallerAbandon{}
  100. mapstructure.Decode(event, status)
  101. data = status
  102. case "ParkedCall":
  103. status := &model.ParkedCall{}
  104. mapstructure.Decode(event, status)
  105. data = status
  106. case "ParkedCallTimeOut":
  107. status := &model.ParkedCallTimeOut{}
  108. mapstructure.Decode(event, status)
  109. data = status
  110. case "ParkedCallGiveUp":
  111. status := &model.ParkedCallGiveUp{}
  112. mapstructure.Decode(event, status)
  113. data = status
  114. case "UnParkedCall":
  115. status := &model.UnParkedCall{}
  116. mapstructure.Decode(event, status)
  117. data = status
  118. case "MeetmeEnd":
  119. status := &model.MeetmeEnd{}
  120. mapstructure.Decode(event, status)
  121. data = status
  122. case "MeetmeJoin":
  123. fallthrough
  124. case "MeetmeLeave":
  125. fallthrough
  126. case "MeetmeMute":
  127. fallthrough
  128. case "MeetmeTalking":
  129. fallthrough
  130. case "MeetmeTalkRequest":
  131. status := &model.Meetme{}
  132. mapstructure.Decode(event, status)
  133. data = status
  134. case "PresenceStateChange":
  135. status := &model.PresenceStateChange{}
  136. mapstructure.Decode(event, status)
  137. if status.Presentity != "" {
  138. data := strings.Split(status.Presentity, ":")
  139. if len(data) == 2 {
  140. status.Extension = data[1]
  141. }
  142. }
  143. if status.Status == "dnd" {
  144. status.DndStatus = "yes"
  145. } else {
  146. status.DndStatus = ""
  147. }
  148. data = status
  149. case "DialBegin":
  150. fallthrough
  151. case "DialEnd":
  152. fallthrough
  153. case "DialState":
  154. status := &model.Dial{}
  155. mapstructure.Decode(event, status)
  156. data = status
  157. case "Newstate":
  158. status := &model.Newstate{}
  159. mapstructure.Decode(event, status)
  160. data = status
  161. case "Hangup":
  162. status := &model.Hangup{}
  163. mapstructure.Decode(event, status)
  164. data = status
  165. case "UserEvent":
  166. switch event["UserEvent"] {
  167. case "SetDND":
  168. status := &model.SetDND{}
  169. mapstructure.Decode(event, status)
  170. data = status
  171. event["Event"] = event["UserEvent"]
  172. case "WakeUpStatus":
  173. status := &model.WakeUpStatus{}
  174. mapstructure.Decode(event, status)
  175. data = status
  176. event["Event"] = event["UserEvent"]
  177. default:
  178. data = event
  179. }
  180. case "SuccessfulAuth":
  181. // 获取上线 IP 地址
  182. status := &model.SuccessfulAuth{}
  183. mapstructure.Decode(event, status)
  184. status.GetAddress()
  185. data = status
  186. case "MessageWaiting":
  187. status := &model.MessageWaiting{}
  188. mapstructure.Decode(event, status)
  189. status.GetExtension()
  190. data = status
  191. if status.Extension == "" {
  192. lfshook.NewLogger().Warnf("MessageWaiting error %+v", event)
  193. return
  194. }
  195. default:
  196. // if !strings.Contains(event["Event"], "RTP") &&
  197. // !strings.Contains(event["Event"], "RTCP") &&
  198. // !strings.Contains(event["Event"], "VarSet") &&
  199. // !strings.Contains(event["Event"], "Bridge") &&
  200. // !strings.Contains(event["Event"], "New") &&
  201. // !strings.Contains(event["Event"], "SuccessfulAuth") &&
  202. // !strings.Contains(event["Event"], "ChallengeSent") {
  203. // lfshook.NewLogger().Info(event)
  204. // }
  205. }
  206. if data != nil {
  207. //socketio.SocketIOServer.BroadcastToNamespace("", event["Event"], data)
  208. }
  209. }
  210. func Connected() bool {
  211. if AminInstance != nil {
  212. return AminInstance.Connected()
  213. }
  214. return false
  215. }