public async Task <ProcessedChat> ProcessChatMessagesAsync(TeamsDataContext ctx, Chat chat, IEnumerable <Message> messages)
        {
            var result = new ProcessedChat(chat);
            // like 00000000-0000-beef-0000-000000000000
            var userId = ctx.Tenant.UserId;
            // from oldest to newest
            var orderedMessages = messages.OrderBy(m => m.originalarrivaltime);
            // TODO: combine this with the conversion logic of processedMessageFactory.CreateProcessedMessage().InitFromMessageAsync -> extract users first to have names ready, then generate processed messages
            HashSet <TeamsUserWithSource> usersFromChat;

            usersFromChat = CollectUsersFromChatAndMessages(chat, orderedMessages.ToList());
            result.UserIds.AddRange(usersFromChat.Select(value => value.User).Distinct()); // TODO: check if this is still necessary of if we use TeamsUserStore instead
            await UpdateUserObjectsAsync(ctx, result.UserIds);

            // note: it is important to process them from oldest to newest to catch all user names floating around in messages (e.g. chat messages contain user display names needed to put names in call end messages)
            // note2: this does not always work which is why there is the job to resolve unknown user ids
            result.OrderedMessages = (await Task.WhenAll(orderedMessages.Select(async m => await processedMessageFactory.CreateProcessedMessage().InitFromMessageAsync(ctx, chat.id, m)))).OrderBy(m => m.OriginalArrivalTime);

            // case 1: there is a custom title
            var title = chat.title?.Trim() ?? "";

            // this handles a title containing user mris (instead of custom title set by the user)
            var matches = Regex.Matches(title, TeamsParticipant.MriPatternOpen);

            // case 2: Teams provides a title consisting of user ids - collect them
            if (matches.Count > 0)
            {
                usersFromChat.AddRange(matches.Select(g => new TeamsUserWithSource((TeamsParticipant)g.Value, TeamsUserSource.FoundInChatTitle)));
            }

            // remove self and remove any "chat" that participated
            usersFromChat.RemoveWhere(value => value.User.Equals(ctx.Tenant.UserId) || value.User.Kind == ParticipantKind.TeamsChat);
            if (usersFromChat.Count == 0)
            {
                // no users left? add self...
                usersFromChat.Add(new TeamsUserWithSource(ctx.Tenant.UserId, TeamsUserSource.Self));
            }

            if (string.IsNullOrWhiteSpace(title))
            {
                title = string.Join(", ", usersFromChat
                                    .Where(value => value.UserSource == TeamsUserSource.ChatCreator || value.UserSource == TeamsUserSource.FoundInChatTitle || value.UserSource == TeamsUserSource.OfficialChatMember || value.UserSource == TeamsUserSource.SenderOfMessageInChat || value.UserSource == TeamsUserSource.Self)
                                    .Select(value => value.User)
                                    .Distinct());
            }

            title = await teamsUserRegistry.ReplaceUserIdsWithDisplayNamesAsync(ctx, title?.Trim());

            if (string.IsNullOrEmpty(title))
            {
                title = chat.id;
            }
            result.ChatTitle = title;
            return(result);
        }
Exemple #2
0
        public async Task TestStoreAndRetrieveChat()
        {
            using var kernel = new FakeItEasyMockingKernel();
            kernel.Rebind <ILogger>().ToConstant(Log.Logger);
            kernel.Rebind <Configuration>().ToConstant(config);
            kernel.Rebind <ITeamsChatStore>().To <ImapStore>().InSingletonScope();
            var chatStore = kernel.Get <ITeamsChatStore>();

            var chatId = $"chatId-{rand.Next()}";
            var chat1  = new ProcessedChat(new TeamsInternal.TeamsInternalApi.api.csa.api.v1.teams.users.Chat()
            {
                id = chatId, version = 10, threadVersion = 1000
            });
            await chatStore.StoreMailThreadAndUpdateMetadataAsync(fakeContext, "TestGetAllChatMetadata_1", chat1, null);

            var metadata = await chatStore.GetChatMetadataAsync(fakeContext, false, chatId);

            Assert.IsNotNull(metadata);
        }
Exemple #3
0
        public async Task TestStoreAndGetAllChatMetadata()
        {
            using var kernel = new FakeItEasyMockingKernel();
            kernel.Rebind <ILogger>().ToConstant(Log.Logger);
            kernel.Rebind <Configuration>().ToConstant(config);
            kernel.Rebind <ITeamsChatStore>().To <ImapStore>().InSingletonScope();
            var chatStore = kernel.Get <ITeamsChatStore>();

            var chat1 = new ProcessedChat(new TeamsInternal.TeamsInternalApi.api.csa.api.v1.teams.users.Chat()
            {
                id = "chat1", version = 10, threadVersion = 1000
            });
            await chatStore.StoreMailThreadAndUpdateMetadataAsync(fakeContext, "TestGetAllChatMetadata_1", chat1, null);

            var chat2 = new ProcessedChat(new TeamsInternal.TeamsInternalApi.api.csa.api.v1.teams.users.Chat()
            {
                id = "chat2", version = 20, threadVersion = 2000
            });
            await chatStore.StoreMailThreadAndUpdateMetadataAsync(fakeContext, "TestGetAllChatMetadata_2", chat2, null);

            //await chatStore.GetAllChatMetadataRecursivelyAsync(fakeContext);

            //Assert.IsTrue(sw.ElapsedMilliseconds < 10000, "Needing quite a lot of time to store users");
        }
Exemple #4
0
        public async Task StoreMailThreadAsyncAndUpdateMetadataAsync(TeamsDataContext ctx, string title, ProcessedChat chat, IOrderedEnumerable <IChatMessage> messages)
        {
            await chatStore.StoreMailThreadAndUpdateMetadataAsync(ctx, title, chat, messages);

            await BlobCache.UserAccount.InsertObject(GetChatMetadataCacheKey(chat.Id), chat, DateTimeOffset.Now + TimeSpan.FromMinutes(10));
        }