1. Example 1: Hello World

Note

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

1.1. Цели примера

  • Показать, как написать самого простого бота, используя pywood

1.2. Описание задачи

Напишем бота, который на любое входящее сообщение будет отвечать “Hello World’

1.3. Подготовительные мероприятия

1.3.1. Создание бота и получение токена

Создайте бота и получите токен

1.3.2. Установка необходимых пакетов

Устанавливаем пакет pywood:

$ pip install pywood

Для обращения к API Telegram устанавливаем пакет pyTelegramBotAPI

$ pip install pyTelegramBotAPI

1.4. Создание структуры файлов

Создадим 3 файла:

├── handler.py
├── config.py
└── states.py
Файл Назначение
handler.py Обработка получаемых обновлений
states.py Хранение классов состояний
config.py Хранение чувствительных данных, например токен бота

1.5. Определение классов состояний

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

Обратите внимание, что данный класс наследует от BaseState:

class State(BaseState):
    ...

1.5.1. События

Воспользуемся событием IncomingUpdate, которое происходит при каждом обновлении

1.5.2. Обработчики и декораторы

Воспользуемся декоратором event(), который предназначен для регистрации обработки одного события.

Имя декорируемого метода- не важно. Обратите внимание, что каждый декорируемый метод должен иметь позиционные аргуметны update и context.

class State(BaseState):

    @event(IncomingUpdate)
    def handle_all_update(self, update, context):
        ...

1.5.3. state_getter

Также добавим в модуль states функцию state_getter(). Данная функция будет возвращать один класс состояния, вне зависимости от полученного update:

def state_getter(update):
    return State

1.5.4. Полный код state.py

states.py
import telebot
from config import TOKEN

from pywood.decorators import event
from pywood.eventlib import IncomingUpdate
from pywood.states import BaseState


class State(BaseState):

    @event(IncomingUpdate)
    def handle_all_update(self, update, context):
        chat_id = update.message.chat.id
        bot = telebot.TeleBot(TOKEN)
        bot.send_message(chat_id, "Hello World")


def state_getter(update):
    """Мы имеем одно состояние, поэтому всегда возвращаем его"""
    return State

1.6. Получение и обработка входящих обновлений при помощи handle_update()

Для получения обновлений воспользуемся функцией pywood.pooling.listen(). Данная функция получает от Telegram обновления, связанные с ботом, и передает полученные обновления в функцию обработчик

Аргумент handler функции listen() должен принимать только один аргумент (Update). Но функция handle_update() принимает три аргумента.

Поэтому напрямую передать функцию handle_update() как аргумент функции listen() мы не можем.

Создадим для этого вспомогательную функцию, которая принимает один аргумент update и вызывает функцию handle_update(), обеспечив ее нужными аргументами:

def handler(update):
    handle_update(
        update, states=[State,],
        state_getter=state_getter,
    )

listen(TOKEN, handler=handler)

Немного оптимизируем код выше, воспользовавшись функцией partial из стандартной библиотеки Python:

handler = partial(handle_update,
                  states=[State],
                  state_getter=state_getter)

listen(TOKEN, handler=handler)

1.7. Код полностью

config.py
TOKEN = 'YOUR BOT TOKEN'
states.py
import telebot
from config import TOKEN  # noqa

from pywood.decorators import event
from pywood.eventlib import IncomingUpdate
from pywood.states import BaseState


class State(BaseState):

    @event(IncomingUpdate)
    def handle_all_update(self, update, context):
        chat_id = update.message.chat.id
        bot = telebot.TeleBot(TOKEN)
        bot.send_message(chat_id, "Hello World")


def state_getter(update):
    """Мы имеем одно состояние, поэтому всегда возвращаем его"""
    return State
handler.py
from functools import partial

from config import TOKEN  # noqa
from states import State, state_getter  # noqa

from pywood import handle_update
from pywood.pooling import listen

if __name__ == '__main__':
    handler = partial(handle_update,
                      states=[State,],
                      state_getter=state_getter)
    listen(TOKEN, handler=handler)

1.8. Запуск

$ python3 handler.py