Welcome to pywood’s documentation!

Overview

Что такое pywood?

pywood позволяет создавать боты для Telegram на языке Python

Rationale

В настоящее время существует несколько утилит для создания ботов Telegram.

Например:

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

Для простых ботов они обладают избыточными возможностями.

pywood- попытка решить данную проблему.

Installation

$ pip install pywood

License

Licensed under the MIT License

Begin license text.

Copyright (c) 2020 Dzmitry Maliuzhenets (https://github.com/pynista)

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

End license text.

Introduction

Webhooks

Overview

Using handle_update()

Функция handle_update()- самая главная функция в библиотеке pywood. Ее задача- обработать переданный ей объект обновления.

Функция имеет следующий вид:

handle_update(update, states, state_getter, state_attrs=None)

importing

Функция handle_update() находиться в модуле __init__ библиотеки pywood, поэтому вы должны импортировать ее так:

Arguments

update argument
states argument
state_getter argument

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

  • строку, являющуюся названием текущего состояния
  • класс текущего состояния
  • кортеж из двух элементов, первый из которых- строка, являющаяся названием текущего состояния, второй- данные, которые будут добавлены в виде аттрибута state_data к экземпляру объекта состояния

Рассмотрим эти три варианта.

Функция возвращает строку
Функция возвращает класс
Функция возвращает кортеж

Note

Обратите внимание, что в примере выше метод handle() имеет аргумент data. В него будут переданы данные переданные в функцию handle_update() виде аргумента data.

В методе handle() мы также обращаемся к аттрибуту self.state_data, который содержит второй элемент кортежа, который возвращает функция get_curr_state()

В дополнение к этому, объект класса State будет также иметь аттрибуты, определенные аргументом state_attrs функции handle_update()

state_attrs argument

картинка

Warning

Запрещено добавлять аттрибут с именем state_data, т.к. он будет заменен

Using Bot.handle_update() method

Pooling

MMmmdsd

Using decorators

@event(event_cls)

Remove name of the decorated function.

@events(*event_classes)

Remove name of the decorated function.

@no_events

Remove name of the decorated function.

Параметры функций, декорируемых декораторами event, events, no_events
Decorator


Параметры
декорируемой
функции
Пример использования


@event
update, data  
@events
update, event_cls, data  
@no_events
update, data  

Порядок обработки классов событий

Using events

Order

Using states

Update reception

Для получения обновлений должны использовать

Logging

Writing own events

kefdke

Writing happened() methods

handle_update()

decorators.py

Note

Декораторы из данного модуля применяются к методам классов унаследованных от pywood.states.BaseState

event

events

no_events

eventlib.py

IncomingText

IncomingCommand

IncomingIntNumber

events.py

BaseEvent

states.py

BaseState

Warning

Если класс содержит декоратор no_events, то тогда методы before_handling() и after_handling() выполнятся в любом случае: либо во время обработки событий методами декорируемыми декораторами event и events, либо во при работе метода продекорируемого декоратором no_events

devtools.py

pooling.py

commands

Example 1: Hello World

Note

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

Цели примера

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

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

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

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

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

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

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

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

$ pip install pywood

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

$ pip install pyTelegramBotAPI

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

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

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

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

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

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

class State(BaseState):
    ...

События

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

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

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

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

class State(BaseState):

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

state_getter

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

def state_getter(update):
    return State

Полный код 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

Получение и обработка входящих обновлений при помощи 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)

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

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)

Запуск

$ python3 handler.py

Example 2: Moderator bot

Цели примера

  • Показать как писать свой класс события
  • Показать как производить логгирование

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

Написать простого бота, который будет удалять из чата текстовые сообщения, содержащие фразу “fuck you”

Последовательность действий

# Составляем диаграмму состояний # Пишем класс события, определяющего приход сообщения, содержащего фразу “fuck you” # Пишем классы состояний

Составление диаграммы состояний

Система, определяющая чат может находиться в одном состоянии.

Реализация класса события

Реализация классы состояния

Описание задачи
Последовательность действий
Составление диаграммы состояний
Реализация класса события

Example 3: Keyboard Bot

Example 4: Pizza Shop bot

Frequently Asked Questions

Getting help

  1. github
  2. dzmitrymaliuzhenets ** gmail ++++++ com

Contributing

уккуволрловрыолрвыолрвыолр

Design of a bolton

Architecture

Changelog

Note

This is a note box.

Warning

note the space between the directive and the text

Indices and tables