DeviceEventHandler.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. using System.Security.Authentication;
  2. using Hotline.CallCenter;
  3. using Hotline.CallCenter.Devices;
  4. using Hotline.Share.Notifications;
  5. using MapsterMapper;
  6. using MediatR;
  7. using Microsoft.Extensions.Logging;
  8. using NewRock.Sdk.Events;
  9. using NewRock.Sdk.Extensions;
  10. using NewRock.Sdk.Security;
  11. using XF.Domain.Dependency;
  12. namespace Hotline.NewRock.Handlers
  13. {
  14. public class DeviceEventHandler : IDeviceEventHandler, IScopeDependency
  15. {
  16. private readonly IMediator _mediator;
  17. private readonly IMapper _mapper;
  18. private readonly ILogger<DeviceEventHandler> _logger;
  19. private static readonly string _cdrMarkup = "<Cdr id=";
  20. public DeviceEventHandler(
  21. IMediator mediator,
  22. IMapper mapper,
  23. ILogger<DeviceEventHandler> logger)
  24. {
  25. _mediator = mediator;
  26. _mapper = mapper;
  27. _logger = logger;
  28. }
  29. public async Task HandleAsync(Stream eventStream, CallCenterConfiguration deviceConfigs,
  30. CancellationToken cancellationToken)
  31. {
  32. var sr = new StreamReader(eventStream);
  33. var content = await sr.ReadToEndAsync();
  34. _logger.LogInformation("收到设备事件:\r\n{content}", content);
  35. if (content.Contains(_cdrMarkup))
  36. {
  37. // cdr事件
  38. //通话记录报告
  39. var eventBase = content.DeserializeWithAuthorize<NewRockCdrEvent>();
  40. if (eventBase.value == null) return;
  41. if (deviceConfigs.DeviceConfigs.Authorize && (eventBase.authorize == null ||
  42. !eventBase.authorize.IsAuthorized(deviceConfigs.DeviceConfigs.SendKey)))
  43. throw new AuthenticationException("无有效身份认证信息");
  44. var cdrRcv = content.DeserializeWithAuthorize<CdrEvent>();
  45. await _mediator.Publish(_mapper.Map<CdrNotification>(cdrRcv.value!), cancellationToken);
  46. }
  47. else
  48. {
  49. var eventBase = content.DeserializeWithAuthorize<NewRockEvent>();
  50. if (eventBase.value == null) return;
  51. if (deviceConfigs.DeviceConfigs.Authorize && (eventBase.authorize == null ||
  52. !eventBase.authorize.IsAuthorized(deviceConfigs.DeviceConfigs.SendKey)))
  53. throw new AuthenticationException("无有效身份认证信息");
  54. switch (eventBase.value.Attribute)
  55. {
  56. //分机上线事件发布
  57. case Event.ONLINE:
  58. var onLineRcv = content.DeserializeWithAuthorize<OnlineEvent>();
  59. await _mediator.Publish(_mapper.Map<OnlineNotification>(onLineRcv.value!), cancellationToken);
  60. break;
  61. //分机下线事件
  62. case Event.OFFLINE:
  63. var offLineRcv = content.DeserializeWithAuthorize<OfflineEvent>();
  64. await _mediator.Publish(_mapper.Map<OfflineNotification>(offLineRcv.value!), cancellationToken);
  65. break;
  66. //分机示闲事件
  67. case Event.IDLE:
  68. var idleRcv = content.DeserializeWithAuthorize<IdleEvent>();
  69. await _mediator.Publish(_mapper.Map<IdleNotification>(idleRcv.value!), cancellationToken);
  70. break;
  71. //分机示忙事件
  72. case Event.BUSY:
  73. var busyRcv = content.DeserializeWithAuthorize<BusyEvent>();
  74. await _mediator.Publish(_mapper.Map<BusyNotification>(busyRcv.value!), cancellationToken);
  75. break;
  76. //振铃事件
  77. case Event.RING:
  78. var ringRcv = content.DeserializeWithAuthorize<RingEvent>();
  79. //判断是哪种振铃事件
  80. //分机呼分机
  81. if (ringRcv.value?.Ext.Count > 1)
  82. {
  83. //await _mediator.Publish(_mapper.Map<RingExtToExtNotification>(ringRcv.value!),cancellationToken);
  84. }
  85. //来电转分机
  86. else if (ringRcv.value?.Ext.Count == 1 && ringRcv.value.Visitor != null)
  87. {
  88. await _mediator.Publish(_mapper.Map<RingVisitorToExtNotification>(ringRcv.value!),
  89. cancellationToken);
  90. }
  91. //分机外呼
  92. else if (ringRcv.value?.Ext.Count == 1 && ringRcv.value.Outer != null && ringRcv.value.Outer.Id != "")
  93. {
  94. await _mediator.Publish(_mapper.Map<RingExtToOuterNotification>(ringRcv.value!), cancellationToken);
  95. }
  96. //menu呼叫分机
  97. else if (ringRcv.value?.Ext.Count == 1 && ringRcv.value.Menu != null)
  98. {
  99. await _mediator.Publish(_mapper.Map<RingMenuToExtNotification>(ringRcv.value!),
  100. cancellationToken);
  101. }
  102. break;
  103. //回铃事件
  104. case Event.ALERT:
  105. var alertRcv = content.DeserializeWithAuthorize<AlertEvent>();
  106. //判断是 哪种回铃事件
  107. //来电转分机,分机回铃
  108. if (alertRcv.value?.Ext.Count == 1 && alertRcv.value.Visitor != null)
  109. {
  110. await _mediator.Publish(_mapper.Map<AlertVisitorToExtNotification>(alertRcv.value!),
  111. cancellationToken);
  112. }
  113. //分机呼外部电话,外部电话回铃
  114. else if (alertRcv.value?.Ext.Count == 1 && alertRcv.value.Outer != null)
  115. {
  116. await _mediator.Publish(_mapper.Map<AlertExtToOuterNotification>(alertRcv.value!),
  117. cancellationToken);
  118. }
  119. //分机呼分机,被叫分机回铃
  120. else if (alertRcv.value?.Ext.Count > 1)
  121. {
  122. await _mediator.Publish(_mapper.Map<AlertExtToExtNotification>(alertRcv.value!),
  123. cancellationToken);
  124. }
  125. //Menu外呼,外部电话回铃
  126. else if ((alertRcv.value?.Ext == null || alertRcv.value?.Ext.Count == 0) &&
  127. alertRcv.value?.Outer != null)
  128. {
  129. await _mediator.Publish(_mapper.Map<AlertMenuToOuterNotification>(alertRcv.value!),
  130. cancellationToken);
  131. }
  132. break;
  133. //呼叫应答事件
  134. case Event.ANSWER:
  135. var answerRcv = content.DeserializeWithAuthorize<AnswerEvent>();
  136. //分机呼分机,被叫分机应答
  137. if (answerRcv.value?.Ext.Count > 1)
  138. {
  139. await _mediator.Publish(_mapper.Map<AnswerExtToExtNotification>(answerRcv.value!),
  140. cancellationToken);
  141. }
  142. //来电转分机,分机应答
  143. else if (answerRcv.value?.Ext.Count == 1 && answerRcv.value.Visitor != null)
  144. {
  145. await _mediator.Publish(_mapper.Map<AnswerViisitorToExtNotification>(answerRcv.value!),
  146. cancellationToken);
  147. }
  148. //去电转分机,分机应答
  149. else if (answerRcv.value?.Ext.Count == 1 && answerRcv.value?.Outer != null)
  150. {
  151. await _mediator.Publish(_mapper.Map<AnswerExtToOuterNotification>(answerRcv.value!),
  152. cancellationToken);
  153. }
  154. break;
  155. //呼叫被应答事件
  156. case Event.ANSWERED:
  157. var answeredRcv = content.DeserializeWithAuthorize<AnsweredEvent>();
  158. //分机呼分机,主叫分机检查到被叫分机应答
  159. if (answeredRcv.value?.Ext.Count > 1)
  160. {
  161. await _mediator.Publish(_mapper.Map<AnsweredExtToExtNotification>(answeredRcv.value!),
  162. cancellationToken);
  163. }
  164. //分机呼外部电话,分机检查到外部电话应答
  165. else if (answeredRcv.value?.Ext.Count == 1 && answeredRcv.value?.Outer != null)
  166. {
  167. await _mediator.Publish(_mapper.Map<AnsweredExtToOuterNotification>(answeredRcv.value!),
  168. cancellationToken);
  169. }
  170. //来电呼叫分机
  171. else if (answeredRcv.value?.Visitor != null && answeredRcv.value?.Ext.Count == 1)
  172. {
  173. await _mediator.Publish(_mapper.Map<AnsweredVisitorToExtNotification>(answeredRcv.value!),
  174. cancellationToken);
  175. }
  176. //分机呼外部电话,转接其他分机,其他分机应答
  177. else if (answeredRcv.value?.Outer != null)
  178. {
  179. await _mediator.Publish(
  180. _mapper.Map<AnsweredExtToOuterToExtNotification>(answeredRcv.value!),
  181. cancellationToken);
  182. }
  183. break;
  184. //通话结束事件
  185. case Event.BYE:
  186. var byeRcv = content.DeserializeWithAuthorize<ByeEvent>();
  187. //来电和分机的通话结束,来电挂断
  188. if (byeRcv.value?.Ext.Count==1 && byeRcv.value?.Visitor != null)
  189. {
  190. await _mediator.Publish(_mapper.Map<ByeVisitorAndExtNotification>(byeRcv.value!),
  191. cancellationToken);
  192. }
  193. //来电和分机的通话,分机挂断
  194. else if (byeRcv.value?.Visitor != null)
  195. {
  196. await _mediator.Publish(_mapper.Map<ByeVisitorOffNotification>(byeRcv.value!),
  197. cancellationToken);
  198. }
  199. //来电转去电的通话结束,来电挂断
  200. else if (byeRcv.value?.Outer != null && byeRcv.value?.Visitor != null)
  201. {
  202. await _mediator.Publish(_mapper.Map<ByeVisitorAndOuterNotification>(byeRcv.value!),
  203. cancellationToken);
  204. }
  205. //分机和分机结束通话,挂断
  206. else if(byeRcv.value?.Ext.Count==2)
  207. {
  208. await _mediator.Publish(_mapper.Map<ByeExtAndExtNotification>(byeRcv.value!), cancellationToken);
  209. }
  210. //其他条件
  211. else if (byeRcv.value?.Outer != null)
  212. {
  213. //分机和去电的通话结束,分机挂断 类型一
  214. if (byeRcv.value?.Ext.Count == 1)
  215. {
  216. await _mediator.Publish(_mapper.Map<ByeExtAndOuterOneNotification>(byeRcv.value!),
  217. cancellationToken);
  218. }
  219. //双向外呼的通话结束,两个去电分别各有一个 BYE 事件
  220. else if (byeRcv.value?.Outer.From != "")
  221. {
  222. await _mediator.Publish(_mapper.Map<ByeOuterAndOuterNotification>(byeRcv.value!),
  223. cancellationToken);
  224. }
  225. //分机和去电的通话结束,分机挂断 类型二
  226. else
  227. {
  228. await _mediator.Publish(_mapper.Map<ByeExtAndOuterTwoNotification>(byeRcv.value!),
  229. cancellationToken);
  230. }
  231. }
  232. break;
  233. //呼叫转移事件
  234. case Event.DIVERT:
  235. var divertRcv = content.DeserializeWithAuthorize<DivertEvent>();
  236. //来电呼叫分机时,因分机设置了呼叫转移等原因,导致该呼叫被转移
  237. if (divertRcv.value?.Visitor != null)
  238. {
  239. await _mediator.Publish(_mapper.Map<DivertVisitorToExtNotification>(divertRcv.value!),
  240. cancellationToken);
  241. }
  242. //分机呼叫其他分机时,因被叫分机设置了呼叫转移等原因,导致该呼叫被转移
  243. else if (divertRcv.value?.Ext != null)
  244. {
  245. await _mediator.Publish(_mapper.Map<DivertExtToExtNotification>(divertRcv.value!),
  246. cancellationToken);
  247. }
  248. break;
  249. //呼叫临时事件
  250. case Event.TRANSIENT:
  251. var transientRcv = content.DeserializeWithAuthorize<TransientEvent>();
  252. if (transientRcv.value?.Outer != null)
  253. {
  254. await _mediator.Publish(_mapper.Map<TransientOuterNotification>(transientRcv.value!),
  255. cancellationToken);
  256. }
  257. else if (transientRcv.value?.Visitor != null)
  258. {
  259. await _mediator.Publish(_mapper.Map<TransientVisitorNotification>(transientRcv.value!),
  260. cancellationToken);
  261. }
  262. //TODO 处理来电临时事件
  263. break;
  264. //呼叫失败事件
  265. case Event.FAILED:
  266. var failedRcv = content.DeserializeWithAuthorize<FailedEvent>();
  267. await _mediator.Publish(_mapper.Map<FailedNotification>(failedRcv.value!), cancellationToken);
  268. break;
  269. //来电呼叫请求事件
  270. case Event.INVITE:
  271. var inviteRcv = content.DeserializeWithAuthorize<InviteEvent>();
  272. await _mediator.Publish(_mapper.Map<InviteNotification>(inviteRcv.value!), cancellationToken);
  273. break;
  274. //来电呼入事件
  275. case Event.INCOMING:
  276. var incomingRcv = content.DeserializeWithAuthorize<IncomingEvent>();
  277. await _mediator.Publish(_mapper.Map<IncomingNotification>(incomingRcv.value!),
  278. cancellationToken);
  279. break;
  280. //按键信息事件
  281. case Event.DTMF:
  282. var dtmfRcv = content.DeserializeWithAuthorize<DtmfEvent>();
  283. await _mediator.Publish(_mapper.Map<DtmfNotification>(dtmfRcv.value!), cancellationToken);
  284. break;
  285. //语音文件播放完毕事件
  286. case Event.EndOfAnn:
  287. var endOfAnnRcv = content.DeserializeWithAuthorize<EndOfAnnEvent>();
  288. //来电转menu
  289. if (endOfAnnRcv.value?.Visitor != null && endOfAnnRcv.value?.Menu != null)
  290. {
  291. await _mediator.Publish(_mapper.Map<EndOfAnnVisitorToMenuNotification>(endOfAnnRcv.value!),
  292. cancellationToken);
  293. }
  294. //去电转menu
  295. else if (endOfAnnRcv.value?.Outer != null && endOfAnnRcv.value?.Menu != null)
  296. {
  297. await _mediator.Publish(_mapper.Map<EndOfAnnOuterToMenuNotification>(endOfAnnRcv.value!),
  298. cancellationToken);
  299. }
  300. //分机转menu
  301. else if (endOfAnnRcv.value?.Ext != null && endOfAnnRcv.value?.Menu != null)
  302. {
  303. await _mediator.Publish(_mapper.Map<EndOfAnnExtToMenuNotification>(endOfAnnRcv.value!),
  304. cancellationToken);
  305. }
  306. break;
  307. //分机组队列事件
  308. case Event.QUEUE:
  309. var queueRcv = content.DeserializeWithAuthorize<QueueEvent>();
  310. //分机呼入分机组
  311. if (queueRcv.value?.Ext != null && queueRcv.value?.Waiting != null)
  312. {
  313. //组内分机全忙,分机和来电相继呼入分机组
  314. if (queueRcv.value?.Waiting.Reason == "")
  315. {
  316. await _mediator.Publish(_mapper.Map<QueueExtToGroupBusyNotification>(queueRcv.value!),
  317. cancellationToken);
  318. }
  319. //若所有分机离线,分机和来电呼叫分机组
  320. else if (queueRcv.value?.Waiting.Reason == "offline")
  321. {
  322. await _mediator.Publish(
  323. _mapper.Map<QueueExtToGroupOfflineNotification>(queueRcv.value!),
  324. cancellationToken);
  325. }
  326. //若排队满了,分机和来电呼叫分机组
  327. else if (queueRcv.value?.Waiting.Reason == "full")
  328. {
  329. await _mediator.Publish(_mapper.Map<QueueExtToGroupFullNotification>(queueRcv.value!),
  330. cancellationToken);
  331. }
  332. }
  333. //组内分机全忙,分机和来电相继呼入分机组
  334. //来电呼入分机组
  335. else if (queueRcv.value?.Visitor != null && queueRcv.value?.Waiting != null)
  336. {
  337. //组内分机全忙,分机和来电相继呼入分机组
  338. if (queueRcv.value?.Waiting.Reason == "")
  339. {
  340. await _mediator.Publish(
  341. _mapper.Map<QueueVisitorToGroupBusyNotification>(queueRcv.value!),
  342. cancellationToken);
  343. }
  344. else if (queueRcv.value?.Waiting.Reason == "offline")
  345. {
  346. await _mediator.Publish(
  347. _mapper.Map<QueueVisitorToGroupOfflineNotification>(queueRcv.value!),
  348. cancellationToken);
  349. }
  350. else if (queueRcv.value?.Waiting.Reason == "full")
  351. {
  352. await _mediator.Publish(
  353. _mapper.Map<QueueVisitorToGroupFullNotification>(queueRcv.value!),
  354. cancellationToken);
  355. }
  356. }
  357. break;
  358. //系统重启事件
  359. case Event.BOOTUP:
  360. var bootupRcv = content.DeserializeWithAuthorize<BootupEvent>();
  361. await _mediator.Publish(_mapper.Map<BootupNotification>(bootupRcv.value!), cancellationToken);
  362. break;
  363. default:
  364. break;
  365. }
  366. }
  367. }
  368. }
  369. }