Skip to content

Commit 4b5ae30

Browse files
committed
Adding Dialogs and other missing API methods
1 parent 44ac9ed commit 4b5ae30

File tree

84 files changed

+1568
-118
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+1568
-118
lines changed

SlackNet.AspNetCore/AspNetCoreExtensions.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System;
22
using Microsoft.AspNetCore.Builder;
33
using Microsoft.Extensions.DependencyInjection;
4+
using Microsoft.Extensions.DependencyInjection.Extensions;
5+
using SlackNet.Interaction;
46

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

1922
return serviceCollection;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using System.Threading.Tasks;
4+
using SlackNet.Interaction;
5+
6+
namespace SlackNet.AspNetCore
7+
{
8+
public class NullDialogSubmissionHandler : IDialogSubmissionHandler
9+
{
10+
public Task<IEnumerable<DialogError>> Handle(DialogSubmission dialog) => Task.FromResult(Enumerable.Empty<DialogError>());
11+
}
12+
}

SlackNet.AspNetCore/ResolvedActionHandler.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Threading.Tasks;
33
using Microsoft.Extensions.DependencyInjection;
4+
using SlackNet.Interaction;
45

56
namespace SlackNet.AspNetCore
67
{
@@ -24,10 +25,13 @@ public ResolvedActionHandler(IServiceProvider serviceProvider, string actionName
2425
_serviceProvider = serviceProvider;
2526
}
2627

27-
public override Task<MessageResponse> Handle(InteractiveMessage message)
28+
public override async Task<MessageResponse> Handle(InteractiveMessage message)
2829
{
29-
var handler = _serviceProvider.GetRequiredService<T>();
30-
return handler.Handle(message);
30+
using (var scope = _serviceProvider.CreateScope())
31+
{
32+
var handler = scope.ServiceProvider.GetRequiredService<T>();
33+
return await handler.Handle(message).ConfigureAwait(false);
34+
}
3135
}
3236
}
3337
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Threading.Tasks;
4+
using Microsoft.Extensions.DependencyInjection;
5+
using SlackNet.Interaction;
6+
7+
namespace SlackNet.AspNetCore
8+
{
9+
public class ResolvedDialogSubmissionHandler<T> : IDialogSubmissionHandler
10+
where T : IDialogSubmissionHandler
11+
{
12+
private readonly IServiceProvider _serviceProvider;
13+
public ResolvedDialogSubmissionHandler(IServiceProvider serviceProvider) => _serviceProvider = serviceProvider;
14+
15+
public async Task<IEnumerable<DialogError>> Handle(DialogSubmission dialog)
16+
{
17+
using (var scope = _serviceProvider.CreateScope())
18+
{
19+
var handler = scope.ServiceProvider.GetRequiredService<T>();
20+
return await handler.Handle(dialog).ConfigureAwait(false);
21+
}
22+
}
23+
}
24+
}

SlackNet.AspNetCore/ResolvedOptionProvider.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Threading.Tasks;
33
using Microsoft.Extensions.DependencyInjection;
4+
using SlackNet.Interaction;
45

56
namespace SlackNet.AspNetCore
67
{

SlackNet.AspNetCore/SlackActionsService.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Collections.Generic;
22
using System.Threading.Tasks;
3+
using SlackNet.Interaction;
34

45
namespace SlackNet.AspNetCore
56
{

SlackNet.AspNetCore/SlackEventsMiddleware.cs

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
using System.Collections.Generic;
12
using System.IO;
23
using System.Linq;
34
using System.Net;
45
using System.Threading.Tasks;
56
using Microsoft.AspNetCore.Http;
67
using Newtonsoft.Json;
78
using SlackNet.Events;
9+
using SlackNet.Interaction;
810

911
namespace SlackNet.AspNetCore
1012
{
@@ -15,21 +17,24 @@ class SlackEventsMiddleware
1517
private readonly ISlackEvents _slackEvents;
1618
private readonly ISlackActions _slackActions;
1719
private readonly ISlackOptions _slackOptions;
20+
private readonly IDialogSubmissionHandler _dialogSubmissionHandler;
1821
private readonly SlackJsonSettings _jsonSettings;
1922

2023
public SlackEventsMiddleware(
21-
RequestDelegate next,
22-
SlackEndpointConfiguration configuration,
23-
ISlackEvents slackEvents,
24-
ISlackActions slackActions,
24+
RequestDelegate next,
25+
SlackEndpointConfiguration configuration,
26+
ISlackEvents slackEvents,
27+
ISlackActions slackActions,
2528
ISlackOptions slackOptions,
29+
IDialogSubmissionHandler dialogSubmissionHandler,
2630
SlackJsonSettings jsonSettings)
2731
{
2832
_next = next;
2933
_configuration = configuration;
3034
_slackEvents = slackEvents;
3135
_slackActions = slackActions;
3236
_slackOptions = slackOptions;
37+
_dialogSubmissionHandler = dialogSubmissionHandler;
3338
_jsonSettings = jsonSettings;
3439
}
3540

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

6166
if (body is EventCallback eventCallback && IsValidToken(eventCallback.Token))
6267
{
68+
var response = context.Respond(HttpStatusCode.OK).ConfigureAwait(false);
6369
_slackEvents.Handle(eventCallback);
64-
return await context.Respond(HttpStatusCode.OK).ConfigureAwait(false);
70+
return await response;
6571
}
6672

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

75-
var interactiveMessage = await DeserializePayload<InteractiveMessage>(context).ConfigureAwait(false);
81+
var interactionRequest = await DeserializePayload<InteractionRequest>(context).ConfigureAwait(false);
7682

77-
if (interactiveMessage != null && IsValidToken(interactiveMessage.Token))
83+
if (interactionRequest != null && IsValidToken(interactionRequest.Token))
7884
{
79-
var response = await _slackActions.Handle(interactiveMessage).ConfigureAwait(false);
80-
81-
var responseJson = response == null ? null
82-
: interactiveMessage.IsAppUnfurl ? Serialize(new AttachmentUpdateResponse(response))
83-
: Serialize(new MessageUpdateResponse(response));
84-
85-
return await context.Respond(HttpStatusCode.OK, "application/json", responseJson).ConfigureAwait(false);
85+
switch (interactionRequest)
86+
{
87+
case InteractiveMessage interactiveMessage:
88+
return await HandleInteractiveMessage(context, interactiveMessage).ConfigureAwait(false);
89+
case DialogSubmission dialogSubmission:
90+
return await HandleDialogSubmission(context, dialogSubmission).ConfigureAwait(false);
91+
}
8692
}
8793

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

97+
private async Task<HttpResponse> HandleInteractiveMessage(HttpContext context, InteractiveMessage interactiveMessage)
98+
{
99+
var response = await _slackActions.Handle(interactiveMessage).ConfigureAwait(false);
100+
101+
var responseJson = response == null ? null
102+
: interactiveMessage.IsAppUnfurl ? Serialize(new AttachmentUpdateResponse(response))
103+
: Serialize(new MessageUpdateResponse(response));
104+
105+
return await context.Respond(HttpStatusCode.OK, "application/json", responseJson).ConfigureAwait(false);
106+
}
107+
108+
private async Task<HttpResponse> HandleDialogSubmission(HttpContext context, DialogSubmission dialog)
109+
{
110+
var errors = (await _dialogSubmissionHandler.Handle(dialog).ConfigureAwait(false))?.ToList()
111+
?? new List<DialogError>();
112+
113+
return errors.Any()
114+
? await context.Respond(HttpStatusCode.OK, "application/json", Serialize(new DialogErrorResponse { Errors = errors })).ConfigureAwait(false)
115+
: await context.Respond(HttpStatusCode.OK).ConfigureAwait(false);
116+
}
117+
91118
private async Task<HttpResponse> HandleSlackOptions(HttpContext context)
92119
{
93120
if (context.Request.Method != "POST")

SlackNet.AspNetCore/SlackOptionsService.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Collections.Generic;
22
using System.Threading.Tasks;
3+
using SlackNet.Interaction;
34

45
namespace SlackNet.AspNetCore
56
{

SlackNet.AspNetCore/SlackServiceConfiguration.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Microsoft.Extensions.DependencyInjection;
22
using SlackNet.Events;
3+
using SlackNet.Interaction;
34

45
namespace SlackNet.AspNetCore
56
{
@@ -43,6 +44,13 @@ public SlackServiceConfiguration RegisterOptionProvider<TProvider>(string action
4344
return this;
4445
}
4546

47+
public SlackServiceConfiguration RegisterDialogSubmissionHandler<THandler>()
48+
where THandler : IDialogSubmissionHandler
49+
{
50+
_serviceCollection.AddSingleton<IDialogSubmissionHandler>(c => new ResolvedDialogSubmissionHandler<THandler>(c));
51+
return this;
52+
}
53+
4654
public string ApiToken { get; private set; }
4755
}
4856
}

SlackNet.EventsExample/ColorSelector.cs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Drawing;
33
using System.Linq;
44
using System.Threading.Tasks;
5+
using SlackNet.Interaction;
56

67
namespace SlackNet.EventsExample
78
{
@@ -11,12 +12,13 @@ public class ColorSelector : IActionHandler, IOptionProvider
1112

1213
public async Task<MessageResponse> Handle(InteractiveMessage message)
1314
{
14-
message.OriginalAttachment.Color = message.Action.SelectedValue;
15-
message.OriginalAttachment.Actions[0].SelectedOptions = new List<Option>
15+
var menu = (Menu)message.Action;
16+
message.OriginalAttachment.Color = menu.SelectedValue;
17+
((Menu)message.OriginalAttachment.Actions[0]).SelectedOptions = new List<Option>
1618
{
1719
GetOptions(string.Empty)
18-
.FirstOrDefault(o => o.Value == message.Action.SelectedValue)
19-
?? new Option { Text = message.Action.SelectedValue, Value = message.Action.SelectedValue }
20+
.FirstOrDefault(o => o.Value == menu.SelectedValue)
21+
?? new Option { Text = menu.SelectedValue, Value = menu.SelectedValue }
2022
};
2123

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

38-
public static IList<Action> Actions => new List<Action>
40+
public static IList<ActionElement> Actions => new List<ActionElement>
3941
{
40-
new Action
42+
new Menu
4143
{
42-
Type = ActionType.Select,
4344
Name = ActionName,
4445
Text = "Select a color",
4546
DataSource = DataSource.External

0 commit comments

Comments
 (0)