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

JavaScriptNode.JSDIY
Конечно, каждый из нас любит подарки, но больше всего мы любим сопровождающие их пожелания. И, до недавнего времени, у нас не было возможности приятно удивить человека тёплыми словами, пока в голову не пришла идея: а что, если дать людям возможность обмениваться валентинками (на носу же 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, если желаете. Спасибо за внимание!
Tags:ВКчат-боты14 февраляjavascriptnode js
Hubs: JavaScript Node.JS DIY
+10
10.9k 80
Comments 6

Popular right now

Senior Javascript/Node.JS Разработчик
from 2,500 to 3,300 $MakeomaticRemote job
Javascript разработчик
from 130,000 to 180,000 ₽ArtezioНижний Новгород
JavaScript Fullstack developer
from 80,000 to 150,000 ₽IntspiritКраснодарRemote job
Full-Stack JavaScript developer
from 5,000 to 6,500 $LuminatiRemote job