refine states
This commit is contained in:
parent
a6d57e417c
commit
7ae9e3ef60
|
|
@ -22,6 +22,7 @@
|
|||
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||
<PackageReference Include="System.Text.Json" Version="8.0.1" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
namespace BotSharp.Abstraction.Conversations.Enums;
|
||||
|
||||
public class StateDataType
|
||||
{
|
||||
public const string String = "string";
|
||||
public const string Boolean = "boolean";
|
||||
public const string Number = "number";
|
||||
public const string Currency = "currency";
|
||||
public const string Date = "date";
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
namespace BotSharp.Abstraction.Conversations.Enums;
|
||||
|
||||
public class StateSource
|
||||
{
|
||||
public const string External = "external";
|
||||
public const string Application = "application";
|
||||
public const string User = "user";
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
using BotSharp.Abstraction.Conversations.Enums;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace BotSharp.Abstraction.Conversations;
|
||||
|
|
@ -12,7 +13,8 @@ public interface IConversationStateService
|
|||
string GetState(string name, string defaultValue = "");
|
||||
bool ContainsState(string name);
|
||||
Dictionary<string, string> GetStates();
|
||||
IConversationStateService SetState<T>(string name, T value, bool isNeedVersion = true, int activeRounds = -1);
|
||||
IConversationStateService SetState<T>(string name, T value, bool isNeedVersion = true,
|
||||
int activeRounds = -1, string valueType = StateDataType.String, string source = StateSource.User);
|
||||
void SaveStateByArgs(JsonDocument args);
|
||||
void CleanStates();
|
||||
void Save();
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
using BotSharp.Abstraction.Conversations.Enums;
|
||||
|
||||
namespace BotSharp.Abstraction.Conversations.Models;
|
||||
|
||||
public class StateKeyValue
|
||||
|
|
@ -16,6 +18,12 @@ public class StateKeyValue
|
|||
Key = key;
|
||||
Values = values;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var lastValue = Values.LastOrDefault();
|
||||
return $"{Key} => ({lastValue?.ToString()})";
|
||||
}
|
||||
}
|
||||
|
||||
public class StateValue
|
||||
|
|
@ -30,6 +38,12 @@ public class StateValue
|
|||
[JsonPropertyName("active_rounds")]
|
||||
public int ActiveRounds { get; set; }
|
||||
|
||||
[JsonPropertyName("data_type")]
|
||||
public string DataType { get; set; } = StateDataType.String;
|
||||
|
||||
[JsonPropertyName("source")]
|
||||
public string Source { get; set; }
|
||||
|
||||
[JsonPropertyName("update_time")]
|
||||
public DateTime UpdateTime { get; set; }
|
||||
|
||||
|
|
@ -37,4 +51,11 @@ public class StateValue
|
|||
{
|
||||
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var isActive = Active ? "Yes" : "No";
|
||||
var activeRounds = ActiveRounds <= 0 ? "infinity" : ActiveRounds.ToString();
|
||||
return $"Data: {Data}, Active: {isActive}, Active rounds: {activeRounds}, Source: {Source}";
|
||||
}
|
||||
}
|
||||
|
|
@ -3,10 +3,13 @@ using BotSharp.Abstraction.Messaging.Enums;
|
|||
using BotSharp.Abstraction.Messaging.Models.RichContent.Template;
|
||||
using BotSharp.Abstraction.Messaging.Models.RichContent;
|
||||
using System.Text.Json;
|
||||
using System.Reflection;
|
||||
using Newtonsoft.Json;
|
||||
using JsonSerializer = System.Text.Json.JsonSerializer;
|
||||
|
||||
namespace BotSharp.Core.Messaging;
|
||||
|
||||
public static class MessageParser
|
||||
public static class BotSharpMessageParser
|
||||
{
|
||||
|
||||
public static IRichMessage? ParseRichMessage(JsonElement root, JsonSerializerOptions options)
|
||||
|
|
@ -43,13 +46,13 @@ public static class MessageParser
|
|||
if (root.TryGetProperty("element_type", out element))
|
||||
{
|
||||
var elementType = element.GetString();
|
||||
if (elementType == typeof(GenericElement).Name)
|
||||
var wrapperType = typeof(GenericTemplateMessage<>);
|
||||
var genericType = Assembly.GetExecutingAssembly().GetTypes().FirstOrDefault(x => x.Name == elementType);
|
||||
|
||||
if (wrapperType != null && genericType != null)
|
||||
{
|
||||
res = JsonSerializer.Deserialize<GenericTemplateMessage<GenericElement>>(jsonText, options);
|
||||
}
|
||||
else if (elementType == typeof(ButtonElement).Name)
|
||||
{
|
||||
res = JsonSerializer.Deserialize<GenericTemplateMessage<ButtonElement>>(jsonText, options);
|
||||
var targetType = wrapperType.MakeGenericType(genericType);
|
||||
res = JsonConvert.DeserializeObject(jsonText, targetType) as IRichMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -88,13 +91,13 @@ public static class MessageParser
|
|||
if (root.TryGetProperty("element_type", out element))
|
||||
{
|
||||
var elementType = element.GetString();
|
||||
if (elementType == typeof(GenericElement).Name)
|
||||
var wrapperType = typeof(GenericTemplateMessage<>);
|
||||
var genericType = Assembly.GetExecutingAssembly().GetTypes().FirstOrDefault(x => x.Name == elementType);
|
||||
|
||||
if (wrapperType != null && genericType != null)
|
||||
{
|
||||
res = JsonSerializer.Deserialize<GenericTemplateMessage<GenericElement>>(jsonText, options);
|
||||
}
|
||||
else if (elementType == typeof(ButtonElement).Name)
|
||||
{
|
||||
res = JsonSerializer.Deserialize<GenericTemplateMessage<ButtonElement>>(jsonText, options);
|
||||
var targetType = wrapperType.MakeGenericType(genericType);
|
||||
res = JsonConvert.DeserializeObject(jsonText, targetType) as ITemplateMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ public class RichContentJsonConverter : JsonConverter<IRichMessage>
|
|||
{
|
||||
using var jsonDoc = JsonDocument.ParseValue(ref reader);
|
||||
var root = jsonDoc.RootElement;
|
||||
var res = MessageParser.ParseRichMessage(root, options);
|
||||
var res = BotSharpMessageParser.ParseRichMessage(root, options);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ public class TemplateMessageJsonConverter : JsonConverter<ITemplateMessage>
|
|||
{
|
||||
using var jsonDoc = JsonDocument.ParseValue(ref reader);
|
||||
var root = jsonDoc.RootElement;
|
||||
var res = MessageParser.ParseTemplateMessage(root, options);
|
||||
var res = BotSharpMessageParser.ParseTemplateMessage(root, options);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using BotSharp.Abstraction.Conversations.Enums;
|
||||
using BotSharp.Abstraction.Users.Enums;
|
||||
|
||||
namespace BotSharp.Core.Conversations.Services;
|
||||
|
|
@ -33,7 +34,8 @@ public class ConversationStateService : IConversationStateService, IDisposable
|
|||
/// <param name="value"></param>
|
||||
/// <param name="isNeedVersion">whether the state is related to message or not</param>
|
||||
/// <returns></returns>
|
||||
public IConversationStateService SetState<T>(string name, T value, bool isNeedVersion = true, int activeRounds = -1)
|
||||
public IConversationStateService SetState<T>(string name, T value, bool isNeedVersion = true,
|
||||
int activeRounds = -1, string valueType = StateDataType.String, string source = StateSource.User)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
|
|
@ -56,18 +58,21 @@ public class ConversationStateService : IConversationStateService, IDisposable
|
|||
_logger.LogInformation($"[STATE] {name} = {value}");
|
||||
var routingCtx = _services.GetRequiredService<IRoutingContext>();
|
||||
|
||||
foreach (var hook in hooks)
|
||||
if (!ContainsState(name) || preValue != currentValue || preActiveRounds != curActiveRounds)
|
||||
{
|
||||
hook.OnStateChanged(new StateChangeModel
|
||||
foreach (var hook in hooks)
|
||||
{
|
||||
ConversationId = _conversationId,
|
||||
MessageId = routingCtx.MessageId,
|
||||
Name = name,
|
||||
BeforeValue = preValue,
|
||||
BeforeActiveRounds = preActiveRounds,
|
||||
AfterValue = currentValue,
|
||||
AfterActiveRounds = curActiveRounds
|
||||
}).Wait();
|
||||
hook.OnStateChanged(new StateChangeModel
|
||||
{
|
||||
ConversationId = _conversationId,
|
||||
MessageId = routingCtx.MessageId,
|
||||
Name = name,
|
||||
BeforeValue = preValue,
|
||||
BeforeActiveRounds = preActiveRounds,
|
||||
AfterValue = currentValue,
|
||||
AfterActiveRounds = curActiveRounds
|
||||
}).Wait();
|
||||
}
|
||||
}
|
||||
|
||||
var newPair = new StateKeyValue
|
||||
|
|
@ -82,6 +87,8 @@ public class ConversationStateService : IConversationStateService, IDisposable
|
|||
MessageId = routingCtx.MessageId,
|
||||
Active = true,
|
||||
ActiveRounds = curActiveRounds,
|
||||
DataType = valueType,
|
||||
Source = source,
|
||||
UpdateTime = DateTime.UtcNow,
|
||||
};
|
||||
|
||||
|
|
@ -132,6 +139,8 @@ public class ConversationStateService : IConversationStateService, IDisposable
|
|||
MessageId = curMsgId,
|
||||
Active = false,
|
||||
ActiveRounds = value.ActiveRounds,
|
||||
DataType = value.DataType,
|
||||
Source = value.Source,
|
||||
UpdateTime = DateTime.UtcNow
|
||||
});
|
||||
continue;
|
||||
|
|
@ -192,6 +201,8 @@ public class ConversationStateService : IConversationStateService, IDisposable
|
|||
MessageId = curMsgId,
|
||||
Active = false,
|
||||
ActiveRounds = lastValue.ActiveRounds,
|
||||
DataType = lastValue.DataType,
|
||||
Source = lastValue.Source,
|
||||
UpdateTime = utcNow
|
||||
});
|
||||
}
|
||||
|
|
@ -246,7 +257,7 @@ public class ConversationStateService : IConversationStateService, IDisposable
|
|||
{
|
||||
if (!string.IsNullOrEmpty(property.Value.ToString()))
|
||||
{
|
||||
SetState(property.Name, property.Value);
|
||||
SetState(property.Name, property.Value, source: StateSource.Application);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue