Skip to content
Troy Köhler

Я сделал бота, который ведет семейный бюджет в Notion вместо меня [pet-проект для программиста]

программирование4 min read

Assorted bank notes
Photo by Annie Spratt / Unsplash

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

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

Если обобщить его ответ коротко, то это было:

— Ты слишком много читаешь. А надо больше делать.

Это был драгоценный совет.

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

Первым моим проектом стала автоматизация ведения нашего семейного бюджета с помощью Notion API и Telegram API.

Итак, поехали.

Зачем я использую Notion?

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

1

Сама карточка в базе данных выглядит вот так.

2

Вся база данных выглядит вот так.

3

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

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

Конечно же, эффективность разных товаров для разных семей разнится, но, думаю, суть вы уловили.

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

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

Библиотеки, которые я использовал

Я использовал flask, python-telegram-bot и notion-client. Последняя имеет версию 0.4.0 на момент написания моего поста и это значит она еще не считается готовой для серьезных проектов.

Мой проект не серьезный, в нем вполне может что-то поломаться и я не буду сильно расстраиваться. Мне очень понравилось пользоваться библиотекой, в ней есть подсказки по типам и аннотации под функции.

Принцип работы

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

Так же я сделал регулярную задачу с помощью job_queue (подробнее о нем можно почитать в библиотеке python-telegram-bot), суть которой каждый день смотреть сколько у нас осталось денег на разные категории расходов и публиковать информацию об этом в наш семейный телеграм канал.

Каждый раз, как я или моя девушка, публикуем сообщение в общий телеграм канал с расходами, вот такого вида:

<категория расходов>
поездка на метро 8

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

Для сравнения строк, я использую:

SequenceMatcher(None, tokens[0], type_of_spend["title"]).ratio() > 0.6

После этого из каждого токена (строки) вытягиваются числа вот таким регулярным выражением:

re.findall(r"[-+]?\d*\.\d+|\d+", token)

Потом идет взаимодействии с апи, создается карточка и обработка нового сообщения завершается.

В библиотеке python-telegram-bot есть один большой минус, аттрибуты у Update из телеграмма не постоянны и есть высокий риск напороться на то, что у вашего апдейта не будет того аттрибута, который вы ожидаете, что у него будет. Поэтому я рекомендую быть очень осторожным с проверками того, что содержится в апдейте.

Вот так выглядит моя функция, которая обрабатывает обновления, которые присылает моему серверу телеграм.

def notion_card_creater(update: Update, context):
    if hasattr(update, "channel_post"):
        chat_id = update.channel_post.chat_id
        if chat_id == our_home_chat_id:
            content = update.channel_post.text
            make_notion_card(content)

Размещение в облаке

Я разместил свой сервер в облаке бесплатно, используя Google Cloud Run. У этого сервиса гугла достаточно жирный free tier, на домашнего бота хватает более чем.

Вот мой Dockerfile для сборки образа.

FROM python:3.8-slim
ENV PYTHONUNBUFFERED True
WORKDIR /app
COPY *.txt .
RUN pip install --no-cache-dir --upgrade pip -r requirements.txt
COPY . ./

CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 bot:app

Я пользовался отличной статьей Hosting Telegram bots on Cloud Run for free.

В Google Cloud Run можно настроить continious deployment с вашего репозитория на гитхабе. Это очень удобная штука.

Почему я не выкладываю код в открытом виде?

Я хочу, чтобы этот пост вдохновил на создание чего-то своего.

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

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

Это очень помогает поверить в собственные силы, полюбить программирование и избежать того, что в английском называется programming tutorial hell.

Спасибо моему тим лиду Игорю Можаровскому, который натолкнул меня на эти мысли.

У меня есть email рассылка.

Не могу сказать, что она о чем-то конкретном, поэтому подписывайтесь на свой страх и риск!

Высылаю 1 письмо в месяц.