예제 #1
0
 public HomeController()
 {
     this.ApiClient = new FreshDeskClient
     {
         Domain           = "yourdomain",
         ApiKey           = "yourapikey",
         GetAllTickets    = "api/v2/tickets",
         GetOpenTickets   = "api/v2/search/tickets?query=\"status:2\"",
         GetOnHoldTickets =
             "api/v2/search/tickets?query=\"status:3 or status: 6 or status: 7 or status: 8\""
     };
 }
        public static async Task ProcessChannel(IConfigurationRoot config, ILogger log)
        {
            //Read config values
            BotFrameworkDirectLine.directLineSecret = config["DirectLineSecret"];
            BotFrameworkDirectLine.botId            = config["BotId"];

            CosmosDB.cosmosDBEndpointUri = config["CosmosDBEndpointUri"];
            CosmosDB.cosmosDBPrimaryKey  = config["CosmosDBPrimaryKey"];
            CosmosDB.cosmosDBDatabaseId  = config["CosmosDBDatabaseId"];
            CosmosDB.cosmosDBContainerId = config["CosmosDBContainerId"];

            FreshDeskClient.freshDeskClientUrl = config["FreshDeskClientUrl"];
            FreshDeskClient.freshDeskAPIKey    = config["FreshDeskAPIKey"];

            preProcessingExtensibility  = config["PreProcessingExtensibility"];
            postProcessingExtensibility = config["PostProcessingExtensibility"];


            // Set last run time for differentials
            DateTime lastRun = await CosmosDB.UpdateLastRun(log);   //TODO: this doesn't work well when bot crashes halfway (batch will not be reprocessed)


            // Read all updated FreshDesk tickets
            List <FreshDeskTicket> listUpdatedFreshDeskTickets = await FreshDeskClient.GetUpdatedFreshDeskTicketsAsync(lastRun, log);

            foreach (FreshDeskTicket freshDeskTicket in listUpdatedFreshDeskTickets)
            {
                await ProcessTicket(freshDeskTicket, lastRun, log);
            }


            // TODO: Read all other open tickets to process for delayed bot responses


            // TODO: Close conversation for any resolved tickets?
        }
        public static async Task ProcessTicket(FreshDeskTicket freshDeskTicket, DateTime lastRun, ILogger log)
        {
            //Start or continue conversation for ticketId
            botConversationState = await CosmosDB.ReadItemAsync(freshDeskTicket.Id.ToString(), log);

            if (botConversationState == null)
            {
                //start bot conversation
                Conversation conversation = await BotFrameworkDirectLine.StartBotConversation(log);

                log.LogInformation("Starting conversation ID: " + conversation.ConversationId);

                //record new Bot conversation in CosmosDB, keeping track of TicketId<>BotConversationId
                botConversationState = new BotConversationState
                {
                    FreshDeskId       = freshDeskTicket.Id.ToString(),
                    BotConversationId = conversation.ConversationId,
                    BotWatermark      = "0",
                    Status            = (BotConversationState.FreshDeskTicketStatus)freshDeskTicket.Status
                };
                await CosmosDB.AddItemsToContainerAsync(botConversationState, log);
            }
            else
            {
                //continue bot conversation
                Conversation conversation = await BotFrameworkDirectLine.ContinueBotConveration(botConversationState.BotConversationId, log);

                log.LogInformation("Continuing conversation ID: " + conversation.ConversationId);
            }


            // List new customer messages in FreshDesk
            List <FreshDeskChannelData> listCustomerMessagesToProcess = new List <FreshDeskChannelData>();

            //Original ticket description to process?
            if (freshDeskTicket.Created_at > lastRun)
            {
                FreshDeskChannelData customerInitialMessage = new FreshDeskChannelData()
                {
                    TicketId      = freshDeskTicket.Id,
                    Subject       = freshDeskTicket.Subject,
                    Message       = freshDeskTicket.Description_text,
                    Group_id      = freshDeskTicket.Group_id,
                    Responder_id  = freshDeskTicket.Responder_id,
                    Source        = freshDeskTicket.Source,
                    Company_id    = freshDeskTicket.Company_id,
                    Status        = (FreshDeskChannelData.FreshDeskTicketStatus)freshDeskTicket.Status,
                    Product_id    = freshDeskTicket.Product_id,
                    Due_by        = freshDeskTicket.Due_by,
                    MessageType   = "initial_message",
                    Private       = false,
                    FromEmail     = freshDeskTicket.Requester.Email,
                    RequesterName = freshDeskTicket.Requester.Name,
                    Mobile        = freshDeskTicket.Requester.Mobile,
                    Phone         = freshDeskTicket.Requester.Phone
                };
                listCustomerMessagesToProcess.Add(customerInitialMessage);
            }

            //Any new incoming conversations in this ticket to process?
            List <FreshDeskConversation> listTicketConversations = await FreshDeskClient.GetFreshDeskTicketConversationsAsync(freshDeskTicket.Id, log);

            List <FreshDeskConversation> listIncomingConversationsSinceLastRun = (from c in listTicketConversations
                                                                                  where c.Incoming == true && c.Updated_at > lastRun
                                                                                  orderby c.Updated_at ascending
                                                                                  select c).ToList();

            foreach (FreshDeskConversation incomingConversation in listIncomingConversationsSinceLastRun)
            {
                FreshDeskChannelData customerConversationMessage = new FreshDeskChannelData()
                {
                    TicketId      = freshDeskTicket.Id,
                    Subject       = freshDeskTicket.Subject,
                    Message       = incomingConversation.Body_text,
                    Group_id      = freshDeskTicket.Group_id,
                    Responder_id  = freshDeskTicket.Responder_id,
                    Source        = freshDeskTicket.Source,
                    Company_id    = freshDeskTicket.Company_id,
                    Status        = (FreshDeskChannelData.FreshDeskTicketStatus)freshDeskTicket.Status,
                    Product_id    = freshDeskTicket.Product_id,
                    Due_by        = freshDeskTicket.Due_by,
                    MessageType   = "continued_conversation",
                    Private       = incomingConversation.Private,
                    FromEmail     = incomingConversation.From_email,
                    RequesterName = freshDeskTicket.Requester.Name,
                    Mobile        = freshDeskTicket.Requester.Mobile,
                    Phone         = freshDeskTicket.Requester.Phone
                };

                listCustomerMessagesToProcess.Add(customerConversationMessage);
            }


            // Send new customer messages to Bot Framework for processing
            foreach (FreshDeskChannelData freshDeskChannelData in listCustomerMessagesToProcess)
            {
                // Run Pre-processing Extensibility
                FreshDeskChannelData processedFreshDeskChannelData = freshDeskChannelData;
                if (!String.IsNullOrEmpty(preProcessingExtensibility))
                {
                    processedFreshDeskChannelData = await PreProcessingExtensibility(preProcessingExtensibility, freshDeskChannelData, log);
                }

                await BotFrameworkDirectLine.SendMessagesAsync(botConversationState.BotConversationId, processedFreshDeskChannelData, log);
            }


            // Read any new Bot Framework responses on this ticket
            ActivitySet activitySet = await BotFrameworkDirectLine.ReadBotMessagesAsync(botConversationState.BotConversationId, botConversationState.BotWatermark, log);

            //Update the bot watermark in CosmosDB, to keep track which Bot Framework conversations we have already read
            botConversationState.BotWatermark = activitySet?.Watermark;
            await CosmosDB.ReplaceFreshDeskBotStateAsync(botConversationState, log);

            //Send Bot Framework responses back to FreshDesk as ticket responses to the customer
            foreach (Activity activity in activitySet.Activities)
            {
                //If there is specific ChannelData add it to the message, otherwise default to standard customer reply message
                BotResponseChannelData botResponseChannelData;
                if (activity.ChannelData != null)
                {
                    var options = new JsonSerializerOptions
                    {
                        PropertyNameCaseInsensitive = true
                    };
                    botResponseChannelData = JsonSerializer.Deserialize <BotResponseChannelData>(activity.ChannelData.ToString(), options);
                }
                else
                {
                    // Default to a standard reply message
                    botResponseChannelData = new BotResponseChannelData
                    {
                        Message     = activity.Text,
                        MessageType = "reply",
                        Status      = BotResponseChannelData.FreshDeskTicketStatus.Pending
                    };
                }

                // Run post-processing Extensibility
                BotResponseChannelData processedBotResponseChannelData = botResponseChannelData;
                if (!String.IsNullOrEmpty(postProcessingExtensibility))
                {
                    processedBotResponseChannelData = await PostProcessingExtensibility(postProcessingExtensibility, botResponseChannelData, log);
                }

                // Send the bot response to FreshDesk in the chosen messageType (current allowed values: note, reply)
                switch (processedBotResponseChannelData.MessageType)
                {
                case "note":
                    await FreshDeskClient.SendFreshDeskNote(freshDeskTicket.Id.ToString(), processedBotResponseChannelData.Message, processedBotResponseChannelData.Private, processedBotResponseChannelData.NotifyEmails, log);

                    break;

                case "reply":
                    await FreshDeskClient.SendFreshDeskTicketReply(freshDeskTicket.Id.ToString(), processedBotResponseChannelData.Message, log);

                    await FreshDeskClient.SetTicketStatus(freshDeskTicket.Id.ToString(), processedBotResponseChannelData.Status, log);

                    break;
                }
            }
        }