1
votes

I'm creating an event system where a chatbot can be used to trigger a job on an external system. Once the job has been received by the external system, it runs what it needs to run, and then notifies a queue held in azure that the job has been finished.

Next, I have a function app which looks at this queue. Once new information has been received (Contains an ID, ConversationReferenceObject and a job response), it notifies the bot via a ProactiveMessage:

var conversationReference = JsonConvert.DeserializeObject<ConversationReference>(subscription.ConversationReference);

MicrosoftAppCredentials.TrustServiceUrl(conversationReference.ServiceUrl);

var client = new ConnectorClient(new Uri(conversationReference.ServiceUrl), new MicrosoftAppCredentials(appId, appPassword));

var result = conversationReference.GetPostToBotMessage().CreateReply($@"[ProactiveMessage] Your job response: {response.data}");

client.Conversations.ReplyToActivity((Activity)result);

Now, rather than posting this reply to the bot activity I want the chatbot to intercept the [ProactiveMessage] and then only respond to the user if a dialog is not currently active - just generally managing the conversation flow correctly.

Now, I'm wondering if the client.Conversations has a different function where I can post to the chatbot rather then replying to the current conversation? I'm a bit stuck.

1
I'm not entirely clear what you are trying to do. Do you want to message the user, or the bot? Using the ConverasationReference object, you could load the state for that conversation inside the function and determine if the dialog stack has a dialog. If you want a new conversation, you would need to create that inside the function. - Eric Dahlvang
This is a snippet of code inside a function app. It responds back to the user, but I want to do some further checking before just spitting out the proactive message. - Johnathan Brown

1 Answers

1
votes

If you want to check the current dialog stack for the user who originally sent the message, you can use something like this:

var fromConversation = conversationReference.GetPostToBotMessage();

using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, fromConversation))
{
    var botData = scope.Resolve<IBotData>();
    await botData.LoadAsync(default(CancellationToken));

    var stack = scope.Resolve<IDialogTask>();
    if (stack.Frames != null && stack.Frames.Count > 0)
    {
        var lastFrame = stack.Frames[stack.Frames.Count - 1];
        var frameValue = lastFrame.Target.GetType().GetFields()[0].GetValue(lastFrame.Target);
        if (frameValue is NodeRootDialog) //<-- only reply if user is in NodeRootDialog
        {
            var reply = fromConversation.CreateReply("used converation reference to reply");
            var connector = new ConnectorClient(new Uri(activity.ServiceUrl));
            await connector.Conversations.ReplyToActivityAsync(reply);
        }
    }
}