Chatbot async improvements (#446)
* Add better chatbot handling by making them asynchronous Removes the need for having RunInTimespan as await Task.Delay now can handle this * Remove now unused classes * Handle commando's commands with ValueTask * Set values as not nullable, client sends all of these
This commit is contained in:
@@ -199,15 +199,13 @@ public class DialogueCallbacks(
|
||||
/// Handle client/mail/msg/send
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual ValueTask<string> SendMessage(
|
||||
public virtual async ValueTask<string> SendMessage(
|
||||
string url,
|
||||
SendMessageRequest request,
|
||||
string sessionID
|
||||
)
|
||||
{
|
||||
return new ValueTask<string>(
|
||||
_httpResponseUtil.GetBody(_dialogueController.SendMessage(sessionID, request))
|
||||
);
|
||||
return _httpResponseUtil.GetBody(await _dialogueController.SendMessage(sessionID, request));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -538,15 +538,22 @@ public class DialogueController(
|
||||
/// <param name="sessionId">Session/Player id</param>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
public virtual string SendMessage(string sessionId, SendMessageRequest request)
|
||||
public virtual async ValueTask<string> SendMessage(string sessionId, SendMessageRequest request)
|
||||
{
|
||||
_mailSendService.SendPlayerMessageToNpc(sessionId, request.DialogId!, request.Text!);
|
||||
|
||||
return (
|
||||
_dialogueChatBots
|
||||
.FirstOrDefault(cb => cb.GetChatBot().Id == request.DialogId)
|
||||
?.HandleMessage(sessionId, request) ?? request.DialogId
|
||||
) ?? string.Empty;
|
||||
var chatBot = _dialogueChatBots.FirstOrDefault(cb =>
|
||||
cb.GetChatBot().Id == request.DialogId
|
||||
);
|
||||
|
||||
if (chatBot is not null)
|
||||
{
|
||||
return await chatBot.HandleMessage(sessionId, request);
|
||||
}
|
||||
else
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -3,7 +3,6 @@ using SPTarkov.Server.Core.Models.Eft.Dialog;
|
||||
using SPTarkov.Server.Core.Models.Eft.Profile;
|
||||
using SPTarkov.Server.Core.Models.Utils;
|
||||
using SPTarkov.Server.Core.Services;
|
||||
using SPTarkov.Server.Core.Utils.Callbacks;
|
||||
|
||||
namespace SPTarkov.Server.Core.Helpers.Dialogue;
|
||||
|
||||
@@ -20,7 +19,7 @@ public abstract class AbstractDialogChatBot(
|
||||
|
||||
public abstract UserDialogInfo GetChatBot();
|
||||
|
||||
public string? HandleMessage(string sessionId, SendMessageRequest request)
|
||||
public async ValueTask<string> HandleMessage(string sessionId, SendMessageRequest request)
|
||||
{
|
||||
if ((request.Text ?? "").Length == 0)
|
||||
{
|
||||
@@ -37,14 +36,14 @@ public abstract class AbstractDialogChatBot(
|
||||
&& commando.GetCommands().Contains(splitCommand[1])
|
||||
)
|
||||
{
|
||||
return commando.Handle(splitCommand[1], GetChatBot(), sessionId, request);
|
||||
return await commando.Handle(splitCommand[1], GetChatBot(), sessionId, request);
|
||||
}
|
||||
|
||||
if (
|
||||
string.Equals(splitCommand.FirstOrDefault(), "help", StringComparison.OrdinalIgnoreCase)
|
||||
)
|
||||
{
|
||||
return SendPlayerHelpMessage(sessionId, request);
|
||||
return await SendPlayerHelpMessage(sessionId, request);
|
||||
}
|
||||
|
||||
_mailSendService.SendUserMessageToPlayer(
|
||||
@@ -55,10 +54,13 @@ public abstract class AbstractDialogChatBot(
|
||||
null
|
||||
);
|
||||
|
||||
return null;
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
protected string? SendPlayerHelpMessage(string sessionId, SendMessageRequest request)
|
||||
protected async ValueTask<string> SendPlayerHelpMessage(
|
||||
string sessionId,
|
||||
SendMessageRequest request
|
||||
)
|
||||
{
|
||||
_mailSendService.SendUserMessageToPlayer(
|
||||
sessionId,
|
||||
@@ -67,40 +69,34 @@ public abstract class AbstractDialogChatBot(
|
||||
[],
|
||||
null
|
||||
);
|
||||
// due to BSG being dumb with messages we need a mandatory timeout between messages so they get out on the right order
|
||||
TimeoutCallback.RunInTimespan(
|
||||
() =>
|
||||
{
|
||||
foreach (var chatCommand in _chatCommands.Values)
|
||||
{
|
||||
_mailSendService.SendUserMessageToPlayer(
|
||||
sessionId,
|
||||
GetChatBot(),
|
||||
$"Commands available for \"{chatCommand.GetCommandPrefix()}\" prefix:",
|
||||
[],
|
||||
null
|
||||
);
|
||||
foreach (var chatCommand in _chatCommands.Values)
|
||||
{
|
||||
// due to BSG being dumb with messages we need a mandatory timeout between messages so they get out on the right order
|
||||
await Task.Delay(TimeSpan.FromSeconds(1));
|
||||
|
||||
TimeoutCallback.RunInTimespan(
|
||||
() =>
|
||||
{
|
||||
foreach (var subCommand in chatCommand.GetCommands())
|
||||
{
|
||||
_mailSendService.SendUserMessageToPlayer(
|
||||
sessionId,
|
||||
GetChatBot(),
|
||||
$"Subcommand {subCommand}:\n{chatCommand.GetCommandHelp(subCommand)}",
|
||||
[],
|
||||
null
|
||||
);
|
||||
}
|
||||
},
|
||||
TimeSpan.FromSeconds(1)
|
||||
);
|
||||
}
|
||||
},
|
||||
TimeSpan.FromSeconds(1)
|
||||
);
|
||||
_mailSendService.SendUserMessageToPlayer(
|
||||
sessionId,
|
||||
GetChatBot(),
|
||||
$"Commands available for \"{chatCommand.GetCommandPrefix()}\" prefix:",
|
||||
[],
|
||||
null
|
||||
);
|
||||
|
||||
await Task.Delay(TimeSpan.FromSeconds(1));
|
||||
|
||||
foreach (var subCommand in chatCommand.GetCommands())
|
||||
{
|
||||
_mailSendService.SendUserMessageToPlayer(
|
||||
sessionId,
|
||||
GetChatBot(),
|
||||
$"Subcommand {subCommand}:\n{chatCommand.GetCommandHelp(subCommand)}",
|
||||
[],
|
||||
null
|
||||
);
|
||||
|
||||
await Task.Delay(TimeSpan.FromSeconds(1));
|
||||
}
|
||||
}
|
||||
|
||||
return request.DialogId;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ public interface IChatCommand
|
||||
public string GetCommandPrefix();
|
||||
public string GetCommandHelp(string command);
|
||||
public List<string> GetCommands();
|
||||
public string Handle(
|
||||
public ValueTask<string> Handle(
|
||||
string command,
|
||||
UserDialogInfo commandHandler,
|
||||
string sessionId,
|
||||
|
||||
@@ -50,14 +50,14 @@ public class SptCommandoCommands : IChatCommand
|
||||
return _sptCommands.Keys.ToList();
|
||||
}
|
||||
|
||||
public string Handle(
|
||||
public async ValueTask<string> Handle(
|
||||
string command,
|
||||
UserDialogInfo commandHandler,
|
||||
string sessionId,
|
||||
SendMessageRequest request
|
||||
)
|
||||
{
|
||||
return _sptCommands[command].PerformAction(commandHandler, sessionId, request);
|
||||
return await _sptCommands[command].PerformAction(commandHandler, sessionId, request);
|
||||
}
|
||||
|
||||
public void RegisterSptCommandoCommand(ISptCommand command)
|
||||
|
||||
+9
-9
@@ -52,7 +52,7 @@ public class GiveSptCommand(
|
||||
+ "give [locale] [\"item name\"] [quantity]\n\t\tEx: spt give fr \"figurine de chat\" 3";
|
||||
}
|
||||
|
||||
public string PerformAction(
|
||||
public ValueTask<string> PerformAction(
|
||||
UserDialogInfo commandHandler,
|
||||
string sessionId,
|
||||
SendMessageRequest request
|
||||
@@ -65,7 +65,7 @@ public class GiveSptCommand(
|
||||
commandHandler,
|
||||
"Invalid use of give command. Use 'help' for more information."
|
||||
);
|
||||
return request.DialogId;
|
||||
return new ValueTask<string>(request.DialogId);
|
||||
}
|
||||
|
||||
var result = _commandRegex.Match(request.Text);
|
||||
@@ -86,7 +86,7 @@ public class GiveSptCommand(
|
||||
commandHandler,
|
||||
"Invalid use of give command. Use 'help' for more information."
|
||||
);
|
||||
return request.DialogId;
|
||||
return new ValueTask<string>(request.DialogId);
|
||||
}
|
||||
|
||||
_savedCommand.TryGetValue(sessionId, out var savedCommand);
|
||||
@@ -98,7 +98,7 @@ public class GiveSptCommand(
|
||||
commandHandler,
|
||||
"Invalid selection. Outside of bounds! Use 'help' for more information."
|
||||
);
|
||||
return request.DialogId;
|
||||
return new ValueTask<string>(request.DialogId);
|
||||
}
|
||||
|
||||
item = savedCommand.PotentialItemNames[locationSixValue - 1];
|
||||
@@ -128,7 +128,7 @@ public class GiveSptCommand(
|
||||
commandHandler,
|
||||
"Invalid quantity! Must be 1 or higher. Use 'help' for more information."
|
||||
);
|
||||
return request.DialogId;
|
||||
return new ValueTask<string>(request.DialogId);
|
||||
}
|
||||
|
||||
if (isItemName)
|
||||
@@ -197,7 +197,7 @@ public class GiveSptCommand(
|
||||
$"Could not find exact match. Closest are:\n{string.Join("\n", itemList)}\n\nUse 'spt give [above number]' to select one."
|
||||
);
|
||||
|
||||
return request.DialogId;
|
||||
return new ValueTask<string>(request.DialogId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -224,7 +224,7 @@ public class GiveSptCommand(
|
||||
commandHandler,
|
||||
"That item could not be found. Please refine your request and try again."
|
||||
);
|
||||
return request.DialogId;
|
||||
return new ValueTask<string>(request.DialogId);
|
||||
}
|
||||
|
||||
List<Item> itemsToSend = [];
|
||||
@@ -286,7 +286,7 @@ public class GiveSptCommand(
|
||||
"Too many items requested. Please lower the amount and try again."
|
||||
);
|
||||
|
||||
return request.DialogId;
|
||||
return new ValueTask<string>(request.DialogId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -300,7 +300,7 @@ public class GiveSptCommand(
|
||||
itemsToSend
|
||||
);
|
||||
|
||||
return request.DialogId;
|
||||
return new ValueTask<string>(request.DialogId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -7,7 +7,7 @@ public interface ISptCommand
|
||||
{
|
||||
public string GetCommand();
|
||||
public string GetCommandHelp();
|
||||
public string PerformAction(
|
||||
public ValueTask<string> PerformAction(
|
||||
UserDialogInfo commandHandler,
|
||||
string sessionId,
|
||||
SendMessageRequest request
|
||||
|
||||
+7
-7
@@ -42,7 +42,7 @@ public class ProfileSptCommand(
|
||||
+ "spt profile skill metabolism 51";
|
||||
}
|
||||
|
||||
public string PerformAction(
|
||||
public ValueTask<string> PerformAction(
|
||||
UserDialogInfo commandHandler,
|
||||
string sessionId,
|
||||
SendMessageRequest request
|
||||
@@ -58,7 +58,7 @@ public class ProfileSptCommand(
|
||||
commandHandler,
|
||||
"Invalid use of trader command. Use 'help' for more information."
|
||||
);
|
||||
return request.DialogId;
|
||||
return new ValueTask<string>(request.DialogId);
|
||||
}
|
||||
|
||||
var result = _commandRegex.Match(request.Text);
|
||||
@@ -82,7 +82,7 @@ public class ProfileSptCommand(
|
||||
commandHandler,
|
||||
"Invalid use of profile command, the level was outside bounds: 1 to 70. Use 'help' for more information."
|
||||
);
|
||||
return request.DialogId;
|
||||
return new ValueTask<string>(request.DialogId);
|
||||
}
|
||||
|
||||
profileChangeEvent = HandleLevelCommand(quantity);
|
||||
@@ -102,7 +102,7 @@ public class ProfileSptCommand(
|
||||
commandHandler,
|
||||
"Invalid use of profile command, the skill was not found. Use 'help' for more information."
|
||||
);
|
||||
return request.DialogId;
|
||||
return new ValueTask<string>(request.DialogId);
|
||||
}
|
||||
|
||||
if (quantity is < 0 or > 51)
|
||||
@@ -112,7 +112,7 @@ public class ProfileSptCommand(
|
||||
commandHandler,
|
||||
"Invalid use of profile command, the skill level was outside bounds: 1 to 51. Use 'help' for more information."
|
||||
);
|
||||
return request.DialogId;
|
||||
return new ValueTask<string>(request.DialogId);
|
||||
}
|
||||
|
||||
profileChangeEvent = HandleSkillCommand(enumSkill, quantity);
|
||||
@@ -129,7 +129,7 @@ public class ProfileSptCommand(
|
||||
commandHandler,
|
||||
$"If you are reading this, this is bad. Please report this to SPT staff with a screenshot. Command: {command}."
|
||||
);
|
||||
return request.DialogId;
|
||||
return new ValueTask<string>(request.DialogId);
|
||||
}
|
||||
|
||||
_mailSendService.SendSystemMessageToPlayer(
|
||||
@@ -149,7 +149,7 @@ public class ProfileSptCommand(
|
||||
[profileChangeEvent]
|
||||
);
|
||||
|
||||
return request.DialogId;
|
||||
return new ValueTask<string>(request.DialogId);
|
||||
}
|
||||
|
||||
protected ProfileChangeEvent HandleSkillCommand(SkillTypes? skill, int level)
|
||||
|
||||
+5
-5
@@ -34,7 +34,7 @@ public class TraderSptCommand(
|
||||
return "spt trader \n ======== \n Sets the reputation or money spent to the input quantity through the message system.\n\n\tspt trader [trader] rep [quantity]\n\t\tEx: spt trader prapor rep 2\n\n\tspt trader [trader] spend [quantity]\n\t\tEx: spt trader therapist spend 1000000";
|
||||
}
|
||||
|
||||
public string PerformAction(
|
||||
public ValueTask<string> PerformAction(
|
||||
UserDialogInfo commandHandler,
|
||||
string sessionId,
|
||||
SendMessageRequest request
|
||||
@@ -47,7 +47,7 @@ public class TraderSptCommand(
|
||||
commandHandler,
|
||||
"Invalid use of trader command. Use 'help' for more information."
|
||||
);
|
||||
return request.DialogId;
|
||||
return new ValueTask<string>(request.DialogId);
|
||||
}
|
||||
|
||||
var result = _commandRegex.Match(request.Text);
|
||||
@@ -75,7 +75,7 @@ public class TraderSptCommand(
|
||||
"Invalid use of trader command, the trader was not found. Use 'help' for more information."
|
||||
);
|
||||
|
||||
return request.DialogId;
|
||||
return new ValueTask<string>(request.DialogId);
|
||||
}
|
||||
|
||||
NotificationEventType profileChangeEventType;
|
||||
@@ -96,7 +96,7 @@ public class TraderSptCommand(
|
||||
"Invalid use of trader command, ProfileChangeEventType was not found. Use 'help' for more information."
|
||||
);
|
||||
|
||||
return request.DialogId;
|
||||
return new ValueTask<string>(request.DialogId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ public class TraderSptCommand(
|
||||
[CreateProfileChangeEvent(profileChangeEventType, quantity, dbTrader.Id)]
|
||||
);
|
||||
|
||||
return request.DialogId;
|
||||
return new ValueTask<string>(request.DialogId);
|
||||
}
|
||||
|
||||
protected ProfileChangeEvent CreateProfileChangeEvent(
|
||||
|
||||
@@ -6,5 +6,10 @@ namespace SPTarkov.Server.Core.Helpers.Dialogue;
|
||||
public interface IDialogueChatBot
|
||||
{
|
||||
public UserDialogInfo GetChatBot();
|
||||
public string? HandleMessage(string sessionId, SendMessageRequest request);
|
||||
|
||||
/// <summary>
|
||||
/// Handles messages for the chatbot. If a message can't be handled, <see cref="string.Empty"/> should be used.
|
||||
/// </summary>
|
||||
/// <returns>The response of the bot, or <see cref="string.Empty"/> if the request could not be handled.</returns>
|
||||
public ValueTask<string> HandleMessage(string sessionId, SendMessageRequest request);
|
||||
}
|
||||
|
||||
@@ -13,9 +13,7 @@ namespace SPTarkov.Server.Core.Helpers.Dialogue;
|
||||
|
||||
[Injectable]
|
||||
public class SptDialogueChatBot(
|
||||
ISptLogger<AbstractDialogChatBot> _logger,
|
||||
MailSendService _mailSendService,
|
||||
IEnumerable<IChatCommand> _chatCommands,
|
||||
ConfigServer _configServer,
|
||||
ProfileHelper _profileHelper,
|
||||
IEnumerable<IChatMessageHandler> chatMessageHandlers
|
||||
@@ -42,7 +40,7 @@ public class SptDialogueChatBot(
|
||||
};
|
||||
}
|
||||
|
||||
public string? HandleMessage(string sessionId, SendMessageRequest request)
|
||||
public ValueTask<string> HandleMessage(string sessionId, SendMessageRequest request)
|
||||
{
|
||||
var sender = _profileHelper.GetPmcProfile(sessionId);
|
||||
var sptFriendUser = GetChatBot();
|
||||
@@ -57,7 +55,7 @@ public class SptDialogueChatBot(
|
||||
{
|
||||
handler.Process(sessionId, sptFriendUser, sender, request);
|
||||
|
||||
return request.DialogId;
|
||||
return new ValueTask<string>(request.DialogId);
|
||||
}
|
||||
|
||||
_mailSendService.SendUserMessageToPlayer(
|
||||
@@ -68,7 +66,7 @@ public class SptDialogueChatBot(
|
||||
null
|
||||
);
|
||||
|
||||
return request.DialogId;
|
||||
return new ValueTask<string>(request.DialogId);
|
||||
}
|
||||
|
||||
protected static List<IChatMessageHandler> ChatMessageHandlerSetup(
|
||||
@@ -86,7 +84,7 @@ public class SptDialogueChatBot(
|
||||
return "Unknown command.";
|
||||
}
|
||||
|
||||
protected string? SendPlayerHelpMessage(string sessionId, SendMessageRequest request)
|
||||
protected ValueTask<string> SendPlayerHelpMessage(string sessionId, SendMessageRequest request)
|
||||
{
|
||||
_mailSendService.SendUserMessageToPlayer(
|
||||
sessionId,
|
||||
@@ -96,6 +94,6 @@ public class SptDialogueChatBot(
|
||||
null
|
||||
);
|
||||
|
||||
return request.DialogId;
|
||||
return new ValueTask<string>(request.DialogId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,14 +10,14 @@ public record SendMessageRequest : IRequestData
|
||||
public Dictionary<string, object>? ExtensionData { get; set; }
|
||||
|
||||
[JsonPropertyName("dialogId")]
|
||||
public string? DialogId { get; set; }
|
||||
public required string DialogId { get; set; }
|
||||
|
||||
[JsonPropertyName("type")]
|
||||
public MessageType? Type { get; set; }
|
||||
public required MessageType Type { get; set; }
|
||||
|
||||
[JsonPropertyName("text")]
|
||||
public string? Text { get; set; }
|
||||
public required string Text { get; set; }
|
||||
|
||||
[JsonPropertyName("replyTo")]
|
||||
public string? ReplyTo { get; set; }
|
||||
public required string ReplyTo { get; set; }
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
namespace SPTarkov.Server.Core.Utils.Callbacks;
|
||||
|
||||
public static class TimeoutCallback
|
||||
{
|
||||
public static Task RunInTimespan(Action action, TimeSpan timeSpan)
|
||||
{
|
||||
return Task.Factory.StartNew(() =>
|
||||
{
|
||||
Thread.Sleep(timeSpan);
|
||||
action();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
using System.Diagnostics;
|
||||
using SPTarkov.DI.Annotations;
|
||||
|
||||
namespace SPTarkov.Server.Core.Utils;
|
||||
|
||||
[Injectable]
|
||||
public class TimerUtil
|
||||
{
|
||||
protected readonly Stopwatch _stopwatch;
|
||||
|
||||
public TimerUtil()
|
||||
{
|
||||
_stopwatch = new Stopwatch();
|
||||
_stopwatch.Start();
|
||||
}
|
||||
|
||||
public int Stop(string unit = "sec")
|
||||
{
|
||||
_stopwatch.Stop();
|
||||
var timePassed = _stopwatch.Elapsed;
|
||||
|
||||
return unit switch
|
||||
{
|
||||
"ns" => timePassed.Nanoseconds,
|
||||
"ms" => timePassed.Milliseconds,
|
||||
_ => timePassed.Seconds,
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user