From 7ae9e3ef60f2c62d89c6ad95069861fc600f1183 Mon Sep 17 00:00:00 2001
From: Jicheng Lu <103353@smsassist.com>
Date: Tue, 2 Apr 2024 11:38:18 -0500
Subject: [PATCH] refine states
---
.../BotSharp.Abstraction.csproj | 1 +
.../Conversations/Enums/StateDataType.cs | 10 ++++++
.../Conversations/Enums/StateSource.cs | 8 +++++
.../IConversationStateService.cs | 4 ++-
.../Conversations/Models/StateKeyValue.cs | 21 +++++++++++
...sageParser.cs => BotSharpMessageParser.cs} | 29 ++++++++-------
.../RichContentJsonConverter .cs | 2 +-
.../TemplateMessageJsonConverter.cs | 2 +-
.../Services/ConversationStateService.cs | 35 ++++++++++++-------
9 files changed, 84 insertions(+), 28 deletions(-)
create mode 100644 src/Infrastructure/BotSharp.Abstraction/Conversations/Enums/StateDataType.cs
create mode 100644 src/Infrastructure/BotSharp.Abstraction/Conversations/Enums/StateSource.cs
rename src/Infrastructure/BotSharp.Abstraction/Messaging/{MessageParser.cs => BotSharpMessageParser.cs} (75%)
diff --git a/src/Infrastructure/BotSharp.Abstraction/BotSharp.Abstraction.csproj b/src/Infrastructure/BotSharp.Abstraction/BotSharp.Abstraction.csproj
index bbade11e..65424adb 100644
--- a/src/Infrastructure/BotSharp.Abstraction/BotSharp.Abstraction.csproj
+++ b/src/Infrastructure/BotSharp.Abstraction/BotSharp.Abstraction.csproj
@@ -22,6 +22,7 @@
+
diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Enums/StateDataType.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Enums/StateDataType.cs
new file mode 100644
index 00000000..20d635f4
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/Enums/StateDataType.cs
@@ -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";
+}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Enums/StateSource.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Enums/StateSource.cs
new file mode 100644
index 00000000..31f32e16
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/Enums/StateSource.cs
@@ -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";
+}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationStateService.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationStateService.cs
index 07eab6c1..d71111fd 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationStateService.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationStateService.cs
@@ -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 GetStates();
- IConversationStateService SetState(string name, T value, bool isNeedVersion = true, int activeRounds = -1);
+ IConversationStateService SetState(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();
diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/StateKeyValue.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/StateKeyValue.cs
index 53618242..c70dbf03 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/StateKeyValue.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/StateKeyValue.cs
@@ -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}";
+ }
}
\ No newline at end of file
diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/MessageParser.cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/BotSharpMessageParser.cs
similarity index 75%
rename from src/Infrastructure/BotSharp.Abstraction/Messaging/MessageParser.cs
rename to src/Infrastructure/BotSharp.Abstraction/Messaging/BotSharpMessageParser.cs
index b739709c..6697ef34 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Messaging/MessageParser.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/BotSharpMessageParser.cs
@@ -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>(jsonText, options);
- }
- else if (elementType == typeof(ButtonElement).Name)
- {
- res = JsonSerializer.Deserialize>(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>(jsonText, options);
- }
- else if (elementType == typeof(ButtonElement).Name)
- {
- res = JsonSerializer.Deserialize>(jsonText, options);
+ var targetType = wrapperType.MakeGenericType(genericType);
+ res = JsonConvert.DeserializeObject(jsonText, targetType) as ITemplateMessage;
}
}
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/RichContentJsonConverter .cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/RichContentJsonConverter .cs
index 98230871..94d12796 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/RichContentJsonConverter .cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/RichContentJsonConverter .cs
@@ -9,7 +9,7 @@ public class RichContentJsonConverter : JsonConverter
{
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;
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/TemplateMessageJsonConverter.cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/TemplateMessageJsonConverter.cs
index da5fcfd1..84963d39 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/TemplateMessageJsonConverter.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/TemplateMessageJsonConverter.cs
@@ -9,7 +9,7 @@ public class TemplateMessageJsonConverter : JsonConverter
{
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;
}
diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs
index 9356e2f5..32fbb30a 100644
--- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs
+++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs
@@ -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
///
/// whether the state is related to message or not
///
- public IConversationStateService SetState(string name, T value, bool isNeedVersion = true, int activeRounds = -1)
+ public IConversationStateService SetState(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();
- 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);
}
}
}