예제 #1
0
        public static CVR APICallNodeValidations_ERROR(ChatFlowPack pack)
        {
            var res          = new CVR();
            var msgs         = new List <string>();
            var apicallNodes = pack.ChatNodes.Where(x => x.NodeType == NodeTypeEnum.ApiCall).ToList();

            if (apicallNodes.Count > 0)
            {
                foreach (var node in apicallNodes)
                {
                    var nodeMsg = $"Error: In node '{node.Identifer()}', ";
                    if (node.ApiMethod == null)
                    {
                        msgs.Add($"{nodeMsg} '{nameof(node.ApiMethod)}' field is not set! Set it to the Method(HTTP Verb) of the api you want to use.");
                        res.SetStatus(CVS.Error);
                    }

                    if (string.IsNullOrWhiteSpace(node.ApiUrl))
                    {
                        msgs.Add($"{nodeMsg} '{nameof(node.ApiUrl)}' field is not set! Set it to the api you want to use.");
                        res.SetStatus(CVS.Error);
                    }
                    else if (!Uri.TryCreate(node.ApiUrl, UriKind.Absolute, out Uri uri))
                    {
                        msgs.Add($"{nodeMsg} '{nameof(node.ApiUrl)}' field has invalid URL! Set it to a valid URL. Did you forget to start with http:// or https://");
                        res.SetStatus(CVS.Error);
                    }
                }
            }
            if (msgs.Count > 0)
            {
                return(res.SetMsg(msgs.Join("\r\n")).SetStatus(CVS.Error));
            }
            return(res.Valid());
        }
예제 #2
0
        public static CVR NodesWithGetXTypeButtonsShouldHaveVariableName_ERROR(ChatFlowPack pack)
        {
            var res = new CVR();
            var nonEmptyVarNameBtnTypes = new HashSet <ButtonTypeEnum>(new[]
            {
                ButtonTypeEnum.GetText,
                ButtonTypeEnum.GetTime,
                ButtonTypeEnum.GetVideo,
                ButtonTypeEnum.GetFile,
                ButtonTypeEnum.GetImage,
                ButtonTypeEnum.GetItemFromSource,
                ButtonTypeEnum.GetLocation,
                ButtonTypeEnum.GetNumber,
                ButtonTypeEnum.GetPhoneNumber,
                ButtonTypeEnum.GetDate,
                ButtonTypeEnum.GetDateTime,
                ButtonTypeEnum.GetAudio
            });
            var respMessage = new List <string>();

            foreach (var node in pack.ChatNodes)
            {
                if (node.Buttons.Any(x => nonEmptyVarNameBtnTypes.Contains(x.ButtonType)) && string.IsNullOrWhiteSpace(node.VariableName))
                {
                    respMessage.Add($"Error: Node '{node.Identifer()}' must not have Variable Name field empty as it is being used to capture information. Variable Name will allow you to refer the captured information later in the flow to display or to send it to any APIs");
                }
            }
            if (respMessage.Count > 0)
            {
                return(res.SetMsg(string.Join("\r\n", respMessage)).SetStatus(CVS.Error));
            }
            return(res.Valid());
        }
예제 #3
0
        public async Task <ActionResult> SaveChatFlow()
        {
            try
            {
                ChatFlowPack req = null;
                using (var s = new StreamReader(Request.Body))
                    req = BsonSerializer.Deserialize <ChatFlowPack>(s.ReadToEnd());

                if (req == null)
                {
                    return(BadRequest(new { Message = "No chat flow received to save!" }));
                }

                var saved = await MongoHelper.SaveChatFlowAsync(req);

                if (saved)
                {
                    return(Content(new { Message = "Chat flow saved", Data = req }.ToJson(), "text/plain"));
                }
            }
            catch (System.Exception ex)
            {
                return(BadRequest(new { Message = "Unable to save chat flow!. Ex: " + ex.Message }));
            }
            return(BadRequest(new { Message = "Unable to save chat flow!" }));
        }
예제 #4
0
파일: MongoHelper.cs 프로젝트: zazz19/ANA
        public static async Task <bool> SaveChatFlowAsync(ChatFlowPack chatFlow)
        {
            try
            {
                var chatsColl = ChatDB.GetCollection <ChatFlowPack>(Settings.ChatFlowPacksCollectionName);
                if (string.IsNullOrWhiteSpace(chatFlow.ProjectId))
                {
                    chatFlow.ProjectId = ObjectId.GenerateNewId().ToString();
                }

                if (await chatsColl.CountAsync(x => x.ProjectId == chatFlow.ProjectId, new CountOptions {
                    Limit = 1
                }) > 0)
                {
                    chatFlow.UpdatedOn = DateTime.UtcNow;
                    await chatsColl.ReplaceOneAsync(x => x.ProjectId == chatFlow.ProjectId, chatFlow);

                    return(true);
                }
                chatFlow.CreatedOn = chatFlow.UpdatedOn = DateTime.UtcNow;
                await chatsColl.InsertOneAsync(chatFlow);
            }
            catch (Exception ex)
            {
                Logger.LogError(new EventId((int)LoggerEventId.MONGO_HELPER_ERROR), ex, "SaveChatFlowAsync: {0}", ex.Message);
            }
            return(false);
        }
예제 #5
0
        /// <summary>
        /// Should be the first in the validator's list
        /// </summary>
        /// <param name="pack"></param>
        /// <returns></returns>
        private static CVR EmptyValidation_ERROR(ChatFlowPack pack)
        {
            var res = new CVR();

            if (pack == null || pack.ChatNodes == null || pack.ChatNodes.Count == 0)
            {
                return(res.SetMsg("Error: The chat flow is empty! Please add at least one chat node").SetStatus(CVS.Error));
            }
            return(res.Valid());
        }
예제 #6
0
        public static CVR AllNodesShouldHaveAName_WARNING(ChatFlowPack pack)
        {
            var res            = new CVR();
            var emptyNameNodes = pack.ChatNodes.Where(x => string.IsNullOrWhiteSpace(x.Name)).ToList();

            if (emptyNameNodes.Count > 0)
            {
                return(res.SetMsg($"Warning: {emptyNameNodes.Count} chat node(s) have empty name(s). It's recommended to give each node a name which can help you identify it. These are the node ids, search them and give them a name. ({emptyNameNodes.Select(x => x.Id).Join(", ")})").SetStatus(ChatFlowValidationStatus.Warning));
            }
            return(res.Valid());
        }
예제 #7
0
        public static List <ChatNode> Build(ChatFlowPack chatFlow)
        {
            try
            {
                var nodesList = new ConcurrentBag <ChatNode>(chatFlow.ChatNodes);
                var content   = new ConcurrentBag <BaseContent>(chatFlow.ChatContent);
                Parallel.ForEach(nodesList, chatNode =>
                {
                    try
                    {
                        foreach (Section section in chatNode.Sections)
                        {
                            FillSectionWithContent(section, content);
                        }
                        foreach (Button button in chatNode.Buttons)
                        {
                            var cnt               = content.GetFor(button);
                            button.ButtonText     = cnt?.ButtonText;
                            button.ButtonName     = cnt?.ButtonName;
                            button.ContentId      = cnt?._id;
                            button.ContentEmotion = cnt?.Emotion;

                            if (string.IsNullOrWhiteSpace(button.ButtonName))
                            {
                                button.ButtonName = button.ButtonText;                                 //For backward comparability
                            }
                            if (string.IsNullOrWhiteSpace(button.ButtonText))
                            {
                                button.ButtonText = button.ButtonName;                                 //For backward comparability
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger.Write(ex);
                    }
                });

                var startNode = nodesList.FirstOrDefault(x => x.IsStartNode);
                if (startNode != null)                 //If start chat node is present, move it up
                {
                    var result = nodesList.Where(x => x != startNode).ToList();
                    result.Insert(0, startNode);
                    return(result);
                }
                return(nodesList.ToList());
            }
            catch (Exception ex)
            {
                Logger.Write(ex);
            }
            return(null);
        }
예제 #8
0
        public async Task <bool> SaveChatFlowAsync()
        {
            if (ChatFlow != null)
            {
                var saveChatFlowResp = await HitPost <DataResponse <ChatFlowPack>, ChatFlowPack>(SaveChatFlowPackAPI, ChatFlow, true);

                if (saveChatFlowResp.Status)
                {
                    ChatFlow = saveChatFlowResp.Data;
                    return(true);
                }
            }
            return(false);
        }
예제 #9
0
        public async Task <bool> LoadChatFlowAsync(string projectId)
        {
            if (ChatFlowProjects != null && ChatFlowProjects.Any(x => x._id == projectId))
            {
                var chatFlowResp = await Hit <DataResponse <ChatFlowPack> >(FetchChatFlowPackAPI.Replace("{projectId}", projectId), true);

                if (chatFlowResp.Status)
                {
                    ChatFlow = chatFlowResp.Data;
                    ChatFlowBuilder.Build(ChatFlow);
                    return(true);
                }
            }
            return(false);
        }
예제 #10
0
        public static CVR OnlyOneTextInputButtonIsAllowedPerNode_ERROR(ChatFlowPack pack)
        {
            var res  = new CVR();
            var msgs = new List <string>();

            foreach (var node in pack.ChatNodes.Where(x => x.Buttons != null && x.Buttons.Count > 0))
            {
                if (node.Buttons.Count(x => InputTextButtonTypes.Contains(x.ButtonType)) > 1)
                {
                    msgs.Add($"Error: Node '{node.Identifer()}' has multiple text input buttons. Only one text input button is allowed per node.");
                }
            }
            if (msgs.Count > 0)
            {
                return(res.SetMsg(msgs.Join("\r\n")).SetStatus(CVS.Error));
            }
            return(res.Valid());
        }
예제 #11
0
        public async Task <ActionResult> Chat([FromQuery] string projectId = null, [FromQuery] string projectName = null, [FromQuery] bool enableAgentChat = true)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(projectId) && string.IsNullOrWhiteSpace(projectName))
                {
                    return(BadRequest(new { Message = "Either project id or project name has to be provided" }));
                }

                ChatFlowPack chatFlowPack = null;
                if (!string.IsNullOrWhiteSpace(projectId))
                {
                    chatFlowPack = await MongoHelper.GetChatFlowPackAsync(projectId);
                }
                else if (!string.IsNullOrWhiteSpace(projectName))
                {
                    chatFlowPack = await MongoHelper.GetChatFlowPackByProjectNameAsync(projectName);
                }

                if (chatFlowPack == null)
                {
                    return(BadRequest(new { Message = "No chat flow found by the given project id or name" }));
                }

                var chatNodes = ChatFlowBuilder.Build(chatFlowPack);
                if (chatNodes == null || chatNodes.Count == 0)
                {
                    return(Ok(new object[] { }));
                }

                if (enableAgentChat)
                {
                    AddAgentChatNodes(chatNodes);
                }

                return(Json(chatNodes, PublishJsonSettings));
            }
            catch (System.Exception ex)
            {
                _log.LogError(new EventId((int)LoggerEventId.CHAT_ACTION_ERROR), ex, ex.Message);
                return(StatusCode(500, new { Message = ex.Message }));
            }
        }
예제 #12
0
        private static CVR EmptyNodeValidation_ERROR(ChatFlowPack pack)
        {
            var res         = new CVR();
            var respMessage = new List <string>();

            foreach (var node in pack.ChatNodes.Where(x => x.NodeType == NodeTypeEnum.Combination))
            {
                if (node.Sections == null || node.Sections.Count <= 0)
                {
                    respMessage.Add($"Error: Node '{node.Identifer()}' has no sections/content! Combination nodes cannot be empty.");
                }
            }

            if (respMessage.Count > 0)
            {
                return(res.SetMsg(string.Join("\r\n", respMessage)).SetStatus(CVS.Error));
            }
            return(res.Valid());
        }
예제 #13
0
        public static List <ChatNode> Build(ChatFlowPack chatFlow)
        {
            try
            {
                var filter = Builders <ChatFlowPack> .Filter;

                var nodesList = new ConcurrentBag <ChatNode>(chatFlow.ChatNodes);
                var content   = new ConcurrentBag <BaseContent>(chatFlow.ChatContent);
                Parallel.ForEach(nodesList, chatNode =>
                {
                    try
                    {
                        foreach (Section section in chatNode.Sections)
                        {
                            FillSectionWithContent(section, content);
                        }
                        foreach (Button button in chatNode.Buttons)
                        {
                            button.ButtonText = content.GetFor(button)?.ButtonText;
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger.LogError(new EventId((int)LoggerEventId.MONGO_HELPER_ERROR), ex, "RetrieveRecordsFromChatNode Error: {0}", ex.Message);
                    }
                });

                var startNode = nodesList.FirstOrDefault(x => x.IsStartNode);
                if (startNode != null) //If start chat node is present, move it up
                {
                    var result = nodesList.Where(x => x != startNode).ToList();
                    result.Insert(0, startNode);
                    return(result);
                }
                return(nodesList.ToList());
            }
            catch (Exception ex)
            {
                Logger.LogError(new EventId((int)LoggerEventId.MONGO_HELPER_ERROR), ex, "RetrieveRecordsFromChatNode Error: {0}", ex.Message);
            }
            return(null);
        }
예제 #14
0
        public static CVR MandatoryFieldsPerButtonType_ERROR(ChatFlowPack pack)
        {
            var res  = new CVR();
            var msgs = new List <string>();

            foreach (var node in pack.ChatNodes.Where(x => x.Buttons != null && x.Buttons.Count > 0))
            {
                var nodeMsg = $"Error: In node '{node.Identifer()}', ";
                foreach (var btn in node.Buttons)
                {
                    if (node.NodeType == NodeTypeEnum.Combination && btn.ButtonType == ButtonTypeEnum.NextNode && !btn.Hidden && string.IsNullOrWhiteSpace(btn.NextNodeId))
                    {
                        msgs.Add($"{nodeMsg} button '{btn}' is of type '{btn.ButtonType}' and is not hidden. So, it must be mapped to a node. Any NextNode button which is not hidden must be mapped to a next node.");
                    }
                    if (node.NodeType == NodeTypeEnum.Combination && btn.ButtonType == ButtonTypeEnum.NextNode && !btn.Hidden && (string.IsNullOrWhiteSpace(btn.ButtonName) && string.IsNullOrWhiteSpace(btn.ButtonText)))
                    {
                        msgs.Add($"{nodeMsg} button '{btn}' is of type '{btn.ButtonType}' and is not hidden. So, it must have text! Any NextNode button which is not hidden must have text which is displayed on the button.");
                    }
                    if (btn.ButtonType == ButtonTypeEnum.DeepLink && string.IsNullOrWhiteSpace(btn.DeepLinkUrl))
                    {
                        msgs.Add($"{nodeMsg} button '{btn}' is of type '{btn.ButtonType}' but the field '{nameof(btn.DeepLinkUrl)}' is empty! Set it to the target deeplink url.");
                    }
                    if ((btn.ButtonType == ButtonTypeEnum.FetchChatFlow || btn.ButtonType == ButtonTypeEnum.OpenUrl) && string.IsNullOrWhiteSpace(btn.Url))
                    {
                        msgs.Add($"{nodeMsg} button '{btn}' is of type '{btn.ButtonType}' but the field '{nameof(btn.Url)}' is empty! Set it to the target url.");
                    }
                    if (btn.ButtonType == ButtonTypeEnum.FetchChatFlow && string.IsNullOrWhiteSpace(btn.NextNodeId))
                    {
                        msgs.Add($"{nodeMsg} button '{btn}' is of type '{btn.ButtonType}' but the field '{nameof(btn.NextNodeId)}' is empty! Set it to the target next node id.");
                    }
                }
            }
            if (msgs.Count > 0)
            {
                return(res.SetMsg(msgs.Join("\r\n")).SetStatus(CVS.Error));
            }
            return(res.Valid());
        }
예제 #15
0
        public static List <CVR> Validate(ChatFlowPack pack)
        {
            var fails = new List <CVR>();

            foreach (var validation in ChatFlowValidatorList)
            {
                try
                {
                    var res = validation(pack);
                    if (res.Status != CVS.Valid)
                    {
                        fails.Add(res);
                    }
                }
                catch (Exception ex)
                {
                    fails.Add(new CVR {
                        Message = "Oops! Something went wrong while validating the flow!" + ex.Message, Status = CVS.Error, ValidationName = "Exception"
                    });
                }
            }
            return(fails);
        }
예제 #16
0
        public (bool, string) LoadChatFlowProject()
        {
            try
            {
                if (!string.IsNullOrWhiteSpace(ProjectFilePath))
                {
                    var rawProjectJson = File.ReadAllText(ProjectFilePath);
                    ChatFlow = BsonSerializer.Deserialize <ChatFlowPack>(rawProjectJson);
                }
                else
                {
                    var firstNode = new ChatNode {
                        Name = "New Node"
                    };
                    firstNode.Id = ObjectId.GenerateNewId().ToString();

                    ChatFlow = new ChatFlowPack
                    {
                        ChatNodes     = new List <ChatNode>(new[] { firstNode }),
                        ChatContent   = new List <Models.BaseContent>(),
                        NodeLocations = new Dictionary <string, Models.LayoutPoint> {
                            { firstNode.Id, new Models.LayoutPoint {
                                  X = 500, Y = 500
                              } }
                        }
                    };
                }
                LastChatFlowSavedHash = Utilities.GenerateHash(ChatFlow.ToJson());
                ChatFlowBuilder.Build(ChatFlow);
                return(true, "");
            }
            catch (Exception ex)
            {
                return(false, ex.Message);
            }
        }
예제 #17
0
        public static CVR CarouselSectionsValidations_ERROR(ChatFlowPack pack)
        {
            var res = new CVR();
            var carouselSectionNodes = pack.ChatNodes.Where(x => x.Sections.Any(y => y.SectionType == SectionTypeEnum.Carousel));
            var msgs = new List <string>();

            foreach (var node in carouselSectionNodes)
            {
                var nodeMsg = $"Error: In node '{node.Identifer()}' ";

                foreach (var sec in node.Sections.Where(x => x.SectionType == SectionTypeEnum.Carousel))
                {
                    var carSec    = sec as CarouselSection;
                    var carSecMsg = $"{nodeMsg} in Carousel Section '{carSec}' ";
                    if (carSec.Items == null || carSec.Items.Count == 0)
                    {
                        msgs.Add($"{carSecMsg} has no items!");
                        res.SetStatus(CVS.Error);
                        continue;
                    }
                    foreach (var carItem in carSec.Items)
                    {
                        var carItemMsg = $"{carSecMsg} Carousel Item '{carItem}' ";
                        if (carItem.Buttons != null)
                        {
                            if (carItem.Buttons.Count > 3)
                            {
                                msgs.Add($"{carItemMsg} has more than 3 buttons! A carousel item can have maximum of 3 buttons.");
                                res.SetStatus(CVS.Error);
                            }

                            foreach (var carBtn in carItem.Buttons)
                            {
                                var carItemBtnMsg = $"{carItemMsg} Carousel Button '{carBtn}' ";
                                if (string.IsNullOrWhiteSpace(carBtn.Text))
                                {
                                    msgs.Add($"{carItemBtnMsg}, text is empty!");
                                    res.SetStatus(CVS.Error);
                                }
                                if ((carBtn.Type == CardButtonType.DeepLink || carBtn.Type == CardButtonType.OpenUrl) && string.IsNullOrWhiteSpace(carBtn.Url))
                                {
                                    msgs.Add($"{carItemBtnMsg} is of type '{carBtn.Type}' but the '{nameof(carBtn.Url)}' field is empty! Set it to the target url.");
                                    res.SetStatus(CVS.Error);
                                }
                                if (carBtn.Type == CardButtonType.NextNode && string.IsNullOrWhiteSpace(carBtn.NextNodeId))
                                {
                                    msgs.Add($"{carItemBtnMsg} is of type '{carBtn.Type}' but the '{nameof(carBtn.NextNodeId)}' field is empty! Set it to the target Next Node Id.");
                                    res.SetStatus(CVS.Error);
                                }
                            }
                        }
                    }
                }
            }

            if (msgs.Count > 0)
            {
                return(res.SetMsg(msgs.Join("\r\n")).SetStatus(CVS.Error));
            }
            return(res.Valid());
        }