Работа с пошаговыми командами

PRTelegramBot бот предоставляет функционал пошагового выполнения команд. Допустим нужно чтобы пользователь прошел по следующим этапам:

  • Ввод имени

  • Ввод даты рождения

Для создание следующего шага используется класс StepTelegram.

/// <summary>
/// Позволяет выполнить пользователю команды пошагово.
/// </summary>
public sealed class StepTelegram : IExecuteStep
{
    #region Свойства и константы

    /// <summary>
    /// Ссылка на метод который должен быть выполнен.
    /// </summary>
    public Func<IBotContext, Task> CommandDelegate { get; set; }

    /// <summary>
    /// До какого времени команду можно выполнить.
    /// </summary>
    public DateTime? ExpiredTime { get; set; }

    /// <summary>
    /// Кэш данных.
    /// </summary>
    private ITelegramCache cache { get; set; }

    #endregion

    #region IExecuteStep

    /// <inheritdoc/>
    public bool LastStepExecuted { get; set; }

    /// <inheritdoc/>
    public bool IgnoreBasicCommands { get; set; }

    /// <inheritdoc/>
    public async Task<ExecuteStepResult> ExecuteStep(IBotContext context)
    {
        if (ExpiredTime is not null && DateTime.Now > ExpiredTime)
        {
            context.Update.ClearStepUserHandler();
            return ExecuteStepResult.ExpiredTime;
        }

        try
            {
                await CommandDelegate.Invoke(context);
                return ExecuteStepResult.Success;
            }
            catch (Exception ex)
            {
                context.Current.Events.OnErrorLogInvoke(new ErrorLogEventArgs(context, ex));
                return ExecuteStepResult.Failure;
            }
        }

        /// <inheritdoc/>
        public Func<IBotContext, Task> GetExecuteMethod()
        {
            return CommandDelegate;
        }

        /// <inheritdoc/>
        public bool CanExecute()
        {
            return ExpiredTime is null || DateTime.Now < ExpiredTime;
        }

        #endregion

        #region Методы

        /// <summary>
        /// Регистрация следующего шага.
        /// </summary>
        /// <param name="nextStep">Метод для следующей обработки.</param>
        public void RegisterNextStep(Func<IBotContext, Task> nextStep)
        {
            RegisterNextStep(nextStep, null);
        }

        /// <summary>
        /// Регистрация следующего шага.
        /// </summary>
        /// <param name="nextStep">Метод для следующей обработки.</param>
        /// <param name="addTime">До какого времени команду можно выполнить</param>
        public void RegisterNextStep(Func<IBotContext, Task> nextStep, TimeSpan addTime)
        {
            RegisterNextStep(nextStep, DateTime.Now.Add(addTime));
        }

        /// <summary>
        /// Регистрация следующего шага.
        /// </summary>
        /// <param name="nextStep">Метод для следующей обработки.</param>
        /// <param name="expiriedTime"> До какого времени команду можно выполнить.</param>
        public void RegisterNextStep(Func<IBotContext, Task> nextStep, DateTime? expiriedTime)
        {
            RegisterNextStep(nextStep, expiriedTime, false);
        }

        /// <summary>
        /// Регистрация следующего шага.
        /// </summary>
        /// <param name="nextStep">Метод для следующей обработки.</param>
        /// <param name="expiriedTime"> До какого времени команду можно выполнить.</param>
        /// <param name="ignoreBasicCommands">Игнорировать базовые команды при выполнение шагов.</param>
        public void RegisterNextStep(Func<IBotContext, Task> nextStep, DateTime? expiriedTime, bool ignoreBasicCommands)
        {
            CommandDelegate = nextStep;
            ExpiredTime = expiriedTime;
            IgnoreBasicCommands = ignoreBasicCommands;
        }

        /// <summary>
        /// Получение текущего кэша
        /// </summary>
        /// <typeparam name="T">Класс для хранения кэша</typeparam>
        /// <returns>Кэш</returns>
        public T GetCache<T>()
        {
            return cache is T resultCache ? resultCache : default;
        }

        #endregion

        #region Конструкторы класса

        /// <summary>
        /// Создать новый следующий шаг.
        /// </summary>
        /// <param name="command">Команда для выполнения</param>
        public StepTelegram(Func<IBotContext, Task> command)
            : this(command, null, null) { }

        /// <summary>
        /// Создать новый следующий шаг.
        /// </summary>
        /// <param name="command">Команда для выполнения.</param>
        /// <param name="cache">Кэш.</param>
        public StepTelegram(Func<IBotContext, Task> command, ITelegramCache cache)
            : this(command, null, cache, false) { }

        /// <summary>
        /// Создать новый следующий шаг.
        /// </summary>
        /// <param name="command">Команда для выполнения.</param>
        /// <param name="expiriedTime">Максимальный срок выполнения команды после чего команда будет проигнорирована.</param>
        public StepTelegram(Func<IBotContext, Task> command, DateTime expiriedTime)
            : this(command, expiriedTime, null, false) { }

        /// <summary>
        /// Создать новый следующий шаг.
        /// </summary>
        /// <param name="command">Команда для выполнения.</param>
        /// <param name="expiriedTime">Максимальный срок выполнения команды после чего команда будет проигнорирована.</param>
        /// <param name="cache">Кэш.</param>
        public StepTelegram(Func<IBotContext, Task> command, DateTime? expiriedTime, ITelegramCache cache)
            : this(command, expiriedTime, cache, false) { }

        /// <summary>
        /// Создать новый следующий шаг.
        /// </summary>
        /// <param name="command">Команда для выполнения.</param>
        /// <param name="expiriedTime">Максимальный срок выполнения команды после чего команда будет проигнорирована.</param>
        /// <param name="cache">Кэш.</param>
        /// <param name="ignoreBasicCommands">Игнорировать базовые команды при выполнение шагов.</param>
        public StepTelegram(Func<IBotContext, Task> command, DateTime? expiriedTime, ITelegramCache cache, bool ignoreBasicCommands)
        {
            this.cache = cache;
            IgnoreBasicCommands = ignoreBasicCommands;
            CommandDelegate = command;
            ExpiredTime = expiriedTime;
        }

        #endregion
    }

Для работы с шагами используется следующие методы расширения StepExtension:

Пользователь может прервать пошаговое выполнение команд в любой момент, для этого ему требуется вызвать ранее зарегистрированную команду. Допустим написать в чате Тест, в наших примерам можно было увидеть, что используется команда Тест.

Для хранение кэша (промежуточных данных) создадим класс StepCache.

Пример

Завершение пошагового выполнение команд на последнем шаге

Начиная с версии 0.6 есть возможность взвести флаг, который оповестит, что это последний шаг в системе и пошаговое выполнение нужно завершить.

Пример:

Игнорирование базовых команд при выполнение пошаговых команд

Начиная с версии 0.6 есть возможность взвести флаг, который оповестит систему, что в данный момент нужно игнорировать все команды, кроме пошаговых.

Пример:

Last updated