public async Task <ActionResult> IVRConfig_Partial(Model model) { if (model.GenerateKeys) { string publicKey, privateKey; RSACrypto.MakeNewKeys(out publicKey, out privateKey); model.PrivateKey = privateKey; model.PublicKey = publicKey; model.GenerateKeys = false; } using (IVRConfigDataProvider configDP = new IVRConfigDataProvider()) { IVRConfig config = await configDP.GetItemAsync();// get the original item model.UpdateData(config); if (!ModelState.IsValid) { return(PartialView(model)); } config = model.GetData(config); // merge new data into original model.SetData(config); // and all the data back into model for final display await configDP.UpdateConfigAsync(config); using (ScriptDataProvider scriptDP = new ScriptDataProvider()) { scriptDP.ClearScript(); } return(FormProcessed(model, this.__ResStr("okSaved", "IVR settings saved"), NextPage: Manager.ReturnToUrl)); } }
public void UpdateData(IVRConfig data) { TestMode = data.TestMode; LiveAccountSid = data.LiveAccountSid; LiveAuthToken = data.LiveAuthToken; TestAccountSid = data.TestAccountSid; TestAuthToken = data.TestAuthToken; }
public async Task <ActionResult> IVRConfig() { using (IVRConfigDataProvider dataProvider = new IVRConfigDataProvider()) { Model model = new Model { }; IVRConfig data = await dataProvider.GetItemAsync(); if (data == null) { throw new Error(this.__ResStr("notFound", "The IVR settings could not be found")); } model.SetData(data); model.UpdateData(data); return(View(model)); } }
public async Task <ModuleAction> GetAction_DisplayAsync(string url, int id) { if (url == null) { IVRConfig config = await IVRConfigDataProvider.GetConfigAsync(); url = config.DisplayVoiceMailUrl; } return(new ModuleAction(this) { Url = string.IsNullOrWhiteSpace(url) ? ModulePermanentUrl : url, QueryArgs = new { Id = id }, Image = "#Display", LinkText = this.__ResStr("displayLink", "Display"), MenuText = this.__ResStr("displayText", "Display"), Tooltip = this.__ResStr("displayTooltip", "Display the voice mail entry"), Legend = this.__ResStr("displayLegend", "Displays an existing voice mail entry"), Style = ModuleAction.ActionStyleEnum.Popup, Category = ModuleAction.ActionCategoryEnum.Read, Mode = ModuleAction.ActionModeEnum.Any, Location = ModuleAction.ActionLocationEnum.NoAuto, SaveReturnUrl = true, }); }
public void SetData(IVRConfig data) { ObjectSupport.CopyData(data, this); }
public IVRConfig GetData(IVRConfig data) { ObjectSupport.CopyData(this, data); return(data); }
public async Task <ActionResult> Process(string request, string extension, int errCount, string token) { LogCall(request, extension); TwilioData twilioConfig = await TwilioConfigDataProvider.GetConfigCondAsync(); if (twilioConfig == null || !twilioConfig.IsConfigured()) { return(RejectResult("Twilio is not configured")); } string authToken = twilioConfig.TestMode ? twilioConfig.TestAuthToken : twilioConfig.LiveAuthToken; IVRConfig ivrConfig = await IVRConfigDataProvider.GetConfigCondAsync(); if (ivrConfig == null || string.IsNullOrWhiteSpace(ivrConfig.PublicKey) || string.IsNullOrWhiteSpace(ivrConfig.PrivateKey)) { return(RejectResult("Config settings not available")); } #if !DEBUG // There is something very peculiar about twilio verification. The initial request will validate correctly, but anything after that will not. // Even if the only difference is CallStatus (tested with a redirect to Request=Main. So I gave up and validate just the first one // and add my own token validation (as argument) if (string.IsNullOrWhiteSpace(token)) { if (!Verify.VerifyTwilio(authToken, twilioConfig.TestMode ? ivrConfig.TestVerificationProcessCallUrl : ivrConfig.LiveVerificationProcessCallUrl)) { return(RejectResult("Twilio verification failed")); } } else { // verify token. If it wasn't generated within the last 5 minutes, reject it. string decryptedToken; RSACrypto.Decrypt(ivrConfig.PrivateKey, token, out decryptedToken); DateTime tokenTime = new DateTime(Convert.ToInt64(decryptedToken)); if (tokenTime < DateTime.UtcNow.AddMinutes(-5)) { return(RejectResult("Token verification failed")); } } #endif if (string.IsNullOrWhiteSpace(request)) { // call log using (CallLogDataProvider callLogDP = new CallLogDataProvider()) { await callLogDP.AddItemAsync(new CallLogEntry { Caller = GetForm("From")?.Truncate(Globals.MaxPhoneNumber), CallerCity = GetForm("CallerCity")?.Truncate(CallLogEntry.MaxCity), CallerCountry = GetForm("CallerCountry")?.Truncate(CallLogEntry.MaxCountry), CallerState = GetForm("CallerState")?.Truncate(CallLogEntry.MaxState), CallerZip = GetForm("CallerZip")?.Truncate(CallLogEntry.MaxZip), To = GetForm("Called")?.Truncate(Globals.MaxPhoneNumber), }); } // check for blocked numbers using (BlockedNumberDataProvider blockedDP = new BlockedNumberDataProvider()) { BlockedNumberEntry blockedEntry = await blockedDP.GetItemAsync(GetForm("From")); if (blockedEntry != null) { return(RejectResult($"Blocked number {GetForm("From")}")); } } // notify (new call) foreach (ExtensionPhoneNumber notifyNumber in ivrConfig.NotificationNumbers) { if (notifyNumber.SendSMS) { SendSMS sendSMS = new SendSMS(); await sendSMS.SendMessageAsync(notifyNumber.PhoneNumber, this.__ResStr("notifySMS", "Incoming call received from {0} ({1}, {2}, {3}, {4}) - {5}", GetForm("Caller"), GetForm("CallerCity"), GetForm("CallerState"), GetForm("CallerZip"), GetForm("CallerCountry"), GetForm("To")), ThrowError : false); } } // determine main action to run request = SECTION_MAIN; using (HolidayEntryDataProvider holidayDP = new HolidayEntryDataProvider()) { HolidayEntry holiday = await holidayDP.GetItemAsync(DateTime.Now.Date.ToUniversalTime()); if (holiday != null) { request = SECTION_MAINHOLIDAY; } else if (ivrConfig.OpeningHours.IsClosed(DateTime.UtcNow)) { request = SECTION_MAINCLOSED; } } } string called; if (!TryGetForm("CalledVia", out called)) { called = GetForm("Called"); } if (ivrConfig.MaxErrors != 0 && errCount >= ivrConfig.MaxErrors) { request = SECTION_MAINGOODBYE; } request = request.ToLower(); using (ScriptDataProvider scriptDP = new ScriptDataProvider()) { ScriptData script = await scriptDP.GetScriptAsync(called); if (script == null) { return(RejectResult($"Script not found for {called}")); } // See if a valid extension was entered if (request == SECTION_GATHEREXTENSION.ToLower()) { string digits; if (TryGetForm("Digits", out digits)) { Extension ext = script.FindExtension(digits); if (ext != null) { extension = ext.Digits; request = SECTION_ENTEREDEXTENSION.ToLower(); // a valid extension was entered, run EnteredExtension instead } } } // find the entry that matches the name and parameters List <ScriptEntry> entries = (from e in script.Scripts where e.Tag == request select e).ToList(); foreach (ScriptEntry entry in entries) { if (entry.Parms.Count > 0) { // check parms bool valid = true; foreach (ScriptParm parm in entry.Parms) { if (GetForm(parm.Name) != parm.Value) { valid = false; break; } } if (!valid) { continue; } } return(await RunEntryAsync(ivrConfig, script, called, extension, entry, errCount)); } throw new InternalError($"Nothing to execute - tag \"{request}\" for {called}"); } }
private async Task <ActionResult> RunEntryAsync(IVRConfig ivrConfig, ScriptData script, string called, string extension, ScriptEntry entry, int errCount) { string extensionName = null; string extensionSpaced = null; if (!string.IsNullOrWhiteSpace(extension)) { extensionSpaced = Spaced(extension); Extension e = script.FindExtension(extension); if (e != null) { extensionName = e.Name; } } string digits; TryGetForm("Digits", out digits); string actionUrl = Utility.UrlFor(typeof(CallController), nameof(Process)); #if DEBUG actionUrl = Manager.CurrentSite.MakeFullUrl(actionUrl, SecurityType: YetaWF.Core.Pages.PageDefinition.PageSecurityType.Any); #else actionUrl = Manager.CurrentSite.MakeFullUrl(actionUrl, SecurityType: YetaWF.Core.Pages.PageDefinition.PageSecurityType.httpsOnly); #endif string token = DateTime.UtcNow.Ticks.ToString(); string encryptedToken; RSACrypto.Encrypt(ivrConfig.PublicKey, token, out encryptedToken); object parms = new { Url = actionUrl, Caller = GetForm("Caller"), CallerSpaced = Spaced(GetForm("Caller").TruncateStart("+1")), CallerCity = GetForm("CallerCity"), CallerCountry = GetForm("CallerCountry"), Digits = digits, Extension = extension, ExtensionSpaced = extensionSpaced, ExtensionName = extensionName, ErrCount = errCount, ErrCountPlus1 = errCount + 1, Token = encryptedToken, Voice = ivrConfig.Voice, VoiceInternal = ivrConfig.VoiceInternal, }; string text = entry.Text; Variables vars = new Variables(Manager, parms) { EncodingType = Variables.EncodingTypeEnum.XML }; Extension ext = script.FindExtension(digits); if (ext != null) { text = RepeatableNumbers(ext, text); } if (text.Contains("RECORDVOICEMAIL")) { text = text.Replace("RECORDVOICEMAIL", ""); VoiceMailData voiceMail; using (VoiceMailDataProvider voiceMailDP = new VoiceMailDataProvider()) { voiceMail = new VoiceMailData { Caller = GetForm("Caller").Truncate(Globals.MaxPhoneNumber), CallerCity = GetForm("CallerCity").Truncate(VoiceMailData.MaxCity), CallerState = GetForm("CallerState").Truncate(VoiceMailData.MaxState), CallerZip = GetForm("CallerZip").Truncate(VoiceMailData.MaxZip), CallerCountry = GetForm("CallerCountry").Truncate(VoiceMailData.MaxCountry), CallSid = GetForm("CallSid"), RecordingSid = GetForm("RecordingSid"), Duration = ConvertToInt(GetForm("RecordingDuration")), To = called, Extension = extension, RecordingUrl = GetForm("RecordingUrl").Truncate(Globals.MaxUrl) }; if (!await voiceMailDP.AddItemAsync(voiceMail)) { Logging.AddErrorLog($"Couldn't record voice mail status for call from {GetForm("Caller")}"); } } if (!string.IsNullOrWhiteSpace(extension)) { ext = script.FindExtension(extension); if (ext != null) { DisplayVoiceMailModule dispMod = (DisplayVoiceMailModule)await ModuleDefinition.LoadAsync(ModuleDefinition.GetPermanentGuid(typeof(DisplayVoiceMailModule))); ModuleAction displayAction = await dispMod.GetAction_DisplayAsync(null, voiceMail.Id); if (displayAction != null) { string viewUrl = displayAction.GetCompleteUrl(); foreach (ExtensionNumber extNumber in ext.Numbers) { if (extNumber.SendSMSVoiceMail) { SendSMS sendSMS = new SendSMS(); await sendSMS.SendMessageAsync(extNumber.Number, this.__ResStr("voiceSMS", "A voice mail was received for extension {0} ({1}) from {2}, {3}, {4}, {5} {6} - {7}", extension, GetForm("To"), GetForm("Caller"), GetForm("CallerCity"), GetForm("CallerState"), GetForm("CallerZip"), GetForm("CallerCountry"), viewUrl), ThrowError : false); } } } } } } text = vars.ReplaceVariables(text); Logging.AddLog($"{nameof(RunEntryAsync)}: {text}"); return(Content(text, "text/xml")); }