public static async Task <bool> ProcessCallQueueItem(CallQueueItem cqi) { try { if (cqi != null && cqi.Call != null && cqi.Call.HasAnyDispatches()) { if (_communicationService == null) { _communicationService = Bootstrapper.GetKernel().Resolve <ICommunicationService>(); } if (_callsService == null) { _callsService = Bootstrapper.GetKernel().Resolve <ICallsService>(); } List <int> groupIds = new List <int>(); /* Trying to see if I can eek out a little perf here now that profiles are in Redis. Previously the * the parallel operation would cause EF errors. This shouldn't be the case now because profiles are * cached and GetProfileForUser operations will hit that first. */ if (cqi.Profiles == null || !cqi.Profiles.Any()) { if (_userProfilesService == null) { _userProfilesService = Bootstrapper.GetKernel().Resolve <IUserProfileService>(); } cqi.Profiles = (await _userProfilesService.GetAllProfilesForDepartmentAsync(cqi.Call.DepartmentId)).Select(x => x.Value).ToList(); } if (cqi.CallDispatchAttachmentId > 0) { //var callsService = Bootstrapper.GetKernel().Resolve<ICallsService>(); cqi.Call.ShortenedAudioUrl = await _callsService.GetShortenedAudioUrlAsync(cqi.Call.CallId, cqi.CallDispatchAttachmentId); } cqi.Call.ShortenedCallUrl = await _callsService.GetShortenedCallLinkUrl(cqi.Call.CallId); try { cqi.Call.CallPriority = await _callsService.GetCallPrioritiesByIdAsync(cqi.Call.DepartmentId, cqi.Call.Priority, false); } catch { /* Doesn't matter */ } var dispatchedUsers = new HashSet <string>(); // Dispatch Personnel if (cqi.Call.Dispatches != null && cqi.Call.Dispatches.Any()) { Parallel.ForEach(cqi.Call.Dispatches, d => { dispatchedUsers.Add(d.UserId); try { var profile = cqi.Profiles.FirstOrDefault(x => x.UserId == d.UserId); if (profile != null) { _communicationService.SendCallAsync(cqi.Call, d, cqi.DepartmentTextNumber, cqi.Call.DepartmentId, profile, cqi.Address); } } catch (SocketException sex) { } }); } if (_departmentGroupsService == null) { _departmentGroupsService = Bootstrapper.GetKernel().Resolve <IDepartmentGroupsService>(); } // Dispatch Groups if (cqi.Call.GroupDispatches != null && cqi.Call.GroupDispatches.Any()) { foreach (var d in cqi.Call.GroupDispatches) { if (!groupIds.Contains(d.DepartmentGroupId)) { groupIds.Add(d.DepartmentGroupId); } var members = await _departmentGroupsService.GetAllMembersForGroupAsync(d.DepartmentGroupId); foreach (var member in members) { if (!dispatchedUsers.Contains(member.UserId)) { dispatchedUsers.Add(member.UserId); try { var profile = cqi.Profiles.FirstOrDefault(x => x.UserId == member.UserId); await _communicationService.SendCallAsync(cqi.Call, new CallDispatch() { UserId = member.UserId }, cqi.DepartmentTextNumber, cqi.Call.DepartmentId, profile, cqi.Address); } catch (SocketException sex) { } catch (Exception ex) { Logging.LogException(ex); } } } } } // Dispatch Units if (cqi.Call.UnitDispatches != null && cqi.Call.UnitDispatches.Any()) { if (_unitsService == null) { _unitsService = Bootstrapper.GetKernel().Resolve <IUnitsService>(); } foreach (var d in cqi.Call.UnitDispatches) { var unit = await _unitsService.GetUnitByIdAsync(d.UnitId); if (unit != null && unit.StationGroupId.HasValue) { if (!groupIds.Contains(unit.StationGroupId.Value)) { groupIds.Add(unit.StationGroupId.Value); } } await _communicationService.SendUnitCallAsync(cqi.Call, d, cqi.DepartmentTextNumber, cqi.Address); var unitAssignedMembers = await _unitsService.GetCurrentRolesForUnitAsync(d.UnitId); if (unitAssignedMembers != null && unitAssignedMembers.Count() > 0) { foreach (var member in unitAssignedMembers) { if (!dispatchedUsers.Contains(member.UserId)) { dispatchedUsers.Add(member.UserId); try { var profile = cqi.Profiles.FirstOrDefault(x => x.UserId == member.UserId); await _communicationService.SendCallAsync(cqi.Call, new CallDispatch() { UserId = member.UserId }, cqi.DepartmentTextNumber, cqi.Call.DepartmentId, profile, cqi.Address); } catch (SocketException sex) { } catch (Exception ex) { Logging.LogException(ex); } } } } else { if (unit.StationGroupId.HasValue) { var members = await _departmentGroupsService.GetAllMembersForGroupAsync(unit.StationGroupId.Value); foreach (var member in members) { if (!dispatchedUsers.Contains(member.UserId)) { dispatchedUsers.Add(member.UserId); try { var profile = cqi.Profiles.FirstOrDefault(x => x.UserId == member.UserId); await _communicationService.SendCallAsync(cqi.Call, new CallDispatch() { UserId = member.UserId }, cqi.DepartmentTextNumber, cqi.Call.DepartmentId, profile, cqi.Address); } catch (SocketException sex) { } catch (Exception ex) { Logging.LogException(ex); } } } } } } } // Dispatch Roles if (cqi.Call.RoleDispatches != null && cqi.Call.RoleDispatches.Any()) { if (_rolesService == null) { _rolesService = Bootstrapper.GetKernel().Resolve <IPersonnelRolesService>(); } foreach (var d in cqi.Call.RoleDispatches) { var members = await _rolesService.GetAllMembersOfRoleAsync(d.RoleId); foreach (var member in members) { if (!dispatchedUsers.Contains(member.UserId)) { dispatchedUsers.Add(member.UserId); try { var profile = cqi.Profiles.FirstOrDefault(x => x.UserId == member.UserId); await _communicationService.SendCallAsync(cqi.Call, new CallDispatch() { UserId = member.UserId }, cqi.DepartmentTextNumber, cqi.Call.DepartmentId, profile, cqi.Address); } catch (SocketException sex) { } catch (Exception ex) { Logging.LogException(ex); } } } } } // Send Call Print to Printer if (_printerProvider == null) { _printerProvider = Bootstrapper.GetKernel().Resolve <IPrinterProvider>(); } Dictionary <int, DepartmentGroup> fetchedGroups = new Dictionary <int, DepartmentGroup>(); if (cqi.Call.Dispatches != null && cqi.Call.Dispatches.Any()) { foreach (var d in cqi.Call.Dispatches) { var group = await _departmentGroupsService.GetGroupForUserAsync(d.UserId, cqi.Call.DepartmentId); if (group != null) { if (!groupIds.Contains(group.DepartmentGroupId)) { groupIds.Add(group.DepartmentGroupId); } if (!fetchedGroups.ContainsKey(group.DepartmentGroupId)) { fetchedGroups.Add(group.DepartmentGroupId, group); } } } } foreach (var groupId in groupIds) { try { DepartmentGroup group = null; if (fetchedGroups.ContainsKey(groupId)) { group = fetchedGroups[groupId]; } else { group = await _departmentGroupsService.GetGroupByIdAsync(groupId); } if (!String.IsNullOrWhiteSpace(group.PrinterData) && group.DispatchToPrinter) { var printerData = JsonConvert.DeserializeObject <DepartmentGroupPrinter>(group.PrinterData); var apiKey = SymmetricEncryption.Decrypt(printerData.ApiKey, Config.SystemBehaviorConfig.ExternalLinkUrlParamPassphrase); var callUrl = await _callsService.GetShortenedCallPdfUrl(cqi.Call.CallId, true, groupId); var printJob = _printerProvider.SubmitPrintJob(apiKey, printerData.PrinterId, "CallPrint", callUrl); } } catch (Exception ex) { Logging.LogException(ex); } } } } finally { _communicationService = null; } return(true); }
public async Task <ActionResult> VoiceCall(string userId, int callId) { var response = new VoiceResponse(); var call = await _callsService.GetCallByIdAsync(callId); call = await _callsService.PopulateCallData(call, true, true, true, true, true, true, true); if (call == null) { response.Say("This call has been closed. Goodbye.").Hangup(); //return Request.CreateResponse(HttpStatusCode.OK, response.Element, new XmlMediaTypeFormatter()); return(Ok(new StringContent(response.ToString(), Encoding.UTF8, "application/xml"))); } if (call.State == (int)CallStates.Cancelled || call.State == (int)CallStates.Closed || call.IsDeleted) { response.Say(string.Format("This call, Id {0} has been closed. Goodbye.", call.Number)).Hangup(); //return Request.CreateResponse(HttpStatusCode.OK, response.Element, new XmlMediaTypeFormatter()); return(Ok(new StringContent(response.ToString(), Encoding.UTF8, "application/xml"))); } var stations = await _departmentGroupsService.GetAllStationGroupsForDepartmentAsync(call.DepartmentId); if (call.Attachments != null && call.Attachments.Count(x => x.CallAttachmentType == (int)CallAttachmentTypes.DispatchAudio) > 0) { var audio = call.Attachments.FirstOrDefault(x => x.CallAttachmentType == (int)CallAttachmentTypes.DispatchAudio); if (audio != null) { var url = await _callsService.GetShortenedAudioUrlAsync(call.CallId, audio.CallAttachmentId); Play playResponse = new Play(); playResponse.Url = new Uri(url); Gather gatherResponse1 = new Gather(); gatherResponse1.NumDigits = 1; gatherResponse1.Timeout = 10; gatherResponse1.Method = "GET"; gatherResponse1.Action = new Uri(string.Format("{0}/Twilio/VoiceCallAction/{1}/{2}", Config.SystemBehaviorConfig.ResgridApiBaseUrl, userId, callId)); StringBuilder sb1 = new StringBuilder(); sb1.Append("Press 0 to repeat, Press 1 to respond to the scene"); for (int i = 0; i < stations.Count; i++) { if (i >= 8) { break; } sb1.Append(string.Format(", press {0} to respond to {1}", i + 2, stations[i].Name)); } response.Play(playResponse).Say(sb1.ToString()).Gather(gatherResponse1).Pause(10).Hangup(); return(new ContentResult { Content = response.ToString(), ContentType = "application/xml", StatusCode = 200 }); } } string address = call.Address; if (String.IsNullOrWhiteSpace(address) && !string.IsNullOrWhiteSpace(call.GeoLocationData)) { try { string[] points = call.GeoLocationData.Split(char.Parse(",")); if (points != null && points.Length == 2) { address = await _geoLocationProvider.GetAproxAddressFromLatLong(double.Parse(points[0]), double.Parse(points[1])); } } catch { } } if (String.IsNullOrWhiteSpace(address) && !String.IsNullOrWhiteSpace(call.Address)) { address = call.Address; } StringBuilder sb = new StringBuilder(); if (!String.IsNullOrWhiteSpace(address)) { sb.Append(string.Format("{0}, Priority {1} Address {2} Nature {3}", call.Name, call.GetPriorityText(), call.Address, call.NatureOfCall)); } else { sb.Append(string.Format("{0}, Priority {1} Nature {2}", call.Name, call.GetPriorityText(), call.NatureOfCall)); } sb.Append(", Press 0 to repeat, Press 1 to respond to the scene"); for (int i = 0; i < stations.Count; i++) { if (i >= 8) { break; } sb.Append(string.Format(", press {0} to respond to {1}", i + 2, stations[i].Name)); } Gather gatherResponse = new Gather(); gatherResponse.NumDigits = 1; gatherResponse.Timeout = 10; gatherResponse.Method = "GET"; gatherResponse.Action = new Uri(string.Format("{0}/Twilio/VoiceCallAction/{1}/{2}", Config.SystemBehaviorConfig.ResgridApiBaseUrl, userId, callId)); response.Gather(gatherResponse).Say(sb.ToString()).Pause(10).Hangup(); return(new ContentResult { Content = response.ToString(), ContentType = "application/xml", StatusCode = 200 }); }