Allow Interaction Commands to run for up to 15 minutes by replying to discord immediately and handling the command in a separate thread
This commit is contained in:
parent
699a93200b
commit
17cb5951ee
4 changed files with 43 additions and 16 deletions
|
@ -7,6 +7,6 @@ namespace Geekbot.Interactions
|
||||||
public interface IInteractionCommandManager
|
public interface IInteractionCommandManager
|
||||||
{
|
{
|
||||||
Dictionary<string, Command> CommandsInfo { get; init; }
|
Dictionary<string, Command> CommandsInfo { get; init; }
|
||||||
Task<InteractionResponse> RunCommand(Interaction interaction);
|
InteractionResponse? RunCommand(Interaction interaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using Geekbot.Core;
|
||||||
using Geekbot.Core.GuildSettingsManager;
|
using Geekbot.Core.GuildSettingsManager;
|
||||||
|
using Geekbot.Core.Logger;
|
||||||
using Geekbot.Interactions.ApplicationCommand;
|
using Geekbot.Interactions.ApplicationCommand;
|
||||||
using Geekbot.Interactions.Request;
|
using Geekbot.Interactions.Request;
|
||||||
using Geekbot.Interactions.Response;
|
using Geekbot.Interactions.Response;
|
||||||
|
@ -14,6 +16,8 @@ namespace Geekbot.Interactions
|
||||||
|
|
||||||
private readonly IGuildSettingsManager _guildSettingsManager;
|
private readonly IGuildSettingsManager _guildSettingsManager;
|
||||||
|
|
||||||
|
private readonly IGeekbotLogger _logger;
|
||||||
|
|
||||||
private readonly Dictionary<CommandType, Dictionary<string, Type>> _commands = new() {
|
private readonly Dictionary<CommandType, Dictionary<string, Type>> _commands = new() {
|
||||||
{ CommandType.Message, new Dictionary<string, Type>() },
|
{ CommandType.Message, new Dictionary<string, Type>() },
|
||||||
{ CommandType.User, new Dictionary<string, Type>() },
|
{ CommandType.User, new Dictionary<string, Type>() },
|
||||||
|
@ -22,10 +26,12 @@ namespace Geekbot.Interactions
|
||||||
|
|
||||||
public Dictionary<string, Command> CommandsInfo { get; init; }
|
public Dictionary<string, Command> CommandsInfo { get; init; }
|
||||||
|
|
||||||
public InteractionCommandManager(IServiceProvider provider, IGuildSettingsManager guildSettingsManager)
|
public InteractionCommandManager(IServiceProvider provider, IGuildSettingsManager guildSettingsManager, IGeekbotLogger logger)
|
||||||
{
|
{
|
||||||
_provider = provider;
|
_provider = provider;
|
||||||
_guildSettingsManager = guildSettingsManager;
|
_guildSettingsManager = guildSettingsManager;
|
||||||
|
_logger = logger;
|
||||||
|
|
||||||
var interactions = Assembly.GetCallingAssembly()
|
var interactions = Assembly.GetCallingAssembly()
|
||||||
.GetTypes()
|
.GetTypes()
|
||||||
.Where(type => type.IsClass && !type.IsAbstract && type.IsSubclassOf(typeof(InteractionBase)))
|
.Where(type => type.IsClass && !type.IsAbstract && type.IsSubclassOf(typeof(InteractionBase)))
|
||||||
|
@ -42,16 +48,8 @@ namespace Geekbot.Interactions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<InteractionResponse> RunCommand(Interaction interaction)
|
private async Task HandleInteraction(Interaction interaction, InteractionBase command)
|
||||||
{
|
{
|
||||||
var type = _commands[interaction.Data.Type][interaction.Data.Name];
|
|
||||||
var command = ActivatorUtilities.CreateInstance(_provider, type) as InteractionBase;
|
|
||||||
|
|
||||||
if (command == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var guildSettings = _guildSettingsManager.GetSettings(ulong.Parse(interaction.GuildId));
|
var guildSettings = _guildSettingsManager.GetSettings(ulong.Parse(interaction.GuildId));
|
||||||
var language = guildSettings.Language;
|
var language = guildSettings.Language;
|
||||||
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(language);
|
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(language);
|
||||||
|
@ -72,7 +70,36 @@ namespace Geekbot.Interactions
|
||||||
command.AfterExecute(interaction);
|
command.AfterExecute(interaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
return response;
|
try
|
||||||
|
{
|
||||||
|
await HttpAbstractions.Patch(
|
||||||
|
new Uri($"https://discord.com/api/v8/webhooks/{interaction.ApplicationId}/{interaction.Token}/messages/@original"),
|
||||||
|
response.Data
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.Error(LogSource.Interaction, "Failed to send interaction response", e);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public InteractionResponse? RunCommand(Interaction interaction)
|
||||||
|
{
|
||||||
|
var type = _commands[interaction.Data.Type][interaction.Data.Name];
|
||||||
|
var command = ActivatorUtilities.CreateInstance(_provider, type) as InteractionBase;
|
||||||
|
|
||||||
|
if (command == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Task.Run(() => HandleInteraction(interaction, command).ConfigureAwait(false));
|
||||||
|
|
||||||
|
return new InteractionResponse()
|
||||||
|
{
|
||||||
|
Type = InteractionResponseType.DeferredChannelMessageWithSource
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -49,7 +49,7 @@ public class InteractionController : ControllerBase
|
||||||
return (interaction.Type, interaction.Version) switch
|
return (interaction.Type, interaction.Version) switch
|
||||||
{
|
{
|
||||||
(InteractionType.Ping, 1) => Ping(),
|
(InteractionType.Ping, 1) => Ping(),
|
||||||
(InteractionType.ApplicationCommand, 1) => await ApplicationCommand(interaction),
|
(InteractionType.ApplicationCommand, 1) => ApplicationCommand(interaction),
|
||||||
(InteractionType.MessageComponent, 1) => MessageComponent(interaction),
|
(InteractionType.MessageComponent, 1) => MessageComponent(interaction),
|
||||||
_ => StatusCode(501)
|
_ => StatusCode(501)
|
||||||
};
|
};
|
||||||
|
@ -64,9 +64,9 @@ public class InteractionController : ControllerBase
|
||||||
return Ok(response);
|
return Ok(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<IActionResult> ApplicationCommand(Interaction interaction)
|
private IActionResult ApplicationCommand(Interaction interaction)
|
||||||
{
|
{
|
||||||
var result = await _interactionCommandManager.RunCommand(interaction);
|
var result = _interactionCommandManager.RunCommand(interaction);
|
||||||
|
|
||||||
if (result == null)
|
if (result == null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,7 +28,7 @@ public static class WebApiStartup
|
||||||
builder.Services.AddControllers();
|
builder.Services.AddControllers();
|
||||||
builder.Services.AddCors(options => options.AddPolicy("AllowSpecificOrigin", cors => cors.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod()));
|
builder.Services.AddCors(options => options.AddPolicy("AllowSpecificOrigin", cors => cors.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod()));
|
||||||
|
|
||||||
var interactionCommandManager = new InteractionCommandManager(commandProvider, commandProvider.GetService<IGuildSettingsManager>());
|
var interactionCommandManager = new InteractionCommandManager(commandProvider, commandProvider.GetService<IGuildSettingsManager>(), logger);
|
||||||
var highscoreManager = new HighscoreManager(commandProvider.GetService<DatabaseContext>(), commandProvider.GetService<IUserRepository>());
|
var highscoreManager = new HighscoreManager(commandProvider.GetService<DatabaseContext>(), commandProvider.GetService<IUserRepository>());
|
||||||
|
|
||||||
builder.Services.AddSingleton(databaseContext);
|
builder.Services.AddSingleton(databaseContext);
|
||||||
|
|
Loading…
Reference in a new issue