Створення бота-провідника. Частина 1 — Розвиток коду

Dan Voronov
7 min readAug 14, 2023

Розповім про те, як розвивалася та створювалася моя ідея Бот-провідника у Telegram.

Щодо самого маршруту, для чого і чому я розповім у наступній частині. Ця замітка містить технічні деталі, пов’язані з програмуванням та вирішенням ряду проблем.

Версія 1 🚀 —скрипт в Google Docs

У 2019 році я створив телеграм-ботів, які “читали” п’єсу в публічному чаті, докладніше на Medium. Ідея використовувати ботів для розповідання історій мені здалася перспективною. Отже, наступним етапом я прагнув спробувати автоматизувати екскурсію містом.

Для знаходження туторіалів щодо створення телеграм-бота на GAS увійдіть до YouTube та введіть запит “Telegram bot with Google Apps Script”.

В основі “читтаня” лежала немодифікована п’єса у вигляді документа на Google Диску. Для бота-провідника я вирішив використовувати Google Таблицю, де кожен стовпець відповідав би за контрольну точку: коли людина досягає певної точки, бот “розповідає” їй, що там відбувалося, за допомогою повідомлень з таблиці рядок за рядком. Далі відправляє координати наступної точки, ітд.

Коли: зима 2019–2020, весна 2020.

🛠️ Реалізація: Google Таблиця з координатами та історією де стовпці відповідають за точки, рядки — повідомлення. Основний код написаний на Google Apps Script (це підмножина JavaScript), який я добре знав та мав досвід використання його разом із API телеграм-ботів.

🚧 Проблеми: припинення виконання скрипта. На кожній точці я бажав відправити близько 5–10 повідомлень та, щоб людина мала час прочитати, робив паузу між ними. В більшості точок це працювало, але іноді Google припиняв виконання скрипта, вважаючи його таким, що більше не відповідає на команди.

Версія 2 🌐— перехід на Heroku node.js

Було очевидно, що проекту не вистачало ресурсів платформи Google Документів. Після дослідження я знайшов Heroku, який в 2020 використовували майже всі для своїх pet проектів, оскільки безкоштовний план був досить потужним.

На Google Документах я створив обгортку, яка відправляла “бот прокидається”, оскільки Heroku переводив безкоштовні програми у сплячий режим після періоду неактивності, і це могло займати до 5 секунд на старт. Я не хотів, щоб користувач міг подумати, що бот не працює після натискання “старт”.

Використання хостінгу також надало можливість завантажувати багато файлів — координати стали окремим файлом, кожна точка мала свій власний файл з фотографією.

Коли: березень-липень 2020 року.

27 березня я зробив свій перший heroku коміт для тесту “express”.

🛠️ Реалізація: все та ж таблиця, але оскільки код вже був на JS, я почав вивчати і переносити його на node.js, використовуючи пакет npm ‘google-spreadsheet’. Точки я виніс у окремий файл points.kml, який було легко редагувати на мапі через Google Earth, і читати його можливо було за допомогою пакету npm ‘read-xml’.

Heroku надавав внутрішню git-адресу якто https://git.heroku.com/babiy-yar-bot-prod.git, при пуші на яку контейнер перебудовувався. Код я писав локально у Sublime Text.

🚧 Проблеми: Тепер бот не відключався, але все ще працював повільно, оскільки не тільки безкоштовний план Heroku був повільним, а і постійні звертання до таблиці Google.

Версія 3 🗃️— перехід до Postgre SQL

Виявилося, що, прив’язавши номер кредитної картки, і навіть не роблячи жодних покупок, в Heroku відкривається можливість використовувати їхній SQL-двіжок бази даних, що, очевидно, буде швидше, ніж постійно запитувати Google Таблицю.

Я вивчав SQL ще в університеті в середині 2000-х і писав на стеку LAMP у 2010-х, тому цей було мені плюс.

Тепер я міг збільшити кількість і контрольних точок прогулянки до 44 і повідомлень на точці.

Коли: серпень-листопад 2020 року.

🛠️ Реалізація: таблиця в Google залишилась, оскільки в ній було зручно писати історію, але при запуску контейнера на Heroku вона завантажувалась у базу даних postgre один раз, і всі наступні дані читалися за допомогою SQL. Я створив команду “/up” для бота, яка дозволяє завантажити оновлення історії з Google Таблиці в БД без перезапуску контейнера.

Всі дані користувачів фіксував в БД, також використовував формат jsonb для збереження великого об’єкта, в якому фіксувався час прибуття на кожну точку.

🚧 Проблеми: хоча все добре працювало, мені не подобалося, як я спочатку задумав бота— людина приходить до точки, надсилає своє місцезнаходження, і якщо вона знаходиться де треба, бот починає відправляти повідомлення з цієї контрольної точки. Всі разом. Потім знову користувач повинен йти до наступної точки, не використовуючи бота.

Версія 4 🗺️ — перехід до live location та Airtable

З 2017 року у Telegram існує можливість відправляти маячок і програма буде відстежувати твоє розташування в реальному часі. Я це постійно робив з друзями і у загальних чатах свого проекту походів Києвом.

Проте, дивно, але я довго вірив, що це працює лише для людей, а не для ботів. Нарешті вирішив перевірити, які повідомлення приходять мені на вебхук, коли надсилаю їх своєму боту.

Виявилось, що приходить повідомлення “локація відредагована”, і це було саме те, що мені потрібно.

У той же час я почав створювати мод бота под другу історію-прогулянку, яка була базована не на тексті, а на аудіо. При цьому стало очевидним, яка зручна та швидка платфомра Airtable, тож я відмовився від Google Таблиць.

Коли: січень-серпень 2021 року.

🛠️ Реалізація: я створив копію бота, розташував точки навколо свого будинку, і взимку виходив перевірити та записувати логи, як це дійсно працює, з якою частотою відбувається оновлення тощо. Це мене влаштовувало, тому я переробив основний код так, щоб кожного разу визначалася відстань до контрольної точки, і всі повідомлення про неї надходили з рівним інтервалом поки людина в дорозі. Код я переніс на GitHub, щоб не бути прив’язаним до Heroku. Дані у postgre на старті тепер завантажував за допомогою npm модуля “airtable-plus”.

🚧Проблеми: “довгий” код. По-перше, коду стало вже багато, на невелику кількість файлів (botdb.js, const.js, data.js, send.js, service.js, telegram.js), і деяка частина цього коду була ще з версії 1. По-друге, виникла проблема з тим, що не завжди можна розпізнати помилки на старті контейнера, і, наприклад, під час тестового проходження я йду 4 години по місту контрольними точками, і все добре, а після цього виникає якась помилка, і бот “вмирає”.

Версія 5 🧹 — чистий код

Друг, який давно працює програмістом, порекомендував мені книгу “Чистий код” Роберта Мартина (goodreads), і хоча ця книга на Java, в ній є багато світоглядних та практичних ідей, які дозволяють писати код зрозумілим та швидким.

Мене особливо вразили ідеї, що коментарі — це немоч, і код повинен пояснювати сам себе через назви змінних та функцій; одна функція — одна дія.

Також важливим було розбиття на логічні рівні абстракції.

Коли: вересень-грудень 2021 року.

🛠️ Реалізація: я розклав свій код за рівнями абстракції, створив папки та підпапки, багато файлів з невеликою кількістю коду в кожному. Це дозволило виявити зайвий код та проблеми в логіці.

🚧 Проблеми: під час рефакторінгу я допускав багато дрібних помилок, які потрібно було постійно виправляти. Для тестування використовував підмінну локацію в телефоні через режим розробника на Android та програму “Listick Fake GPS” (github). Мені доводилося вручну емулювати прогулянку, клацаючі постійно по мапі. Хоча, звісно, це було набагато швидше, ніж ходити весь маршрут у місті пішки. Програма не завжди деактивувалася, що викликало дивне поводження телефона.

💥 У 2022 році було не на часі працювати над проектом. До того ж в кінці року Heroku припинив надавати безкоштовні плани.

Версія 6 🧪— перехід до Dynobase та автоматичні тести

Бот-провідник, в якого я вклав стільки зусиль, був просто вимкнутий та далі видалений компанією Heroku, але код залишився на github. З грудня 2022 поступово я шукав новий хостинг, вибираючи те, що підходить мені найкраще з базовим безкоштовним планом.

На жаль, через пандемію багато компаній були змушені обмежити безкоштовні послуги, і це стало впливати на доступність ресурсів та сервісів. Одного ранку у п’ятницю, 13 січня знайшов у себе в епощті листа від Rachel Schipull <rachel.schipull@cyclic.sh> “Hey friend, You spoke and we listened. You can now deploy private GitHub repositories on our Free Forever tier.”.

Я вирішив запуститися на Cyclic.sh. У них не було SQL-бази, тому мій вибір був або зовнішній сервер (звичайно ні), або перехід до NoSQL, що врешті-решт сталося і я розпочав переписувати всю гілку, яка працює з базою даних. Також я вирішив створити внутрішній HTML-інтерфейс, який мені відображатиме статистику проходження для кожного користувача та кожної точки.

Продовжуючи ідеї з “Чистого коду”, я все ж таки вирішив витратити місяць на написання функціональних автотестів, щоб уникнути проблем з фейковою локацією на телефоні.

Коли: весна-осінь 2023 року.

🛠️ Реалізація: Cyclic.sh має свою власну обгортку навколо Dynobase, тому я спочатку написав код, щоб перевірити, що вона може (це також порада з “Чистого коду”). Також я розглянув їхній репозеторій, щоб побачити всі можливі функції, які я можу використовувати.

Автоматичні тести пишу на JEST — в коді запитів до API Telegram я перейшов на fetch, тому я почав його мокувати, щоб створити фейкову поведінку користувача бота як для оптимального проходження, так і для помилкових дій.

🚧 Проблеми: …чекаємо :)

--

--

Dan Voronov

http://danvoronov.com/ #creative #art #designthinking ♥️ #nonmonogamy #equality 👣 🛴 #КИЕВнасквозь