Skip to content

Commit

Permalink
Adding Dialogs and other missing API methods
Browse files Browse the repository at this point in the history
  • Loading branch information
soxtoby committed Jan 2, 2018
1 parent 44ac9ed commit 4b5ae30
Show file tree
Hide file tree
Showing 84 changed files with 1,568 additions and 118 deletions.
3 changes: 3 additions & 0 deletions SlackNet.AspNetCore/AspNetCoreExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using SlackNet.Interaction;

namespace SlackNet.AspNetCore
{
Expand All @@ -14,6 +16,7 @@ public static IServiceCollection AddSlackNet(this IServiceCollection serviceColl
serviceCollection.AddSingleton<ISlackEvents, SlackEventsService>();
serviceCollection.AddSingleton<ISlackActions, SlackActionsService>();
serviceCollection.AddSingleton<ISlackOptions, SlackOptionsService>();
serviceCollection.TryAddSingleton<IDialogSubmissionHandler, NullDialogSubmissionHandler>();
serviceCollection.AddTransient<ISlackApiClient>(c => new SlackApiClient(c.GetService<IHttp>(), c.GetService<ISlackUrlBuilder>(), c.GetService<SlackJsonSettings>(), configuration.ApiToken));

return serviceCollection;
Expand Down
12 changes: 12 additions & 0 deletions SlackNet.AspNetCore/NullDialogSubmissionHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using SlackNet.Interaction;

namespace SlackNet.AspNetCore
{
public class NullDialogSubmissionHandler : IDialogSubmissionHandler
{
public Task<IEnumerable<DialogError>> Handle(DialogSubmission dialog) => Task.FromResult(Enumerable.Empty<DialogError>());
}
}
10 changes: 7 additions & 3 deletions SlackNet.AspNetCore/ResolvedActionHandler.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using SlackNet.Interaction;

namespace SlackNet.AspNetCore
{
Expand All @@ -24,10 +25,13 @@ public ResolvedActionHandler(IServiceProvider serviceProvider, string actionName
_serviceProvider = serviceProvider;
}

public override Task<MessageResponse> Handle(InteractiveMessage message)
public override async Task<MessageResponse> Handle(InteractiveMessage message)
{
var handler = _serviceProvider.GetRequiredService<T>();
return handler.Handle(message);
using (var scope = _serviceProvider.CreateScope())
{
var handler = scope.ServiceProvider.GetRequiredService<T>();
return await handler.Handle(message).ConfigureAwait(false);
}
}
}
}
24 changes: 24 additions & 0 deletions SlackNet.AspNetCore/ResolvedDialogSubmissionHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using SlackNet.Interaction;

namespace SlackNet.AspNetCore
{
public class ResolvedDialogSubmissionHandler<T> : IDialogSubmissionHandler
where T : IDialogSubmissionHandler
{
private readonly IServiceProvider _serviceProvider;
public ResolvedDialogSubmissionHandler(IServiceProvider serviceProvider) => _serviceProvider = serviceProvider;

public async Task<IEnumerable<DialogError>> Handle(DialogSubmission dialog)
{
using (var scope = _serviceProvider.CreateScope())
{
var handler = scope.ServiceProvider.GetRequiredService<T>();
return await handler.Handle(dialog).ConfigureAwait(false);
}
}
}
}
1 change: 1 addition & 0 deletions SlackNet.AspNetCore/ResolvedOptionProvider.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using SlackNet.Interaction;

namespace SlackNet.AspNetCore
{
Expand Down
1 change: 1 addition & 0 deletions SlackNet.AspNetCore/SlackActionsService.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using SlackNet.Interaction;

namespace SlackNet.AspNetCore
{
Expand Down
55 changes: 41 additions & 14 deletions SlackNet.AspNetCore/SlackEventsMiddleware.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using SlackNet.Events;
using SlackNet.Interaction;

namespace SlackNet.AspNetCore
{
Expand All @@ -15,21 +17,24 @@ class SlackEventsMiddleware
private readonly ISlackEvents _slackEvents;
private readonly ISlackActions _slackActions;
private readonly ISlackOptions _slackOptions;
private readonly IDialogSubmissionHandler _dialogSubmissionHandler;
private readonly SlackJsonSettings _jsonSettings;

public SlackEventsMiddleware(
RequestDelegate next,
SlackEndpointConfiguration configuration,
ISlackEvents slackEvents,
ISlackActions slackActions,
RequestDelegate next,
SlackEndpointConfiguration configuration,
ISlackEvents slackEvents,
ISlackActions slackActions,
ISlackOptions slackOptions,
IDialogSubmissionHandler dialogSubmissionHandler,
SlackJsonSettings jsonSettings)
{
_next = next;
_configuration = configuration;
_slackEvents = slackEvents;
_slackActions = slackActions;
_slackOptions = slackOptions;
_dialogSubmissionHandler = dialogSubmissionHandler;
_jsonSettings = jsonSettings;
}

Expand Down Expand Up @@ -60,8 +65,9 @@ private async Task<HttpResponse> HandleSlackEvent(HttpContext context)

if (body is EventCallback eventCallback && IsValidToken(eventCallback.Token))
{
var response = context.Respond(HttpStatusCode.OK).ConfigureAwait(false);
_slackEvents.Handle(eventCallback);
return await context.Respond(HttpStatusCode.OK).ConfigureAwait(false);
return await response;
}

return await context.Respond(HttpStatusCode.BadRequest, body: "Invalid token or unrecognized content").ConfigureAwait(false);
Expand All @@ -72,22 +78,43 @@ private async Task<HttpResponse> HandleSlackAction(HttpContext context)
if (context.Request.Method != "POST")
return await context.Respond(HttpStatusCode.MethodNotAllowed).ConfigureAwait(false);

var interactiveMessage = await DeserializePayload<InteractiveMessage>(context).ConfigureAwait(false);
var interactionRequest = await DeserializePayload<InteractionRequest>(context).ConfigureAwait(false);

if (interactiveMessage != null && IsValidToken(interactiveMessage.Token))
if (interactionRequest != null && IsValidToken(interactionRequest.Token))
{
var response = await _slackActions.Handle(interactiveMessage).ConfigureAwait(false);

var responseJson = response == null ? null
: interactiveMessage.IsAppUnfurl ? Serialize(new AttachmentUpdateResponse(response))
: Serialize(new MessageUpdateResponse(response));

return await context.Respond(HttpStatusCode.OK, "application/json", responseJson).ConfigureAwait(false);
switch (interactionRequest)
{
case InteractiveMessage interactiveMessage:
return await HandleInteractiveMessage(context, interactiveMessage).ConfigureAwait(false);
case DialogSubmission dialogSubmission:
return await HandleDialogSubmission(context, dialogSubmission).ConfigureAwait(false);
}
}

return await context.Respond(HttpStatusCode.BadRequest, body: "Invalid token or unrecognized content").ConfigureAwait(false);
}

private async Task<HttpResponse> HandleInteractiveMessage(HttpContext context, InteractiveMessage interactiveMessage)
{
var response = await _slackActions.Handle(interactiveMessage).ConfigureAwait(false);

var responseJson = response == null ? null
: interactiveMessage.IsAppUnfurl ? Serialize(new AttachmentUpdateResponse(response))
: Serialize(new MessageUpdateResponse(response));

return await context.Respond(HttpStatusCode.OK, "application/json", responseJson).ConfigureAwait(false);
}

private async Task<HttpResponse> HandleDialogSubmission(HttpContext context, DialogSubmission dialog)
{
var errors = (await _dialogSubmissionHandler.Handle(dialog).ConfigureAwait(false))?.ToList()
?? new List<DialogError>();

return errors.Any()
? await context.Respond(HttpStatusCode.OK, "application/json", Serialize(new DialogErrorResponse { Errors = errors })).ConfigureAwait(false)
: await context.Respond(HttpStatusCode.OK).ConfigureAwait(false);
}

private async Task<HttpResponse> HandleSlackOptions(HttpContext context)
{
if (context.Request.Method != "POST")
Expand Down
1 change: 1 addition & 0 deletions SlackNet.AspNetCore/SlackOptionsService.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using SlackNet.Interaction;

namespace SlackNet.AspNetCore
{
Expand Down
8 changes: 8 additions & 0 deletions SlackNet.AspNetCore/SlackServiceConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Microsoft.Extensions.DependencyInjection;
using SlackNet.Events;
using SlackNet.Interaction;

namespace SlackNet.AspNetCore
{
Expand Down Expand Up @@ -43,6 +44,13 @@ public SlackServiceConfiguration RegisterOptionProvider<TProvider>(string action
return this;
}

public SlackServiceConfiguration RegisterDialogSubmissionHandler<THandler>()
where THandler : IDialogSubmissionHandler
{
_serviceCollection.AddSingleton<IDialogSubmissionHandler>(c => new ResolvedDialogSubmissionHandler<THandler>(c));
return this;
}

public string ApiToken { get; private set; }
}
}
15 changes: 8 additions & 7 deletions SlackNet.EventsExample/ColorSelector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Drawing;
using System.Linq;
using System.Threading.Tasks;
using SlackNet.Interaction;

namespace SlackNet.EventsExample
{
Expand All @@ -11,12 +12,13 @@ public class ColorSelector : IActionHandler, IOptionProvider

public async Task<MessageResponse> Handle(InteractiveMessage message)
{
message.OriginalAttachment.Color = message.Action.SelectedValue;
message.OriginalAttachment.Actions[0].SelectedOptions = new List<Option>
var menu = (Menu)message.Action;
message.OriginalAttachment.Color = menu.SelectedValue;
((Menu)message.OriginalAttachment.Actions[0]).SelectedOptions = new List<Option>
{
GetOptions(string.Empty)
.FirstOrDefault(o => o.Value == message.Action.SelectedValue)
?? new Option { Text = message.Action.SelectedValue, Value = message.Action.SelectedValue }
.FirstOrDefault(o => o.Value == menu.SelectedValue)
?? new Option { Text = menu.SelectedValue, Value = menu.SelectedValue }
};

return new MessageResponse
Expand All @@ -35,11 +37,10 @@ private static List<Option> GetOptions(string search) =>
.Select(c => new Option { Text = c.Name, Value = $"#{c.R:X2}{c.G:X2}{c.B:X2}" })
.ToList();

public static IList<Action> Actions => new List<Action>
public static IList<ActionElement> Actions => new List<ActionElement>
{
new Action
new Menu
{
Type = ActionType.Select,
Name = ActionName,
Text = "Select a color",
DataSource = DataSource.External
Expand Down
9 changes: 5 additions & 4 deletions SlackNet.EventsExample/Counter.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using SlackNet.Interaction;

namespace SlackNet.EventsExample
{
Expand Down Expand Up @@ -28,21 +29,21 @@ public async Task<MessageResponse> Handle(InteractiveMessage message)
return null;
}

public static IList<Action> Actions => new List<Action>
public static IList<ActionElement> Actions => new List<ActionElement>
{
new Action
new Button
{
Name = ActionName,
Value = "1",
Text = "Add 1"
},
new Action
new Button
{
Name = ActionName,
Value = "5",
Text = "Add 5"
},
new Action
new Button
{
Name = ActionName,
Value = "10",
Expand Down
Loading

0 comments on commit 4b5ae30

Please sign in to comment.