bridge.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. package ami
  2. import (
  3. socketio "crm-api/internal/app/socket_io"
  4. "crm-api/pkg/lfshook"
  5. "fmt"
  6. "sync"
  7. "github.com/mitchellh/mapstructure"
  8. )
  9. var bridgeMap sync.Map
  10. const bridgeEventName = "CustomBridgeEvent"
  11. type BridgeEvent struct {
  12. Event string `json:"event"`
  13. // Timestamp string `json:"timestamp"`
  14. BridgeUniqueid string `json:"-"`
  15. Channel string `json:"channel"`
  16. ChannelState string `json:"channelState"`
  17. ChannelStateDesc string `json:"channelStateDesc"`
  18. CallerIDNum string `json:"callerIDNumber"`
  19. CallerIDName string `json:"callerIDName"`
  20. CallerConnectedLineNum string `json:"callerConnectedLineNumber"`
  21. CallerConnectedLineName string `json:"callerConnectedLineName"`
  22. BridgeType string `json:"bridgeType"`
  23. BridgeNumChannels string `json:"bridgeNumberChannels"`
  24. Uniqueid string `json:"uniqueid"`
  25. }
  26. func (event BridgeEvent) String() string {
  27. return fmt.Sprintf("channel: %s, uniqueid: %s\n", event.Channel, event.Uniqueid)
  28. }
  29. func handleAMIBridge(event map[string]string) {
  30. if event["BridgeType"] != "basic" {
  31. return
  32. }
  33. if event["CallerIDName"] == "conference" {
  34. return
  35. }
  36. switch event["Event"] {
  37. case "BridgeCreate":
  38. bridgeMap.Store(event["BridgeUniqueid"], []*BridgeEvent{})
  39. case "BridgeEnter":
  40. status := &BridgeEvent{}
  41. mapstructure.Decode(event, status)
  42. if events, ok := bridgeMap.Load(status.BridgeUniqueid); ok {
  43. bridgeMap.Store(status.BridgeUniqueid, append(events.([]*BridgeEvent), status))
  44. } else {
  45. lfshook.NewLogger().Warnf("BridgeEnter add failure id: %s on load", status.BridgeUniqueid)
  46. }
  47. socketio.SocketIOServer.BroadcastToNamespace("", bridgeEventName, GetBridgeMapValue())
  48. case "BridgeLeave":
  49. status := &BridgeEvent{}
  50. mapstructure.Decode(event, status)
  51. if events, ok := bridgeMap.Load(status.BridgeUniqueid); ok {
  52. events := events.([]*BridgeEvent)
  53. for index, event := range events {
  54. if event.Channel == status.Channel {
  55. if index == len(events)-1 {
  56. bridgeMap.Store(status.BridgeUniqueid, events[:index])
  57. } else {
  58. bridgeMap.Store(status.BridgeUniqueid, append(events[:index], events[index+1]))
  59. }
  60. break
  61. }
  62. }
  63. } else {
  64. lfshook.NewLogger().Warnf("BridgeLeave remove failure id: %s on load", status.BridgeUniqueid)
  65. }
  66. socketio.SocketIOServer.BroadcastToNamespace("", bridgeEventName, GetBridgeMapValue())
  67. case "BridgeDestroy":
  68. bridgeMap.Delete(event["BridgeUniqueid"])
  69. socketio.SocketIOServer.BroadcastToNamespace("", bridgeEventName, GetBridgeMapValue())
  70. }
  71. }
  72. func GetBridgeMapValue() (result map[string][]*BridgeEvent) {
  73. result = make(map[string][]*BridgeEvent)
  74. bridgeMap.Range(func(key, value interface{}) bool {
  75. events := value.([]*BridgeEvent)
  76. result[key.(string)] = events
  77. return true
  78. })
  79. return
  80. }
  81. // ClearBridge Asterisk 重启,内部通话清空, AMI 重连成功也需求清空 Bridge
  82. func ClearBridge() {
  83. bridgeMap.Range(func(key, value interface{}) bool {
  84. bridgeMap.Delete(key)
  85. return true
  86. })
  87. }