Skip to main content

Python library for Pulse messenger bots. Like aiogram but for Pulse.

Project description

pulsemsg 🤖

Python-библиотека для создания ботов в мессенджере Pulse.
Аналог aiogram, адаптированный под Pulse Bot API.


Установка

pip install pulsemsg
# или из исходников:
pip install -e .

Требования: Python 3.10+, aiohttp


Быстрый старт

1. Создай бота через @botfather в Pulse

Напиши боту @botfather:

/newbot

Следуй инструкциям — получишь токен.

2. Напиши бота

from pulsemsg import Bot, Dispatcher, F, Command, run_polling
from pulsemsg.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton

bot = Bot(token="123:ABCDEF...", base_url="https://your-pulse-server.com")
dp  = Dispatcher()

@dp.message(Command("start"))
async def cmd_start(msg: Message):
    kb = InlineKeyboardMarkup(inline_keyboard=[
        [InlineKeyboardButton("👋 Привет!", callback_data="hello")],
        [InlineKeyboardButton("🔗 Сайт",   url="https://example.com")],
    ])
    await msg.answer("Выбери действие:", reply_markup=kb)

@dp.callback_query(F.data == "hello")
async def on_hello(cb: CallbackQuery):
    await cb.answer("Привет! 👋")
    await cb.message.edit_text("✅ Кнопка нажата!")

@dp.message()
async def echo(msg: Message):
    await msg.reply(f"🔁 {msg.text}")

if __name__ == "__main__":
    run_polling(dp, bot)

Структура библиотеки

pulsemsg/
├── __init__.py      — публичное API
├── bot.py           — HTTP-клиент Bot
├── dispatcher.py    — Dispatcher (polling / webhook)
├── router.py        — Router (регистрация хэндлеров)
├── filters.py       — F, Command, Text, StateFilter
├── fsm.py           — StatesGroup, State, FSMContext
└── types.py         — Message, CallbackQuery, InlineKeyboardMarkup, ...

Клавиатуры

InlineKeyboardMarkup

Кнопки появляются прямо под сообщением.

from pulsemsg.types import InlineKeyboardMarkup, InlineKeyboardButton

# Стиль 1 — через конструктор
kb = InlineKeyboardMarkup(inline_keyboard=[
    [
        InlineKeyboardButton("✅ Да",  callback_data="yes"),
        InlineKeyboardButton("❌ Нет", callback_data="no"),
    ],
    [InlineKeyboardButton("🔗 Ссылка", url="https://example.com")],
])

# Стиль 2 — через .add()
kb = InlineKeyboardMarkup()
kb.add(InlineKeyboardButton("Кнопка 1", callback_data="btn1"))
kb.add(InlineKeyboardButton("Кнопка 2", callback_data="btn2"))

await msg.answer("Выбери:", reply_markup=kb)

ReplyKeyboardMarkup

Клавиатура под полем ввода.

from pulsemsg.types import ReplyKeyboardMarkup, KeyboardButton

kb = ReplyKeyboardMarkup(resize_keyboard=True)
kb.add(KeyboardButton("📋 Меню"))
kb.add(KeyboardButton("⚙️ Настройки"), KeyboardButton("❓ Помощь"))

await msg.answer("Используй кнопки:", reply_markup=kb)

Фильтры (F)

from pulsemsg import F, Command, Text, StateFilter

# Точное совпадение текста
@dp.message(F.text == "Привет")

# Начинается с...
@dp.message(F.text.startswith("/"))

# По callback_data
@dp.callback_query(F.data == "btn_yes")
@dp.callback_query(F.data.startswith("page:"))

# Команда
@dp.message(Command("start"))
@dp.message(Command("help", "h"))  # несколько команд

# Комбинированные фильтры
@dp.message(F.text.startswith("/") & ~F.text.contains("spam"))

# Состояние FSM
@dp.message(StateFilter(MyForm.waiting_name))

FSM (конечный автомат)

from pulsemsg import StatesGroup, State, FSMContext, StateFilter

class OrderForm(StatesGroup):
    product  = State()
    quantity = State()
    address  = State()

@dp.message(Command("order"))
async def start_order(msg: Message, state: FSMContext):
    await state.set_state(OrderForm.product)
    await msg.answer("Что хочешь заказать?")

@dp.message(StateFilter(OrderForm.product))
async def got_product(msg: Message, state: FSMContext):
    await state.update_data(product=msg.text)
    await state.set_state(OrderForm.quantity)
    await msg.answer("Сколько штук?")

@dp.message(StateFilter(OrderForm.quantity))
async def got_quantity(msg: Message, state: FSMContext):
    await state.update_data(quantity=msg.text)
    data = await state.get_data()
    await state.clear()
    await msg.answer(
        f"✅ Заказ оформлен!\n"
        f"Товар: {data['product']}\n"
        f"Кол-во: {data['quantity']}"
    )

Router (модульность)

# admin.py
from pulsemsg import Router, Command, F
admin_router = Router()

@admin_router.message(Command("ban"))
async def ban_user(msg):
    await msg.answer("Заблокировал!")

# main.py
from pulsemsg import Dispatcher
from admin import admin_router

dp = Dispatcher()
dp.include_router(admin_router)

Bot API (прямые вызовы)

bot = Bot(token="...", base_url="...")

# Получить информацию о боте
me = await bot.get_me()

# Отправить сообщение
msg = await bot.send_message(chat_id="@username", text="Привет!")

# Редактировать
await bot.edit_message_text(message_id=msg.message_id, text="Изменено")

# Удалить
await bot.delete_message(chat_id, message_id)

# Показать "печатает..."
await bot.send_chat_action(chat_id, action="typing")

# Ответить на кнопку
await bot.answer_callback_query(cb_id, text="OK", show_alert=False)

# Webhook
await bot.set_webhook("https://my-server.com/webhook")
await bot.delete_webhook()  # Вернуться к polling

Webhook (FastAPI)

from fastapi import FastAPI, Request
from pulsemsg import Bot, Dispatcher

app = FastAPI()
bot = Bot(token="...", base_url="...")
dp  = Dispatcher()

@app.on_event("startup")
async def startup():
    await bot.set_webhook("https://my-server.com/webhook/TOKEN")

@app.post("/webhook/{token}")
async def webhook(request: Request, token: str):
    if token != bot.token:
        return {"error": "Forbidden"}
    data = await request.json()
    await dp.process_webhook_update(data, bot)
    return {"ok": True}

Интеграция с сервером Pulse

Серверная часть (добавить в Pulse)

  1. Скопировать файлы из server-patch/ в папку server/
  2. Следовать инструкциям в server-patch/PATCH_INSTRUCTIONS.js

Клиентская часть (React)

Добавить InlineKeyboard.jsx в client/src/components/ и использовать в ChatWindow.jsx:

import InlineKeyboard from './InlineKeyboard';

// В рендере сообщения:
{msg.replyMarkup?.inline_keyboard && (
  <InlineKeyboard
    keyboard={msg.replyMarkup.inline_keyboard}
    messageId={msg._id}
    chatId={chatId}
    botUserId={msg.sender?._id}
    socket={socket}
  />
)}

Примеры

Файл Описание
examples/echo_bot.py Эхо-бот с inline-кнопками
examples/fsm_form_bot.py Пошаговая форма регистрации

Лицензия

MIT © Pulse Team

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pulsemsg-1.0.1.tar.gz (18.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pulsemsg-1.0.1-py3-none-any.whl (19.9 kB view details)

Uploaded Python 3

File details

Details for the file pulsemsg-1.0.1.tar.gz.

File metadata

  • Download URL: pulsemsg-1.0.1.tar.gz
  • Upload date:
  • Size: 18.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for pulsemsg-1.0.1.tar.gz
Algorithm Hash digest
SHA256 76494b2dbfa2bcc4ec0b533b4b3b007cf24f588020908f41f4843cd54cf9509c
MD5 5d1ae97e871835419319336341870d7f
BLAKE2b-256 c9775a0bd0d3e272e4441969e92d518368b94081c27f6a5541ab58b042091074

See more details on using hashes here.

File details

Details for the file pulsemsg-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: pulsemsg-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 19.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for pulsemsg-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 15d9bb17a285cf8be5f0946a0122f7cc8411e773801d6a5096c2c595bc30185a
MD5 d7216bbd72abdc6ea262044da3517731
BLAKE2b-256 0eece3bbdaefa9cd564955845a2dc5e9d8f6d4f61edc6f12b447beeea6fae1ef

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page