Jump to content

Alexa's Personalized Responses are very cool!


chef

Recommended Posts

I was just messing around with Alexa's personalized responses. Yeah she can figure out who is speaking to her.

 

More information here:

 

https://developer.amazon.com/docs/custom-skills/add-personalized-greetings-or-prompts.html

 

Here is my Alexa response for Emby custom Skill, notice the Person object:

using System;
using System.Collections.Generic;

namespace AlexaController.Alexa
{
    public class AlexaRequest
    {
        public Session session { get; set; }
        public Request request { get; set; }
        public Context context { get; set; }
        public string version { get; set; }
    }

    public class Application
    {
        public string applicationId { get; set; }
    }

    public class Attributes
    {
        public string key { get; set; }
    }

    public class Permissions
    {
        public string consentToken { get; set; }
    }

    public class User
    {
        public string userId { get; set; }
        public string accessToken { get; set; }
        public Permissions permissions { get; set; }
    }

    public class Session
    {
        public bool @[member="new"] { get; set; }
        public string sessionId { get; set; }
        public Application application { get; set; }
        public Attributes attributes { get; set; }
        public User user { get; set; }
    }

    public class AudioPlayer
    {
    }

    public class SupportedInterfaces
    {
        public AudioPlayer AudioPlayer { get; set; }
    }

    public class Device
    {
        public string deviceId { get; set; }
        public SupportedInterfaces supportedInterfaces { get; set; }
    }

    public class Application2
    {
        public string applicationId { get; set; }
    }

    public class Permissions2
    {
        public string consentToken { get; set; }
    }

    public class User2
    {
        public string userId { get; set; }
        public string accessToken { get; set; }
        public Permissions2 permissions { get; set; }
    }

    public class Person //right here
    {
        public string personId { get; set; }
        public string accessToken { get; set; }
    }

    public class System
    {
        public Device device { get; set; }
        public Application2 application { get; set; }
        public User2 user { get; set; }
        public Person person { get; set; }
        public string apiEndpoint { get; set; }
        public string apiAccessToken { get; set; }
    }

    public class AudioPlayer2
    {
        public string playerActivity { get; set; }
        public string token { get; set; }
        public int offsetInMilliseconds { get; set; }
    }

    public class Context
    {
        public System System { get; set; }
        public AudioPlayer2 AudioPlayer { get; set; }
    }

   
    public class Intent
    {
        public string name { get; set; }
        public string confirmationStatus { get; set; }
        public Slots slots { get; set; }
    }

    public class Request
    {
        public string type { get; set; }
        public string requestId { get; set; }
        public DateTime timestamp { get; set; }
        public string locale { get; set; }
        public Intent intent { get; set; }
    }

    public class Slots
    {
        //public slotData MediaName { get; set; }
        public slotData SeriesName { get; set; }
        public slotData Username { get; set; }
        public slotData MusicGroup { get; set; }
        public slotData MusicAlbum { get; set; }
        public slotData MovieNames { get; set; }
        public slotData PlayToDevice { get; set; }
        public slotData DeviceNames { get; set; }
        public slotData DeviceRooms { get; set; }


    }

    public class slotData
    {
        public string name { get; set; }
        public string value { get; set; }
    }


    public class Error
    {
        public string type { get; set; }
        public string message { get; set; }
    }


}




Now in the Emby endpoint:

//Most important parts of this class is the 'person' object, and the Id
// Then using conditions to return '<alexa:name type="first personId="{personId}" />  The first name of the recognized User.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Services;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Entities;
using System.IO;
using AlexaController.Alexa;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Session;
using System.Threading.Tasks;
using System.Text;
using System.Net;
using System.Text.RegularExpressions;
using Person = AlexaController.Alexa.Person;


namespace AlexaController.API
{
    [Route("/Alexa", "POST", Summary = "Alexa End Point")]
    public class AlexaRequest: IRequiresRequestStream
    {
        public Stream RequestStream { get; set; }
    }

    [Route("/Alexa", "GET", Summary = "Alexa End Point")]
    public class Test : IReturnVoid
    {
        public Stream test { get; set; }
    }

    public class AlexaApi : IService
    {
        private readonly ILogger logger;
        //private ITVSeriesManager TvSeriesManager { get; set; }

        private IUserManager UserManager { get; }
        //private IMediaSourceManager MediaSourceManager { get; set; }

        private ILibraryManager LibraryManager { get; }
        //private IHttpClient HttpClient { get; set; }

        private ISessionManager SessionManager { get; }
        
        private IJsonSerializer JsonSerializer { get; }
        private IUserDataManager UserDataManager { get; }

       
        // The media item we want to play
        private static BaseItem RequestedMediaItem;
        
        //Was a playback Request
        private static bool IsPlaybackRequest;
        private static bool ResumeMedia;

        // ReSharper disable once TooManyDependencies
        public AlexaApi(ILibraryManager libraryManager, ISessionManager sessionManager, ILogManager logManager, IUserManager userManager, IJsonSerializer json, IUserDataManager userData)
        {
            logger = logManager.GetLogger(GetType().Name);
            //TvSeriesManager = tvSeriesManager;
            
            //MediaSourceManager = mediaSourceManager;
            SessionManager = sessionManager;
            LibraryManager = libraryManager;
            
            UserManager = userManager;
            //HttpClient = httpClient;
            JsonSerializer = json;
            UserDataManager = userData;

        }

        // ReSharper disable once MethodNameNotMeaningful
        public string Get(Test test)
        {
            return "Hello World Yes you can all see this";
        }
        public object Post(AlexaRequest request)
        {
            //parse json request

            var alexaRequest = JsonSerializer.DeserializeFromStream<Alexa.AlexaRequest>(request.RequestStream);
            
            // ReSharper disable once TooManyChainedReferences
            var person = alexaRequest.context.System.person ?? null; //<--I am a person object that might not return anything for privacy reasons

            logger.Debug("ALEXA HERE");
            var r = alexaRequest.request;

            
            switch (r.type)
            {
                case "IntentRequest":
                    PostDirectiveResponseAsync(alexaRequest); //<--I can post a directive response
                    switch (r.intent.name)
                    {
                        case "AMAZON.NavigateHomeIntent":
                            BrowseHome("family room");
                            return BuildAlexaResponse("OK. Here is the Home Screen");
                        case "ShowCollectionLibrary":
                        {
                            RequestedMediaItem = LibraryManager.GetItemById(GetLibraryId("Collections"));
                            BrowseItemAsync("family room", LibraryManager.GetItemById(GetLibraryId("Collections")));
                            return BuildAlexaResponse("Here is the Collections Library.");
                        }
                        case "ShowTVLibrary":
                        {
                            RequestedMediaItem = LibraryManager.GetItemById(GetLibraryId("TV Shows"));
                            BrowseItemAsync("family room", LibraryManager.GetItemById(GetLibraryId("TV Shows")));
                            return BuildAlexaResponse("Here is the TV Series Library.");
                        }
                        case "ShowMovieLibrary":
                        {
                            RequestedMediaItem = LibraryManager.GetItemById(GetLibraryId("Movies"));
                            BrowseItemAsync("family room", LibraryManager.GetItemById(GetLibraryId("Movies")));
                            return BuildAlexaResponse("Here is the Movie Library.");
                        }
                        case "DeviceChoice":
                        {
                            var str = r.intent.slots.DeviceNames.value ?? r.intent.slots.DeviceRooms.value;
                            if (r.intent.slots.DeviceNames == null) { return " Sorry no device by that name was found"; }
                            //PlayMediaItemAsync(str, RequestedMediaItem.MediaType);

                            return BuildAlexaResponse("OK");
                        }
                        case "NewMovies":
                        {
                            
                            return BuildAlexaResponse(GetNewMovies(), true.ToString(), person);
                        }
                        case "NewTV":
                        {
                         
                            return BuildAlexaResponse(GetNewTvNames());
                        }

                        case "AMAZON.PauseIntent":
                        {
                            return RemoteChangeState(PlaystateCommand.Pause, "family room");
                        }
                        case "AMAZON.ResumeIntent":
                        {
                            return RemoteChangeState(PlaystateCommand.Unpause, "family room");
                        }
                        case "remoteSkip":
                        {
                            return RemoteChangeState(PlaystateCommand.NextTrack, "family room");
                        }
                        case "remotePrevious":
                        {
                            return RemoteChangeState(PlaystateCommand.PreviousTrack, "family room");
                        }
                        case "remoteStop":
                        {
                            return RemoteChangeState(PlaystateCommand.Stop, "family room");
                        }
                        case "AMAZON.NoIntent":
                        {
                            if (!IsPlaybackRequest)
                                return BuildAlexaResponse("I'm not sure what you are saying \"no\" to. Sorry");

                            ResumeMedia = false;
                            IsPlaybackRequest = false;
                                
                            PlayMediaItemAsync("family room", RequestedMediaItem);

                            return BuildAlexaResponse(AlexaOptions.HumanizeAlexa() + " Now playing the " +
                                                      RequestedMediaItem.ProductionYear + " film  <break strength='weak' />" +
                                                      RequestedMediaItem.Name.Replace(":", string.Empty)
                                                          .Replace(",", string.Empty));
                        }
                        case "AMAZON.YesIntent":
                        {
                            if (!IsPlaybackRequest)
                                return BuildAlexaResponse("I'm not sure I understand what you are agreeing to. Sorry");

                            ResumeMedia = true;
                            IsPlaybackRequest = false;
                               
                            PlayMediaItemAsync("family room", RequestedMediaItem);

                            return BuildAlexaResponse(AlexaOptions.HumanizeAlexa() + " Now playing the " +
                                                      RequestedMediaItem.ProductionYear + " " + RequestedMediaItem.MediaType + " <break strength='weak' />" +
                                                      RequestedMediaItem.Name.Replace(":", string.Empty)
                                                          .Replace(",", string.Empty));
                        }
                        case "AMAZON.CancelIntent":
                        case "AMAZON.StopIntent":
                            return BuildAlexaResponse(AlexaOptions.HumanizeAlexa() + "Canceling.");

                        case "PlayMovie":
                        {
                            try
                            {
                                RequestedMediaItem = NarrowResults(r.intent.slots.MovieNames.value, new[] { "Movie" });
                                IsPlaybackRequest = true;
                                if (RequestedMediaItem.SupportsPositionTicksResume)
                                {
                                    return BuildAlexaResponse(RequestedMediaItem.Name + " is bookmarked. " +
                                                              AlexaOptions.AlexaInsertStrengthBreak(AlexaOptions.StrengthBreaks.weak) +
                                                              "Would you like to play the Movie from where you left off?", "false", person);
                                }
                                else
                                {
                                    return BuildAlexaResponse(" in what room would you like to watch " +
                                                              RequestedMediaItem.Name.Replace(":", string.Empty), "false");
                                }
                            }
                            catch (Exception)
                            {
                                return BuildAlexaResponse("Sorry. I couldn't find " + r.intent.slots.MovieNames.value + "  in the library");
                            }

                        }

                        case "BrowseCommand":
                        {
                            
                            //The type of media we want to search for - We'll expect a Movie name to start
                            var type = "Movie";
                            //Amazon will return a Movie slot if it is a movie name
                            var searchName = r.intent.slots.MovieNames.value;
                            
                            //If no Movie Name it must be a series Name
                            if(r.intent.slots.MovieNames.value == null)
                            {
                                searchName = r.intent.slots.SeriesName.value;
                                type = "Series";
                            }
                            try
                            {
                                var result = NarrowResults(searchName, new[] { type });

                                if (result != null)
                                {
                                    RequestedMediaItem = result;
                                    IsPlaybackRequest = false;

                                    BrowseItemAsync("family room", result);

                                    string overview = "";
                                    string rating = "";
                                    float? criticRating;
                                    overview = RequestedMediaItem.Overview;
                                    rating = RequestedMediaItem.OfficialRating;
                                    criticRating = RequestedMediaItem.CriticRating;

                                    return BuildAlexaResponse(" Here is the details for " +
                                                              RequestedMediaItem.Name.Replace(":", string.Empty) + ". " +
                                                              AlexaOptions.AlexaInsertStrengthBreak(AlexaOptions.StrengthBreaks.weak) +
                                                              "Rated " + rating + "." + AlexaOptions.AlexaInsertStrengthBreak(AlexaOptions.StrengthBreaks.strong) +
                                                              CalculateCriticRatings(criticRating), true.ToString(), person);
                                }
                            }
                            catch (Exception)
                            {
                                return BuildAlexaResponse("Sorry. I couldn't find " + searchName + "  in the library");
                            }
                            return BuildAlexaResponse("Sorry. I couldn't find " + searchName + "  in the library");
                        }
                   
                        default:
                            return BuildAlexaResponse("no intent found");
                    }

                case "SessionEndedRequest":
                    //Session End Request
                    //No response message is allowed
                    return null;
                case "LaunchRequest":
                    return BuildAlexaResponse("Welcome");
                    //Not an Intent
                    
                default:
                    return BuildAlexaResponse("Unknown");
            }
        }

        private string GetLibraryId(string type)
        {
            var results = LibraryManager.GetVirtualFolders();
            foreach(var item in results)
            {
                if(item.Name == type)
                {
                    return item.ItemId;
                }
            }
            return string.Empty;
        }

        private string GetNewMovies()
        {
            const string user = "Admin";
            var results = LibraryManager.GetItemIds(new InternalItemsQuery
            {
                IncludeItemTypes = new[] { "Movie" },
                IsPlayed = false,
                User = UserManager.GetUserByName(user.AsSpan())
                
            });

            string alexaSpeechString = string.Empty;

            var listOfNewMovies = new List<BaseItem>();
            
            results.ToList().ForEach(item => {
                var itemInfo = LibraryManager.GetItemById(item);
                if (itemInfo.DateCreated >= DateTime.Now.AddDays(-25))
                {
                    listOfNewMovies.Add(itemInfo);
                }
            });
            
            //If the movie is the last name in the list, let Alexa say "and also". She sounds more human.
            int movieCount = 0;
            foreach (var movie in listOfNewMovies)
            {
                if (movieCount == listOfNewMovies.Count - 1)
                {
                    alexaSpeechString += " and also <break strength='weak' /> ";
                }
                alexaSpeechString += movie.Name.Replace(":", string.Empty).Replace("&", "and")  + "<break strength='weak' />. "; //She doesn't like '&' and ':' in strings
                movieCount += 1;
            }

            return "Here are <say-as interpret-as='cardinal'>" + movieCount +
                "</say-as> of the newest movies available in the library <break strength='weak' />" + alexaSpeechString;
        }

        private string GetNewTvNames()
        {
            var results = LibraryManager.GetItemIds(new InternalItemsQuery { IncludeItemTypes = new[] { "Episode" } });
            string str1 = string.Empty;
            string complete;
            int tvCount = 0;

            var listOfNewTv = new List<string>();
            results.ToList().ForEach(item => {
                var itemInfo = LibraryManager.GetItemById(item);
                if (itemInfo.DateCreated >= DateTime.Now.AddDays(-20))
                {
                    listOfNewTv.Add(itemInfo.Parent.Parent.Name); //That would be the Series Name
                }
            });

            if (listOfNewTv.Count == 0)
            {
                complete = "There are no new unwatched episodes";
            }
            else
            {
                var distinctTvSeries = listOfNewTv.Distinct().ToList();
                foreach (var name in distinctTvSeries)
                {
                    //If the tv is the last name in the list, let Alexa say "and also". She sounds more human.
                    if (tvCount == distinctTvSeries.Count - 1)
                    {
                        str1 += " and also <break strength='weak' />";
                    }
                    str1 += name.Replace(":", string.Empty).Replace("&", "and") + "<break strength='weak' />";
                    tvCount += 1;
                }


                complete = "There are <say-as interpret-as='cardinal'>" + listOfNewTv.Distinct().ToList().Count +
                       "</say-as> new episodes available in the library <break strength='weak' />" +
                       "including episodes from  <break strength='weak' />" + str1;
            }
            return complete;
        }

        private string GetDeviceIdFromName(string deviceName)
        {
            if (deviceName.ToLower().Contains("family room") || deviceName.ToLower().Contains("front room"))
            {
                deviceName = "Family Room Fire TV Stick";
            }
            else if (deviceName.ToLower().Contains("back room") || deviceName.ToLower().Contains("kids"))
            {
                deviceName = "Kids TV";
            }
            else if (deviceName.ToLower().Contains("bedroom") || deviceName.ToLower().Contains("upstairs"))
            {
                deviceName = "Chromecast0862";
            }
            else if (deviceName.ToLower().Contains("theater") || deviceName.ToLower().Contains("movie theater"))
            {
                deviceName = "CastP6";
            }

            foreach (var session in SessionManager.Sessions)
            {
                //If it is a browse request then we'll have have to use an emby app with a UI display to show the details
                //example: Emby Theater


                if (session.Client.ToLower().Contains("androidtv") && deviceName == "Family Room Fire TV Stick")
                {
                    return session.DeviceId;
                }

                if (session.DeviceName.ToLower().Contains(deviceName.ToLower()))
                {
                    return session.DeviceId;
                }
                if (session.Client.ToLower().Contains(deviceName.ToLower()))
                {
                    return session.DeviceId;
                }


            }
            return string.Empty;
        }

        private SessionInfo GetSession(string deviceId)
        {
            //logger.Info("Looking for sessions for device " + deviceId);
            var r = SessionManager.Sessions.Where(i => i.DeviceId == deviceId); // "db464421188f5622f73acab7252660facbd63078");
            var sessionInfos = r.ToList();
            logger.Info("Found {0} sessions for device {1}", sessionInfos.Count().ToString(), deviceId);
            return sessionInfos.FirstOrDefault();
        }

        private void BrowseHome(string device)
        {
            var d = GetDeviceIdFromName(device);
            var user = "Admin";
            var s = GetSession(d);
            
            //DO NOT AWAIT THIS! ALEXA HATES YOU FOR IT
            SessionManager.SendGeneralCommand(null, s.Id, new GeneralCommand()
            {
                Name = "GoHome",
                
                ControllingUserId = UserManager.GetUserByName(user.AsSpan()).Id.ToString(),
                
            },
                CancellationToken.None);

        }

        private void BrowseItemAsync(string device, BaseItem request)
        {
            try
            {
                var d = GetDeviceIdFromName(device);

                var s = GetSession(d);
                ////DO NOT AWAIT THIS! ALEXA HATES YOU FOR IT
                //SessionManager.SendGeneralCommand(null, s.Id, new GeneralCommand()
                //{
                //    Name = "GoHome",
                //    ControllingUserId = UserManager.GetUserByName("Admin").Id.ToString()
                //},
                //    CancellationToken.None);

                Task.Delay(1500).Wait();

                SessionManager.SendBrowseCommand(null, s.Id, new BrowseRequest()
                {
                    ItemId = request.Id.ToString(),
                    ItemName = request.Name,
                    ItemType = request.MediaType
                }, CancellationToken.None);

            }
            catch
            {
                BuildAlexaResponse("I'm sorry. I'm unable to show details for " + RequestedMediaItem.Name.Replace(":", string.Empty) + " in the family room because the theater is not currently running.");

            }
        }

        private async void PlayMediaItemAsync(string device, BaseItem request)
        {
            var s = GetSession(GetDeviceIdFromName(device));

            if (s == null) return;// "I'm sorry the " + device + " device is currently unavailable."; 

            long startTicks = 0;
            var user = "Admin";
            if (ResumeMedia)
            {
                startTicks = UserDataManager.GetUserData(UserManager.GetUserByName(user.AsSpan()).Id.ToString(), RequestedMediaItem).PlaybackPositionTicks;
            }
            SessionManager.SendPlayCommand(null, s.Id, new PlayRequest
            {
                StartPositionTicks = startTicks,
                PlayCommand = PlayCommand.PlayNow,
                ItemIds = new[] { request.InternalId },
                ControllingUserId = UserManager.GetUserByName(user.AsSpan()).Id.ToString()
                
            }, CancellationToken.None);
            
           
        }

        private async Task<string> RemoteChangeState(PlaystateCommand psCmd, string device)
        {
            var d = GetDeviceIdFromName(device);
            
            var s = GetSession(d);
            var user = "Admin";
            if (s == null) { return "device is not setup or is unavailable"; }
            var command = new PlaystateRequest()
            {
                Command = psCmd,
                ControllingUserId = UserManager.GetUserByName(user.AsSpan()).Id.ToString()
            };
            try
            {   //DO NOT AWAIT THIS! ALEXA HATES YOU FOR IT
                SessionManager.SendPlaystateCommand(null, s.Id, command, new CancellationToken(false));
            } catch
            {

            }
            return BuildAlexaResponse("ok");
        }

        public string GetSeriesId(string seriesName)
        {
            var r = LibraryManager.GetItemIds(new InternalItemsQuery {
                IncludeItemTypes = new[] { "Series" },
                Name = seriesName
            });
            return r.Any() ? r.FirstOrDefault().ToString() : "";
        }

        
        //Actual Response
        private string BuildAlexaResponse(string text, string sessionEnd = "true", Person person = null)
        {
            var jsonString = "{\"version\": \"1.0\",\"response\": {\"outputSpeech\": {\"type\": \"SSML\",\"ssml\": ";
            jsonString += "\"<speak>";
            jsonString += AlexaOptions.HumanizeAlexa();
          
            // ReSharper disable ComplexConditionExpression
            jsonString += person != null ? " <alexa:name type='first' personId='" + person.personId + "'/> " : " ";
            jsonString += AlexaOptions.AlexaInsertStrengthBreak(AlexaOptions.StrengthBreaks.strong);
            jsonString += " ";
            jsonString += text;
            jsonString += "</speak>\" }, \"shouldEndSession\": ";
            jsonString += sessionEnd + "},\"sessionAttributes\": { } }";
            logger.Log(LogSeverity.Debug, jsonString);
            return jsonString; 
        }


        private void PostDirectiveResponseAsync(Alexa.AlexaRequest alexaRequest)
        {
            //const string uri = "https://api.amazonalexa.com/v1/directives";


            var res = new DirectiveResponse
            {
                header = new Header { requestId = alexaRequest.request.requestId },
                directive = new Directive
                {
                    type = "VoicePlayer.Speak",
                    speech = "<speak>" + AlexaOptions.HumanizeAlexa() + "Accessing Media Server." +
                             AlexaOptions.AlexaInsertStrengthBreak(AlexaOptions.StrengthBreaks.weak) + " One moment please." +
                             "<audio src='https://s3.amazonaws.com/ask-soundlibrary/scifi/amzn_sfx_scifi_radar_high_ping_01.mp3'/></speak>"
                }
            };



            string json = JsonSerializer.SerializeToString(res);

            //Encode the JSON string into a byte array
            byte[] data = Encoding.ASCII.GetBytes(json);
            //Where we will send the info and how: POST
            var request = (HttpWebRequest)WebRequest.Create("https://api.amazonalexa.com/v1/directives");
            request.Method = "POST";
            request.ContentType = "application/json";
            request.Headers["Authorization"] = "Bearer " + alexaRequest.context.System.apiAccessToken;
            request.ContentLength = data.Length;
            //Write the data to amazon
            using (var stream = request.GetRequestStream())
            {
                stream.Write(data, 0, data.Length);
            }

        }

        private static string CalculateCriticRatings(float? percent)
        {
           
            if (percent <= 25.0F)
            { 
                return "This film didn't get great reviews.";
            } else if (percent <= 50.0F)
            {
                return "This film has got some fair reviews.";
            } else if (percent <= 75.0F)
            {
                return "This film has got some decent reviews.";
            } else if (percent <= 90.0F)
            {
                return "This film has got some good reviews.";
            } else if (percent <= 100.0F)
            {
                return "This film has got great reviews.";
            }
            return "";
        }

        //Narrow multiple Search Results From Emby
        private BaseItem NarrowResults(string searchName, string[] type)
        {
            
            var result = LibraryManager.GetItemIds(new InternalItemsQuery
            {
                Name = searchName,
                IncludeItemTypes = type,
                
            });

                     

            if (!result.Any())
            {
                var queryResult = LibraryManager.QueryItems(new InternalItemsQuery()
                {
                    IncludeItemTypes = type,
                    NameStartsWith = ReturnStartWithString(searchName)
                });

                return queryResult.Items.FirstOrDefault(r => RemoveSpecialCharacters(r.Name).Contains(RemoveSpecialCharacters(searchName)));
            }

            if (!result.Any())
            {
                var queryResult = LibraryManager.QueryItems(new InternalItemsQuery()
                {
                    IncludeItemTypes = type,
                    SearchTerm = ReturnStartWithString(searchName)
                });

                return queryResult.Items.FirstOrDefault(r => RemoveSpecialCharacters(r.Name).Contains(RemoveSpecialCharacters(searchName)));
            }

            return LibraryManager.GetItemById(result.FirstOrDefault());
        }


        private static string ReturnStartWithString(string name)
        {
            try
            {
                name = name[0].ToString();
            }
            catch { }
            return name;
        }

        private static string RemoveSpecialCharacters(string sample)
        {
            var result = sample.Replace("-", string.Empty)
                .Replace("&", string.Empty)
                .Replace(":", string.Empty)
                .Replace(Regex.Match(sample, "/(([0-9][0-9][0-9][0-9])/)").Groups[0].ToString(), string.Empty)
                .Replace("1", "one");
            return result.Replace(" ", string.Empty).ToLower();
        }
       
    }




}




Now use the home brew Alexa Options class to give her random response from a dictionary:

using System.Collections.Generic;

namespace AlexaController.Alexa
{
    class AlexaOptions
    {
        public static Dictionary<int, string> humanSpeechLibrarySpoiler = new Dictionary<int, string>
            {
                {
                    1,
                     AlexaExpressiveInterjection("Spoiler Alert. ")
                },
                {
                    2,
                     AlexaOptions.AlexaExpressiveInterjection("Watch out.") +
                     AlexaOptions.AlexaInsertStrengthBreak(StrengthBreaks.weak) +
                     AlexaOptions.AlexaExpressiveInterjection("Spoilers!!")
                },
                {
                    3,
                     "Hope this doesn't spoil it for you. " +
                     AlexaInsertStrengthBreak(StrengthBreaks.weak)
                },

                {
                    4,
                     "I don't want to spoil it for you. " +
                     AlexaInsertStrengthBreak(StrengthBreaks.weak)
                },

                {
                    5,
                     AlexaSayWithEffect(Effect.whispered, "I don't want to spoil it for you.") +
                     AlexaInsertStrengthBreak(StrengthBreaks.weak) + " But, here is the overview." +
                     AlexaInsertStrengthBreak(StrengthBreaks.weak)
                }
            };

        // ReSharper disable once ComplexConditionExpression
        public static Dictionary<int, string> humanSpeechLibraryAgree = new Dictionary<int, string>
        {
            { 1, AlexaEmphasis(" alright ", Emphasis.reduced) },

            { 2, AlexaEmphasis(" Very well ", Emphasis.reduced) },

            { 3, AlexaEmphasis(" sounds good ", Emphasis.reduced) },

            { 4, AlexaExpressiveInterjection(" sure ") + AlexaInsertStrengthBreak(StrengthBreaks.weak) },

            { 5, AlexaExpressiveInterjection(" yeah ") + AlexaInsertStrengthBreak(StrengthBreaks.weak) },

            { 6, AlexaExpressiveInterjection(" OK ") + AlexaInsertStrengthBreak(StrengthBreaks.weak) },

            { 7, AlexaExpressiveInterjection(" you bet ") + AlexaInsertStrengthBreak(StrengthBreaks.weak) }
        };

        public static string HumanizeAlexaSpoiler()
        {
            int rInt = Plugin.r.Next(1, 5);
            return humanSpeechLibrarySpoiler[rInt];
        }

        private static int tempHumanSpeechChoices = 1;
        public static string HumanizeAlexa()
        {
            int rInt = Plugin.r.Next(1, 7);
            while (tempHumanSpeechChoices == rInt)
            {
                rInt = Plugin.r.Next(1, 7);
            }
            tempHumanSpeechChoices = rInt;

            return humanSpeechLibraryAgree[rInt];
        }


        public enum StrengthBreaks
        {
            weak = 0,
            medium = 1,
            strong = 2
        }

        public enum Emphasis
        {
            /// <summary>
            /// Decrease the volume and speed up the speaking rate. The speech is softer and faster.
            /// </summary>
            reduced = 0,

            /// <summary>
            ///  Increase the volume and slow down the speaking rate so the speech is louder and slower.
            /// </summary>
            strong = 1,

            /// <summary>
            /// Increase the volume and slow down the speaking rate, but not as much as when set to strong. This is used as a default if level is not provided.
            /// </summary>
            moderate = 2
        }

        public enum Rate
        {
            slow = 0,
            medium = 1,
            fast = 2
        }

        public enum Effect
        {
            whispered = 0
        }


        public static string AlexaSayWithEffect(Effect effect, string text)
        {
            return "<amazon:effect name='" + effect + "'>" + text + "</amazon:effect>";
        }

        public static string AlexaSayAsCardinal(string text)
        {
            return "<say-as interpret-as='cardinal'>" + text + "</say-as>";
        }

        public static string AlexaSpellOut(string text)
        {
            return "<say-as interpret-as='spell-out'>" + text + "</say-as>.";
        }

        public static string AlexaInsertTimedBreak(string intDurationSeconds)
        {

            return "<break time='" + intDurationSeconds + "s'/>";
        }

        public static string AlexaInsertStrengthBreak(StrengthBreaks strength)
        {

            return "<break strength='" + strength + "'/>";
        }

        public static string AlexaEmphasis(string text, Emphasis emphasis)
        {
            return "<emphasis level='" + emphasis + "'>" + text + "</emphasis>";
        }

        public static string AlexaSpeechRate(Rate rate, string text)
        {
            return ("<prosody rate='" + rate + "'>" + rate + "</prosody>");
        }

        public static string AlexaExpressiveInterjection(string text)
        {
            return "<say-as interpret-as='interjection'>" + text + "</say-as>";
        }
    }
}

Now she reply's in a very human and personal way.

 

 

It's super cool guys!  :D 

  • Like 2
Link to comment
Share on other sites

  • 4 months later...
  • 3 weeks later...
  • 4 weeks later...
BillOatman

But, not allowing your son to watch Deadpool is child abuse!  Deadpool 2 not so much ;)

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...