Example #1
0
        public async Task SetupClient()
        {
            if (!Initialized)
            {
                TwilioData config = await TwilioConfigDataProvider.GetConfigAsync();

                if (!config.IsConfigured())
                {
                    throw new Error(this.__ResStr("notConfigured", "Twilio is not configured."));
                }
                string acctSid = null, acctToken = null;
                if (config.TestMode)
                {
                    acctSid   = config.TestAccountSid;
                    acctToken = config.TestAuthToken;
                }
                else
                {
                    acctSid   = config.LiveAccountSid;
                    acctToken = config.LiveAuthToken;
                }
                TwilioClient.Init(acctSid, acctToken);
                Initialized = true;
            }
        }
        public void Post([FromBody] TwilioData data)
        {
            var body = data.Body;

            if (string.IsNullOrEmpty(body))
            {
                return;
            }

            body = body.ToLower();
            if (!body.Contains("play"))
            {
                return;
            }

            body = body
                   .Replace("play", "")
                   .ToLower()
                   .Trim();

            var videoKey = ConfigurationManager.AppSettings[body];

            if (string.IsNullOrEmpty(videoKey))
            {
                return;
            }

            //TODO: Figure out the correct way to do this logic
            var temp  = char.ToUpper(body[0]);
            var array = body.ToCharArray();

            array[0] = temp;

            Clients.All.deliverMessage(data.From, new { Title = new string(array), Key = videoKey });
        }
Example #3
0
 public void UpdateData(TwilioData data)
 {
     LiveAccountSid = data.LiveAccountSid;
     LiveAuthToken  = data.LiveAuthToken;
     TestAccountSid = data.TestAccountSid;
     TestAuthToken  = data.TestAuthToken;
 }
Example #4
0
        /// <summary>
        /// Returns whether the SMS provider is in test mode.
        /// </summary>
        /// <returns>True if it is in test mode, false otherwise.</returns>
        public async Task <bool> IsTestModeAsync()
        {
            if (!await IsAvailableAsync())
            {
                throw new InternalError("SMS processing not available");
            }
            TwilioData config = await TwilioConfigDataProvider.GetConfigAsync();

            return(config.TestMode);
        }
Example #5
0
        public async Task SendSMSAsync(string toNumber, string text, string FromNumber)
        {
            TwilioData config = await TwilioConfigDataProvider.GetConfigAsync();

            string accountSid = config.TestMode ? config.TestAccountSid : config.LiveAccountSid;
            string authToken  = config.TestMode ? config.TestAuthToken : config.LiveAuthToken;
            string fromNumber = config.TestMode ? config.TestSMSNumber : config.LiveSMSNumber;

            if (!string.IsNullOrWhiteSpace(FromNumber))
            {
                fromNumber = FromNumber;
            }
            fromNumber = PhoneNumberNationalAttribute.GetE164(fromNumber);
            if (fromNumber == null)
            {
                throw new InternalError($"Invalid fromNumber {fromNumber} - {nameof(SendSMSAsync)}");
            }
            toNumber = PhoneNumberNationalAttribute.GetE164(toNumber);
            if (toNumber == null)
            {
                throw new InternalError($"Invalid toNumber {toNumber} - {nameof(SendSMSAsync)}");
            }
            string callbackUrl = null;

            if (config.DeliveryReceipts)
            {
                callbackUrl = YetaWFManager.Manager.CurrentSite.MakeUrl(
                    Utility.UrlFor(typeof(TwilioResponseController), nameof(TwilioResponseController.Response), new { ValidateToNumber = toNumber }),
                    PagePageSecurity: config.UseHttps?YetaWF.Core.Pages.PageDefinition.PageSecurityType.httpsOnly: YetaWF.Core.Pages.PageDefinition.PageSecurityType.httpOnly
                    );
            }

            TwilioClient.Init(accountSid, authToken);
            MessageResource m = MessageResource.Create(
                from: fromNumber, // From number, must be an SMS-enabled Twilio number
                to: toNumber,
                body: text,
                statusCallback: callbackUrl != null ? new Uri(callbackUrl) : null
                );

            if (m.ErrorCode != null)
            {
                Logging.AddErrorLog("TwilioProcessor SendSMS failed: {0} {1} - {2} - {3}", fromNumber, toNumber, m.ErrorCode, m.ErrorMessage);
            }
            else
            {
                Logging.AddLog("TwilioProcessor SendSMS queued: {0} {1}", fromNumber, toNumber);
            }
        }
Example #6
0
        public async Task <ActionResult> TwilioConfig()
        {
            using (TwilioConfigDataProvider dataProvider = new TwilioConfigDataProvider()) {
                Model model     = new Model {
                };
                TwilioData data = await dataProvider.GetItemAsync();

                if (data == null)
                {
                    throw new Error(this.__ResStr("notFound", "The TwilioProcessor settings could not be found"));
                }
                model.SetData(data);
                model.UpdateData(data);
                return(View(model));
            }
        }
Example #7
0
        public async Task <ActionResult> TwilioConfig_Partial(Model model)
        {
            using (TwilioConfigDataProvider configDP = new TwilioConfigDataProvider()) {
                TwilioData 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);

                return(FormProcessed(model, this.__ResStr("okSaved", "TwilioProcessor settings saved"), NextPage: Manager.ReturnToUrl));
            }
        }
Example #8
0
 public void SetData(TwilioData data)
 {
     ObjectSupport.CopyData(data, this);
 }
Example #9
0
 public TwilioData GetData(TwilioData data)
 {
     ObjectSupport.CopyData(this, data);
     return(data);
 }
Example #10
0
        /// <summary>
        /// Returns whether the SMS provider is available.
        /// </summary>
        /// <returns>True if it is available, false otherwise.</returns>
        public async Task <bool> IsAvailableAsync()
        {
            TwilioData twilioConfig = await TwilioConfigDataProvider.GetConfigCondAsync();

            return(twilioConfig != null && twilioConfig.IsSMSConfigured());
        }
Example #11
0
        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}");
            }
        }