Access UserProfile from NotifyBot

早过忘川 提交于 2021-02-11 14:22:38

问题


I'm trying to kind of merge the functionality of EchoBot and ProactiveBot. A bot that parses user commands, which can also be triggered through a URL to send some users a message based on the contents of their UserProfile.

I managed to get both parts to work, but I'm having trouble accessing the UserProfiles from the NotifyController, or solving the problem another way. I tried a few things, read many of the tutorials and also this excellent explanation, but I'm still stuck.

So my question is: How do I rewrite NotifyController so it calls a method in my Bot class (the one implementing ActivityHandler) - just like BotController (from EchoBot) does?

Or, if that's better: How do I get a reference to the UserProfile in the message handler in NotifyController?

Thanks!


回答1:


Alright, I got it to work.

Basically I duplicated all the code for the conversationReferences, because those get stored in the Bot and are used in NotifyController.

Some code, in case somebody else is trying to do the same:

Startup.cs

Create another Singleton.

services.AddSingleton<ConcurrentDictionary<string, UserProfile>>();

In the bot class

I have a variable storing UserProfiles just like the one for ConversationReferences

private readonly ConcurrentDictionary<string, ConversationReference> _conversationReferences;
private readonly ConcurrentDictionary<string, UserProfile> _userProfiles;

The constructor now starts like this

public RmindrBot(ConversationState conversationState, 
   UserState userState,
   ConcurrentDictionary<string, ConversationReference> conversationReferences,
   ConcurrentDictionary<string, UserProfile> userProfiles)
{
    _conversationReferences = conversationReferences;
    _userProfiles = userProfiles;
    ...

(I think this is the most surprising bit for me - didn't think the framework would just magically figure out the new signature.)

A method for adding references:

private void AddConversationReference(Activity activity)
{
    var conversationReference = activity.GetConversationReference();
    _conversationReferences.AddOrUpdate(
        conversationReference.User.Id,
        conversationReference, 
           (key, newValue) => conversationReference);
}

...which is called in OnMessageActivityAsync:

var userProfile = await userStateAccessors.GetAsync(turnContext, () => new UserProfile());
userProfile.ID = turnContext.Activity.From.Id;
AddUserProfile(userProfile);

NotifyController

private readonly ConcurrentDictionary<string, UserProfile> _userProfiles;

public NotifyController(
    IBotFrameworkHttpAdapter adapter,
    IConfiguration configuration,
    ConcurrentDictionary<string, ConversationReference> conversationReferences)
    ConcurrentDictionary<string, ConversationReference> conversationReferences,
    ConcurrentDictionary<string, UserProfile> userProfiles)
{
    _adapter = adapter;
    _conversationReferences = conversationReferences;
    _userProfiles = userProfiles;
    ...

And then we can finally use it in the callback method and match the user to their ID:

private async Task BotCallback(ITurnContext turnContext, CancellationToken cancellationToken)
{
    var userProfile = _userProfiles[turnContext.Activity.From.Id];

    await turnContext.SendActivityAsync("proactive hello " + userProfile.ID);
}


来源:https://stackoverflow.com/questions/64490008/access-userprofile-from-notifybot

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!