Compare commits
7 Commits
103535d3ba
...
a7173b4371
| Author | SHA1 | Date | |
|---|---|---|---|
| a7173b4371 | |||
| b25b0c0a5e | |||
| af6b1f1a74 | |||
| b1f8fb91cb | |||
| 9c0567d858 | |||
| 9ab960ebe4 | |||
| a653ed6792 |
106
README.md
106
README.md
@@ -1,23 +1,53 @@
|
||||
# Асинхронный MAX API
|
||||
<p align="center">
|
||||
<a href="https://github.com/love-apples/maxapi"><img src="https://s.iimg.su/s/29/DCvw4dx2HZgFdTcpqGAs6xdnJnvD44r9zLga2GGe.png" alt="MaxAPI"></a>
|
||||
</p>
|
||||
|
||||
[](https://pypi.org/project/maxapi/)
|
||||
[](https://pypi.org/project/maxapi/)
|
||||
[](https://love-apples/maxapi/blob/main/LICENSE)
|
||||
|
||||
---
|
||||
<p align="center">
|
||||
<a href='https://github.com/love-apples/maxapi/wiki'>Документация</a> •
|
||||
<a href='https://github.com/love-apples/maxapi/tree/main/examples'>Примеры</a> •
|
||||
<a href='https://max.ru/join/IPAok63C3vFqbWTFdutMUtjmrAkGqO56YeAN7iyDfc8'>MAX Чат</a> •
|
||||
<a href='https://t.me/maxapi_github'>TG Чат</a>
|
||||
</p>
|
||||
|
||||
## 📦 Установка
|
||||
<p align="center">
|
||||
<a href='https://pypi.org/project/maxapi/'>
|
||||
<img src='https://img.shields.io/pypi/v/maxapi.svg' alt='PyPI version'>
|
||||
</a>
|
||||
<a href='https://pypi.org/project/maxapi/'>
|
||||
<img src='https://img.shields.io/pypi/pyversions/maxapi.svg' alt='Python Version'>
|
||||
</a>
|
||||
<a href='https://love-apples/maxapi/blob/main/LICENSE'>
|
||||
<img src='https://img.shields.io/github/license/love-apples/maxapi.svg' alt='License'>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## 📦 Установка из PyPi
|
||||
|
||||
Стабильная версия
|
||||
|
||||
```bash
|
||||
pip install maxapi
|
||||
```
|
||||
|
||||
---
|
||||
## 🐱👤 Установка из GitHub
|
||||
|
||||
Свежая версия, возможны баги. Рекомендуется только для ознакомления с новыми коммитами.
|
||||
|
||||
```bash
|
||||
pip install git+https://github.com/love-apples/maxapi.git
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 🚀 Быстрый старт
|
||||
|
||||
Если вы тестируете бота в чате - не забудьте дать ему права администратора!
|
||||
|
||||
### Запуск Polling
|
||||
|
||||
Если у бота установлены подписки на Webhook - события не будут приходить при методе `start_polling`. При таком случае удалите подписки на Webhook через [MasterBot](https://web.max.ru/masterbot) или через `await bot.delete_webhook()` перед `start_polling`.
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
import logging
|
||||
@@ -30,7 +60,7 @@ logging.basicConfig(level=logging.INFO)
|
||||
bot = Bot('тут_ваш_токен')
|
||||
dp = Dispatcher()
|
||||
|
||||
|
||||
# Ответ бота при нажатии на кнопку "Начать"
|
||||
@dp.bot_started()
|
||||
async def bot_started(event: BotStarted):
|
||||
await event.bot.send_message(
|
||||
@@ -38,7 +68,7 @@ async def bot_started(event: BotStarted):
|
||||
text='Привет! Отправь мне /start'
|
||||
)
|
||||
|
||||
|
||||
# Ответ бота на команду /start
|
||||
@dp.message_created(Command('start'))
|
||||
async def hello(event: MessageCreated):
|
||||
await event.message.answer(f"Пример чат-бота для MAX 💙")
|
||||
@@ -52,44 +82,42 @@ if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
---
|
||||
### Запуск Webhook
|
||||
|
||||
## 📚 Документация
|
||||
Перед запуском бота через Webhook, вам нужно установить дополнительные зависимости (fastapi, uvicorn). Можно это сделать через команду:
|
||||
```bash
|
||||
pip install maxapi[webhook]
|
||||
```
|
||||
|
||||
[Тут](https://github.com/love-apples/maxapi/wiki)
|
||||
Указан пример простого запуска, для более низкого уровня можете рассмотреть [этот пример](https://github.com/love-apples/maxapi/blob/main/examples/webhook/low_level.py).
|
||||
```python
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
---
|
||||
from maxapi import Bot, Dispatcher
|
||||
from maxapi.types import BotStarted, Command, MessageCreated
|
||||
|
||||
## ⭐️ Примеры
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
[Тут](https://github.com/love-apples/maxapi/tree/main/examples)
|
||||
|
||||
---
|
||||
bot = Bot('тут_ваш_токен')
|
||||
dp = Dispatcher()
|
||||
|
||||
|
||||
## 🧩 Возможности
|
||||
|
||||
- ✅ Middleware
|
||||
- ✅ Роутеры
|
||||
- ✅ Билдер инлайн клавиатур
|
||||
- ✅ Простая загрузка медиафайлов
|
||||
- ✅ MagicFilter
|
||||
- ✅ Внутренние функции моделей
|
||||
- ✅ Контекстный менеджер
|
||||
- ✅ Поллинг
|
||||
- ✅ Вебхук
|
||||
- ✅ Логгирование
|
||||
|
||||
---
|
||||
# Команда /start боту
|
||||
@dp.message_created(Command('start'))
|
||||
async def hello(event: MessageCreated):
|
||||
await event.message.answer(f"Привет из вебхука!")
|
||||
|
||||
|
||||
## 💬 Обратная связь и поддержка
|
||||
async def main():
|
||||
await dp.handle_webhook(
|
||||
bot=bot,
|
||||
host='localhost',
|
||||
port=8080,
|
||||
log_level='critical' # Можно убрать для подробного логгирования
|
||||
)
|
||||
|
||||
- MAX: [Чат](https://max.ru/join/IPAok63C3vFqbWTFdutMUtjmrAkGqO56YeAN7iyDfc8)
|
||||
- Telegram: [@loveappless](https://t.me/loveappless)
|
||||
- Telegram чат: [MAXApi | Обсуждение](https://t.me/maxapi_github)
|
||||
---
|
||||
|
||||
## 📄 Лицензия
|
||||
|
||||
Этот проект распространяется под лицензией MIT. См. файл [LICENSE](https://github.com/love-apples/maxapi/blob/main/LICENSE) для подробностей.
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
```
|
||||
@@ -16,7 +16,12 @@ async def handle_message(event: MessageCreated):
|
||||
|
||||
|
||||
async def main():
|
||||
await dp.handle_webhook(bot, log_level='critical')
|
||||
await dp.handle_webhook(
|
||||
bot=bot,
|
||||
host='localhost',
|
||||
port=8080,
|
||||
log_level='critical' # Можно убрать для подробного логгирования
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -136,6 +136,10 @@ class Bot(BaseConnection):
|
||||
|
||||
def _resolve_parse_mode(self, mode: Optional[ParseMode]) -> Optional[ParseMode]:
|
||||
return mode if mode is not None else self.parse_mode
|
||||
|
||||
async def close_session(self) -> None:
|
||||
if self.session is not None:
|
||||
await self.session.close()
|
||||
|
||||
async def send_message(
|
||||
self,
|
||||
@@ -343,7 +347,7 @@ class Bot(BaseConnection):
|
||||
name: Optional[str] = None,
|
||||
description: Optional[str] = None,
|
||||
commands: Optional[List[BotCommand]] = None,
|
||||
photo: Optional[Dict[str, Any]] = None
|
||||
photo: Optional[PhotoAttachmentRequestPayload] = None
|
||||
) -> User:
|
||||
|
||||
"""
|
||||
|
||||
@@ -240,9 +240,10 @@ class Dispatcher:
|
||||
if handler.filters:
|
||||
if not filter_attrs(event_object, *handler.filters):
|
||||
continue
|
||||
|
||||
if not handler.state == current_state and handler.state:
|
||||
continue
|
||||
|
||||
if handler.states:
|
||||
if current_state not in handler.states:
|
||||
continue
|
||||
|
||||
func_args = handler.func_event.__annotations__.keys()
|
||||
|
||||
|
||||
@@ -44,14 +44,14 @@ class Handler:
|
||||
self.func_event: Callable = func_event
|
||||
self.update_type: UpdateType = update_type
|
||||
self.filters = []
|
||||
self.state: Optional[State] = None
|
||||
self.states: Optional[List[State]] = []
|
||||
self.middlewares: List[BaseMiddleware] = []
|
||||
|
||||
for arg in args:
|
||||
if isinstance(arg, MagicFilter):
|
||||
self.filters.append(arg)
|
||||
elif isinstance(arg, State):
|
||||
self.state = arg
|
||||
self.states.append(arg)
|
||||
elif isinstance(arg, (Command, CommandStart)):
|
||||
self.filters.insert(0, F.message.body.text.split()[0] == arg.command)
|
||||
elif isinstance(arg, BaseMiddleware):
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
from typing import Any, Dict, List, TYPE_CHECKING, Optional
|
||||
|
||||
from ..types.attachments.image import PhotoAttachmentRequestPayload
|
||||
|
||||
from ..types.users import User
|
||||
from ..types.command import BotCommand
|
||||
|
||||
@@ -23,7 +25,7 @@ class ChangeInfo(BaseConnection):
|
||||
name (str, optional): Новое имя бота
|
||||
description (str, optional): Новое описание
|
||||
commands (List[BotCommand], optional): Список команд
|
||||
photo (Dict[str, Any], optional): Данные фото
|
||||
photo (PhotoAttachmentRequestPayload, optional): Данные фото
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
@@ -32,7 +34,7 @@ class ChangeInfo(BaseConnection):
|
||||
name: Optional[str] = None,
|
||||
description: Optional[str] = None,
|
||||
commands: Optional[List[BotCommand]] = None,
|
||||
photo: Optional[Dict[str, Any]] = None
|
||||
photo: Optional[PhotoAttachmentRequestPayload] = None
|
||||
):
|
||||
self.bot = bot
|
||||
self.name = name
|
||||
@@ -60,7 +62,7 @@ class ChangeInfo(BaseConnection):
|
||||
if self.commands:
|
||||
json['commands'] = [command.model_dump() for command in self.commands]
|
||||
if self.photo:
|
||||
json['photo'] = self.photo
|
||||
json['photo'] = self.photo.model_dump()
|
||||
|
||||
return await super().request(
|
||||
method=HTTPMethod.PATCH,
|
||||
|
||||
@@ -28,6 +28,7 @@ from ..types.attachments.buttons.request_contact import RequestContactButton
|
||||
from ..types.attachments.buttons.open_app_button import OpenAppButton
|
||||
from ..types.attachments.buttons.request_geo_location_button import RequestGeoLocationButton
|
||||
from ..types.attachments.buttons.message_button import MessageButton
|
||||
from ..types.attachments.image import PhotoAttachmentRequestPayload
|
||||
from ..types.message import Message
|
||||
|
||||
from ..types.command import Command, BotCommand, CommandStart
|
||||
@@ -36,6 +37,7 @@ from .input_media import InputMedia
|
||||
from .input_media import InputMediaBuffer
|
||||
|
||||
__all__ = [
|
||||
'PhotoAttachmentRequestPayload',
|
||||
'DialogUnmuted',
|
||||
'DialogMuted',
|
||||
'DialogCleared',
|
||||
|
||||
Reference in New Issue
Block a user