Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Utility / helpers naming #216

Merged
merged 1 commit into from
Mar 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
using Alexa.NET.Request.Type;
using Alexa.NET.Response;
using Bot.Builder.Community.Adapters.Alexa.Core.Attachments;
using Bot.Builder.Community.Adapters.Alexa.Core.Utility;
using Bot.Builder.Community.Adapters.Alexa.Core.Helpers;
using Microsoft.Bot.Schema;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,53 +1,53 @@
using System;
using Microsoft.MarkedNet;
namespace Bot.Builder.Community.Adapters.Alexa.Core.Utility
{
/// <summary>
/// Simple Markdown renderer to turn markdown into plain text for Alexa.
/// </summary>
public static class AlexaMarkdownToPlaintextRenderer
{
private static readonly Marked _marked = new Marked(new Options { Renderer = new RemoveMarkupRenderer() });
public static string Render(string source) => _marked.Parse(source);
private class RemoveMarkupRenderer : MarkdownRenderer
{
private const string ListItemMarker = "$$ListItemMarker$$";
public override string Blockquote(string quote) => string.Concat(quote, ". ");
public override string Br() => ". ";
public override string Code(string code, string lang, bool escaped) => code;
public override string Codespan(string text) => text;
public override string Del(string text) => text;
public override string Em(string text) => text;
public override string Heading(string text, int level, string raw) => string.Concat(text, ". ");
public override string Hr() => ". ";
public override string Html(string html) => string.Empty;
public override string Image(string href, string title, string text) => title ?? text;
public override string Link(string href, string title, string text) => $"{title ?? text} {href}";
public override string List(string body, bool ordered, int start)
{
if (ordered)
{
for (int marker = start, markerIndex = body.IndexOf(ListItemMarker); markerIndex >= 0; markerIndex = body.IndexOf(ListItemMarker), ++marker)
{
body = body.Substring(0, markerIndex) + marker + ". " + body.Substring(markerIndex + ListItemMarker.Length);
}
}
else
{
body = body.Replace(ListItemMarker, string.Empty);
}
return $"{body.Trim().TrimEnd(',')}. ";
}
public override string ListItem(string text) => $"{ListItemMarker}{text}, ";
public override string Paragraph(string text) => string.Concat(text.TrimEnd('.'), ". ");
public override string Strong(string text) => text;
public override string Table(string header, string body) => string.Empty;
public override string TableCell(string content, TableCellFlags flags) => string.Empty;
public override string TableRow(string content) => string.Empty;
}
}
}
using System;
using Microsoft.MarkedNet;

namespace Bot.Builder.Community.Adapters.Alexa.Core.Helpers
{
/// <summary>
/// Simple Markdown renderer to turn markdown into plain text for Alexa.
/// </summary>
public static class AlexaMarkdownToPlaintextRenderer
{
private static readonly Marked _marked = new Marked(new Options { Renderer = new RemoveMarkupRenderer() });

public static string Render(string source) => _marked.Parse(source);

private class RemoveMarkupRenderer : MarkdownRenderer
{
private const string ListItemMarker = "$$ListItemMarker$$";

public override string Blockquote(string quote) => string.Concat(quote, ". ");
public override string Br() => ". ";
public override string Code(string code, string lang, bool escaped) => code;
public override string Codespan(string text) => text;
public override string Del(string text) => text;
public override string Em(string text) => text;
public override string Heading(string text, int level, string raw) => string.Concat(text, ". ");
public override string Hr() => ". ";
public override string Html(string html) => string.Empty;
public override string Image(string href, string title, string text) => title ?? text;
public override string Link(string href, string title, string text) => $"{title ?? text} {href}";
public override string List(string body, bool ordered, int start)
{
if (ordered)
{
for (int marker = start, markerIndex = body.IndexOf(ListItemMarker); markerIndex >= 0; markerIndex = body.IndexOf(ListItemMarker), ++marker)
{
body = body.Substring(0, markerIndex) + marker + ". " + body.Substring(markerIndex + ListItemMarker.Length);
}
}
else
{
body = body.Replace(ListItemMarker, string.Empty);
}
return $"{body.Trim().TrimEnd(',')}. ";
}
public override string ListItem(string text) => $"{ListItemMarker}{text}, ";
public override string Paragraph(string text) => string.Concat(text.TrimEnd('.'), ". ");
public override string Strong(string text) => text;
public override string Table(string header, string body) => string.Empty;
public override string TableCell(string content, TableCellFlags flags) => string.Empty;
public override string TableRow(string content) => string.Empty;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,92 +1,92 @@
using System;
using Alexa.NET.Response;
using Bot.Builder.Community.Adapters.Alexa.Core.Attachments;
using Microsoft.Bot.Schema;
using Microsoft.Rest;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Bot.Builder.Community.Adapters.Alexa.Core.Utility
{
public static class AttachmentUtility
{
/// <summary>
/// Convert all Alexa specific attachments to their correct type.
/// </summary>
/// <param name="activity"></param>
public static void ConvertAlexaAttachmentContent(this Activity activity)
{
if (activity == null || activity.Attachments == null)
{
return;
}
foreach (var attachment in activity.Attachments)
{
if (attachment.ContentType == AlexaAttachmentContentTypes.Card)
{
Convert<ICard>(attachment);
}
else if (attachment.ContentType == AlexaAttachmentContentTypes.Directive)
{
Convert<IDirective>(attachment);
}
}
}
private static void Convert<T>(Attachment attachment)
{
// Alexa-skills-dotnet has a custom JsonConverter that converts ICards and IDirective to their correct type so we don't need to do that.
// However, it throws in two main cases:
// 1) [JsonException] When the json fails to deserialize due to various reasons. In this case we want to throw a validation exception to
// let the bot developer know something is wrong.
// 2) [Exception] When it doesn't recognize the type. In this case we want to leave the attachment unconverted - we ignore it.
//
// See: https://github.com/timheuer/alexa-skills-dotnet/blob/master/Alexa.NET/Response/Converters/CardConverter.cs
// https://github.com/timheuer/alexa-skills-dotnet/blob/master/Alexa.NET/Response/Converters/DirectiveConverter.cs
try
{
attachment.Content = attachment.ContentAs<T>();
}
catch (JsonException ex)
{
throw new ValidationException($"Failed to convert Alexa Attachment with ContentType {attachment?.ContentType} to {typeof(T).Name}", ex);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
/// <summary>
/// Convert the Attachment Content field to the given type. An exception is thrown if the conversion fails.
/// </summary>
public static T ContentAs<T>(this Attachment attachment)
{
if (attachment == null)
throw new ArgumentNullException(nameof(attachment));
if (attachment.Content == null)
{
return default;
}
if (typeof(T).IsValueType)
{
return (T)System.Convert.ChangeType(attachment.Content, typeof(T));
}
if (attachment.Content is T)
{
return (T)attachment.Content;
}
if (typeof(T) == typeof(byte[]))
{
return (T)(object)System.Convert.FromBase64String(attachment.Content.ToString());
}
if (attachment.Content is string)
{
return JsonConvert.DeserializeObject<T>((string)attachment.Content);
}
return (T)((JObject)attachment.Content).ToObject<T>();
}
}
}
using System;
using Alexa.NET.Response;
using Bot.Builder.Community.Adapters.Alexa.Core.Attachments;
using Microsoft.Bot.Schema;
using Microsoft.Rest;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Bot.Builder.Community.Adapters.Alexa.Core.Helpers
{
public static class AttachmentHelper
{
/// <summary>
/// Convert all Alexa specific attachments to their correct type.
/// </summary>
/// <param name="activity"></param>
public static void ConvertAlexaAttachmentContent(this Activity activity)
{
if (activity == null || activity.Attachments == null)
{
return;
}

foreach (var attachment in activity.Attachments)
{
if (attachment.ContentType == AlexaAttachmentContentTypes.Card)
{
Convert<ICard>(attachment);
}
else if (attachment.ContentType == AlexaAttachmentContentTypes.Directive)
{
Convert<IDirective>(attachment);
}
}
}

private static void Convert<T>(Attachment attachment)
{
// Alexa-skills-dotnet has a custom JsonConverter that converts ICards and IDirective to their correct type so we don't need to do that.
// However, it throws in two main cases:
// 1) [JsonException] When the json fails to deserialize due to various reasons. In this case we want to throw a validation exception to
// let the bot developer know something is wrong.
// 2) [Exception] When it doesn't recognize the type. In this case we want to leave the attachment unconverted - we ignore it.
//
// See: https://github.com/timheuer/alexa-skills-dotnet/blob/master/Alexa.NET/Response/Converters/CardConverter.cs
// https://github.com/timheuer/alexa-skills-dotnet/blob/master/Alexa.NET/Response/Converters/DirectiveConverter.cs
try
{
attachment.Content = attachment.ContentAs<T>();
}
catch (JsonException ex)
{
throw new ValidationException($"Failed to convert Alexa Attachment with ContentType {attachment?.ContentType} to {typeof(T).Name}", ex);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}

/// <summary>
/// Convert the Attachment Content field to the given type. An exception is thrown if the conversion fails.
/// </summary>
public static T ContentAs<T>(this Attachment attachment)
{
if (attachment == null)
throw new ArgumentNullException(nameof(attachment));

if (attachment.Content == null)
{
return default;
}
if (typeof(T).IsValueType)
{
return (T)System.Convert.ChangeType(attachment.Content, typeof(T));
}
if (attachment.Content is T)
{
return (T)attachment.Content;
}
if (typeof(T) == typeof(byte[]))
{
return (T)(object)System.Convert.FromBase64String(attachment.Content.ToString());
}
if (attachment.Content is string)
{
return JsonConvert.DeserializeObject<T>((string)attachment.Content);
}
return (T)((JObject)attachment.Content).ToObject<T>();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using Alexa.NET.Request.Type;
using Alexa.NET.Response;
using Bot.Builder.Community.Adapters.Alexa.Core;
using Bot.Builder.Community.Adapters.Alexa.Tests.Utility;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Schema;
using Microsoft.Extensions.Logging;
Expand All @@ -13,6 +12,7 @@
using Alexa.NET.Response.Directive.Templates;
using Alexa.NET.Response.Directive.Templates.Types;
using Bot.Builder.Community.Adapters.Alexa.Core.Attachments;
using Bot.Builder.Community.Adapters.Alexa.Tests.Helpers;
using Xunit;

namespace Bot.Builder.Community.Adapters.Alexa.Tests
Expand Down Expand Up @@ -168,7 +168,7 @@ public void MergeActivitiesCorrectlyConvertsMarkdownToPlainText()
[Fact]
public void PlainTextMessageActivityConverted()
{
var skillRequest = SkillRequestUtility.CreateIntentRequest();
var skillRequest = SkillRequestHelper.CreateIntentRequest();
var mapper = new AlexaRequestMapper();

var activity = Activity.CreateMessageActivity() as Activity;
Expand All @@ -182,7 +182,7 @@ public void PlainTextMessageActivityConverted()
[Fact]
public void NonMessageActivityConverted()
{
var skillRequest = SkillRequestUtility.CreateIntentRequest();
var skillRequest = SkillRequestHelper.CreateIntentRequest();
var mapper = new AlexaRequestMapper();

var activity = Activity.CreateTraceActivity("This is a trace") as Activity;
Expand All @@ -194,7 +194,7 @@ public void NonMessageActivityConverted()
[Fact]
public void SimpleIntentRequestConverted()
{
var skillRequest = SkillRequestUtility.CreateIntentRequest();
var skillRequest = SkillRequestHelper.CreateIntentRequest();
var mapperOptions = new AlexaRequestMapperOptions { ServiceUrl = "service url" };
var mapper = new AlexaRequestMapper(mapperOptions);

Expand All @@ -208,7 +208,7 @@ public void SimpleIntentRequestConverted()
[Fact]
public void MessageActivityWithAlexaCardDirectiveAttachmentsConverted()
{
var skillRequest = SkillRequestUtility.CreateIntentRequest();
var skillRequest = SkillRequestHelper.CreateIntentRequest();
var mapper = new AlexaRequestMapper();

var activity = Activity.CreateMessageActivity() as Activity;
Expand Down
Loading