push.go 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. package zoho
  2. import (
  3. "crm-api/pkg/httpclient"
  4. "crm-api/pkg/lfshook"
  5. "encoding/json"
  6. "fmt"
  7. "io/ioutil"
  8. "net/http"
  9. "strconv"
  10. "strings"
  11. "time"
  12. "gopkg.in/ini.v1"
  13. )
  14. var TimestampList = make(map[string]string)
  15. var StartTimeList = make(map[string]time.Time) // 事件中 Timestamp 转 StartTime 有问题,重新记录时间
  16. var LinkedidList = make(map[string]string) // 临时记录 incoming 和 outgoing
  17. var DialStatusList = make(map[string]string) // 临时记录 DialStatus:ANSWER NOANSWER
  18. var CallTypeList = make(map[string]string) //通过Linkedid临时记录拨打类型呼入还是呼出
  19. func CallNotify(event map[string]string) {
  20. confPath := "/etc/asterisk/crm_api.conf"
  21. cfg, err := ini.Load(confPath)
  22. if err != nil {
  23. lfshook.NewLogger().Error(err)
  24. return
  25. }
  26. ZOHO_URL := cfg.Section("general").Key("zohoUrl").String()
  27. if ZOHO_URL == "" {
  28. lfshook.NewLogger().Error("/etc/asterisk/crm_api.conf not set zohoUrl")
  29. return
  30. }
  31. // var getURL string
  32. // fmt.Println("Context = ", event["Context"])
  33. // 呼叫发起事件
  34. // if event["Event"] == "DialBegin" && event["Context"] == "macro-stdexten" {
  35. // if event["Event"] == "DialBegin" && strings.Compare(event["Context"], "macro-stdexten") == 0 {
  36. if event["Event"] == "DialBegin" {
  37. Channel := strings.Split(event["Channel"], "/")
  38. fmt.Println("Channel[0] = ", Channel[0])
  39. // Outgoing Call - Ringing
  40. if event["Context"] == "macro-trunkdial-failover" {
  41. lfshook.NewLogger().Info("Outgoing Call - Ringing")
  42. fmt.Println("event[] = ", event)
  43. fmt.Println("event = ", event["Event"])
  44. fmt.Println("Linkedid = ", event["Timestamp"])
  45. StartTimeList[event["Linkedid"]] = time.Now().Add(-8 * time.Hour)
  46. // https://www.zohoapis.com/phonebridge/v3/callnotify?type=dialed&state=ringing&id=10031&from=123456789&to=12300000001
  47. getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=dialed&state=ringing&id=%s&from=%s&to=%s", ZOHO_URL, event["Linkedid"], event["CallerIDNum"], event["DestCallerIDNum"])
  48. // if zohoUser != "" {
  49. // getURL = fmt.Sprintf("%s&zohouser=%s", getURL, zohoUser)
  50. // }
  51. fmt.Println("getURL = ", getURL)
  52. go httpclient.ZohoGet(getURL)
  53. // Incoming Call - Ringing
  54. // if event["Context"] == "macro-stdexten" {
  55. } else if (event["Context"] == "macro-stdexten" && Channel[0] != "Local") || (event["Context"] == "macro-stdexten-withoutvm" && Channel[0] != "Local") { // 开启语音留言:macro-stdexten 关闭语音留言:macro-stdexten-withoutvm
  56. lfshook.NewLogger().Error("Incoming Call - Ringing")
  57. fmt.Println("event[] = ", event)
  58. fmt.Println("event = ", event["Event"])
  59. StartTimeList[event["Linkedid"]] = time.Now().Add(-8 * time.Hour)
  60. fmt.Println("Linkedid = ", event["Timestamp"])
  61. // if strings.Compare(event["Context"], "macro-stdexten") == 0 { // OK
  62. // https://www.zohoapis.com/phonebridge/v3/callnotify?type=received&state=ringing&id=10033&from=12300000001&to=123456789
  63. // getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=ringing&id=%s&from=%s&to=%s", ZOHO_URL, callId, event["Exten"], callDest) // 取得from to 可能不准
  64. getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=ringing&id=%s&from=%s&to=%s", ZOHO_URL, event["Linkedid"], event["CallerIDNum"], event["DestCallerIDNum"])
  65. // if zohoUser != "" {
  66. // getURL = fmt.Sprintf("%s&zohouser=%s", getURL, zohoUser)
  67. // }
  68. fmt.Println("getURL = ", getURL)
  69. go httpclient.ZohoGet(getURL)
  70. } else if strings.HasPrefix(event["Context"], "department") || strings.HasSuffix(event["Context"], "queue") {
  71. getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=ringing&id=%s&from=%s&to=%s", ZOHO_URL, event["Linkedid"], event["CallerIDNum"], event["DestCallerIDNum"])
  72. // if zohoUser != "" {
  73. // getURL = fmt.Sprintf("%s&zohouser=%s", getURL, zohoUser)
  74. // }
  75. fmt.Println("getURL = ", getURL)
  76. go httpclient.ZohoGet(getURL)
  77. }
  78. // 呼叫结束事件
  79. } else if event["Event"] == "DialEnd" {
  80. Channel := strings.Split(event["Channel"], "/")
  81. // 记录呼叫状态
  82. DialStatusList[event["Linkedid"]] = event["DialStatus"]
  83. fmt.Println("DialEnd[] = ", event)
  84. fmt.Println("Channel[0] = ", Channel[0])
  85. // Outgoing Call - Unattended
  86. if event["Context"] == "macro-trunkdial-failover" && event["DialStatus"] == "CANCEL" {
  87. lfshook.NewLogger().Info("Outgoing Call - CANCEL")
  88. fmt.Println("event[] = ", event)
  89. fmt.Println("event = ", event["Event"])
  90. fmt.Println("Linkedid = ", event["Timestamp"])
  91. // startTime := StartTimeList[event["Linkedid"]].Format("2006-01-02 15:04:09")
  92. startTimeutc := StartTimeList[event["Linkedid"]].In(time.UTC) // 存储从string 改为 time.Time
  93. startTime := startTimeutc.Format(time.RFC3339)
  94. fmt.Println("startTime: ", startTime)
  95. // https://www.zohoapis.com/phonebridge/v3/callnotify?type=dialed&state=busy&id=10025&from=123456789&to=12300000001&start_time=2024-12-04 15:09:10
  96. getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=dialed&state=busy&id=%s&from=%s&to=%s&start_time=%s", ZOHO_URL, event["Linkedid"], event["CallerIDNum"], event["DestCallerIDNum"], startTime)
  97. // if zohoUser != "" {
  98. // getURL = fmt.Sprintf("%s&zohouser=%s", getURL, zohoUser)
  99. // }
  100. fmt.Println("getURL = ", getURL)
  101. go httpclient.ZohoGet(getURL)
  102. delete(StartTimeList, event["Linkedid"])
  103. // Incoming Call - Missed
  104. // if event["Context"] == "macro-stdexten" && event["DialStatus"] != "ANSWER" {
  105. } else if event["Context"] == "macro-trunkdial-failover" && event["DialStatus"] == "NOANSWER" {
  106. lfshook.NewLogger().Info("Outgoing Call - NOANSWER")
  107. fmt.Println("event[] = ", event)
  108. fmt.Println("event = ", event["Event"])
  109. fmt.Println("Linkedid = ", event["Timestamp"])
  110. // startTime := StartTimeList[event["Linkedid"]].Format("2006-01-02 15:04:09")
  111. startTimeutc := StartTimeList[event["Linkedid"]].In(time.UTC) // 存储从string 改为 time.Time
  112. startTime := startTimeutc.Format(time.RFC3339)
  113. fmt.Println("startTime: ", startTime)
  114. // https://www.zohoapis.com/phonebridge/v3/callnotify?type=dialed&state=busy&id=10025&from=123456789&to=12300000001&start_time=2024-12-04 15:09:10
  115. getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=dialed&state=noanswer&id=%s&from=%s&to=%s&start_time=%s", ZOHO_URL, event["Linkedid"], event["CallerIDNum"], event["DestCallerIDNum"], startTime)
  116. // if zohoUser != "" {
  117. // getURL = fmt.Sprintf("%s&zohouser=%s", getURL, zohoUser)
  118. // }
  119. fmt.Println("getURL = ", getURL)
  120. go httpclient.ZohoGet(getURL)
  121. delete(StartTimeList, event["Linkedid"])
  122. // Incoming Call - Missed
  123. // if event["Context"] == "macro-stdexten" && event["DialStatus"] != "ANSWER" {
  124. } else if event["Context"] == "macro-trunkdial-failover" && event["DialStatus"] == "BUSY" {
  125. lfshook.NewLogger().Info("Outgoing Call - BUSY")
  126. fmt.Println("event[] = ", event)
  127. fmt.Println("event = ", event["Event"])
  128. fmt.Println("Linkedid = ", event["Timestamp"])
  129. // startTime := StartTimeList[event["Linkedid"]].Format("2006-01-02 15:04:09")
  130. startTimeutc := StartTimeList[event["Linkedid"]].In(time.UTC) // 存储从string 改为 time.Time
  131. startTime := startTimeutc.Format(time.RFC3339)
  132. fmt.Println("startTime: ", startTime)
  133. // https://www.zohoapis.com/phonebridge/v3/callnotify?type=dialed&state=busy&id=10025&from=123456789&to=12300000001&start_time=2024-12-04 15:09:10
  134. getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=dialed&state=rejected&id=%s&from=%s&to=%s&start_time=%s", ZOHO_URL, event["Linkedid"], event["CallerIDNum"], event["DestCallerIDNum"], startTime)
  135. // if zohoUser != "" {
  136. // getURL = fmt.Sprintf("%s&zohouser=%s", getURL, zohoUser)
  137. // }
  138. fmt.Println("getURL = ", getURL)
  139. go httpclient.ZohoGet(getURL)
  140. delete(StartTimeList, event["Linkedid"])
  141. // Incoming Call - Missed
  142. // if event["Context"] == "macro-stdexten" && event["DialStatus"] != "ANSWER" {
  143. } else if (event["Context"] == "macro-stdexten" && event["DialStatus"] != "ANSWER" && Channel[0] != "Local") || (event["Context"] == "macro-stdexten-withoutvm" && event["DialStatus"] != "ANSWER" && Channel[0] != "Local") { // 开启语音留言:macro-stdexten 关闭语音留言:macro-stdexten-withoutvm
  144. lfshook.NewLogger().Error("Incoming Call - Missed")
  145. fmt.Println("event[] = ", event)
  146. fmt.Println("event = ", event["Event"])
  147. // startTime := StartTimeList[event["Linkedid"]].Format("2006-01-02 15:04:09")
  148. startTimeutc := StartTimeList[event["Linkedid"]].In(time.UTC) // 存储从string 改为 time.Time
  149. startTime := startTimeutc.Format(time.RFC3339)
  150. fmt.Println("startTime: ", startTime)
  151. fmt.Println("Linkedid = ", event["Timestamp"])
  152. // https://www.zohoapis.com/phonebridge/v3/callnotify?type=received&state=missed&id=10005&from=12300000001&to=123456789&start_time=2024-12-04 15:09:10
  153. getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=missed&id=%s&from=%s&to=%s&start_time=%s", ZOHO_URL, event["Linkedid"], event["CallerIDNum"], event["DestCallerIDNum"], startTime)
  154. // if zohoUser != "" {
  155. // getURL = fmt.Sprintf("%s&zohouser=%s", getURL, zohoUser)
  156. // }
  157. fmt.Println("getURL = ", getURL)
  158. go httpclient.ZohoGet(getURL)
  159. delete(StartTimeList, event["Linkedid"])
  160. }
  161. // 呼叫已连接事件
  162. } else if event["Event"] == "BridgeEnter" {
  163. Channel := strings.Split(event["Channel"], "/")
  164. fmt.Println("Channel[0] = ", Channel[0])
  165. // Outgoing Call - Answered
  166. if event["Context"] == "macro-trunkdial-failover" && event["Priority"] == "1" { // 注意这里选择 Priority:1 的,便于确认 CallerIDNum,ConnectedLineNum
  167. // 记录开始时间
  168. // TimestampList[event["Uniqueid"]] = event["Timestamp"] // error 需要把 Uniqueid 改为 Linkedid
  169. // StartTimeList[event["Uniqueid"]] = time.Now() // error 需要把 Uniqueid 改为 Linkedid
  170. lfshook.NewLogger().Info("Outgoing Call - Answered")
  171. fmt.Println("event[] = ", event)
  172. fmt.Println("event = ", event["Event"])
  173. fmt.Println("Linkedid = ", event["Timestamp"])
  174. TimestampList[event["Linkedid"]] = event["Timestamp"]
  175. StartTimeList[event["Linkedid"]] = time.Now().Add(-8 * time.Hour)
  176. LinkedidList["Linkedid"] = event["Linkedid"]
  177. CallTypeList[event["Linkedid"]] = "outgoing"
  178. // https: //www.zohoapis.com/phonebridge/v3/callnotify?type=dialed&state=answered&id=10003&from=123456789&to=12300000001
  179. // getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=dialed&state=answered&id=%s&from=%s&to=%s", ZOHO_URL, callId, event["CallerIDNum"], event["ConnectedLineNum"])
  180. getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=dialed&state=answered&id=%s&from=%s&to=%s", ZOHO_URL, event["Linkedid"], event["ConnectedLineNum"], event["CallerIDNum"])
  181. // if zohoUser != "" {
  182. // getURL = fmt.Sprintf("%s&zohouser=%s", getURL, zohoUser)
  183. // }
  184. fmt.Println("getURL = ", getURL)
  185. go httpclient.ZohoGet(getURL)
  186. // Incoming Call - Answered
  187. // if event["Context"] == "macro-stdexten" {
  188. } else if (event["Context"] == "macro-stdexten" || event["Context"] == "macro-stdexten-withoutvm") && Channel[0] != "Local" { // 开启语音留言:macro-stdexten 关闭语音留言:macro-stdexten-withoutvm
  189. // 记录开始时间
  190. // TimestampList[event["Uniqueid"]] = event["Timestamp"] // Uniqueid 有时通话也不合适 NG // 都改为 Linkedid
  191. // StartTimeList[event["Uniqueid"]] = time.Now() // Uniqueid 有时通话也不合适 NG // 都改为 Linkedid
  192. lfshook.NewLogger().Error("Incoming Call - Answered")
  193. fmt.Println("event[] = ", event)
  194. fmt.Println("event = ", event["Event"])
  195. fmt.Println("Linkedid = ", event["Timestamp"])
  196. TimestampList[event["Linkedid"]] = event["Timestamp"] // 呼入时设置 Uniqueid 不是 Linkedid
  197. StartTimeList[event["Linkedid"]] = time.Now().Add(-8 * time.Hour) // 呼入时设置 Uniqueid 不是 Linkedid
  198. LinkedidList["Linkedid"] = event["Linkedid"]
  199. CallTypeList[event["Linkedid"]] = "incoming"
  200. // https://www.zohoapis.com/phonebridge/v3/callnotify?type=received&state=answered&id=10023&from=12300000001&to=123456789
  201. getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=answered&id=%s&from=%s&to=%s", ZOHO_URL, event["Linkedid"], event["CallerIDNum"], event["ConnectedLineNum"])
  202. // if zohoUser != "" {
  203. // getURL = fmt.Sprintf("%s&zohouser=%s", getURL, zohoUser)
  204. // }
  205. fmt.Println("getURL = ", getURL)
  206. go httpclient.ZohoGet(getURL)
  207. } else if (strings.HasPrefix(event["Context"], "department") && event["Priority"] == "1") || strings.HasSuffix(event["Context"], "queue") {
  208. TimestampList[event["Linkedid"]] = event["Timestamp"] // 呼入时设置 Uniqueid 不是 Linkedid
  209. StartTimeList[event["Linkedid"]] = time.Now().Add(-8 * time.Hour) // 呼入时设置 Uniqueid 不是 Linkedid
  210. LinkedidList["Linkedid"] = event["Linkedid"]
  211. CallTypeList[event["Linkedid"]] = "incoming"
  212. if event["Priority"] == "1" {
  213. getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=answered&id=%s&from=%s&to=%s", ZOHO_URL, event["Linkedid"], event["ConnectedLineNum"], event["CallerIDNum"])
  214. // if zohoUser != "" {
  215. // getURL = fmt.Sprintf("%s&zohouser=%s", getURL, zohoUser)
  216. // }
  217. fmt.Println("getURL = ", getURL)
  218. go httpclient.ZohoGet(getURL)
  219. } else {
  220. getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=answered&id=%s&from=%s&to=%s", ZOHO_URL, event["Linkedid"], event["CallerIDNum"], event["ConnectedLineNum"])
  221. // if zohoUser != "" {
  222. // getURL = fmt.Sprintf("%s&zohouser=%s", getURL, zohoUser)
  223. // }
  224. fmt.Println("getURL = ", getURL)
  225. go httpclient.ZohoGet(getURL)
  226. }
  227. }
  228. // 呼叫挂断事件
  229. } else if event["Event"] == "HangupRequest" {
  230. // * ===================================================================================== */
  231. // 判断呼叫状态,为 ANSWER 时才推送,否则见以上推送 Outgoing Call - Unattended 或 Incoming Call - Missed
  232. Channel := strings.Split(event["Channel"], "/")
  233. fmt.Println("event[] = ", event)
  234. fmt.Println("Channel[0] = ", Channel[0])
  235. // lfshook.NewLogger().Errorf("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa %+v", event["Context"])
  236. fmt.Println("ChannelHangupRequest1 = ", DialStatusList[event["Linkedid"]])
  237. fmt.Println("ChannelHangupRequest1 = ", event["DialStatus"])
  238. // if DialStatusList[event["Linkedid"]] == "ANSWER" {//暂时不使用dialend的呼叫状态
  239. lfshook.NewLogger().Errorf("ChannelHangupRequest = %+v", event["Uniqueid"])
  240. fmt.Println("event[] = ", event)
  241. fmt.Println("event = ", event["Event"])
  242. startTimeutc := StartTimeList[event["Linkedid"]].In(time.UTC) // 存储从string 改为 time.Time
  243. startTime := startTimeutc.Format(time.RFC3339)
  244. fmt.Println("startTime: ", startTime)
  245. // Outgoing Call - Ended
  246. if event["Context"] == "macro-trunkdial-failover" && CallTypeList[event["Linkedid"]] == "outgoing" {
  247. fmt.Println("Linkedid = ", event["Timestamp"])
  248. durationTime := getDuration(event["Linkedid"], event["Timestamp"])
  249. lfshook.NewLogger().Errorf("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaCallTypeList %+v", CallTypeList)
  250. if durationTime != -1 {
  251. if event["Priority"] == "1" {
  252. // https://www.zohoapis.com/phonebridge/v3/callnotify?type=dailed&state=ended&id=10030&from=123456789&to=12300000001&start_time=2024-12-04 11:32:15&duration=325
  253. // getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=dailed&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, callId, event["CallerIDNum"], event["ConnectedLineNum"], startTime, durationTime)
  254. getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=dailed&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, event["Linkedid"], event["ConnectedLineNum"], event["CallerIDNum"], startTime, durationTime)
  255. // if zohoUser != "" {
  256. // getURL = fmt.Sprintf("%s&zohouser=%s", getURL, zohoUser)
  257. // }
  258. fmt.Println("getURL = ", getURL)
  259. go httpclient.ZohoGet(getURL)
  260. } else {
  261. // https://www.zohoapis.com/phonebridge/v3/callnotify?type=dailed&state=ended&id=10030&from=123456789&to=12300000001&start_time=2024-12-04 11:32:15&duration=325
  262. // getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=dailed&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, callId, event["CallerIDNum"], event["ConnectedLineNum"], startTime, durationTime)
  263. getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=dailed&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, event["Linkedid"], event["CallerIDNum"], event["ConnectedLineNum"], startTime, durationTime)
  264. // if zohoUser != "" {
  265. // getURL = fmt.Sprintf("%s&zohouser=%s", getURL, zohoUser)
  266. // }
  267. fmt.Println("getURL = ", getURL)
  268. go httpclient.ZohoGet(getURL)
  269. }
  270. }
  271. // 删除记录时间
  272. delete(StartTimeList, event["Linkedid"])
  273. delete(CallTypeList, event["Linkedid"])
  274. // Incoming Call - Ended
  275. // // if event["Context"] == "macro-stdexten" { // Context:DialPlan1
  276. // } else if Channel[0] != "Local" && durationTime != -1 { // 开启语音留言:macro-stdexten 关闭语音留言:macro-stdexten-withoutvm
  277. } else if Channel[0] != "Local" && CallTypeList[event["Linkedid"]] == "incoming" {
  278. // if event["Context"] != "macro-trunkdial-failover" {
  279. fmt.Println("Linkedid = ", event["Timestamp"])
  280. durationTime := getDuration(event["Linkedid"], event["Timestamp"])
  281. if durationTime != -1 {
  282. if event["Priority"] == "1" {
  283. getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, event["Linkedid"], event["ConnectedLineNum"], event["CallerIDNum"], startTime, durationTime)
  284. // getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, callId, event["ConnectedLineNum"], event["CallerIDName"], startTime, durationTime)
  285. // if zohoUser != "" {
  286. // getURL = fmt.Sprintf("%s&zohouser=%s", getURL, zohoUser)
  287. // }
  288. fmt.Println("getURL = ", getURL)
  289. go httpclient.ZohoGet(getURL)
  290. } else {
  291. getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, event["Linkedid"], event["CallerIDNum"], event["ConnectedLineNum"], startTime, durationTime)
  292. // getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, callId, event["ConnectedLineNum"], event["CallerIDName"], startTime, durationTime)
  293. // if zohoUser != "" {
  294. // getURL = fmt.Sprintf("%s&zohouser=%s", getURL, zohoUser)
  295. // }
  296. fmt.Println("getURL = ", getURL)
  297. go httpclient.ZohoGet(getURL)
  298. }
  299. }
  300. delete(StartTimeList, event["Linkedid"])
  301. delete(CallTypeList, event["Linkedid"])
  302. // 还需优化判断,开启语音留言时,主叫挂断才是 macro-stdexten , 被叫挂断是 DialPlan1
  303. // 关闭语音留言时,主叫挂断才是 macro-stdexten-withoutvm , 被叫挂断是 DialPlan1
  304. // 如果 Outgoing Call 只会是 macro-trunkdial-failover 的话,那么和以下判断换一下,else 不判断,都为 Incoming Call 处理
  305. }
  306. // }
  307. } else if event["Event"] == "SoftHangupRequest" {
  308. if event["Exten"] == "s-CHANUNAVAIL" {
  309. startTimebj := time.Now().Add(-8 * time.Hour)
  310. startTimeutc := startTimebj.In(time.UTC) // 存储从string 改为 time.Time
  311. startTime := startTimeutc.Format(time.RFC3339)
  312. ConnectedLineNum := strings.Split(strings.Split(event["ConnectedLineNum"], "<")[1], ">")[0]
  313. getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=missed&id=%s&from=%s&to=%s&start_time=%s", ZOHO_URL, event["Linkedid"], event["CallerIDNum"], ConnectedLineNum, startTime)
  314. // if zohoUser != "" {
  315. // getURL = fmt.Sprintf("%s&zohouser=%s", getURL, zohoUser)
  316. // }
  317. fmt.Println("getURL = ", getURL)
  318. go httpclient.ZohoGet(getURL)
  319. }
  320. } else if event["Event"] == "AttendedTransfer" { //热转接
  321. if event["Result"] == "Success" {
  322. durationTime := getDuration(event["SecondTransfererLinkedid"], event["Timestamp"])
  323. startTimeutc := StartTimeList[event["SecondTransfererLinkedid"]].In(time.UTC) // 存储从string 改为 time.Time
  324. startTime := startTimeutc.Format(time.RFC3339)
  325. fmt.Println("startTime: ", startTime)
  326. getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, event["SecondTransfererLinkedid"], event["TransfereeCallerIDNum"], event["TransfereeConnectedLineNum"], startTime, durationTime)
  327. // if zohoUser != "" {
  328. // getURL = fmt.Sprintf("%s&zohouser=%s", getURL, zohoUser)
  329. // }
  330. fmt.Println("getURL = ", getURL)
  331. go httpclient.ZohoGet(getURL)
  332. }
  333. }
  334. // else if event["Event"] == "Cdr" {
  335. // if event["Disposition"] == "ANSWERED" && event["CallType"] == "incoming" && strings.HasPrefix(event["DestinationContext"], "department") {
  336. // durationTime := getDuration(LinkedidList["Linkedid"], event["Timestamp"])
  337. // startTimeutc := StartTimeList[LinkedidList["Linkedid"]].In(time.UTC) // 存储从string 改为 time.Time
  338. // startTime := startTimeutc.Format(time.RFC3339)
  339. // getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, event["Linkedid"], event["Source"], event["Destination"], startTime, durationTime)
  340. // // getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, callId, event["ConnectedLineNum"], event["CallerIDName"], startTime, durationTime)
  341. // // if zohoUser != "" {
  342. // // getURL = fmt.Sprintf("%s&zohouser=%s", getURL, zohoUser)
  343. // // }
  344. // fmt.Println("getURL = ", getURL)
  345. // go httpclient.ZohoGet(getURL)
  346. // delete(LinkedidList, "Linkedid")
  347. // }
  348. // }
  349. // else if event["Event"] == "Cdr" {
  350. // if event["Disposition"] == "ANSWERED" {
  351. // durationTime := getDuration(LinkedidList["Linkedid"], event["Timestamp"])
  352. // startTimeutc := StartTimeList[LinkedidList["Linkedid"]].In(time.UTC) // 存储从string 改为 time.Time
  353. // startTime := startTimeutc.Format(time.RFC3339)
  354. // CallSrcNum := strings.Split(strings.Split(event["CallSrcNum"], "<")[1], ">")[0]
  355. // if event["CallType"] == "outgoing" {
  356. // getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=dailed&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, LinkedidList["Linkedid"], CallSrcNum, event["CallDestNum"], startTime, durationTime)
  357. // // if zohoUser != "" {
  358. // // getURL = fmt.Sprintf("%s&zohouser=%s", getURL, zohoUser)
  359. // // }
  360. // fmt.Println("getURL = ", getURL)
  361. // go httpclient.ZohoGet(getURL)
  362. // delete(LinkedidList, "Linkedid")
  363. // } else if event["CallType"] == "incoming" {
  364. // getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, LinkedidList["Linkedid"], CallSrcNum, event["CallDestNum"], startTime, durationTime)
  365. // // getURL := fmt.Sprintf("%s/phonebridge/v3/callnotify?type=received&state=ended&id=%s&from=%s&to=%s&start_time=%s&duration=%d", ZOHO_URL, callId, event["ConnectedLineNum"], event["CallerIDName"], startTime, durationTime)
  366. // // if zohoUser != "" {
  367. // // getURL = fmt.Sprintf("%s&zohouser=%s", getURL, zohoUser)
  368. // // }
  369. // fmt.Println("getURL = ", getURL)
  370. // go httpclient.ZohoGet(getURL)
  371. // delete(LinkedidList, "Linkedid")
  372. // }
  373. // }
  374. // }
  375. // fmt.Println("getURL = ", getURL)
  376. // 测试验证下上面有没有删除,以防TimestampList越来越大
  377. // for k, v := range TimestampList {
  378. // fmt.Printf("===Linkedid:%s Timestamp:%s===\n", k, v)
  379. // }
  380. }
  381. // 使用事件中event["Timestamp"]的值计算时间间隔
  382. // func getDuration(uniqueid string, timeStamp string) int {
  383. func getDuration(linkedid string, timeStamp string) int { // 都改为 Linkedid
  384. fmt.Println("startTimeStamp Str: ", TimestampList[linkedid])
  385. if TimestampList[linkedid] == "" || timeStamp == "" {
  386. fmt.Printf("linkedid 或 timeStamp 为空\n")
  387. return -1
  388. }
  389. startTimeStamp, err := strconv.ParseFloat(TimestampList[linkedid], 64)
  390. if err != nil {
  391. fmt.Printf("startTimeStamp转换出错: %v\n", err)
  392. return -1
  393. }
  394. fmt.Printf("startTimeStamp=%f\n", startTimeStamp)
  395. endTimeStamp, err := strconv.ParseFloat(timeStamp, 64)
  396. if err != nil {
  397. fmt.Printf("endTimeStamp转换出错: %v\n", err)
  398. return -1
  399. }
  400. fmt.Printf("endTimeStamp=%f\n", endTimeStamp)
  401. durationTime := time.Duration(endTimeStamp-startTimeStamp) * time.Second
  402. // fmt.Println("durationTime=", durationTime) // durationTime= 35s
  403. // fmt.Printf("durationTime=%d\n", durationTime) // durationTime=35000000000
  404. // fmt.Printf("durationTime=%d\n", durationTime.Seconds()) // durationTime=%!d(float64=35)
  405. // fmt.Printf("durationTime=%f\n", durationTime.Seconds()) // durationTime=35.000000
  406. fmt.Printf("durationTime=%d\n", int(durationTime.Seconds())) // durationTime=35
  407. // durationTime001 := time.Duration(endTimeStamp - startTimeStamp)
  408. // fmt.Println("durationTime001=", durationTime001) // durationTime001= 35ns
  409. // durationTime003 := time.Duration(endTimeStamp - startTimeStamp).Seconds()
  410. // fmt.Println("durationTime003=", durationTime003) // durationTime003= 3.5e-08
  411. // 删除记录时间
  412. delete(TimestampList, linkedid)
  413. // return durationTime
  414. return int(durationTime.Seconds())
  415. }
  416. // @tags PBX-zoho
  417. // @Summary 刷新token
  418. // @Description 刷新token
  419. // @Security ZohoToken
  420. // @Accept json
  421. // @Produce json
  422. // @Router /api/zoho/refresh-token [post]
  423. func RefreshToken() {
  424. fmt.Printf("RefreshToken ............\n")
  425. // 获取配置文件信息
  426. // confPath := "/etc/asterisk/vtiger_api.conf"
  427. confPath := "/etc/asterisk/crm_api.conf"
  428. cfg, err := ini.Load(confPath)
  429. if err != nil {
  430. lfshook.NewLogger().Error(err)
  431. return
  432. }
  433. ZohoAuthUrl := cfg.Section("general").Key("zohoAuthUrl").String()
  434. ZohoRefreshToken := cfg.Section("general").Key("zohoRefreshToken").String()
  435. ZohoClientId := cfg.Section("general").Key("zohoClientId").String()
  436. ZohoClientSecret := cfg.Section("general").Key("zohoClientSecret").String()
  437. if ZohoAuthUrl == "" || ZohoRefreshToken == "" || ZohoClientId == "" || ZohoClientSecret == "" {
  438. lfshook.NewLogger().Error("/etc/asterisk/crm_api.conf not set zohoAuthUrl or zohoRefreshToken or zohoClientId or zohoClientSecret")
  439. return
  440. }
  441. // 创建请求
  442. // https://accounts.zoho.com/oauth/v2/token?refresh_token=1004.86c8c0e3db7bfe9133598825bef28eb9.17a82a3bf3e675c504f478c1b0b5c456
  443. // &client_id=1004.LWJCJZD5O9DB6SZLL5YJEWHT7LH0BV&client_secret=fc3aef43dc58af8a49d3ed597710924200b03f74d0&grant_type=refresh_token
  444. getURL := fmt.Sprintf("%s/oauth/v2/token?refresh_token=%s&client_id=%s&client_secret=%s&grant_type=refresh_token", ZohoAuthUrl, ZohoRefreshToken, ZohoClientId, ZohoClientSecret)
  445. fmt.Printf("getURL = %s\n", getURL)
  446. // data := httpRequest(ctx, "POST", getURL)
  447. // /* =====================================================================================
  448. req, err := http.NewRequest("POST", getURL, nil)
  449. if err != nil {
  450. fmt.Println("创建请求时发生错误:", err)
  451. return
  452. }
  453. // 创建HTTP客户端
  454. client := &http.Client{}
  455. // req.Header.Set("Authorization", "Bearer "+accessToken) // 刷新token时不需要
  456. // 发送请求
  457. resp, err := client.Do(req)
  458. if err != nil {
  459. fmt.Println("发送请求时发生错误:", err)
  460. return
  461. }
  462. defer resp.Body.Close()
  463. // 读取请求后的响应
  464. data, err := ioutil.ReadAll(resp.Body)
  465. if err != nil {
  466. // 读取数据错误
  467. lfshook.NewLogger().Warn("ioutil ReadAll failed :", err.Error())
  468. // api.Error(ctx, http.StatusInternalServerError, err.Error())
  469. return
  470. }
  471. lfshook.NewLogger().Infof("data %+v", string(data))
  472. // * ===================================================================================== */
  473. refreshTokenData := RefreshTokenResp{}
  474. err = json.Unmarshal([]byte(data), &refreshTokenData)
  475. if err != nil {
  476. // 转换数据错误
  477. lfshook.NewLogger().Warn("json unmarshal failed :", err.Error())
  478. // api.Error(ctx, http.StatusInternalServerError, err.Error())
  479. return
  480. }
  481. // 将获取的 access_token 写入文件 crm_api.conf
  482. cfg.Section("general").Key("zohoAccessToken").SetValue(refreshTokenData.AccessToken)
  483. err = cfg.SaveTo(confPath)
  484. if err != nil {
  485. lfshook.NewLogger().Error(err)
  486. // api.Error(ctx, http.StatusInternalServerError, err.Error())
  487. return
  488. }
  489. // 打印请求后的响应
  490. fmt.Printf("data = %+v\n", string(data))
  491. // api.Success(ctx, string(data))
  492. // api.Success(ctx, refreshTokenData)
  493. // return
  494. }
  495. // 每隔55分钟刷新token
  496. func RefreshTokenTicker() {
  497. fmt.Printf("RefreshTokenTicker ............\n")
  498. ticker := time.NewTicker(55 * time.Minute)
  499. defer ticker.Stop()
  500. done := make(chan bool)
  501. // go func() { // 注释掉OK
  502. for {
  503. select {
  504. case <-done:
  505. return
  506. case t := <-ticker.C:
  507. fmt.Println("Tick at", t)
  508. RefreshToken()
  509. }
  510. }
  511. // }()
  512. }