Giter Club home page Giter Club logo

cheweatherbot's Introduction

¡Yahoo! 🥳

I am a programmer from Cherepovets, studying at SPbU, Saint Petersburg.

Open for hiring!

I mostly write in Python - Backend and Fullstack, but also interested in Scala and Rust.

Here is the list of some of my projects:

  • CheWeatherBot - Telegram-bot about weather in my hometown.
  • 💬 ZIF - Forum-like social network.
  • 🎓 Tasker - Online platform to learn programming.

cheweatherbot's People

Contributors

bobaubisoft17 avatar masynchin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

Forkers

bobaubisoft17

cheweatherbot's Issues

Сделать class-based хендлеры

В чём проблема?

Развивая #3. Решением было бы нечто похожее на takes, где каждый take (в терминологии takes), он же хендлер (в терминологии aiogram), является объектом, а не тупой ручкой. Так, каждый хендлер имел бы свои зависимости, и мы бы избавились бы от глобальных.

Решение?

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

Удалить совместимость с PostgreSQL

Продолжение работы #10.

Совместимость с PostgreSQL требовалась только для Хероку, тогда как на локалке и сервере используется строго SQLite. Раз Хероку больше не используется, то и совместимость можно убрать.

Возможный баг рассылки при вебхуке

Описание бага

При запуске бота в режиме вебхука задача (asyncio.Task) рассылки может не выполнятся.

Когда

В текущей (59855de) версии бага нет, но он возможен при переходе на aiohttp >= 3.8.0.

Что проверить

Всё, что связано с aiogram/aiogram#794.

Настроить CI

В чём проблема?

Тесты есть, линтеры есть, форматтеры есть, а не используется (всё держится на моём честном слове)

Что делать?

Настроить github-actions, запускающий тесты на главной ветке и всяких PR. В одном action линт и тесты, как это сделано у FastAPI.

Избавление от глобальных зависимостей

Сейчас в коде есть несколько глобальных зависимостей:

  • Конфиг
  • База данных
  • Погода
  • Логгер

Просто так их убрать, скорее всего, не получится (из-за aiogram, так как нельзя сделать class-based бота). Но есть наработки того, как их можно превратить в injectable (хотел бы русское слово подобрать, да лексикон маловат) зависимости. Представлены в отдельных комментариях.

Настроить CD

Что было до?

На Хероку было два проекта, которые сами следили за обновлением веток. На каждое обновление заново разворачивали бота - develop и release версии.

Что надо теперь?

В идеале - то же самое. Пока нашёл два варианта:

  • dokku
    Мини-Хероку. Почти ничего не знаю о нём.

  • spot
    Есть пример с клоном репозитория + запуском докера.

Использовать YAML для стикеров

Как сейчас?

Стикеры хранятся в JSON-формате

Альтернатива

YAML-формат. Для парсинга нужна сторонняя библиотека.

Пример, как может выглядеть yaml-файл со стикерами:

stickers:
  maintaince:
    "CAACAgIAAxkBAAOzX6qTAfXKDu2AHZeIsvL5hOqaOjQAAid3AAKezgsAAbn1MA3HuSrzHgQ"
  undefinedWeather:
    - "CAACAgIAAxkBAAIFrGB5qECtEzAUElFqyyqKTRtxowABYQACtBAAAowt_QcV3E-B7MVlSB8E"
    - "CAACAgIAAxkBAAIGamB54uujPvJlXz6UzoTxQwjTftxeAAKxEAACjC39B73fqL1y8JozHwQ"
  weatherTypes:
    Clouds:
      - "CAACAgIAAxkBAAIFqmB5p_nYqUZxB8jEyWl7jR2407pzAAK2EAACjC39B1-3aJ2Pm2f-HwQ"
    Rain:
      - "CAACAgIAAxkBAAOkX6lhlZV6aMKJ14jLAAG8waq9xvneAAI9AQACMNSdERD3ygdxko_uHgQ"
      - "CAACAgIAAxkBAAOnX6lig43GAz5okVxxdCFi4ds_z6MAArIBAAJWnb0KODnd6BWt4QYeBA"
      - "CAACAgIAAxkBAAO3X6qakjSAMKWGE9K9PvstMnVbQ7kAAgx3AAKezgsAAdl0EAUWfhaRHgQ"
    Snow:
      - "CAACAgIAAxkBAAOoX6linckMdNC_cnxvBc5qTuxN-p0AAgkBAAJWnb0K1mZcg9c_qB0eBA"
      - "CAACAgIAAxkBAAOrX6ljHh_ISPAqu5PznXRgf9-n6UgAAtgAAzDUnRGZmYKVaEQuKh4E"
      - "CAACAgIAAxkBAAOwX6qSn6XFcpKHEpg9gCcy3Wh1sEAAAh93AAKezgsAAXtRCiVhuD3PHgQ"
    Hot:
      - "CAACAgIAAxkBAAOpX6lixA0F4Afu__6YqbNzDl3S3lIAAlUAA61lvBSgZXBhikQl4R4E"
      - "CAACAgIAAxkBAAOyX6qS6UhjpQ1DMyLjM_njdRTni0gAAiJ3AAKezgsAAeVLCR2h1FcJHgQ"
      - "CAACAgIAAxkBAAO1X6qTOBAijWiQ2WKMKs6VdVwxyc8AAiZ3AAKezgsAAa9M0LmacOK0HgQ"
    Thunder:
      - "CAACAgIAAxkBAAOqX6li4HA16-5vftTMAat63iObFTMAAqsAAzDUnRHOX5OAFZJfkR4E"
      - "CAACAgIAAxkBAAO2X6qZ5aSwur3pLf1Wi-lmBy99mwUAAg13AAKezgsAASRlrppXpQ5XHgQ" 

Добавить Docker

Что добавить?

  • Dockerfile
  • Инструкцию по запуску

Вопросы

Стоит ли добавлять docker compose и docker-compose.yml?

Обновить тест

В чём проблема?

В #33 было выявлено, что тест пропустил изменение структуры ответа.

Что делать?

Обновить тест, добавив проверку модели.

Классы времени для кнопок

Кнопки клавиатур используют CheDatetime как CheDate и CheTime. Таких классов сейчас нет, но их следует сделать. Так, часть функционала utils, отвечающая за форматирование, будет использоваться этими классами, например, методом .format().

Попробовать uvloop

Что это?

uvloop - drop-in replacement для event-loop'а asyncio, ускоряющий работу программы в x раз.

Можно?

На винде нельзя, но так как разработка и развёртывание происходят на macOS/linux, то теперь можно.

Использовать ресурсы

В чём проблема?

Сервисы (в частности, БД подписчиков и API погоды) создают ресурсы при каждом запросе:

  • Создание соединения к БД для каждого запроса:

CheWeatherBot/app/db.py

Lines 31 to 36 in df8ac22

async def add(self, user_id, mailing_time):
"""Регистрация в БД нового подписчика рассылки"""
async with async_session() as session:
subscriber = Subscriber(id=user_id, mailing_time=mailing_time)
session.add(subscriber)
await session.commit()

  • Создание сессии aiohttp.ClientSession для каждого запроса:

@alru_cache(maxsize=1)
async def _get_weather(url, time):
"""Кешированный прогноз погоды в виде WeatherResponse"""
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
data = await response.json()
return WeatherResponse(**data)

Решение?

Аллоцировать ресурсы в main один раз, и единожды передавать их в сервисы, примерно так:

async def main():
    async with db.connect(...) as conn, aiohttp.ClientSession(...) as session:
        subs = Subscribers(conn)
        weather = OwmWeather(session)

Убрать SqlAlchemy

В чём проблема?

После #14 в проекте используется только Sqlite3, и, соответственно, aiosqlite. Раз так, то зачем нам лишняя прослойка?

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

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

Бот не обрабатывает блокировку пользователями, из-за чего их ID, если они подписались на рассылку, остаются в БД, и при попытке отправить им рассылку бот вызывает исключение.

Лог ошибки

Task exception was never retrieved
future: <Task finished name='Task-3' coro=<mailing() done, defined at /app/app/mailing.py:16> exception=BotBlocked('Forbidden: bot was blocked by the user')>
Traceback (most recent call last):
File "/app/app/mailing.py", line 26, in mailing
await send_mailing(bot, mailing_time.time())
File "/app/app/mailing.py", line 51, in send_mailing
await bot.send_sticker(user_id, sticker)
File "/app/.heroku/python/lib/python3.9/site-packages/aiogram/bot/bot.py", line 2534, in send_sticker
result = await self.request(api.Methods.SEND_STICKER, payload, files)
File "/app/.heroku/python/lib/python3.9/site-packages/aiogram/bot/base.py", line 208, in request
return await api.make_request(self.session, self.server, self.__token, method, data, files,
File "/app/.heroku/python/lib/python3.9/site-packages/aiogram/bot/api.py", line 140, in make_request
return check_result(method, response.content_type, response.status, await response.text())
File "/app/.heroku/python/lib/python3.9/site-packages/aiogram/bot/api.py", line 121, in check_result
exceptions.Unauthorized.detect(description)
File "/app/.heroku/python/lib/python3.9/site-packages/aiogram/utils/exceptions.py", line 140, in detect
raise err(cls.text or description)
aiogram.utils.exceptions.BotBlocked: Forbidden: bot was blocked by the user

Возможные пути решения

  • Обрабатывать исключение, возникшее при отправке рассылки
  • Обрабатывать событие блокировки (если таковое возможно)

Рассылка

При вводе времени отправки рассылки можно положить бота, указав некорректную дату в виде HH (не HM), фиксите

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.