Как сделать квест в телеграмме
Перейти к содержимому

Как сделать квест в телеграмме

  • автор:

Редактор текстовых квестов для телеграма

Примерно год назад я наткнулся на текстовый квест в телеграме @QuestGameBot, там рассказывается увлекательная история о человеке, который очнулся где-то под водой и пытается понять, что вообще происходит. Концепция таких квестов мне понравилась, но я не нашел готовых решений, которые бы позволяли создавать подобные текстовые игры.

В то же время один мой товарищ попросил ему помочь в изучении языка программирования PHP. Как известно, лучше все изучать сразу на практике. Но для практики нужно было придумать проект. (товарищ в итоге слился)

Я подумал, что звезды сошлись и надо делать!

Что-то такое должны сказать люди в теме. И действительно, если поискать на dtf есть статьи про создание текстовых квестов:

Но есть один нюанс. (с)

Все эти квесты требуют специальных приложений. То есть, если я играю в квест, он мне очень вкатывает, я советую его друзьям: «это лучший сценарий, который когда-либо видел». Ииии вряд ли они его скачают. Нужно искать где-то программу, разбираться с интерфейсом, в общем нужно совершать очень много дополнительных телодвижений.

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

Когда мы видим сюжет какой-нибудь нелинейной RPG игры, например ведьмака, мы видим результат работы огромной команды писателей, разработчиков, дизайнеров. В книге «Кровь, пот и пиксели» показано люди создают игры, а потом выгорают и перестают заниматься геймдевом.

Но разработчиков мотивирует не только любовь к созданию игр, но и деньги. Они не могут позволить себе бросить работу просто потому что надоело. Нужно оплачивать квартиру, кормить семью, кота, закрывать кредит за машину.

Как это связано с редактором? Все просто. Я делаю инструмент для других людей и мне хотелось бы, чтобы процес создания игр был максимально прост и понятен с одной стороны. С другой, чтобы игра удивляла игрока. И, к сожалению, это два противоположных конца. Чем интереснее игра, тем дольше и сложнее ее разрабатывать. А значит люди, которые захотят попробовать сделать супер игру в редакторе, будут просто бросать разрабоку на половине пути (и это в лучшем случае).

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

Но такой подход убивает основную фишку игр — нелинейность. Поэтому пришлось от него отказаться.

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

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

Создаем собственный текстовый квест в Telegram

Телеграм боты — это крутой способ взаимодействия с пользователем прямо в привычном ему мессенджере. Это гораздо быстрее и чаще удобнее, чем писать полноценное мобильное приложение. В этой статье мы постраемся создать собственного Telegram бота, который будет предлагать пользователю разыграть полноценный текстовый квест.

Нюансы сюжета вам придется продумать самостоятельно, ну а вся техническая часть — под катом!

Для начала давайте познакомимся с Telegram ботами, по ссылке представлено множество примеров таких программ, от прогноза погоды до общения с рандомным собеседником: https://uip.me/2016/04/50-popular-telegram-bots/.

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

Чтобы создать собственного бота, сперва его надо зарегистрировать. Для этого в телеграме нужно добавить бота @BotFather и следовать инструкциям. После того, как мы введем название бота, @BotFather сообщит нам токен — пароль к нашему почтовому ящику.

После получения токена нам потребуется установить библиотеку pyTelegramBotApi, как и обычно, это делается через pip:

Пробуем создать бота

Давайте сделаем нашего первого бота — бота-попугая. На все сообщения он будет отвечать повторением.

Помимо текстовых сообщений, в телеграме есть команды, они начинаются со слэша, например, /start или /help . Их тоже можно обрабатывать.

Давайте добавим пояснение к нашему боту, которое объяснит пользователю, что он делает.

Взаимодействуем с несколькими пользователями одновременно

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

Если мы будем использовать переменную, то сможем сохранить сообщение только одного пользователя. Например, Вася попросил запомнить слово kitten . Мы положим эту строку в переменную note . А затем Петя, попросить запомнить слово puppy , и мы снова положим это переменную note . Когда Вася попросит нам напомнить его последнее сообщение, мы напишем ему puppy вместо kitten . Совершенно не годится!

> Удобнее всего хранить все данные, которые привязаны к конкретному пользователю в словаре. Ключем в этом словаре будет id пользователя, а значением — произвольные данные.

Предположим, что наш словарь называется notes — заметки. Теперь, когда Вася (id88000) пришлет слово kitten мы положим его в notes[88000] , а слово puppy от Пети (id5300) — в notes[5300] . Посколько теперь мы используем разные переменные для хранения слова, сообщения от разных пользователей не будут путаться.

Реализация:

Добавляем кнопки

Следующий пример демонстрирует, как добавить несколько кнопок к сообщению и реагировать на их нажатия.

Telegram бот для сложных квестов

«В чем же заключается преимущество?» — спросите вы, ну все дело в том, что в нем можно построить логику примерно из следующих выражений:

– Пользователь на шаге N?
– Сообщение содержит изображение и смайлик?
– Текст подходит под регулярное выражению «I am [a-zA-Z]+»?
– Время получения раньше/позже заданного?
– Это было нажатие на клавиатуре/обычное сообщение/inline-кнопка?

Большинство из этих правил могут быть в зависимости друг от друга, но об этом чуть позже.

Для начала, о чем я хочу рассказать:

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

Цель проекта

Это было в конце ноября, я понимал что скоро новый год и необходимо дарить подарки.
Идея с Telegram Bot–ом, в качестве карты поиска, казалась крайней простой и в должном исполнении интересной. Единственное что необходимо было сделать – взять и загуглить. Что собственно я и сделал. Основной посыл запроса – платформа для создания квестов, или же просто чат-бот c дополнительной логикой, написанный на python (желательно Django Framework)
Большинство рассмотренных приложений либо имели захордкоженные данные, либо же были своего рода викторинами. Ни то ни другое не подходило.

Интересными вариантами показались: Django Telegram Bot, PermaBot.

На первом репозитории долго задерживаться нет смысла, так как в описании недвусмысленно сказано «Try Permabots: more stable django app for bots.». Потому выбираем второй.
Стоит отметить что данная платформа сделана достаточно качественно, хоть и без соблюдения pep8 (не камень в огород, но это же де-факто стандарт 🙂 ), однако с комментариями, тестами, а главное документацией по REST API.

При наличии всех этих плюсов были обнаружены и существенные недочеты:

  • старая версия telegram API (версия 4.2.0 против 9.0.0, последний коммит Июнь 2016)
  • полное отсутствие поддержки media (здесь моя идея с изображениями накрылась медным тазом)
  • некоторые отсутствующие фичи (отложенная отправка уведомлений с настройками возможного ответа, гибкая настройка клавиатуры чата).

Веб фреймворк – Django, для асинхронных задач – Celery, брокер сообщений –
Redis, база данных – SQLite. В дальнейшем есть возможность переехать на Postgres/MySQL, но пока тащить всю эту махину с собой бессмысленно.

Что стоит отметить, для разработки и запуска проекта нужен внешний https-адрес, на который будут прилетать веб-хуки. Для этого можно использовать туннелирование на публичный домен посредством Ngrok или LocalTunnel.

Я использовал localtunnel локально и на сервере в связке c nginx и let’s encrypt сертификатами.

Архитектура

Bot – содержит общую информацию и token (аналог telegram.Bot в оф. документации)
Quest – модель квеста, все просто: имя, описание, бот. вынесено в отдельную сущность для логического разграничения
Step – возможные состояния переходов. если имеет флаг is_init=True, то будет выбрано в качестве начального при инициализации квеста
Handler – выступает в роли dispatcher-a, имеет логическое выражение, которое может выполняться либо нет, в зависимости от этого переводит пользователя на определенный шаг и отправляет соответствующие ответы (представлены моделью Response)
Condition – содержит возможные правила для какого–то определенного поля.
Update – объект, который прилетает с веб – хуком и содержит всю информацию
CallbackQuery – используется для inline – сообщений, отправлять таковые возможности пока нет (основной упор был на базовую клавиатуру), однако варианты расширения учитывались.
Reponse – хранит информацию о тексте сообщения, клавиатуре, ее поведении (скрыть, удалить, установить по умолчанию, показать дефолтную)
Message – полученный объект сообщения (telegram.Message)
Chat – хранит информацию о чате (telegram.Chat)
Photo – модель хранящая информацию о изображении (telegram.PhotoSize)
Event – отвечает за отправку сообщений в определенный чат, и имеет возможность одновременной установки состояния (шага) пользователя. все дополнительные данные (текст, клавиатура, настройки к ней) берет из заданной модели Reponse
User – модель пользователя унаследовал от contrib.auth.models.AbstractUser c указанием device_uid, step и еще некоторых дополнительных полей

Полную UML диаграмму можно просмотреть в draw.io, файл db-diagram.xml

Как мне кажется, один из любопытных аспектов это то, как происходит решение о выборе того или иного обработчика.

image

В поле «Mathematics expression» логическое выражение можно задавать двумя способами. Первый – тот что указан в примере, в этом случае условия к данному обработчику будут подставлены в порядке их добавления, во втором варианте – можно указать id условий.

Затем выполняется парсинг. Он проходит два этапа, вначале делается преобразование в булевое отображение, где 1 и 0 – истинность конкретного условия, и затем происходит разбор грамматики с использованием библиотеки pyparsing.

Другая сложность с которой пришлось столкнуться – выбор и указание клавиатуры. Было решено сделать одну по умолчанию и другую предоставлять в ответе. Таким образом появляется возможность задать дефолтную на весь чат, которая может выглядеть примерно так [[«Задать вопрос»], [«Попросить подсказку»]]

image

Также можно увидеть что telegram api позволяет скрывать текущую клавиатуру при нажатии на кнопку или же удалять ее совсем (в этом случае отправляется дефолтная).

Еще одна вещь связанная с клавиатурой – это попытка узнать что же это было, то ли обычное сообщение написанное пользователем или же нажатие на кнопку. Для чего это нужно?
Предположим, на каком-то шаге мы решили запросить текстовый ответ у пользователя и в то же время там отображается стандартная клавиатура с кнопкой «Поменять задание». Несмотря на то что обработчики (Handlers) содержат опциональные поля Step on success и Step on error, гораздо проще организовать логику ограничив тип действия на который они реагируют. Для этого в модели Chat содержится информация еще и о текущей клавиатуре, по ней определяется нажатие это или другой тип события. Это полезно когда необходимо узнать что творится в каком-то определенном чате.

Помимо этого, из фич, которые показались нужными – это функция redirect message. В каждом обработчике можно указать кому перенаправлять сообщение при вынесении вердикта истинности. Пригождается когда нужно проследить специфические моменты (тот же вопрос администратору) или прохождение некоторых этапов пользователем.

Стоило оно того?

Определенно. Тестирование заняло пару вечеров, после чего я настроил и запустил это на сервере. Квест состоял из 10+ состояний и включал в себя выбор вариантов ответа, рассказ истории (суть была в поиске ключевых слов), выполнение задания по карте местности, отправки фотографии года и еще некоторые.

Пожалуй, реакция человека, для которого я это делал, окупила те вечера перед зачетной неделей, которые я потратил.

Перспективы

На данный момент готов рабочий вариант, который разворачивается в docker-контейнере за пару минут, но для полноценной разработки необходимы тесты, продуманное окружение и еще некоторые настройки. Если кому-то проект покажется интересным, то я с желанием продолжу поддержку/разработку, реализация фронтенда под вопросом, но возможна (на emberJS или vueJS).

Первый текстовый квест на базе бота в телеграме ⁠ ⁠

Игра правда затягивает. Я уже около 4 часов играю, но ещё не выбралась. Знакомые писали, что примерный рекорд — 1 час, а кто-то бродит уже третий день.

Надеюсь вам понравится 🙂

Разработчик указан по ссылке, я всего лишь довольный пользователь.

Первый текстовый квест на базе бота в телеграме Квест, Текстовый квест, Telegram

Давайте жить дружно⁠ ⁠

Мы долго жили на съемных квартирах. Бывало всякое: и мусор под дверью какая-то ленивая дрянь каждое утро нам ставила и ключи от подъезда у ребенка забирали, чтоб не бегали эти дети туда-сюда, и обвиняли что несуществующая у нас собака подъезд засрала и нескончаемый ремонт по утрам-вечерам.
Два года назад мы переехали в свою квартиру, и внезапно все стало так хорошо! В первый же вечер в новой квартире отключили свет, естественно все соседи моментально выползли в подъезд проверять щитки. Так и познакомились: "Привет, мы ваши новые соседи из 49, и часто тут так свет отключается?" Оказалось не часто, это вам подарок на новоселье, пошутили соседи. Три месяца назад к нам постучалась соседка из квартиры над нами: "Я в отпуск улетаю, цветы подруга будет приходить поливать, а вам вот ключи, мало ли что, у меня трубы старые, вы следите, особенно на кухне". Сказать что мы охренели — ничего не сказать. Ключи брать отказались, тогда она позвонила в соседнюю дверь, сосед улыбнулся тете Марине и сказал что проследит.
Месяц назад случилась ситуация, которая выбила нас с мужем из колеи. Время 21.10, стук в дверь. Открываю- стоит сосед:
— Добрый вечер, у вас дети не спят?
— Нет
— Мне нужно 2 минуты посверлить, можно?
— Ээ, да, конечно, посверлите если нужно.
Он обошел всех соседей, у всех спросил разрешение. Утром муж встретился с ним на у подъезда, договорились поменять т. Марине трубы на кухне. Сегодня они закончили менять трубы уже в ванной, в жкх ходили все вместе.
А еще у нас на этаже кто-то выставил кресло, хорошее, широкое, мягкое кресло. И теперь на нем сидят подростки. Каждый день разное количество, но целый день. Сидят тихонько в телефонах, болтают о своем, никому не мешают. Они на дверь повесили большую наклейку "курение запрещено" и здороваются когда выходишь из квартиры. Сегодня пошла выносить мусор, на улице ливень и +5, подростков под дверью больше обычного, но их даже не слышно. Один говорит: "я сейчас ухожу, давайте ваш мусор заберу?" Говорю ок, вы так тихо сидите, могу дать вам пароль от вайфая, если никому не будете мешать, а через три дня поменяю, у вас школа начинается.
Может я наивна, но для меня это все примеры правильного соседства, приятно на душе. Всем кто осилил чтение желаю идеальных соседей.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *