diff --git a/Alexa.NET.Tests/Alexa.NET.Tests.csproj b/Alexa.NET.Tests/Alexa.NET.Tests.csproj
index ae2964d..53fe502 100644
--- a/Alexa.NET.Tests/Alexa.NET.Tests.csproj
+++ b/Alexa.NET.Tests/Alexa.NET.Tests.csproj
@@ -20,6 +20,9 @@
PreserveNewest
+
+ PreserveNewest
+
PreserveNewest
@@ -50,6 +53,9 @@
PreserveNewest
+
+ PreserveNewest
+
PreserveNewest
@@ -62,15 +68,33 @@
PreserveNewest
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
PreserveNewest
PreserveNewest
+
+ PreserveNewest
+
+
+ PreserveNewest
+
PreserveNewest
+
+ PreserveNewest
+
PreserveNewest
diff --git a/Alexa.NET.Tests/Examples/CompleteTaskDirective.json b/Alexa.NET.Tests/Examples/CompleteTaskDirective.json
new file mode 100644
index 0000000..d0dc9c6
--- /dev/null
+++ b/Alexa.NET.Tests/Examples/CompleteTaskDirective.json
@@ -0,0 +1,7 @@
+{
+ "type": "Tasks.CompleteTask",
+ "status": {
+ "code": 200,
+ "message": "return as desired"
+ }
+}
\ No newline at end of file
diff --git a/Alexa.NET.Tests/Examples/LaunchRequestWithTask.json b/Alexa.NET.Tests/Examples/LaunchRequestWithTask.json
new file mode 100644
index 0000000..56e0908
--- /dev/null
+++ b/Alexa.NET.Tests/Examples/LaunchRequestWithTask.json
@@ -0,0 +1,18 @@
+{
+ "type": "LaunchRequest",
+ "requestId": "string",
+ "timestamp": "2019-07-03T00:00:00",
+ "locale": "string",
+ "originIpAddress": "string",
+ "task": {
+ "name": "AMAZON.PrintPDF",
+ "version": "1",
+ "input": {
+ "@type": "PrintPDFRequest",
+ "@version": "1",
+ "title": "Flywheel",
+ "description": "Flywheel",
+ "url": "http://www.example.com/flywheel.pdf"
+ }
+ }
+}
\ No newline at end of file
diff --git a/Alexa.NET.Tests/Examples/PrintImageConnection.json b/Alexa.NET.Tests/Examples/PrintImageConnection.json
new file mode 100644
index 0000000..f73bffc
--- /dev/null
+++ b/Alexa.NET.Tests/Examples/PrintImageConnection.json
@@ -0,0 +1,12 @@
+{
+ "type": "Connections.StartConnection",
+ "uri": "connection://AMAZON.PrintImage/1",
+ "input": {
+ "@type": "PrintImageRequest",
+ "@version": "1",
+ "title": "Flywheel Document",
+ "description": "Flywheel",
+ "imageType": "JPEG",
+ "url": "http://www.example.com/flywheel.jpeg"
+ }
+}
\ No newline at end of file
diff --git a/Alexa.NET.Tests/Examples/PrintPDFConnection.json b/Alexa.NET.Tests/Examples/PrintPDFConnection.json
new file mode 100644
index 0000000..1a406a3
--- /dev/null
+++ b/Alexa.NET.Tests/Examples/PrintPDFConnection.json
@@ -0,0 +1,15 @@
+{
+ "type": "Connections.StartConnection",
+ "uri": "connection://AMAZON.PrintPDF/1",
+ "input": {
+ "@type": "PrintPDFRequest",
+ "@version": "1",
+ "title": "title",
+ "description": "description",
+ "context": {
+ "providerId": "your-provider-skill-id"
+ },
+ "url": "http://www.example.com/flywheel.pdf"
+ },
+ "token": "none"
+}
\ No newline at end of file
diff --git a/Alexa.NET.Tests/Examples/PrintWebPageConnection.json b/Alexa.NET.Tests/Examples/PrintWebPageConnection.json
new file mode 100644
index 0000000..c354542
--- /dev/null
+++ b/Alexa.NET.Tests/Examples/PrintWebPageConnection.json
@@ -0,0 +1,11 @@
+{
+ "type": "Connections.StartConnection",
+ "uri": "connection://AMAZON.PrintWebPage/1",
+ "input": {
+ "@type": "PrintWebPageRequest",
+ "@version": "1",
+ "title": "title",
+ "description": "description",
+ "url": "http://www.example.com/flywheel.html"
+ }
+}
\ No newline at end of file
diff --git a/Alexa.NET.Tests/Examples/ScheduleFoodEstablishmentReservation.json b/Alexa.NET.Tests/Examples/ScheduleFoodEstablishmentReservation.json
new file mode 100644
index 0000000..369fdec
--- /dev/null
+++ b/Alexa.NET.Tests/Examples/ScheduleFoodEstablishmentReservation.json
@@ -0,0 +1,24 @@
+{
+ "type": "Connections.StartConnection",
+ "uri": "connection://AMAZON.ScheduleFoodEstablishmentReservation/1",
+ "input": {
+ "@type": "ScheduleFoodEstablishmentReservationRequest",
+ "@version": "1",
+ "startTime": "2018-04-08T01:15:46Z",
+ "partySize": 2,
+ "restaurant": {
+ "@type": "Restaurant",
+ "@version": "1",
+ "name": "Amazon Day 1 Restaurant",
+ "location": {
+ "@type": "PostalAddress",
+ "@version": "1",
+ "streetAddress": "2121 7th Avenue",
+ "locality": "Seattle",
+ "region": "WA",
+ "postalCode": "98121",
+ "country": "US"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Alexa.NET.Tests/Examples/ScheduleTaxiReservation.json b/Alexa.NET.Tests/Examples/ScheduleTaxiReservation.json
new file mode 100644
index 0000000..5594bc0
--- /dev/null
+++ b/Alexa.NET.Tests/Examples/ScheduleTaxiReservation.json
@@ -0,0 +1,27 @@
+{
+ "type": "Connections.StartConnection",
+ "uri": "connection://AMAZON.ScheduleTaxiReservation/1",
+ "input": {
+ "@type": "ScheduleTaxiReservationRequest",
+ "@version": "1",
+ "partySize": 4,
+ "pickupLocation": {
+ "@type": "PostalAddress",
+ "@version": "1",
+ "streetAddress": "415 106th Ave NE",
+ "locality": "Bellevue",
+ "region": "WA",
+ "postalCode": "98004",
+ "country": "US"
+ },
+ "dropoffLocation": {
+ "@type": "PostalAddress",
+ "@version": "1",
+ "streetAddress": "2031 6th Ave.",
+ "locality": "Seattle",
+ "region": "WA",
+ "postalCode": "98121",
+ "country": "US"
+ }
+ }
+}
\ No newline at end of file
diff --git a/Alexa.NET.Tests/Examples/SessionResumedRequest.json b/Alexa.NET.Tests/Examples/SessionResumedRequest.json
new file mode 100644
index 0000000..ee08f10
--- /dev/null
+++ b/Alexa.NET.Tests/Examples/SessionResumedRequest.json
@@ -0,0 +1,16 @@
+{
+ "type": "SessionResumedRequest",
+ "requestId": "string",
+ "timestamp": "2019-07-03T00:00:00",
+ "locale": "en-GB",
+ "originIpAddress": "string",
+ "cause": {
+ "type": "ConnectionCompleted",
+ "token": "1234",
+ "status": {
+ "code": 200,
+ "message": "OK"
+ },
+ "result": null
+ }
+}
\ No newline at end of file
diff --git a/Alexa.NET.Tests/SkillConnectionTests.cs b/Alexa.NET.Tests/SkillConnectionTests.cs
new file mode 100644
index 0000000..08b72c1
--- /dev/null
+++ b/Alexa.NET.Tests/SkillConnectionTests.cs
@@ -0,0 +1,184 @@
+using System;
+using Alexa.NET.ConnectionTasks;
+using Alexa.NET.ConnectionTasks.Inputs;
+using Alexa.NET.Request.Type;
+using Alexa.NET.Response;
+using Alexa.NET.Response.Directive;
+using Xunit;
+
+namespace Alexa.NET.Tests
+{
+ public class SkillConnectionTests
+ {
+ [Fact]
+ public void StartConnectionDirectiveSerializesCorrectly()
+ {
+ var task = new PrintPdfV1
+ {
+ Title = "title",
+ Description = "description",
+ Url = "http://www.example.com/flywheel.pdf",
+ Context = new ConnectionTaskContext { ProviderId = "your-provider-skill-id" }
+ };
+ Utility.CompareJson(task.ToConnectionDirective("none"), "PrintPDFConnection.json");
+ }
+
+ [Fact]
+ public void StartConnectionDirectiveDeserializesCorrectly()
+ {
+ var raw = Utility.ExampleFileContent("PrintPDFConnection.json");
+ Assert.NotNull(raw);
+
+ var directive = Assert.IsType(raw);
+ Assert.Equal("none", directive.Token);
+ Assert.Equal(PrintPdfV1.AssociatedUri, directive.Uri);
+
+ Assert.IsType(directive.Input);
+ }
+
+ [Fact]
+ public void SessionResumedSerializesProperly()
+ {
+ var task = new SessionResumedRequest
+ {
+ RequestId = "string",
+ Timestamp = new DateTime(2019, 07, 03),
+ Locale = "en-GB",
+ OriginIpAddress = "string",
+ Cause = new SessionResumedRequestCause
+ {
+ Type = "ConnectionCompleted",
+ Token = "1234",
+ Status = new TaskStatus(200, "OK")
+ }
+ };
+ Utility.CompareJson(task, "SessionResumedRequest.json");
+ }
+
+ [Fact]
+ public void SessionResumedDeserializesProperly()
+ {
+ var result = Utility.ExampleFileContent("SessionResumedRequest.json");
+ var request = Assert.IsType(result);
+
+ Assert.Equal("1234", request.Cause.Token);
+ Assert.Equal(200, request.Cause.Status.Code);
+ Assert.Equal("OK", request.Cause.Status.Message);
+ }
+
+ [Fact]
+ public void LaunchRequestWithTaskDeserializesCorrectly()
+ {
+ var result = Utility.ExampleFileContent("LaunchRequestWithTask.json");
+ Assert.NotNull(result.Task);
+ Assert.Equal("AMAZON.PrintPDF", result.Task.Name);
+ Assert.Equal("1", result.Task.Version);
+ Assert.IsType(result.Task.Input);
+ }
+
+ [Fact]
+ public void TestCompleteTaskDirective()
+ {
+ var directive = new CompleteTaskDirective(200, "return as desired");
+ Assert.True(Utility.CompareJson(directive, "CompleteTaskDirective.json"));
+ }
+
+ [Fact]
+ public void PrintImageConnectionComparison()
+ {
+ var directive = new PrintImageV1
+ {
+ Title = "Flywheel Document",
+ Description = "Flywheel",
+ ImageV1Type = PrintImageV1Type.JPEG,
+ Url = "http://www.example.com/flywheel.jpeg"
+ }.ToConnectionDirective();
+ Assert.Equal(PrintImageV1.AssociatedUri, directive.Uri);
+ Assert.True(Utility.CompareJson(directive, "PrintImageConnection.json"));
+ Assert.IsType(Utility.ExampleFileContent("PrintImageConnection.json").Input);
+ }
+
+ [Fact]
+ public void PrintPDFConnectionComparison()
+ {
+ var directive = new PrintPdfV1
+ {
+ Title = "title",
+ Description = "description",
+ Url = "http://www.example.com/flywheel.pdf",
+ Context = new ConnectionTaskContext { ProviderId = "your-provider-skill-id" }
+ }.ToConnectionDirective("none");
+ Assert.Equal(PrintPdfV1.AssociatedUri, directive.Uri);
+ Assert.True(Utility.CompareJson(directive, "PrintPDFConnection.json"));
+ Assert.IsType(Utility.ExampleFileContent("PrintPDFConnection.json").Input);
+ }
+
+ [Fact]
+ public void PrintWebPageConnectionComparison()
+ {
+ var directive = new PrintWebPageV1
+ {
+ Title = "title",
+ Description = "description",
+ Url = "http://www.example.com/flywheel.html"
+ }.ToConnectionDirective();
+ Assert.Equal(PrintWebPageV1.AssociatedUri, directive.Uri);
+ Assert.True(Utility.CompareJson(directive, "PrintWebPageConnection.json"));
+ Assert.IsType(Utility.ExampleFileContent("PrintPDFConnection.json").Input);
+ }
+
+ [Fact]
+ public void ScheduleTaxiReservationConnectionComparison()
+ {
+ var directive = new ScheduleTaxiReservation
+ {
+ PartySize = 4,
+ PickupLocation = new PostalAddress
+ {
+ StreetAddress = "415 106th Ave NE",
+ Locality = "Bellevue",
+ Region = "WA",
+ PostalCode = "98004",
+ Country = "US"
+ },
+ DropoffLocation = new PostalAddress
+ {
+ StreetAddress = "2031 6th Ave.",
+ Locality = "Seattle",
+ Region = "WA",
+ PostalCode = "98121",
+ Country = "US"
+ }
+ }.ToConnectionDirective();
+ Assert.Equal(ScheduleTaxiReservation.AssociatedUri, directive.Uri);
+ Assert.True(Utility.CompareJson(directive, "ScheduleTaxiReservation.json"));
+ Assert.IsType(Utility.ExampleFileContent("ScheduleTaxiReservation.json").Input);
+ }
+
+ [Fact]
+ public void ScheduleFoodReservationConnectionComparison()
+ {
+ var directive = new ScheduleFoodEstablishmentReservation
+ {
+ PartySize = 2,
+ StartTime = new DateTime(2018,04,08,01,15,46),
+ Restaurant = new Restaurant
+ {
+ Name = "Amazon Day 1 Restaurant",
+ Location = new PostalAddress
+ {
+ StreetAddress = "2121 7th Avenue",
+ Locality = "Seattle",
+ Region = "WA",
+ PostalCode = "98121",
+ Country = "US"
+ }
+ }
+ }.ToConnectionDirective();
+ Assert.Equal(ScheduleFoodEstablishmentReservation.AssociatedUri, directive.Uri);
+ Assert.True(Utility.CompareJson(directive, "ScheduleFoodEstablishmentReservation.json"));
+ Assert.IsType(Utility.ExampleFileContent("ScheduleFoodEstablishmentReservation.json").Input);
+ }
+
+ }
+}
diff --git a/Alexa.NET/Alexa.NET.csproj b/Alexa.NET/Alexa.NET.csproj
index 22081ec..2c7941a 100644
--- a/Alexa.NET/Alexa.NET.csproj
+++ b/Alexa.NET/Alexa.NET.csproj
@@ -3,13 +3,13 @@
A simple .NET Core library for handling Alexa Skill request/responses.
Alexa.NET
- 1.6.3
+ 1.7.0
Tim Heuer, Steven Pears
netstandard1.6
Alexa.NET
Alexa.NET
amazon;alexa;echo;dot;echo dot;skills
- Added SessionEnd error object; Fix deserialization error; Added permission scopes (by @VinceGusmini); Added response type converters (by @rdlaitila); Added Dynamic Entity support (by @stoiveyp)
+ Added core support for Skill connections (by @stoiveyp) and in association with Alexa.NET.Management enables the end-to-end.
https://github.com/timheuer/alexa-skills-dotnet
MIT
https://github.com/timheuer/alexa-skills-dotnet
diff --git a/Alexa.NET/ConnectionTasks/ConnectionTaskContext.cs b/Alexa.NET/ConnectionTasks/ConnectionTaskContext.cs
new file mode 100644
index 0000000..6728312
--- /dev/null
+++ b/Alexa.NET/ConnectionTasks/ConnectionTaskContext.cs
@@ -0,0 +1,10 @@
+using Newtonsoft.Json;
+
+namespace Alexa.NET.ConnectionTasks
+{
+ public class ConnectionTaskContext
+ {
+ [JsonProperty("providerId")]
+ public string ProviderId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Alexa.NET/ConnectionTasks/IConnectionTask.cs b/Alexa.NET/ConnectionTasks/IConnectionTask.cs
new file mode 100644
index 0000000..e1a79aa
--- /dev/null
+++ b/Alexa.NET/ConnectionTasks/IConnectionTask.cs
@@ -0,0 +1,22 @@
+using System.Text;
+using Alexa.NET.Response.Converters;
+using Newtonsoft.Json;
+
+namespace Alexa.NET.ConnectionTasks
+{
+ [JsonConverter(typeof(ConnectionTaskConverter))]
+ public interface IConnectionTask
+ {
+ [JsonIgnore]
+ string ConnectionUri { get; }
+
+ [JsonProperty("@type")]
+ string Type { get; }
+
+ [JsonProperty("@version")]
+ string Version { get; }
+
+ [JsonProperty("context",NullValueHandling = NullValueHandling.Ignore)]
+ ConnectionTaskContext Context { get; set; }
+ }
+}
diff --git a/Alexa.NET/ConnectionTasks/IConnectionTaskExtensions.cs b/Alexa.NET/ConnectionTasks/IConnectionTaskExtensions.cs
new file mode 100644
index 0000000..1cdac28
--- /dev/null
+++ b/Alexa.NET/ConnectionTasks/IConnectionTaskExtensions.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Alexa.NET.Response.Directive;
+
+namespace Alexa.NET.ConnectionTasks
+{
+ public static class IConnectionTaskExtensions
+ {
+
+ public static StartConnectionDirective ToConnectionDirective(this IConnectionTask task, string token = null)
+ {
+ return new StartConnectionDirective(task, token);
+ }
+ }
+}
diff --git a/Alexa.NET/ConnectionTasks/Inputs/PostalAddress.cs b/Alexa.NET/ConnectionTasks/Inputs/PostalAddress.cs
new file mode 100644
index 0000000..aaf8f86
--- /dev/null
+++ b/Alexa.NET/ConnectionTasks/Inputs/PostalAddress.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Newtonsoft.Json;
+
+namespace Alexa.NET.ConnectionTasks.Inputs
+{
+ public class PostalAddress
+ {
+ [JsonProperty("@type")] public string Type => "PostalAddress";
+ [JsonProperty("@version")] public string Version = 1.ToString();
+ [JsonProperty("streetAddress")] public string StreetAddress { get; set; }
+ [JsonProperty("locality")] public string Locality { get; set; }
+ [JsonProperty("region")] public string Region { get; set; }
+ [JsonProperty("postalCode")] public string PostalCode { get; set; }
+ [JsonProperty("country", NullValueHandling = NullValueHandling.Ignore)] public string Country { get; set; }
+ }
+}
diff --git a/Alexa.NET/ConnectionTasks/Inputs/PrintImageV1.cs b/Alexa.NET/ConnectionTasks/Inputs/PrintImageV1.cs
new file mode 100644
index 0000000..c7a0658
--- /dev/null
+++ b/Alexa.NET/ConnectionTasks/Inputs/PrintImageV1.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Converters;
+
+namespace Alexa.NET.ConnectionTasks.Inputs
+{
+ public class PrintImageV1 : IConnectionTask
+ {
+ public const string AssociatedUri = "connection://AMAZON.PrintImage/1";
+ [JsonIgnore]
+ public string ConnectionUri => AssociatedUri;
+
+ [JsonProperty("@type")]
+ public string Type => "PrintImageRequest";
+
+ [JsonProperty("@version")]
+ public string Version => 1.ToString();
+
+ [JsonProperty("context", NullValueHandling = NullValueHandling.Ignore)]
+ public ConnectionTaskContext Context { get; set; }
+
+ [JsonProperty("title")]
+ public string Title { get; set; }
+
+ [JsonProperty("description")]
+ public string Description { get; set; }
+
+ [JsonProperty("imageType"),JsonConverter(typeof(StringEnumConverter))]
+ public PrintImageV1Type ImageV1Type { get; set; }
+
+ [JsonProperty("url")]
+ public string Url { get; set; }
+ }
+
+ public enum PrintImageV1Type
+ {
+ JPG,
+ JPEG
+ }
+}
diff --git a/Alexa.NET/ConnectionTasks/Inputs/PrintPdfV1.cs b/Alexa.NET/ConnectionTasks/Inputs/PrintPdfV1.cs
new file mode 100644
index 0000000..453f508
--- /dev/null
+++ b/Alexa.NET/ConnectionTasks/Inputs/PrintPdfV1.cs
@@ -0,0 +1,32 @@
+using System;
+using Newtonsoft.Json;
+
+namespace Alexa.NET.ConnectionTasks.Inputs
+{
+ public class PrintPdfV1:IConnectionTask
+ {
+ public const string AssociatedUri = "connection://AMAZON.PrintPDF/1";
+
+ [JsonIgnore]
+ public string ConnectionUri => AssociatedUri;
+
+ [JsonProperty("@type")]
+ public string Type => "PrintPDFRequest";
+
+ [JsonProperty("context", NullValueHandling = NullValueHandling.Ignore)]
+ public ConnectionTaskContext Context { get; set; }
+
+ [JsonProperty("@version")]
+ public string Version => 1.ToString();
+
+ [JsonProperty("title")]
+ public string Title { get; set; }
+
+ [JsonProperty("description")]
+ public string Description { get; set; }
+
+ [JsonProperty("url")]
+ public string Url { get; set; }
+
+ }
+}
diff --git a/Alexa.NET/ConnectionTasks/Inputs/PrintWebPageV1.cs b/Alexa.NET/ConnectionTasks/Inputs/PrintWebPageV1.cs
new file mode 100644
index 0000000..113ac30
--- /dev/null
+++ b/Alexa.NET/ConnectionTasks/Inputs/PrintWebPageV1.cs
@@ -0,0 +1,32 @@
+using System;
+using Newtonsoft.Json;
+
+namespace Alexa.NET.ConnectionTasks.Inputs
+{
+ public class PrintWebPageV1:IConnectionTask
+ {
+ public const string AssociatedUri = "connection://AMAZON.PrintWebPage/1";
+
+ [JsonIgnore]
+ public string ConnectionUri => AssociatedUri;
+
+ [JsonProperty("@type")]
+ public string Type => "PrintWebPageRequest";
+
+ [JsonProperty("context", NullValueHandling = NullValueHandling.Ignore)]
+ public ConnectionTaskContext Context { get; set; }
+
+ [JsonProperty("@version")]
+ public string Version => 1.ToString();
+
+ [JsonProperty("title")]
+ public string Title { get; set; }
+
+ [JsonProperty("description")]
+ public string Description { get; set; }
+
+ [JsonProperty("url")]
+ public string Url { get; set; }
+
+ }
+}
diff --git a/Alexa.NET/ConnectionTasks/Inputs/Restaurant.cs b/Alexa.NET/ConnectionTasks/Inputs/Restaurant.cs
new file mode 100644
index 0000000..c3786d8
--- /dev/null
+++ b/Alexa.NET/ConnectionTasks/Inputs/Restaurant.cs
@@ -0,0 +1,19 @@
+using Newtonsoft.Json;
+
+namespace Alexa.NET.ConnectionTasks.Inputs
+{
+ public class Restaurant
+ {
+ [JsonProperty("@type")]
+ public string Type => "Restaurant";
+
+ [JsonProperty("@version")]
+ public string Version => 1.ToString();
+
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ [JsonProperty("location")]
+ public PostalAddress Location { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Alexa.NET/ConnectionTasks/Inputs/ScheduleFoodEstablishmentReservation.cs b/Alexa.NET/ConnectionTasks/Inputs/ScheduleFoodEstablishmentReservation.cs
new file mode 100644
index 0000000..4bd46dc
--- /dev/null
+++ b/Alexa.NET/ConnectionTasks/Inputs/ScheduleFoodEstablishmentReservation.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Alexa.NET.Helpers;
+using Newtonsoft.Json;
+
+namespace Alexa.NET.ConnectionTasks.Inputs
+{
+ public class ScheduleFoodEstablishmentReservation:IConnectionTask
+ {
+ public const string AssociatedUri = "connection://AMAZON.ScheduleFoodEstablishmentReservation/1";
+ [JsonIgnore]
+ public string ConnectionUri => AssociatedUri;
+
+ [JsonProperty("@type")]
+ public string Type => "ScheduleFoodEstablishmentReservationRequest";
+
+ [JsonProperty("@version")]
+ public string Version => 1.ToString();
+
+ [JsonProperty("context", NullValueHandling = NullValueHandling.Ignore)]
+ public ConnectionTaskContext Context { get; set; }
+
+ [JsonProperty("partySize",NullValueHandling = NullValueHandling.Ignore)]
+ public int PartySize { get; set; }
+
+ [JsonProperty("startTime",NullValueHandling = NullValueHandling.Ignore),JsonConverter(typeof(MixedDateTimeConverter))]
+ public DateTime? StartTime { get; set; }
+
+ [JsonProperty("restaurant")]
+ public Restaurant Restaurant { get; set; }
+ }
+}
diff --git a/Alexa.NET/ConnectionTasks/Inputs/ScheduleTaxiReservation.cs b/Alexa.NET/ConnectionTasks/Inputs/ScheduleTaxiReservation.cs
new file mode 100644
index 0000000..2a16793
--- /dev/null
+++ b/Alexa.NET/ConnectionTasks/Inputs/ScheduleTaxiReservation.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Alexa.NET.Helpers;
+using Newtonsoft.Json;
+
+namespace Alexa.NET.ConnectionTasks.Inputs
+{
+ public class ScheduleTaxiReservation:IConnectionTask
+ {
+ public const string AssociatedUri = "connection://AMAZON.ScheduleTaxiReservation/1";
+ [JsonIgnore]
+ public string ConnectionUri => AssociatedUri;
+
+ [JsonProperty("@type")]
+ public string Type => "ScheduleTaxiReservationRequest";
+
+ [JsonProperty("@version")]
+ public string Version => 1.ToString();
+
+ [JsonProperty("context", NullValueHandling = NullValueHandling.Ignore)]
+ public ConnectionTaskContext Context { get; set; }
+
+ [JsonProperty("partySize")]
+ public int PartySize { get; set; }
+
+ [JsonProperty("pickupLocation",NullValueHandling = NullValueHandling.Ignore)]
+ public PostalAddress PickupLocation { get; set; }
+
+ [JsonProperty("dropoffLocation",NullValueHandling = NullValueHandling.Ignore)]
+ public PostalAddress DropoffLocation { get; set; }
+
+ [JsonProperty("pickupTime",NullValueHandling = NullValueHandling.Ignore),JsonConverter(typeof(MixedDateTimeConverter))]
+ public DateTime? PickupTime { get; set; }
+ }
+}
diff --git a/Alexa.NET/ConnectionTasks/TaskStatus.cs b/Alexa.NET/ConnectionTasks/TaskStatus.cs
new file mode 100644
index 0000000..7b86f44
--- /dev/null
+++ b/Alexa.NET/ConnectionTasks/TaskStatus.cs
@@ -0,0 +1,21 @@
+using Newtonsoft.Json;
+
+namespace Alexa.NET.ConnectionTasks
+{
+ public class TaskStatus
+ {
+ public TaskStatus() { }
+
+ public TaskStatus(int code, string message)
+ {
+ Code = code;
+ Message = message;
+ }
+
+ [JsonProperty("code")]
+ public int Code { get; set; }
+
+ [JsonProperty("message")]
+ public string Message { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Alexa.NET/Request/SkillRequest.cs b/Alexa.NET/Request/SkillRequest.cs
index bed96f7..07f0eea 100644
--- a/Alexa.NET/Request/SkillRequest.cs
+++ b/Alexa.NET/Request/SkillRequest.cs
@@ -15,7 +15,6 @@ public class SkillRequest
public Context Context { get; set; }
[JsonProperty("request")]
- [JsonConverter(typeof(RequestConverter))]
public Type.Request Request { get; set; }
public System.Type GetRequestType()
diff --git a/Alexa.NET/Request/Type/Converters/SkillConnectionRequestTypeConverter.cs b/Alexa.NET/Request/Type/Converters/SkillConnectionRequestTypeConverter.cs
new file mode 100644
index 0000000..b7f1614
--- /dev/null
+++ b/Alexa.NET/Request/Type/Converters/SkillConnectionRequestTypeConverter.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Alexa.NET.Request.Type
+{
+ public class SkillConnectionRequestTypeConverter:IRequestTypeConverter
+ {
+ public bool CanConvert(string requestType)
+ {
+ return requestType == "SessionResumedRequest";
+ }
+
+ public Request Convert(string requestType)
+ {
+ return new SessionResumedRequest();
+ }
+ }
+}
diff --git a/Alexa.NET/Request/Type/LaunchRequest.cs b/Alexa.NET/Request/Type/LaunchRequest.cs
index e31c999..795899e 100644
--- a/Alexa.NET/Request/Type/LaunchRequest.cs
+++ b/Alexa.NET/Request/Type/LaunchRequest.cs
@@ -1,6 +1,10 @@
-namespace Alexa.NET.Request.Type
+using Newtonsoft.Json;
+
+namespace Alexa.NET.Request.Type
{
public class LaunchRequest : Request
{
+ [JsonProperty("task",NullValueHandling = NullValueHandling.Ignore)]
+ public LaunchRequestTask Task { get; set; }
}
}
\ No newline at end of file
diff --git a/Alexa.NET/Request/Type/LaunchRequestTask.cs b/Alexa.NET/Request/Type/LaunchRequestTask.cs
new file mode 100644
index 0000000..17bfa1a
--- /dev/null
+++ b/Alexa.NET/Request/Type/LaunchRequestTask.cs
@@ -0,0 +1,17 @@
+using Alexa.NET.ConnectionTasks;
+using Newtonsoft.Json;
+
+namespace Alexa.NET.Request.Type
+{
+ public class LaunchRequestTask
+ {
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ [JsonProperty("version")]
+ public string Version { get; set; }
+
+ [JsonProperty("input")]
+ public IConnectionTask Input { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Alexa.NET/Request/Type/Request.cs b/Alexa.NET/Request/Type/Request.cs
index 42bec23..69f460d 100644
--- a/Alexa.NET/Request/Type/Request.cs
+++ b/Alexa.NET/Request/Type/Request.cs
@@ -4,6 +4,7 @@
namespace Alexa.NET.Request.Type
{
+ [JsonConverter(typeof(RequestConverter))]
public abstract class Request
{
[JsonProperty("type")]
diff --git a/Alexa.NET/Request/Type/RequestConverter.cs b/Alexa.NET/Request/Type/RequestConverter.cs
index c3674b9..9dbcde3 100644
--- a/Alexa.NET/Request/Type/RequestConverter.cs
+++ b/Alexa.NET/Request/Type/RequestConverter.cs
@@ -14,7 +14,8 @@ public class RequestConverter : JsonConverter
new AudioPlayerRequestTypeConverter(),
new PlaybackRequestTypeConverter(),
new TemplateEventRequestTypeConverter(),
- new SkillEventRequestTypeConverter()
+ new SkillEventRequestTypeConverter(),
+ new SkillConnectionRequestTypeConverter()
});
public override bool CanWrite => false;
diff --git a/Alexa.NET/Request/Type/SessionResumedRequest.cs b/Alexa.NET/Request/Type/SessionResumedRequest.cs
new file mode 100644
index 0000000..4e8f13e
--- /dev/null
+++ b/Alexa.NET/Request/Type/SessionResumedRequest.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+
+namespace Alexa.NET.Request.Type
+{
+ public class SessionResumedRequest:Request
+ {
+ [JsonProperty("originIpAddress")]
+ public string OriginIpAddress { get; set; }
+
+ [JsonProperty("cause")]
+ public SessionResumedRequestCause Cause { get; set; }
+ }
+}
diff --git a/Alexa.NET/Request/Type/SessionResumedRequestCause.cs b/Alexa.NET/Request/Type/SessionResumedRequestCause.cs
new file mode 100644
index 0000000..cd12579
--- /dev/null
+++ b/Alexa.NET/Request/Type/SessionResumedRequestCause.cs
@@ -0,0 +1,20 @@
+using Alexa.NET.ConnectionTasks;
+using Newtonsoft.Json;
+
+namespace Alexa.NET.Request.Type
+{
+ public class SessionResumedRequestCause
+ {
+ [JsonProperty("type")]
+ public string Type { get; set; }
+
+ [JsonProperty("token")]
+ public string Token { get; set; }
+
+ [JsonProperty("status")]
+ public TaskStatus Status { get; set; }
+
+ [JsonProperty("result")]
+ public object Result { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Alexa.NET/Response/Converters/ConnectionTaskConverter.cs b/Alexa.NET/Response/Converters/ConnectionTaskConverter.cs
new file mode 100644
index 0000000..b3b7d58
--- /dev/null
+++ b/Alexa.NET/Response/Converters/ConnectionTaskConverter.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+using Alexa.NET.ConnectionTasks;
+using Alexa.NET.ConnectionTasks.Inputs;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+
+namespace Alexa.NET.Response.Converters
+{
+ public class ConnectionTaskConverter : JsonConverter
+ {
+ public static Dictionary> TaskFactoryFromUri = new Dictionary>
+ {
+ {"PrintPDFRequest/1",() => new PrintPdfV1() },
+ {"PrintImageRequest/1", () => new PrintImageV1() },
+ {"PrintWebPageRequest/1",() => new PrintWebPageV1()},
+ {"ScheduleTaxiReservationRequest/1",() => new ScheduleTaxiReservation() },
+ {"ScheduleFoodEstablishmentReservationRequest/1",() => new ScheduleFoodEstablishmentReservation()}
+ };
+
+ public override bool CanRead => true;
+ public override bool CanWrite => false;
+
+ public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+ {
+ var jsonObject = JObject.Load(reader);
+ var typeKey = jsonObject.Value("@type");
+ var versionKey = jsonObject.Value("@version");
+ var factoryKey = $"{typeKey}/{versionKey}";
+ var hasFactory = TaskFactoryFromUri.ContainsKey(factoryKey);
+
+ if (!hasFactory)
+ throw new Exception(
+ $"unable to deserialize response. " +
+ $"unrecognized task type '{typeKey}' with version '{versionKey}'"
+ );
+
+ var directive = TaskFactoryFromUri[factoryKey]();
+
+ serializer.Populate(jsonObject.CreateReader(), directive);
+
+ return directive;
+ }
+
+ public override bool CanConvert(Type objectType)
+ {
+ return objectType == typeof(IConnectionTask);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Alexa.NET/Response/Converters/DirectiveConverter.cs b/Alexa.NET/Response/Converters/DirectiveConverter.cs
index d98428e..9887c5c 100644
--- a/Alexa.NET/Response/Converters/DirectiveConverter.cs
+++ b/Alexa.NET/Response/Converters/DirectiveConverter.cs
@@ -24,6 +24,8 @@ public class DirectiveConverter : JsonConverter
{ "Hint", () => new HintDirective() },
{ "AudioPlayer.Stop", () => new StopDirective() },
{ "VideoApp.Launch", () => new VideoAppDirective() },
+ { "Connections.StartConnection", () => new StartConnectionDirective() },
+ { "Tasks.CompleteTask",() => new CompleteTaskDirective()}
};
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
diff --git a/Alexa.NET/Response/Directive/CompleteTaskDirective.cs b/Alexa.NET/Response/Directive/CompleteTaskDirective.cs
new file mode 100644
index 0000000..f924d85
--- /dev/null
+++ b/Alexa.NET/Response/Directive/CompleteTaskDirective.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Alexa.NET.ConnectionTasks;
+using Newtonsoft.Json;
+
+namespace Alexa.NET.Response.Directive
+{
+ public class CompleteTaskDirective:IDirective
+ {
+ public CompleteTaskDirective() { }
+
+ public CompleteTaskDirective(int statusCode, string statusMessage)
+ {
+ Status = new TaskStatus(statusCode,statusMessage);
+ }
+
+ [JsonProperty("type")]
+ public string Type => "Tasks.CompleteTask";
+
+ [JsonProperty("status")]
+ public TaskStatus Status { get; set; }
+ }
+}
diff --git a/Alexa.NET/Response/Directive/StartConnectionDirective.cs b/Alexa.NET/Response/Directive/StartConnectionDirective.cs
new file mode 100644
index 0000000..de5706a
--- /dev/null
+++ b/Alexa.NET/Response/Directive/StartConnectionDirective.cs
@@ -0,0 +1,30 @@
+using System;
+using Alexa.NET.ConnectionTasks;
+using Newtonsoft.Json;
+
+namespace Alexa.NET.Response.Directive
+{
+ public class StartConnectionDirective:IDirective
+ {
+ [JsonProperty("type")]
+ public string Type => "Connections.StartConnection";
+
+ [JsonProperty("uri")]
+ public string Uri { get; set; }
+
+ [JsonProperty("input")]
+ public IConnectionTask Input { get; set; }
+
+ [JsonProperty("token",NullValueHandling = NullValueHandling.Ignore)]
+ public string Token { get; set; }
+
+ public StartConnectionDirective(){}
+
+ public StartConnectionDirective(IConnectionTask input, string token)
+ {
+ this.Uri = input.ConnectionUri;
+ this.Input = input;
+ this.Token = token;
+ }
+ }
+}
diff --git a/Alexa.NET/Response/ProgressiveResponse.cs b/Alexa.NET/Response/ProgressiveResponse.cs
index dc8c317..3655873 100644
--- a/Alexa.NET/Response/ProgressiveResponse.cs
+++ b/Alexa.NET/Response/ProgressiveResponse.cs
@@ -69,14 +69,14 @@ public ProgressiveResponse()
}
- public Task SendSpeech(Ssml.Speech speech)
+ public Task SendSpeech(Ssml.Speech ssml)
{
- return Send(new VoicePlayerSpeakDirective(speech));
+ return Send(new VoicePlayerSpeakDirective(ssml));
}
- public Task SendSpeech(string speech)
+ public Task SendSpeech(string ssml)
{
- return Send(new VoicePlayerSpeakDirective(speech));
+ return Send(new VoicePlayerSpeakDirective(ssml));
}
public bool CanSend()