예제 #1
0
        public static bool StepForward(Chat chat, string transitionInput, LibConfigurationModule config)
        {
            var currentMessageBlock = chat.State.CurrentMessageBlock;
            var currentMessage      = chat.State.CurrentMessage;

            if (chat.State.CurrentMessage != chat.State.CurrentMessageBlock.Messages.Last())
            {
                var currentIndex = chat.State.CurrentMessageBlock.Messages.FindIndex(x => x == currentMessage);
                chat.State.CurrentMessage   = chat.State.CurrentMessageBlock.Messages[currentIndex + 1];
                chat.State.CurrentMessageId = chat.State.CurrentMessage.Id;
                return(true);
            }

            if (chat.State.CurrentMessage == chat.State.CurrentMessageBlock.Messages.Last())
            {
                chat.State.HasBeenAtLastMessage = true;
                var allPossibleTransitions = chat.State.Schema.Steps.Where(x => x.FromBlock == currentMessageBlock).Select(x => x.ToBlock).ToList();

                if (allPossibleTransitions != null && allPossibleTransitions.Count == 1)
                {
                    chat.State.CurrentMessageBlock     = allPossibleTransitions.First();
                    chat.State.CurrentMessageBlockName = chat.State.CurrentMessageBlock.Name;
                    chat.State.CurrentMessage          = allPossibleTransitions.First().Messages.First();
                    chat.State.CurrentMessageId        = chat.State.CurrentMessage.Id;
                    chat.State.ProcessedUserInput      = true;
                    return(true);
                }

                var userDefinedSteps = chat.State.Schema.Steps
                                       .Where(x => x.FromBlock == currentMessageBlock && x.Transition.DisplayName == transitionInput)
                                       .Select(x => x.ToBlock).ToList();

                if (userDefinedSteps == null)
                {
                    return(false);
                }

                switch (userDefinedSteps.Count)
                {
                case 0:
                    return(true);

                case 1:
                    chat.State.CurrentMessageBlock     = userDefinedSteps.First();
                    chat.State.CurrentMessageBlockName = chat.State.CurrentMessageBlock.Name;
                    chat.State.CurrentMessage          = userDefinedSteps.First().Messages.First();
                    chat.State.CurrentMessageId        = chat.State.CurrentMessage.Id;
                    chat.State.WaitForUserTransition   = false;
                    chat.State.HasBeenAtLastMessage    = false;
                    chat.State.ProcessedUserInput      = true;
                    return(true);

                default:
                    throw new ApplicationException("2 or more user-defined transitions exist.");
                }
            }

            return(false);
        }
예제 #2
0
 public State(Chat chat, LibConfigurationModule config)
 {
     Id = chat.СhatId;
     //todo: wrap into method with exception thrown similiar to BindChatToSchemaHelpers
     Schema                  = config.SchemasRepository["default"];
     SchemaName              = "default";
     CurrentMessageBlock     = Schema.Steps.First().FromBlock;
     CurrentMessageBlockName = CurrentMessageBlock.Name;
     CurrentMessage          = CurrentMessageBlock.Messages.First();
     CurrentMessageId        = CurrentMessage.Id;
     WaitForUserTransition   = false;
 }
예제 #3
0
        public static Chat GetChatById(long currentChatId, LibConfigurationModule config, LibDbContext ctx)
        {
            var chat = ctx.Chats.Where(x => x.СhatId == currentChatId).FirstOrDefault();

            if (chat == null)
            {
                chat = new Chat(currentChatId, config);
                ctx.Chats.Add(chat);
                ctx.SaveChanges();
            }

            BindChatToSchemaHelpers.UpdateChatToSchemasReferences(chat, config);
            return(chat);
        }
        public static void BindSchema(Chat c, LibConfigurationModule config)
        {
            Schema chatSchema = null;

            config.SchemasRepository.TryGetValue(c.State.SchemaName, out chatSchema);
            if (chatSchema == null)
            {
                throw new Exception($"Schema \"{c.State.SchemaName}\" is not found for chat {c.СhatId.ToString()}");
            }
            else
            {
                c.State.Schema = chatSchema;
            }
            return;
        }
예제 #5
0
        public static string getReportOnCurrentChats(LibConfigurationModule config)
        {
            var result = new StringBuilder();

            result.Append($"{DateTime.Now.ToString()} {System.Environment.NewLine}");

            using (var ctx = (LibDbContext)Activator.CreateInstance(config.DbContextType))
            {
                var chats = ctx.Chats.ToList();
                foreach (var c in chats)
                {
                    result.Append("ChatId " + c.СhatId.ToString() + " has state " + c.State.CurrentMessageBlockName);
                }
            }
            result.Append($"{System.Environment.NewLine}");
            return(result.ToString());
        }
        public static void BindMessageBlock(Chat c, LibConfigurationModule config)
        {
            var messageBlocksCandidates = c.State.Schema.Blocks.Where(x => x.Name == c.State.CurrentMessageBlockName);

            if (messageBlocksCandidates == null)
            {
                throw new Exception($"Message block \"{c.State.CurrentMessageBlockName}\" is not found in schema \"{c.State.SchemaName}\" for chat {c.СhatId.ToString()}");
            }
            else if (messageBlocksCandidates.Count() != 1)
            {
                throw new Exception($"There are several message blocks \"{c.State.CurrentMessageBlockName}\" in schema \"{c.State.SchemaName}\" for chat {c.СhatId.ToString()}");
            }
            else
            {
                c.State.CurrentMessageBlock = messageBlocksCandidates.First();
            }
            return;
        }
예제 #7
0
        public static void WalkThroughSchema(long currentChatId, string userInput, LibConfigurationModule config, CallbackQuery callbackQuery)
        {
            using (var ctx = (LibDbContext)Activator.CreateInstance(config.DbContextType))
            {
                Chat chat = GetChatById(currentChatId, config, ctx);

                do
                {
                    if (callbackQuery != null)
                    {
                        TelegramActions.removeInlineKeyboard(currentChatId, callbackQuery, config.BotClient);
                        callbackQuery = null;
                    }

                    if (chat.State.ProcessedUserInput)
                    {
                        userInput = null;
                    }

                    LibActionResult processedResult = ProcessChatState(chat, userInput, config);
                    if (!processedResult.Status)
                    {
                        string errMsg = processedResult.ErrorMessage ?? chat.State.CurrentMessage.ErrorHandlingMessage;
                        TelegramActions.sendMessage(chat.СhatId, errMsg, null, config.BotClient);
                        break;
                    }
                    StepForward(chat, userInput, config);

                    if (chat.State.CurrentMessage.Type == MessageType.saveUserInput || chat.State.WaitForUserTransition)
                    {
                        chat.State.ProcessedUserInput = false;
                        break;
                    }
                }while (true);

                ctx.SaveChanges();
            }

            return;
        }
예제 #8
0
 public Chat(long chatIdInput, LibConfigurationModule config)
 {
     СhatId      = chatIdInput;
     DataContext = (DataContext)Activator.CreateInstance(config.DomainDataContextType, chatIdInput);
     State       = new State(this, config);
 }
예제 #9
0
        public static LibActionResult ProcessChatState(Chat chat, string userInput, LibConfigurationModule config)
        {
            if (chat.State.WaitForUserTransition)
            {
                return(new LibActionResult()
                {
                    Status = true
                });
            }

            Telegram.Bot.Types.ReplyMarkups.ReplyKeyboardMarkup customKeyboard = null;
            if (chat.State.CurrentMessage == chat.State.CurrentMessageBlock.Messages.Last())
            {
                var possibleSteps = chat.State.Schema.Steps.Where(x => x.FromBlock == chat.State.CurrentMessageBlock).ToList();
                if (possibleSteps.Count >= 2)
                {
                    chat.State.WaitForUserTransition = true;
                    if (chat.State.CurrentMessage.Type != MessageType.saveUserInput || chat.State.HasBeenAtLastMessage)
                    {
                        customKeyboard = KeyboardManagement.createReplyKeyboard(possibleSteps);
                    }
                }
            }

            switch (chat.State.CurrentMessage.Type)
            {
            case MessageType.sendMessage:
                if (!String.IsNullOrEmpty(chat.State.CurrentMessage.Content))
                {
                    TelegramActions.sendMessage(chat.СhatId, chat.State.CurrentMessage.Content, customKeyboard, config.BotClient);
                }
                else if (chat.State.CurrentMessage.TextWithProperties != null)
                {
                    TelegramActions.sendMessage(chat.СhatId, chat.State.CurrentMessage.TextWithProperties(chat), customKeyboard, config.BotClient);
                }
                return(new LibActionResult()
                {
                    Status = true
                });

            case MessageType.sendImage:
                TelegramActions.sendImage(chat.СhatId, chat.State.CurrentMessage.Content, customKeyboard, config.BotClient);
                return(new LibActionResult()
                {
                    Status = true
                });

            case MessageType.saveUserInput:
                if (chat.State.CurrentMessage.CustomMethod != null)
                {
                    var result = chat.State.CurrentMessage.CustomMethod(userInput, chat, config.BotClient);
                    chat.State.ProcessedUserInput = result.Status;
                    return(result);
                }
                else if (chat.State.CurrentMessage.PropertySetter != null)
                {
                    LibActions.SetDataContextProperty(chat, userInput, chat.State.CurrentMessage.PropertySetter);
                    chat.State.ProcessedUserInput = true;
                    return(new LibActionResult()
                    {
                        Status = true
                    });
                }
                else
                {
                    return(new LibActionResult()
                    {
                        Status = false, ErrorMessage = "Действие не задано"
                    });
                }

            case MessageType.pause:
                TelegramActions.sendMessage(chat.СhatId, "Допустим, что тут будет пауза.", customKeyboard, config.BotClient);
                return(new LibActionResult()
                {
                    Status = true
                });

            case MessageType.Custom:
                if (chat.State.CurrentMessage.CustomMethod != null)
                {
                    return(chat.State.CurrentMessage.CustomMethod(userInput, chat, config.BotClient));
                }
                else if (chat.State.CurrentMessage.PropertySetter != null)
                {
                    LibActions.SetDataContextProperty(chat, userInput, chat.State.CurrentMessage.PropertySetter);
                    return(new LibActionResult()
                    {
                        Status = true
                    });
                }
                else
                {
                    TelegramActions.sendMessage(chat.СhatId, "Выполнилась кастомная хрень.", customKeyboard, config.BotClient);
                    return(new LibActionResult()
                    {
                        Status = true
                    });
                }

            default:
                return(new LibActionResult()
                {
                    Status = false
                });
            }
        }
 public static void UpdateChatToSchemasReferences(Chat c, LibConfigurationModule config)
 {
     BindChatToSchemaHelpers.BindSchema(c, config);
     BindChatToSchemaHelpers.BindMessageBlock(c, config);
     BindChatToSchemaHelpers.BindMessage(c, config);
 }