chef 3744 Posted May 26, 2018 Share Posted May 26, 2018 (edited) It is still in an infant form, but there isn't a whole lot of wrappers out there for a c# application and I got bored. I share this with the emby community because it's my favorite. using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Text; using AlexaCognitiveSenseApi.log; using Newtonsoft.Json.Linq; namespace AlexaCognitiveSenseApi.Api.Amazon { /// <summary> /// C# wrapper for AlexaApi Custom Skills /// </summary> public class AlexaApi { public enum Effect { // ReSharper disable once InconsistentNaming whispered = 0 } public enum Emphasis { // ReSharper disable once InconsistentNaming /// <summary> /// Decrease the volume and speed up the speaking rate. The speech is softer and faster. /// </summary> reduced = 0, // ReSharper disable once InconsistentNaming /// <summary> /// Increase the volume and slow down the speaking rate so the speech is louder and slower. /// </summary> strong = 1, // ReSharper disable once InconsistentNaming /// <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 { // ReSharper disable once InconsistentNaming slow = 0, // ReSharper disable once InconsistentNaming medium = 1, // ReSharper disable once InconsistentNaming fast = 2 } public enum StrengthBreaks { // ReSharper disable once InconsistentNaming weak = 0, // ReSharper disable once InconsistentNaming medium = 1, // ReSharper disable once InconsistentNaming strong = 2 } // ReSharper disable once InconsistentNaming //Random used to choose a list item. private static readonly Random random = new Random(); public class HumanizeResponses { public static readonly List<string> Apologetic = new List<string> { "Sorry" + AlexaInsertStrengthBreak(StrengthBreaks.weak), "I'm sorry" + AlexaInsertStrengthBreak(StrengthBreaks.weak), "Ever so sorry" + AlexaInsertStrengthBreak(StrengthBreaks.weak), "I apologize" + AlexaInsertStrengthBreak(StrengthBreaks.weak) }; public static readonly List<string> Compliances = new List<string> { "OK" + AlexaInsertStrengthBreak(StrengthBreaks.weak), "Alright" + AlexaInsertStrengthBreak(StrengthBreaks.weak), "On it!" + AlexaInsertStrengthBreak(StrengthBreaks.weak), "I'll get on that right away" + AlexaInsertStrengthBreak(StrengthBreaks.weak), "Sure thing!" + AlexaInsertStrengthBreak(StrengthBreaks.weak), "I'll do it" + AlexaInsertStrengthBreak(StrengthBreaks.weak) + " sure thing" + AlexaInsertStrengthBreak(StrengthBreaks.weak), "Looking into it now" + AlexaInsertStrengthBreak(StrengthBreaks.weak) }; } /// <summary> /// This request is sent to Amazon to allow for the Alexa device to speak before the custom skill returns its information /// </summary> /// <param name="token"></param> /// <param name="requestId"></param> public static void DirectiveResponseBuilder(string token, string requestId) { //Our Directive POST info var res = new DirectiveResponse { header = new DirectiveResponse.Header {requestId = requestId}, directive = new DirectiveResponse.Directive { type = "VoicePlayer.Speak", speech = "<speak>" + GetHumanizeResponse(HumanizedResponseType.compliance) + "Searching Security Feed" + AlexaInsertStrengthBreak(StrengthBreaks.weak) + " One moment please." + "<audio src='https://s3.amazonaws.com/ask-soundlibrary/scifi/amzn_sfx_scifi_radar_high_ping_01.mp3'/></speak>" } }; //Serialize the C# class itno a Json string string json = new NewtonsoftJsonSerializer().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.Add("Authorization", "Bearer " + token); request.ContentLength = data.Length; //Write the data to amazon using (Stream stream = request.GetRequestStream()) { stream.Write(data, 0, data.Length); } //Doesn't matter about the response, either AlexaApi spoke or it didn't //This is the response for debugging var response = (HttpWebResponse) request.GetResponse(); // ReSharper disable once AssignNullToNotNullAttribute string responseString = new StreamReader(response.GetResponseStream()).ReadToEnd(); Logger.LogInfo(Logger.LogType.Info, responseString); } /// <summary> /// The response to the Custom Skill Alexa will speak back to the user. /// </summary> /// <param name="text"></param> /// <param name="sessionEnd"></param> /// <param name="displayCard"></param> /// <returns></returns> public object ResponseBuilder(string text, bool sessionEnd = true, Card displayCard = null) { var res = new AlexaResponse { version = "1.0", response = new Response { outputSpeech = new OutputSpeech { type = "SSML", ssml = "<speak>" + text + "</speak>" }, shouldEndSession = sessionEnd, card = displayCard } }; //Serialize the AlexaApi into a JSON string string json = new NewtonsoftJsonSerializer().SerializeToString(res); //Convert the JSON string to an actual JSON Object return JObject.Parse(json); } public static Card CardBuilder(Image imageUrl, string content, string title, string text, string type = "Standard") { return new Card {content = content, image = imageUrl, text = text, title = title, type = type}; } // ReSharper disable InconsistentNaming // ReSharper disable ClassNeverInstantiated.Local public static string AlexaSayWithEffect(Effect effect, string text) { return string.Format("<amazon:effect name=\"{0}\">{1}</amazon:effect>", effect, text); } public static string AlexaSayAsCardinal(string text) { return string.Format("<say-as interpret-as=\"cardinal\">{0}</say-as>", text); } public static string AlexaSpellOut(string text) { return string.Format("<say-as interpret-as=\"spell-out\">" + text + "</say-as>."); } public static string AlexaInsertTimedBreak(string intDurationSeconds) { return string.Format("<break time=\"{0}s\"/>", intDurationSeconds); } public static string AlexaInsertStrengthBreak(StrengthBreaks strength) { return string.Format("<break strength=\"{0}\"/>", strength); } public static string AlexaEmphasis(string text, Emphasis emphasis) { return string.Format("<emphasis level=\"{0}\">{1}</emphasis>", emphasis, text); } public static string AlexaSpeechRate(Rate rate, string text) { return string.Format("<prosody rate=\"{0}\">{1}</prosody>", rate, text); } public static string AlexaExpressiveInterjection(string text) { return string.Format("<say-as interpret-as=\"interjection\">{0}</say-as>", text); } public enum HumanizedResponseType { apologetic = 0, compliance = 1, } public static string GetHumanizeResponse(HumanizedResponseType type) { switch (type.ToString()) { case "compliance": return HumanizeResponses.Compliances[random.Next(0, HumanizeResponses.Compliances.Count)]; case "apologetic": return HumanizeResponses.Apologetic[random.Next(0, HumanizeResponses.Apologetic.Count)]; } return string.Empty; } [Serializable] private class AlexaResponse { /// <summary> /// Manditory /// </summary> // ReSharper disable once UnusedAutoPropertyAccessor.Local public string version { get; set; } /// <summary> /// Not Manditory /// </summary> // ReSharper disable once UnusedMember.Local public SessionAttributes sessionAttributes { get; set; } /// <summary> /// Manditory /// </summary> // ReSharper disable once UnusedAutoPropertyAccessor.Local public Response response { get; set; } } [Serializable] public class Card { public string type { get; set; } public string title { get; set; } public string content { get; set; } public string text { get; set; } public Image image { get; set; } } [Serializable] public class Directive { public string type { get; set; } public string speech { get; set; } } [Serializable] public class Image { public string smallImageUrl { get; set; } public string largeImageUrl { get; set; } } [Serializable] internal class OutputSpeech { public string type { get; set; } public string text { get; set; } public string ssml { get; set; } } [Serializable] internal class OutputSpeech2 { public string type { get; set; } public string text { get; set; } public string ssml { get; set; } } [Serializable] internal class Reprompt { public OutputSpeech2 outputSpeech { get; set; } } [Serializable] internal class Response { public OutputSpeech outputSpeech { get; set; } public Card card { get; set; } public Reprompt reprompt { get; set; } public List<Directive> directives { get; set; } public bool shouldEndSession { get; set; } } [Serializable] internal abstract class SessionAttributes { public string key { get; set; } } } public class DirectiveResponse { public Header header { get; set; } public Directive directive { get; set; } public class Directive { public string type { get; set; } public string speech { get; set; } } public class Header { public string requestId { get; set; } } } } There are some cool extras in this wrapper as well: All the speech emphasis types are usable through their own enumerations, and there is an editable list of possible response builder options using types like: 1. Compliances 2. Apologetics This makes Alexa create its own random sentences. It also uses Directives, so Alexa will respond to the user right away, while the custom skill is gathering information in the background prior to the Skills final response. It might be useful. Dunno... I'm using it for my security camera web service, so some of the code needs to be slightly edited for your own use. - Ben Edited May 26, 2018 by chef 1 Link to comment Share on other sites More sharing options...
Angelblue05 4130 Posted May 27, 2018 Share Posted May 27, 2018 Nice Chef. Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now