在一对一聊天中向租户中的用户发送通知
Sending notification in 1-to-1 chat to users in tenant
我正在 Microsoft Teams 中为我的组织开发通知机器人,使用 ASP.NET Core、Graph SDK(来自 Microsoft.Identity.Web.MicrosoftGraphBeta)。
我很难为租户中的特定用户开发一个简单的通知系统。这些用户由电子邮件地址标识。
我已经为用户和团队实现了应用程序的主动安装,方法是:
接收消息以在 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)
}
安装工作正常,returns 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 对象,但没有持久性示例。
- 鉴于上述问题,我无法在机器人适配器上使用 ContinueConversationAsync 方法。
- 无论如何,如果我们查看 documentation,即使它明确表示要检索此 ChatId,它也会使用缓存的 ConversationReference 对象执行操作。
我怎么能做这么“简单”的事情,比如向一个人发送一条简单的消息,而它看起来如此混乱?
要保留对话引用属性,请检查 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 示例代码。
我发现的一个简单解决方案是在为用户安装 Bot 时通过在 json 中序列化并保存到 Sqlite 数据库中,将 ConversationReference 对象保存在 OnTeamsMembersAddedAsync 回调中。为了检索它,我反序列化它并使用
我正在 Microsoft Teams 中为我的组织开发通知机器人,使用 ASP.NET Core、Graph SDK(来自 Microsoft.Identity.Web.MicrosoftGraphBeta)。 我很难为租户中的特定用户开发一个简单的通知系统。这些用户由电子邮件地址标识。 我已经为用户和团队实现了应用程序的主动安装,方法是:
接收消息以在 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)
}
安装工作正常,returns 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 对象,但没有持久性示例。
- 鉴于上述问题,我无法在机器人适配器上使用 ContinueConversationAsync 方法。
- 无论如何,如果我们查看 documentation,即使它明确表示要检索此 ChatId,它也会使用缓存的 ConversationReference 对象执行操作。
我怎么能做这么“简单”的事情,比如向一个人发送一条简单的消息,而它看起来如此混乱?
要保留对话引用属性,请检查 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 示例代码。
我发现的一个简单解决方案是在为用户安装 Bot 时通过在 json 中序列化并保存到 Sqlite 数据库中,将 ConversationReference 对象保存在 OnTeamsMembersAddedAsync 回调中。为了检索它,我反序列化它并使用