【问题标题】:Sending notification in 1-to-1 chat to users in tenant在一对一聊天中向租户中的用户发送通知
【发布时间】:2020-11-20 16:47:18
【问题描述】:

我正在使用 ASP.NET Core、Graph SDK(来自 Microsoft.Identity.Web.MicrosoftGraphBeta)在 Microsoft Teams 中为我的组织开发通知机器人。 我很难为租户中的特定用户开发一个简单的通知系统。这些用户由电子邮件地址标识。 我已经为用户和团队实现了应用的主动安装,具体做法是:

接收消息以在 MS Teams 中发送给特定用户的控制器

[HttpPost]
[Route("notify-approver")]
public async Task<List<string>> NotifyApprover([FromBody] ApproverMessage approverMessage)
{
            var approvers = await _graphServiceClient.Users.Request().Filter($"mail eq '{approverMessage.Email}'").GetAsync();

            var targetApprover = approvers.CurrentPage.ToList().FirstOrDefault();

            var appInstallation= await _graphServiceClient.InstallIfNotAlreadyForUser(targetApprover.Id, _configuration.GetTeamsAppId());


            // PER IL MOMENTO SEMBRA BUG
            var chatId = await _graphServiceClient.GetChatThreadId(targetApprover.Id, appInstallation.Id)

        }

安装工作正常并返回 UserScopeTeamsAppInstallation。 这是我为主动安装而构建的功能:

public static async Task<UserScopeTeamsAppInstallation> InstallIfNotAlreadyForUser(this IGraphServiceClient graphServiceClient, string userId, string teamsAppId)
        {
            var appsCollectionPage = await graphServiceClient.Users[userId].Teamwork.InstalledApps.Request().Expand("teamsAppDefinition")
                .GetAsync();
            var appInstallation = appsCollectionPage.CurrentPage.ToList()
                .Find(a => a.TeamsAppDefinition.TeamsAppId.Equals(teamsAppId));

            if (appInstallation != null) return appInstallation;
            var userScopeTeamsAppInstallation = new UserScopeTeamsAppInstallation()
            {
                AdditionalData = new Dictionary<string, object>
                {
                    {"teamsApp@odata.bind", $"https://graph.microsoft.com/beta/appCatalogs/teamsApps/{teamsAppId}"}
                }
            };
            var freshInstallation = await graphServiceClient.Users[userId].Teamwork.InstalledApps.Request().AddAsync(userScopeTeamsAppInstallation);
            return freshInstallation;

        }

到现在还可以,但不好的部分是在试用主动发送消息;正如documentation 中所建议的那样,我继续获取这个应该有用的chatId。有趣的是,如果我使用 Graph Client v1.0 在检索下面的聊天对象时出现内部服务器错误,然后我切换到 Beta 客户端,它......有点工作。

public static async Task<string> GetChatThreadId(this IGraphServiceClient graphServiceClient, string userId, string teamsAppIdInstallation)
        {
            // forse ci vuole AppInstallationId anziché il semplice teamsAppId della app

            //var chat = await graphServiceClient.Users[userId].Teamwork.InstalledApps[teamsAppIdInstallation].Chat.Request().GetAsync();

            /*
             * Perché dá internal server error?? Possibile bug della API di graph
             * perché viceversa da graph explorer funziona e restituisce l'id della chat
             *
             * Per adesso sono costretto a salvarmi in un database tutte le conversation references.
             */

            var chat =  graphServiceClient.Users[userId].Teamwork.InstalledApps[teamsAppIdInstallation].Chat.Request().GetAsync();


            return chat.Id.ToString();
            //return "CIAONE";
        }

从现在开始,我对分散的信息量越来越感到困惑。 我看到的是,通常情况应该是:

  • 在机器人回调 OnConversationUpdateActivityAsync 上,应保存 ConversationReference,因为它是在安装机器人时触发的。但是这个对象存储在 ConcurrentDictionary 中,并且它的生命周期仅限于运行时。在我的情况下,我应该坚持它,但我找不到要存储的属性以及如何重新创建示例中始终按原样存储的 ConversationReference 对象,但没有持久性示例。
  • 鉴于上述问题,我无法在 bot 适配器上使用 ContinueConversationAsync 方法。
  • 无论如何,如果我们查看 documentation,即使它明确表示要检索此 ChatId,它也会使用缓存的 ConversationReference 对象执行操作。

我应该怎么做这样“简单”的事情,比如向一个人发送一条看起来很混乱的简单消息?

【问题讨论】:

    标签: .net botframework microsoft-teams microsoft-graph-sdks microsoft-graph-teams


    【解决方案1】:

    要保留对话引用属性,请检查Bot State Docs中的存储层概念

    您可以继续尝试将此代码示例放在 startup.cs 文件中:

    services.AddSingleton<IStorage>(new AzureBlobStorage(Configuration["_connectionstring"], Configuration["BlobName"]));
    services.AddSingleton<UserState>();
    services.AddSingleton<ConversationState>();
    services.AddSingleton<BotStateService>(); 
    

    另外,请查看proactive-messages 示例代码。

    【讨论】:

    • 感谢您的回复。最后,通过将每个 ConversationReference 对象保存在本地 Sqlite 数据库中,我找到了一个没有很多麻烦的“简单”解决方案:我将其序列化为 JSON,然后将其保存为 json 字符串,当我检索它时,我从 json 字符串反序列化它并按照主动消息传递文档中的说明使用它
    【解决方案2】:

    我发现一个简单的解决方案是在为用户安装 Bot 时将 ConversationReference 对象保存在 OnTeamsMembersAddedAsync 回调中,方法是将其序列化为 json 并保存到 Sqlite 数据库中。为了检索它,我将其反序列化并使用

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-12
      相关资源
      最近更新 更多