public async Task PostAsync(string encryptedChannelID) { // 0) Get request body data. string bodyStr; using (StreamReader reader = new StreamReader(this.Request.Body, Encoding.UTF8, true, 1024, true)) { bodyStr = await reader.ReadToEndAsync(); } // 0) Decrypt the channelID. var protector = _dataProtectionProvider.CreateProtector(_encryptionKey); var channelID = protector.Unprotect(encryptedChannelID); // 1) Deserialize the body to FlowHttpRequestData format, and deserialize comments of the github issue. var dataFromRequestString = JsonConvert.DeserializeObject(bodyStr).ToString(); dataFromRequest = JsonConvert.DeserializeObject <FlowHttpRequestData>(dataFromRequestString); commentsOfIssue = JsonConvert.DeserializeObject <List <FlowGitHubComment> >(dataFromRequest.Comments); // 2) Get the conversation reference from the database. var databaseName = _config["CosmosDBDatabaseName"]; var conversationReferenceCollectionName = _config["CosmosConversationReferenceCollection"]; FeedOptions queryOptions = new FeedOptions { EnableCrossPartitionQuery = true }; var lookupQuery1 = _documentClient.CreateDocumentQuery <ConversationReferenceData>( UriFactory.CreateDocumentCollectionUri(databaseName, conversationReferenceCollectionName), queryOptions) .Where(c => c.ChannelID == channelID); var match = lookupQuery1.ToList(); var localConversationReferenceData = match[0]; var cachedConversationReference = localConversationReferenceData.ChannelConversationReferenceObject; // 3) Call an appropriate callback. var messageIdCollectionName = _config["CosmosMessageIdCollection"]; var lookupQuery2 = _documentClient.CreateDocumentQuery <ReplyChainData>( UriFactory.CreateDocumentCollectionUri(databaseName, messageIdCollectionName), queryOptions) .Where(r => r.ExternalTicketId == dataFromRequest.Id); // For one external ticket id, there should be one messageID. var messageID = lookupQuery2.ToList(); if (messageID.Count > 0) { // If this ticket already exists, update the previously sent card and send a reply indicating the card is updated. await((BotAdapter)Adapter).ContinueConversationAsync(_appId, cachedConversationReference, BotCallbackForUpdate, default(CancellationToken)); } else { // If this ticket is new, create a new card and mention people in a reply. await((BotAdapter)Adapter).ContinueConversationAsync(_appId, cachedConversationReference, BotCallbackForSend, default(CancellationToken)); } }
// This function gets invoked when an issue is re-opened, closed or a comment was made. private async Task CreateReplyForUpdate(ITurnContext turnContext, string messageId, FlowHttpRequestData dataFromRequest, CancellationToken cancellationToken) { // To create a reply chain, it is necessary to have 'messageID' in the // ID of the given activity's conversation reference object. // This mesageID is used to identify which message to follow up. string firstConversationId = OriginalConversationId(turnContext); UpdateConversationIdForReplyChain(turnContext, firstConversationId, messageId); await ShowUpdatedStatusAndCommentsInReply(turnContext, cancellationToken); // As this turncontext is global (this is created from the one // conversation reference object we save when the bot is installed), // we need to update the id of its activity's conversation reference // object so other newly created cards can create replies properly. // If we don't have this line, the request will have an incorrect // form, eventually causing 502 internal server error. turnContext.Activity.GetConversationReference().Conversation.Id = firstConversationId; }