public static async Task <IBotData> GetBotDataAsync(IAddress userAddress, IBotDataStore <BotData> botDataStore, CancellationToken cancellationToken) { var botData = new JObjectBotData(userAddress, botDataStore); await botData.LoadAsync(cancellationToken); return(botData); }
private async Task HandleUserData(Activity activity) { using (ILifetimeScope scope = DialogModule.BeginLifetimeScope(Conversation.Container, activity)) { IAddress address = Address.FromActivity(activity); IBotDataStore <BotData> botDataStore = scope.Resolve <IBotDataStore <BotData> >(); BotData userData = await botDataStore.LoadAsync(address, BotStoreType.BotUserData, CancellationToken.None); User user = userData.GetProperty <User>("User"); if (user == null) { IUserService userService = scope.Resolve <IUserService>(); UserCondition condition = new UserCondition() { LineUserId = activity.From.Id, UserName = activity.From.Name }; user = userService.GetOrCreate(condition); userData.SetProperty("User", user); await botDataStore.SaveAsync(address, BotStoreType.BotUserData, userData, CancellationToken.None); await botDataStore.FlushAsync(address, CancellationToken.None); } } }
/// <summary> /// Constructs a new <see cref="V3V4Storage"/> /// </summary> /// <param name="v3DataStore">A Bot Builder SDK V3 <see cref="IBotDataStore"/> (required)</param> /// <param name="botStoreType">THe Type of Data Storage (UserData, ConversationData, PrivateConversationData) /// <see cref="BotStoreType"/>Type of storage</param> /// <param name="statePropertyName">This is only relavent in code. The name of the BotState property, /// retrieved and accessed through a property accessor created from an instance of <see cref="V3V4State"/>.</param> public V3V4Storage(IBotDataStore <BotData> v3DataStore, BotStoreType botStoreType = BotStoreType.BotUserData, string statePropertyName = "V3State") { _v3DataStore = v3DataStore ?? throw new ArgumentNullException(nameof(v3DataStore)); _botStoreType = botStoreType; _statePropertyName = statePropertyName; }
private async Task <bool> isNewUser(string userId, Microsoft.Bot.Connector.Activity message, TableBotDataStore botStateStore) { IBotDataStore <BotData> dataStore = botStateStore; pigLatinBotUserData addedUserData = new pigLatinBotUserData(); BotData botData = new BotData(); try { botData = (BotData)await dataStore.LoadAsync(new Address(message.Recipient.Id, message.ChannelId, userId, message.Conversation.Id, message.ServiceUrl), BotStoreType.BotUserData, default(CancellationToken)); } catch (Exception e) { if (e.Message == "Resource not found") { } else { throw e; } } if (botData.Data == null) { botData = new BotData(eTag: "*"); } addedUserData = botData.GetProperty <pigLatinBotUserData>("v1") ?? new pigLatinBotUserData(); if (addedUserData.isNewUser == true) { return(true); } else { return(false); } }
public virtual async Task <HttpResponseMessage> Post([FromBody] Microsoft.Bot.Connector.Activity message) { ConnectorClient connector = new ConnectorClient(new Uri(message.ServiceUrl)); IBotDataStore <BotData> dataStore = botStateStore; storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("piglatinbotsjameslew_AzureStorageConnectionString")); botStateStore = new TableBotDataStore(storageAccount, "botdata"); Microsoft.Bot.Connector.Activity replyMessage = message.CreateReply(); replyMessage.Locale = "en-Us"; replyMessage.TextFormat = TextFormatTypes.Plain; if (message.GetActivityType() != ActivityTypes.Message) { replyMessage = await handleSystemMessagesAsync(message, connector, botStateStore); if (replyMessage != null) { var reply = await connector.Conversations.ReplyToActivityAsync(replyMessage); } } else { if (message.Text.Contains("MessageTypesTest")) { Microsoft.Bot.Connector.Activity mtResult = await messageTypesTest(message, connector); await connector.Conversations.ReplyToActivityAsync(mtResult); } else if (message.Text.Contains("DataTypesTest")) { Microsoft.Bot.Connector.Activity dtResult = await dataTypesTest(message, connector, botStateStore); await connector.Conversations.ReplyToActivityAsync(dtResult); } else if (message.Text.Contains("CardTypesTest")) { Microsoft.Bot.Connector.Activity ctResult = await cardTypesTest(message, connector); await connector.Conversations.ReplyToActivityAsync(ctResult); } try { if (await isNewUser(message.From.Id, message, botStateStore)) { Microsoft.Bot.Connector.Activity introMessage = message.CreateReply(); introMessage.Locale = "en-Us"; introMessage.TextFormat = TextFormatTypes.Plain; introMessage.InputHint = InputHints.IgnoringInput; introMessage.Text = string.Format(translateToPigLatin("Hey there, I'm PigLatinBot. I make intelligible text unintelligible. Ask me how by typing 'Help', and for terms and info, click ") + "[erehay](http://www.piglatinbot.com)", message.From.Name); var reply = await connector.Conversations.ReplyToActivityAsync(introMessage); } replyMessage.InputHint = InputHints.AcceptingInput; replyMessage.Speak = message.Text; replyMessage.Text = translateToPigLatin(message.Text); var httpResponse = await connector.Conversations.ReplyToActivityAsync(replyMessage); } catch (HttpResponseException e) { Trace.WriteLine(e.Message); var Response = Request.CreateResponse(HttpStatusCode.InternalServerError); return(Response); } } var responseOtherwise = Request.CreateResponse(HttpStatusCode.OK); return(responseOtherwise); }
private async Task <Microsoft.Bot.Connector.Activity> handleSystemMessagesAsync(Microsoft.Bot.Connector.Activity message, ConnectorClient connector, TableBotDataStore botStateStore) { Microsoft.Bot.Connector.Activity replyMessage = message.CreateReply(); message.Locale = "en"; IBotDataStore <BotData> dataStore = botStateStore; switch (message.GetActivityType()) { case ActivityTypes.DeleteUserData: //In this case the DeleteUserData message comes from the user so we can clear the data and set it back directly BotData currentBotData = (BotData)await dataStore.LoadAsync(new Address(message.Recipient.Id, message.ChannelId, message.From.Id, message.Conversation.Id, message.ServiceUrl), BotStoreType.BotUserData, default(CancellationToken)); pigLatinBotUserData deleteUserData = new pigLatinBotUserData(); currentBotData.SetProperty("v1", deleteUserData); await dataStore.SaveAsync(new Address(message.Recipient.Id, message.ChannelId, message.From.Id, message.Conversation.Id, message.ServiceUrl), BotStoreType.BotUserData, currentBotData, default(CancellationToken)); replyMessage.Text = translateToPigLatin("I have deleted your data oh masterful one"); Trace.TraceInformation("Clearing user's BotUserData"); return(replyMessage); //if they're new or haven't seen the updated legal documents, send them a message //use the incoming message to set up the outgoing message case ActivityTypes.ConversationUpdate: foreach (ChannelAccount added in message.MembersAdded) { Microsoft.Bot.Connector.Activity addedMessage = message.CreateReply(); bool needToSendWelcomeText = false; pigLatinBotUserData addedUserData = new pigLatinBotUserData(); BotData botData = new BotData(); // is the added member me? if (added.Id == message.Recipient.Id) { addedMessage.Text = string.Format(translateToPigLatin("Hey there, I'm PigLatinBot. I make intelligible text unintelligible. Ask me how by typing 'Help', and for terms and info, click ") + "[erehay](http://www.piglatinbot.com)", added.Name); var reply = await connector.Conversations.ReplyToActivityAsync(addedMessage); continue; } if (await isNewUser(added.Id, message, botStateStore)) { addedUserData.isNewUser = false; needToSendWelcomeText = true; } if (addedUserData.lastReadLegalese < lastModifiedPolicies) { addedUserData.lastReadLegalese = DateTime.UtcNow; needToSendWelcomeText = true; } if (needToSendWelcomeText) { addedMessage.Text = string.Format(translateToPigLatin("Welcome to the chat") + " {0}, " + translateToPigLatin("I'm PigLatinBot. I make intelligible text unintelligible. Ask me how by typing 'Help', and for terms and info, click ") + "[erehay](http://www.piglatinbot.com)", added.Name); addedMessage.Recipient = added; addedMessage.Conversation = null; try { botData.SetProperty("v1", addedUserData); await dataStore.SaveAsync(new Address(message.Recipient.Id, message.ChannelId, added.Id, message.Conversation.Id, message.ServiceUrl), BotStoreType.BotUserData, botData, default(CancellationToken)); } catch (Exception e) { Trace.WriteLine(e.Message); } var ConversationId = await connector.Conversations.CreateDirectConversationAsync(message.Recipient, message.From); addedMessage.Conversation = new ConversationAccount(id: ConversationId.Id); var reply = await connector.Conversations.SendToConversationAsync(addedMessage); } } //maybe someone got removed foreach (ChannelAccount removed in message.MembersRemoved) { Microsoft.Bot.Connector.Activity removedMessage = message.CreateReply(); removedMessage.Locale = "en"; removedMessage.Text = string.Format("{0}", removed.Name) + translateToPigLatin(" has Left the building"); var reply = await connector.Conversations.ReplyToActivityAsync(removedMessage); } return(null); default: return(null); } }
private static async Task TestStoreType(BotStoreType storeType, int iterations, IBotDataStore <BotData> sourceStore, IBotDataStore <BotData> targetStore) { Random rnd = new Random(); // fill source store for (int i = 0; i < iterations; i++) { await sourceStore.SaveAsync(CreateAddress(i), storeType, new BotData(eTag : "*", data : new TestData() { Store = "source", Value = i }), CancellationToken.None); } var bridgeStore = (IBotDataStore <BotData>) new BotDataStoreBridge(sourceStore, targetStore); for (int i = 0; i < iterations; i++) { // every object should be readable from source var result = await bridgeStore.LoadAsync(CreateAddress(i), storeType, CancellationToken.None); Assert.IsNotNull(result.Data); Assert.IsTrue(!String.IsNullOrEmpty(result.ETag)); // every object should not be in target var result2 = await targetStore.LoadAsync(CreateAddress(i), storeType, CancellationToken.None); Assert.IsNull(result2.Data); Assert.IsTrue(String.IsNullOrEmpty(result2.ETag)); } // Save new object should work try { await bridgeStore.SaveAsync(new TestAddress() { BotId = "MyFunctionBot", ChannelId = "test", ConversationId = "ACONVERATION", UserId = "AUSER" }, storeType, new BotData(eTag : "*", data : new TestData() { Store = "target", Value = int.MaxValue }), CancellationToken.None); } catch (Exception err) { Assert.Fail($"Failed to write new record to bridge store:{err.Message}\n{err.ToString()}"); } for (int i = 0; i < iterations; i++) { var address = CreateAddress(i); // Every object should be still be loadable BotData botData = await bridgeStore.LoadAsync(address, storeType, CancellationToken.None); // change object and save var data = ((JObject)botData.Data).ToObject <TestData>(); data.Store = "target"; botData.Data = data; // Every change should be saved to targetStore await bridgeStore.SaveAsync(address, storeType, botData, CancellationToken.None); } // verify write with ETag and precondition failure for (int i = 0; i < iterations; i++) { try { var address = CreateAddress(i); var result = await bridgeStore.LoadAsync(address, storeType, CancellationToken.None); // set Value2 to good await bridgeStore.SaveAsync(address, storeType, new BotData(eTag : result.ETag, data : new TestData() { Store = "target", Value = i, Value2 = "good" }), CancellationToken.None); // bad attempt to set Value2 to bad await bridgeStore.SaveAsync(address, storeType, new BotData(eTag : result.ETag, data : new TestData() { Store = "target", Value = i, Value2 = "bad" }), CancellationToken.None); Assert.Fail("Should throw HttpException with precondition failure"); } catch (HttpException err) { Assert.AreEqual(412, err.GetHttpCode(), "Expected precondition failure"); } } // every object should now be in targetStore for (int i = 0; i < iterations; i++) { var address = CreateAddress(i); BotData result1 = await sourceStore.LoadAsync(address, storeType, CancellationToken.None); BotData result2 = await targetStore.LoadAsync(address, storeType, CancellationToken.None); var data1 = ((JObject)result1.Data).ToObject <TestData>(); var data2 = ((JObject)result2.Data).ToObject <TestData>(); Assert.IsNotNull(result1.Data, "Every object should be loadable from source store"); Assert.IsNotNull(result2.Data, "Every object should be loadable from target store"); Assert.AreEqual(data1.Value, data2.Value, "values should be the same"); Assert.AreEqual(data1.Store, "source", "source record should be source"); Assert.AreEqual(data2.Store, "target", "target record should be target"); Assert.AreEqual(data2.Value2, "good", "target record value2 should be good"); Assert.AreNotEqual(result1.ETag, result2.ETag, "ETags should be different"); } }
static async Task <BotData> GetConversationData(IBotDataStore <BotData> botDataStore, Address key) { var botData = await botDataStore.LoadAsync(key, BotStoreType.BotConversationData, CancellationToken.None); return(botData); }
/// <summary> /// Initializes a new instance of the <see cref="BotDataFactory"/> class. /// </summary> /// <param name="store">The <see cref="IBotDataStore{T}"/></param> public BotDataFactory(IBotDataStore <BotData> store) { store.ThrowIfNull(nameof(store)); this.store = store; }