Я разрабатываю бот для уведомлений для своей организации в 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)
}
Установка работает нормально и возвращает 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>
{
{"[email protected]", $"https://graph.microsoft.com/beta/appCatalogs/teamsApps/{teamsAppId}"}
}
};
var freshInstallation = await graphServiceClient.Users[userId].Teamwork.InstalledApps.Request().AddAsync(userScopeTeamsAppInstallation);
return freshInstallation;
}
До сих пор это нормально, но плохо в пробной версии - проактивно отправлять сообщения; как предложено в документация Я продолжаю получать этот chatId, который должен быть полезен. Забавно то, что если я использую Graph Client v1.0, я получаю внутреннюю ошибку сервера при получении этого объекта чата ниже, затем я переключился на бета-клиент, и он ... вроде как работает.
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.
- В любом случае, если мы посмотрим на документация, даже если он явно говорит, что нужно получить этот ChatId, он выполняет операцию, используя кэшированные объекты ConversationReference.
Как я могу сделать такую простую вещь, как отправить простое сообщение человеку, когда это выглядит так запутанно?