Бот ВК на коленке, или как порадовать людей 14 февраля

    Конечно, каждый из нас любит подарки, но больше всего мы любим сопровождающие их пожелания. И, до недавнего времени, у нас не было возможности приятно удивить человека тёплыми словами, пока в голову не пришла идея: а что, если дать людям возможность обмениваться валентинками (на носу же 14 февраля, всё-таки) не выходя из рамок привычного способа общения — чатов социальной сети?

    Слово за слово, и вот оно — готовый бизнес-план по созданию атмосферы праздника Дня всех влюбленных! Сделаем людей счастливыми?


    За идеей на луну!


    Конечно, в первую очередь необходимо было составить план действий и описать идею. Из-за того, что люди стали более стеснительны, и не всегда готовы доверять кому попало, выбор пал на написание модного и удобного бота для ВК, который имеет знакомый интерфейс, всегда окажется под рукой, а анонимность сообщений будет жестко задана в коде программы.
    К сожалению, помимо всех вышеописанных плюсов, у сообществ есть два минуса: низкая пропускная способность (количество сообщений в секунду) и запрет на старт диалога со случайным пользователем (пользователь должен первым и явно выразить своё согласие на поучение сообщений от имени сообщества).

    Итак, мы имеем пользователя, готового отправить валентинку своей второй половинке, получателя и посредника в виде чат-бота. Схема взаимодействия проста, бот должен: предложить отправку → узнать получателя → сохранить до 14 февраля → доставить → повторить.

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

    Дисклеймер


    Этот проект создавался чисто на энтузиазме двумя людьми, программистом-недоучкой (мной) и идейным вдохновителем (Степаном sadfun Поповым), не несёт в себе цели чему-то вас научить (хоть и может помочь вам понять суть мироздания), лишь поведать интересную историю создания и проследить путь от идеи до наивной реализации.



    Учимся говорить с ВК


    Перебрав 3-4 различных библиотеки по запросу «NodeJS VK API», я понял, что нет простых и функциональных библиотек, позволяющих использвать промисы, а также работу через execute. Помните одну из проблем, описанных выше? Да, исполнение запросов к ВКонтакте не напрямую, а пачками по 25 позволяет в разы увеличить пропускную способность.


    Сравнительная возможность различных методов запросов к ВКонтакте

    Поэтому было принято решение написать что-то своё, надёжное и не очень костыльное решение, основываясь на библиотеке node-fetch.

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

    Так как запросы из программы нужно упаковывать в один execute, они собираются в очередь LIFO, а затем отправляются, если:

    • Вызовов 25 или больше (максимум execute)
    • Прошло достаточно времени с прошлой отправки, не меньше 50 миллисекунд, но не больше 150 (чтобы очередь двигалась, несмотря на маленький размер)

    Запросы из очереди компонуются в код VK Script, который (в этой реализации) выглядит так:

    var returnables = [];
    returnables[0] = API.messages.send({"message": "Привет, Хабр!", "peer_id": 1, "random_id": 561427});
    returnables[1] = API.users.get({"user_ids": 1, "fields": "sex"});
    return returnables;
    

    После выполнения кода запросом к ВК, результат каждого запроса (по индексу returnables) возвращается в свой callback, красиво обёрнутый в Promise. Эффективность подхода зашкаливает — чем больше пользователей (и, следовательно, больше запросов к ВКонтакте на отправку), тем меньше задержка ответа. Чтобы удерживать под контролем лимит, в системе отправки есть счётчик, показывающий количество оставшихся запросов на эту секунду, что позволяет быстро обрабатывать всплеск посетителей.

    Учимся слушать ВК


    Всего способов получать уведомления о событиях из ВКонтакте есть два: Longpoll-запросы и Callback-сервер. Свой сервер удобен тем, что не требует особых телодвижений для использования, а также позволяет получить пропущенные уведомления (например, при перезагрузке сервера). Такой сервер можно написать в несколько строк, используя нативный класс http.Server.

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

    Всё когда-нибудь кончается


    Так как пользователь волен делать в чате всё, что угодно, и остановить мы его не в состоянии, нам нужно его ограничить разумными рамками. С этим отлично справляется конечный автомат, задавая каждый возможный переход внутри системы, а использование кнопок (параметр keyboard в messages.send) сделает использование бота простым, как одно касание экрана.

    Вот схема взаимодействия пользователя с ботом:


    Всё это превращается в набор состояний («Главное меню», «Ввод валентинки» и так далее), переходы между которыми заданы и передаются в кнопках, либо известны изначально и не меняются.


    К слову, о кнопках. Их цветовая гамма невариативна (4 цвета на все случаи жизни), но именно кнопки заставляют свести количество ошибок пользователей к минимуму. На их основе можно построить совершенно любую нелинейную систему, именно поэтому они используются повсеместно. И в этом проекте тоже.

    Но нужно понимать: если вы целитесь на большой охват аудитории, стоит продумать и иной способ взаимодействия, ведь у кого-то может оказаться старое приложение (VK for iPad, например, не обновлялся очень давно, врать не буду, но кажется, больше года, и поддержки клавиатур там нет). А бывает (да, бывает, я проверял), что люди, не понимая, что на кнопки можно нажимать, просто переписывают их содержимое (и тогда параметр кнопки payload, естественно, не передаётся, и всё может сломаться).

    Надо заметить, что не всё бывает так гладко, как это описано на схеме, и иногда встречаются курьёзные случаи. Например, система определения ссылки ВКонтакте некорректно обрабатывала пользователей, короткие ссылки на которых начинались на id, и обрезала это. Удивление людей, встретившихся с этим багом, не описать, ведь они писали валентинку Феде, а получилось, что Олежке.
    Какой Олежка????

    Случайности не случайны


    Итак, если с обычными валентинками всё понятно, есть получатель и отправитель, то как свести двух незнакомых людей? Надо обменять их валентинками, и если людям нравятся валентинки друг друга, то их стоит познакомить! Вот она, формула любви!

    Хоть и звучит это пафосно, но работает, и людям становится интереснее работать с ботом — они получат позитивный отклик, если найдётся хоть один человек (о чём, естественно, бот сам позаботится).

    Из этого вытекает большой плюс — чем больше людей воспользуются этой возможностью, тем больше шансов познакомится, а следовательно, это, как игра, удерживает человека в чате. Стоит признаться, сессия среднестатистического пользователя составляет ~7 минут, здесь же есть потенциал затянуть человека на 10-15 только ради этой фичи.

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


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

    Фейерверк в конце


    Собственно, вот и всё! Если не учитывать некоторые сложности в понимании логики работы VK API, а также с подтверждением аккаунта у одного из провайдеров, всё прошло даже слишком гладко.


    Пример чата с ботом

    Бот работает и будет радовать людей валентинками, делая их счастливыми. Это сделано, чтобы помочь людям быть добрее друг к другу. Оценить всё это вы можете самолично в сообществе Валентиныч — vk.com/verylovebot, если желаете. Спасибо за внимание!

    Комментарии 6

      +1
      Отличная работа!!! А хабраэффекта не боитесь? Хотелось бы потом узнать пиковые значения нагрузок и статью об оптимизации бота под большие нагрузки.
        +1

        Если быть откровенным, то бояться тут нечего — во-первых, бот уже достаточно хорошо оптимизирован с помощью execute, а во-вторых наплыва почти нет (и вряд ли будет).
        Поэтому и о пиковых нагрузках, по крайней мере до 14 февраля, писать не приходится — хорошо, если к нам приходит пара человек в минуту. Рекламы нет, а само сообщество не раскручено — нет и эффекта.

        –1
        Ну такая себе анонимность, когда ты сам уговариваешь человека написать боту
          +1

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

          0
          А чем не подошёл VK-IO?
            +1

            Отлично подошёл бы, но, видимо, беглый взгляд не заметил столь хорошую библиотеку. Жаль, очевидное упущение.
            В любом случае, собственная реализация даёт прекрасное представление о правильной механике работы подобных библиотек, а следовательно и понимание их правильного использования, да и опыт.

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

          Самое читаемое