public async Task <ActionResult> SMSTest_Partial(Model model) { if (!ModelState.IsValid) { return(PartialView(model)); } SendSMS sendSMS = new SendSMS(); await sendSMS.SendMessageAsync(model.PhoneNumber, model.Text); return(FormProcessed(model, this.__ResStr("ok", "SMS sent"))); }
/// <summary> /// Processes all URLs at the specified interval and sends SMS notifications if a site is found down (or back up). /// </summary> /// <returns></returns> public async Task Process() { bool[] LastFailures = new bool[Settings.URLs.Count]; for (int i = 0; i < LastFailures.Length; ++i) { LastFailures[i] = false; } for (;;) { bool[] failures = new bool[Settings.URLs.Count]; int index = 0; foreach (string page in Settings.URLs) { string site = page.TruncateStart("http://").TruncateStart("https://"); failures[index] = false; string msg = null; int status = RetrievePage(page); if (status != 200) { failures[index] = true; if (LastFailures[index] != failures[index]) { msg = $"Site {site} is DOWN!"; } } else { failures[index] = false; if (LastFailures[index] != failures[index]) { msg = $"Site {site} is back UP"; } } LastFailures[index] = failures[index]; index++; if (!string.IsNullOrWhiteSpace(msg)) { Console.WriteLine(msg); SendSMS sendSMS = new SendSMS(); foreach (string smsNotify in Settings.SMSNotify) { await sendSMS.SendMessageAsync(smsNotify, msg); } } } Thread.Sleep(Settings.Interval * 1000); } }
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")); }