public HttpResponseMessage IncomingMessage([FromUri] TwilioMessage request) { if (request == null || string.IsNullOrWhiteSpace(request.To) || string.IsNullOrWhiteSpace(request.From) || string.IsNullOrWhiteSpace(request.Body)) { return(Request.CreateResponse(HttpStatusCode.BadRequest)); } var response = new TwilioResponse(); var textMessage = new TextMessage(); textMessage.To = request.To.Replace("+", ""); textMessage.Msisdn = request.From.Replace("+", ""); textMessage.MessageId = request.MessageSid; textMessage.Timestamp = DateTime.UtcNow.ToLongDateString(); textMessage.Data = request.Body; textMessage.Text = request.Body; var messageEvent = new InboundMessageEvent(); messageEvent.MessageType = (int)InboundMessageTypes.TextMessage; messageEvent.RecievedOn = DateTime.UtcNow; messageEvent.Type = typeof(InboundMessageEvent).FullName; messageEvent.Data = JsonConvert.SerializeObject(textMessage); messageEvent.Processed = false; messageEvent.CustomerId = ""; try { var departmentId = _departmentSettingsService.GetDepartmentIdByTextToCallNumber(textMessage.To); if (departmentId.HasValue) { var department = _departmentsService.GetDepartmentById(departmentId.Value); var textToCallEnabled = _departmentSettingsService.GetDepartmentIsTextCallImportEnabled(departmentId.Value); var textCommandEnabled = _departmentSettingsService.GetDepartmentIsTextCommandEnabled(departmentId.Value); var dispatchNumbers = _departmentSettingsService.GetTextToCallSourceNumbersForDepartment(departmentId.Value); var authroized = _limitsService.CanDepartmentProvisionNumber(departmentId.Value); var customStates = _customStateService.GetAllActiveCustomStatesForDepartment(departmentId.Value); messageEvent.CustomerId = departmentId.Value.ToString(); if (authroized) { bool isDispatchSource = false; if (!String.IsNullOrWhiteSpace(dispatchNumbers)) { isDispatchSource = _numbersService.DoesNumberMatchAnyPattern(dispatchNumbers.Split(Char.Parse(",")).ToList(), textMessage.Msisdn); } // If we don't have dispatchNumbers and Text Command isn't enabled it's a dispatch text if (!isDispatchSource && !textCommandEnabled) { isDispatchSource = true; } if (isDispatchSource && textToCallEnabled) { var c = new Call(); c.Notes = textMessage.Text; c.NatureOfCall = textMessage.Text; c.LoggedOn = DateTime.UtcNow; c.Name = string.Format("TTC {0}", c.LoggedOn.TimeConverter(department).ToString("g")); c.Priority = (int)CallPriority.High; c.ReportingUserId = department.ManagingUserId; c.Dispatches = new Collection <CallDispatch>(); c.CallSource = (int)CallSources.EmailImport; c.SourceIdentifier = textMessage.MessageId; c.DepartmentId = departmentId.Value; var users = _departmentsService.GetAllUsersForDepartment(departmentId.Value, true); foreach (var u in users) { var cd = new CallDispatch(); cd.UserId = u.UserId; c.Dispatches.Add(cd); } var savedCall = _callsService.SaveCall(c); var cqi = new CallQueueItem(); cqi.Call = savedCall; cqi.Profiles = _userProfileService.GetSelectedUserProfiles(users.Select(x => x.UserId).ToList()); cqi.DepartmentTextNumber = _departmentSettingsService.GetTextToCallNumberForDepartment(cqi.Call.DepartmentId); _queueService.EnqueueCallBroadcast(cqi); messageEvent.Processed = true; } if (!isDispatchSource && textCommandEnabled) { var profile = _userProfileService.FindProfileByMobileNumber(textMessage.Msisdn); if (profile != null) { var payload = _textCommandService.DetermineType(textMessage.Text); var customActions = customStates.FirstOrDefault(x => x.Type == (int)CustomStateTypes.Personnel); var customStaffing = customStates.FirstOrDefault(x => x.Type == (int)CustomStateTypes.Staffing); switch (payload.Type) { case TextCommandTypes.None: response.Message("Resgrid (https://resgrid.com) Automated Text System. Unknown command, text help for supported commands."); break; case TextCommandTypes.Help: messageEvent.Processed = true; var help = new StringBuilder(); help.Append("Resgrid Text Commands" + Environment.NewLine); help.Append("---------------------" + Environment.NewLine); help.Append("These are the commands you can text to alter your status and staffing. Text help for help." + Environment.NewLine); help.Append("---------------------" + Environment.NewLine); help.Append("Core Commands" + Environment.NewLine); help.Append("---------------------" + Environment.NewLine); help.Append("STOP: To turn off all text messages" + Environment.NewLine); help.Append("HELP: This help text" + Environment.NewLine); help.Append("CALLS: List active calls" + Environment.NewLine); help.Append("C[CallId]: Get Call Detail i.e. C1445" + Environment.NewLine); help.Append("UNITS: List unit statuses" + Environment.NewLine); help.Append("---------------------" + Environment.NewLine); help.Append("Status or Action Commands" + Environment.NewLine); help.Append("---------------------" + Environment.NewLine); if (customActions != null && customActions.IsDeleted == false && customActions.GetActiveDetails() != null && customActions.GetActiveDetails().Any()) { var activeDetails = customActions.GetActiveDetails(); for (int i = 0; i < activeDetails.Count; i++) { help.Append($"{activeDetails[i].ButtonText.Trim().Replace(" ", "").Replace("-", "").Replace(":", "")} or {i + 1}: {activeDetails[i].ButtonText}" + Environment.NewLine); } } else { help.Append("responding or 1: Responding" + Environment.NewLine); help.Append("notresponding or 2: Not Responding" + Environment.NewLine); help.Append("onscene or 3: On Scene" + Environment.NewLine); help.Append("available or 4: Available" + Environment.NewLine); } help.Append("---------------------" + Environment.NewLine); help.Append("Staffing Commands" + Environment.NewLine); help.Append("---------------------" + Environment.NewLine); if (customStaffing != null && customStaffing.IsDeleted == false && customStaffing.GetActiveDetails() != null && customStaffing.GetActiveDetails().Any()) { var activeDetails = customStaffing.GetActiveDetails(); for (int i = 0; i < activeDetails.Count; i++) { help.Append($"{activeDetails[i].ButtonText.Trim().Replace(" ", "").Replace("-", "").Replace(":", "")} or S{i + 1}: {activeDetails[i].ButtonText}" + Environment.NewLine); } } else { help.Append("available or s1: Available Staffing" + Environment.NewLine); help.Append("delayed or s2: Delayed Staffing" + Environment.NewLine); help.Append("unavailable or s3: Unavailable Staffing" + Environment.NewLine); help.Append("committed or s4: Committed Staffing" + Environment.NewLine); help.Append("onshift or s4: On Shift Staffing" + Environment.NewLine); } response.Message(help.ToString()); //_communicationService.SendTextMessage(profile.UserId, "Resgrid TCI Help", help.ToString(), department.DepartmentId, textMessage.To, profile); break; case TextCommandTypes.Action: messageEvent.Processed = true; _actionLogsService.SetUserAction(profile.UserId, department.DepartmentId, (int)payload.GetActionType()); response.Message(string.Format("Resgrid recieved your text command. Status changed to: {0}", payload.GetActionType())); //_communicationService.SendTextMessage(profile.UserId, "Resgrid TCI Status", string.Format("Resgrid recieved your text command. Status changed to: {0}", payload.GetActionType()), department.DepartmentId, textMessage.To, profile); break; case TextCommandTypes.Staffing: messageEvent.Processed = true; _userStateService.CreateUserState(profile.UserId, department.DepartmentId, (int)payload.GetStaffingType()); response.Message(string.Format("Resgrid recieved your text command. Staffing level changed to: {0}", payload.GetStaffingType())); //_communicationService.SendTextMessage(profile.UserId, "Resgrid TCI Staffing", string.Format("Resgrid recieved your text command. Staffing level changed to: {0}", payload.GetStaffingType()), department.DepartmentId, textMessage.To, profile); break; case TextCommandTypes.Stop: messageEvent.Processed = true; _userProfileService.DisableTextMessagesForUser(profile.UserId); response.Message("Text messages are now turned off for this user, to enable again log in to Resgrid and update your profile."); break; case TextCommandTypes.CustomAction: messageEvent.Processed = true; _actionLogsService.SetUserAction(profile.UserId, department.DepartmentId, payload.GetCustomActionType()); if (customActions != null && customActions.IsDeleted == false && customActions.GetActiveDetails() != null && customActions.GetActiveDetails().Any() && customActions.GetActiveDetails().FirstOrDefault(x => x.CustomStateDetailId == payload.GetCustomActionType()) != null) { var detail = customActions.GetActiveDetails().FirstOrDefault(x => x.CustomStateDetailId == payload.GetCustomActionType()); response.Message(string.Format("Resgrid recieved your text command. Status changed to: {0}", detail.ButtonText)); } else { response.Message("Resgrid recieved your text command and updated your status"); } break; case TextCommandTypes.CustomStaffing: messageEvent.Processed = true; _userStateService.CreateUserState(profile.UserId, department.DepartmentId, payload.GetCustomStaffingType()); if (customStaffing != null && customStaffing.IsDeleted == false && customStaffing.GetActiveDetails() != null && customStaffing.GetActiveDetails().Any() && customStaffing.GetActiveDetails().FirstOrDefault(x => x.CustomStateDetailId == payload.GetCustomStaffingType()) != null) { var detail = customStaffing.GetActiveDetails().FirstOrDefault(x => x.CustomStateDetailId == payload.GetCustomStaffingType()); response.Message(string.Format("Resgrid recieved your text command. Staffing changed to: {0}", detail.ButtonText)); } else { response.Message("Resgrid recieved your text command and updated your staffing"); } break; case TextCommandTypes.MyStatus: messageEvent.Processed = true; var userStatus = _actionLogsService.GetLastActionLogForUser(profile.UserId); var userStaffing = _userStateService.GetLastUserStateByUserId(profile.UserId); var customStatusLevel = _customStateService.GetCustomPersonnelStatus(department.DepartmentId, userStatus); var customStaffingLevel = _customStateService.GetCustomPersonnelStaffing(department.DepartmentId, userStaffing); response.Message($"Hello {profile.FullName.AsFirstNameLastName} at {DateTime.UtcNow.TimeConverterToString(department)} your current status is {customStatusLevel.ButtonText} and your current staffing is {customStaffingLevel.ButtonText}."); break; case TextCommandTypes.Calls: messageEvent.Processed = true; var activeCalls = _callsService.GetActiveCallsByDepartment(department.DepartmentId); var activeCallText = new StringBuilder(); activeCallText.Append($"Active Calls for {department.Name}" + Environment.NewLine); activeCallText.Append("---------------------" + Environment.NewLine); foreach (var activeCall in activeCalls) { activeCallText.Append($"CallId: {activeCall.CallId} Name: {activeCall.Name} Nature:{activeCall.NatureOfCall}" + Environment.NewLine); } response.Message(activeCallText.ToString()); break; case TextCommandTypes.Units: messageEvent.Processed = true; var unitStatus = _unitsService.GetAllLatestStatusForUnitsByDepartmentId(department.DepartmentId); var unitStatusesText = new StringBuilder(); unitStatusesText.Append($"Unit Statuses for {department.Name}" + Environment.NewLine); unitStatusesText.Append("---------------------" + Environment.NewLine); foreach (var unit in unitStatus) { var unitState = _customStateService.GetCustomUnitState(unit); unitStatusesText.Append($"{unit.Unit.Name} is {unitState.ButtonText}" + Environment.NewLine); } response.Message(unitStatusesText.ToString()); break; case TextCommandTypes.CallDetail: messageEvent.Processed = true; var call = _callsService.GetCallById(int.Parse(payload.Data)); var callText = new StringBuilder(); callText.Append($"Call Information for {call.Name}" + Environment.NewLine); callText.Append("---------------------" + Environment.NewLine); callText.Append($"Id: {call.CallId}" + Environment.NewLine); callText.Append($"Number: {call.Number}" + Environment.NewLine); callText.Append($"Logged: {call.LoggedOn.TimeConverterToString(department)}" + Environment.NewLine); callText.Append("-----Nature-----" + Environment.NewLine); callText.Append(call.NatureOfCall + Environment.NewLine); callText.Append("-----Address-----" + Environment.NewLine); if (!String.IsNullOrWhiteSpace(call.Address)) { callText.Append(call.Address + Environment.NewLine); } else if (!string.IsNullOrEmpty(call.GeoLocationData)) { try { string[] points = call.GeoLocationData.Split(char.Parse(",")); if (points != null && points.Length == 2) { callText.Append(_geoLocationProvider.GetAproxAddressFromLatLong(double.Parse(points[0]), double.Parse(points[1])) + Environment.NewLine); } } catch { } } response.Message(callText.ToString()); break; } } } } } else if (textMessage.To == "17753765253") // Resgrid master text number { var profile = _userProfileService.FindProfileByMobileNumber(textMessage.Msisdn); var payload = _textCommandService.DetermineType(textMessage.Text); switch (payload.Type) { case TextCommandTypes.None: response.Message("Resgrid (https://resgrid.com) Automated Text System. Unknown command, text help for supported commands."); break; case TextCommandTypes.Help: messageEvent.Processed = true; var help = new StringBuilder(); help.Append("Resgrid Text Commands" + Environment.NewLine); help.Append("---------------------" + Environment.NewLine); help.Append("This is the Resgrid system for first responders (https://resgrid.com) automated text system. Your department isn't signed up for inbound text messages, but you can send the following commands." + Environment.NewLine); help.Append("---------------------" + Environment.NewLine); help.Append("STOP: To turn off all text messages" + Environment.NewLine); help.Append("HELP: This help text" + Environment.NewLine); response.Message(help.ToString()); break; case TextCommandTypes.Stop: messageEvent.Processed = true; _userProfileService.DisableTextMessagesForUser(profile.UserId); response.Message("Text messages are now turned off for this user, to enable again log in to Resgrid and update your profile."); break; } } } catch (Exception ex) { Framework.Logging.LogException(ex); } finally { _numbersService.SaveInboundMessageEvent(messageEvent); } //return Request.CreateResponse(HttpStatusCode.OK); //var response = new TwilioResponse(); return(Request.CreateResponse(HttpStatusCode.OK, response.Element, new XmlMediaTypeFormatter())); }
public string GetMessageForType(ProcessedNotification notification) { try { NotificationItem data = ObjectSerialization.Deserialize <NotificationItem>(notification.Data); switch (notification.Type) { case EventTypes.UnitStatusChanged: var unitEvent = _unitsService.GetUnitStateById((int)data.StateId); var unitStatus = _customStateService.GetCustomUnitState(unitEvent); if (unitEvent != null && unitEvent.Unit != null) { return(String.Format("Unit {0} is now {1}", unitEvent.Unit.Name, unitStatus.ButtonText)); } else if (unitEvent != null) { return(String.Format("A Unit's status is now {0}", unitStatus.ButtonText)); } else { return("A unit's status changed"); } case EventTypes.PersonnelStaffingChanged: var userStaffing = _userStateService.GetUserStateById((int)data.StateId); var userProfile = _userProfileService.GetProfileByUserId(userStaffing.UserId); var userStaffingText = _customStateService.GetCustomPersonnelStaffing(data.DepartmentId, userStaffing); return(String.Format("{0} staffing is now {1}", userProfile.FullName.AsFirstNameLastName, userStaffingText.ButtonText)); case EventTypes.PersonnelStatusChanged: var actionLog = _actionLogsService.GetActionlogById(data.StateId); UserProfile profile = null; if (actionLog != null) { profile = _userProfileService.GetProfileByUserId(actionLog.UserId); } else if (data.UserId != String.Empty) { profile = _userProfileService.GetProfileByUserId(data.UserId); } var userStatusText = _customStateService.GetCustomPersonnelStatus(data.DepartmentId, actionLog); if (profile != null && userStatusText != null) { return(String.Format("{0} status is now {1}", profile.FullName.AsFirstNameLastName, userStatusText.ButtonText)); } else if (profile != null) { return(String.Format("{0} status has changed", profile.FullName.AsFirstNameLastName)); } return(String.Empty); case EventTypes.UserCreated: var newUserprofile = _userProfileService.GetProfileByUserId(data.UserId); if (newUserprofile != null) { return(String.Format("{0} has been added to your department", newUserprofile.FullName.AsFirstNameLastName)); } else { return("A new user has been added to your department"); } case EventTypes.UserAssignedToGroup: UserProfile groupUserprofile = null; try { if (data.UserId != String.Empty) { groupUserprofile = _userProfileService.GetProfileByUserId(data.UserId); } } catch { } DepartmentGroup newGroup = null; try { if (data.GroupId != 0) { newGroup = _departmentGroupsService.GetGroupById((int)data.GroupId, false); } } catch { } if (groupUserprofile != null && newGroup != null) { return(String.Format("{0} has been assigned to group {1}", groupUserprofile.FullName.AsFirstNameLastName, newGroup.Name)); } else if (groupUserprofile != null && newGroup == null) { return(String.Format("{0} has been assigned to group", groupUserprofile.FullName.AsFirstNameLastName)); } else if (newGroup != null && groupUserprofile == null) { return(String.Format("A user has been assigned to group {0}", newGroup.Name)); } else { return(String.Format("A has been assigned to a group")); } case EventTypes.CalendarEventUpcoming: var calandarItem = _calendarService.GetCalendarItemById((int)data.ItemId); return(String.Format("Event {0} is upcoming", calandarItem.Title)); case EventTypes.DocumentAdded: var document = _documentsService.GetDocumentById((int)data.ItemId); return(String.Format("Document {0} has been added", document.Name)); case EventTypes.NoteAdded: var note = _notesService.GetNoteById((int)data.ItemId); if (note != null) { return(String.Format("Message {0} has been added", note.Title)); } break; case EventTypes.UnitAdded: var unit = _unitsService.GetUnitById((int)data.UnitId); return(String.Format("Unit {0} has been added", unit.Name)); case EventTypes.LogAdded: var log = _workLogsService.GetWorkLogById((int)data.ItemId); if (log != null) { var logUserProfile = _userProfileService.GetProfileByUserId(log.LoggedByUserId); return(String.Format("{0} created log {1}", logUserProfile.FullName.AsFirstNameLastName, log.LogId)); } else { return(String.Format("A new log was created")); } case EventTypes.DepartmentSettingsChanged: return(String.Format("Settings have been updated for your department")); case EventTypes.RolesInGroupAvailabilityAlert: var userStateChanged = _userStateService.GetUserStateById(int.Parse(notification.Value)); var roleForGroup = _personnelRolesService.GetRoleById(notification.PersonnelRoleTargeted); var groupForRole = _departmentGroupsService.GetGroupForUser(userStateChanged.UserId, notification.DepartmentId); return(String.Format("Availability for role {0} in group {1} is at or below the lower limit", roleForGroup.Name, groupForRole.Name)); case EventTypes.RolesInDepartmentAvailabilityAlert: if (notification != null) { var roleForDep = _personnelRolesService.GetRoleById(notification.PersonnelRoleTargeted); if (roleForDep != null) { return(String.Format("Availability for role {0} for the department is at or below the lower limit", roleForDep.Name)); } } break; case EventTypes.UnitTypesInGroupAvailabilityAlert: if (data.UnitId != 0) { var unitForGroup = _unitsService.GetUnitById(data.UnitId); if (unitForGroup != null && unitForGroup.StationGroupId.HasValue) { var groupForUnit = _departmentGroupsService.GetGroupById(unitForGroup.StationGroupId.Value); return(String.Format("Availability for unit type {0} in group {1} is at or below the lower limit", unitForGroup.Type, groupForUnit.Name)); } } return(String.Empty); case EventTypes.UnitTypesInDepartmentAvailabilityAlert: return(String.Format("Availability for unit type {0} for the department is at or below the lower limit", notification.UnitTypeTargeted)); case EventTypes.CalendarEventAdded: var calEvent = _calendarService.GetCalendarItemById(notification.ItemId); var department = _departmentsService.GetDepartmentById(calEvent.DepartmentId); if (calEvent != null) { if (calEvent.ItemType == 0) { if (calEvent.IsAllDay) { return($"New Calendar Event {calEvent.Title} on {calEvent.Start.TimeConverter(department).ToShortDateString()}"); } else { return($"New Calendar Event {calEvent.Title} on {calEvent.Start.TimeConverter(department).ToShortDateString()} at {calEvent.Start.TimeConverter(department).ToShortTimeString()}"); } } else if (calEvent.IsAllDay) { return($"New Calendar RSVP Event {calEvent.Title} on {calEvent.Start.TimeConverter(department).ToShortDateString()}"); } else { return($"New Calendar RSVP Event {calEvent.Title} on {calEvent.Start.TimeConverter(department).ToShortDateString()} at {calEvent.Start.TimeConverter(department).ToShortTimeString()}"); } } else { return(String.Empty); } case EventTypes.CalendarEventUpdated: var calUpdatedEvent = _calendarService.GetCalendarItemById(notification.ItemId); var calUpdatedEventDepartment = _departmentsService.GetDepartmentById(calUpdatedEvent.DepartmentId); if (calUpdatedEvent != null) { return($"Calendar Event {calUpdatedEvent.Title} on {calUpdatedEvent.Start.TimeConverter(calUpdatedEventDepartment).ToShortDateString()} has changed"); } else { return(String.Empty); } default: throw new ArgumentOutOfRangeException("type"); } } catch (Exception ex) { Logging.LogException(ex, extraMessage: notification.Data); return(String.Empty); } return(String.Empty); }