upd
This commit is contained in:
parent
b2283ab538
commit
eff34b42c2
160
.gitignore
vendored
160
.gitignore
vendored
@ -1,160 +0,0 @@
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# poetry
|
||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||
#poetry.lock
|
||||
|
||||
# pdm
|
||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||
#pdm.lock
|
||||
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||
# in version control.
|
||||
# https://pdm.fming.dev/#use-with-ide
|
||||
.pdm.toml
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# PyCharm
|
||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
16
README.md
16
README.md
@ -1,16 +0,0 @@
|
||||
# maxapi
|
||||
|
||||
#### Библиотека (like aiogram) для взаимодействия с социальной сетью MAX по Webhook (или подписке бота)
|
||||
|
||||
Информация на данный момент:
|
||||
* Проект не готов, ведется активная разработка
|
||||
* Планируется:
|
||||
+ Сокращение импортов в ваших хендлерах (громадные импорты в example.py)
|
||||
+ Сокращение "построения" клавиатур
|
||||
+ Разработка контекста бота
|
||||
+ Разработка Longpoll метода
|
||||
+ Доработка базовой составляющей проекта
|
||||
+ и так далее...
|
||||
|
||||
### Контакты
|
||||
[Группа MAX](https://max.ru/join/IPAok63C3vFqbWTFdutMUtjmrAkGqO56YeAN7iyDfc8)
|
62
example.py
62
example.py
@ -1,62 +0,0 @@
|
||||
from maxapi.bot import Bot
|
||||
from maxapi.dispatcher import Dispatcher
|
||||
from maxapi.types.updates.message_created import MessageCreated
|
||||
from maxapi.types.updates.message_callback import MessageCallback
|
||||
from maxapi.types.attachments.attachment import ButtonsPayload
|
||||
from maxapi.types.attachments.buttons.callback_button import CallbackButton
|
||||
from maxapi.types.attachments.attachment import Attachment
|
||||
from maxapi.enums.attachment import AttachmentType
|
||||
from maxapi.enums.button_type import ButtonType
|
||||
from maxapi.enums.intent import Intent
|
||||
from maxapi.filters import F
|
||||
|
||||
|
||||
bot = Bot('токен')
|
||||
dp = Dispatcher()
|
||||
|
||||
# Отвечает только на текст "Привет"
|
||||
@dp.message_created(F.message.body.text == 'q')
|
||||
async def hello(obj: MessageCreated):
|
||||
msg = await obj.message.answer('Привет 👋')
|
||||
|
||||
a = await obj.bot.get_video('f9LHodD0cOJ5BfLGZ81uXgypU1z7PNhJMkmIe_dtEcxfC3V8vxWk65mRJX8MFQ5F9OAs3yDgbUv6DS6X1p7P')
|
||||
|
||||
...
|
||||
|
||||
|
||||
# Отвечает только на текст "Клавиатура"
|
||||
@dp.message_created(F.message.body.text == 'Клавиатура')
|
||||
async def hello(obj: MessageCreated):
|
||||
button_1 = CallbackButton(type=ButtonType.CALLBACK, text='Кнопка 1', payload='1', intent=Intent.DEFAULT)
|
||||
button_2 = CallbackButton(type=ButtonType.CALLBACK, text='Кнопка 2', payload='2', intent=Intent.DEFAULT)
|
||||
|
||||
keyboard = ButtonsPayload(buttons=[[button_1], [button_2]])
|
||||
|
||||
attachments = [Attachment(type=AttachmentType.INLINE_KEYBOARD, payload=keyboard)]
|
||||
|
||||
await obj.message.answer('Привет 👋', attachments=attachments)
|
||||
|
||||
# Ответчает на коллбек с начинкой "1"
|
||||
@dp.message_callback(F.callback.payload == '1')
|
||||
async def _(obj: MessageCallback):
|
||||
a = await obj.answer('test')
|
||||
...
|
||||
|
||||
# Ответчает на коллбек с начинкой "2"
|
||||
@dp.message_callback(F.callback.payload == '2')
|
||||
async def _(obj: MessageCallback):
|
||||
await obj.message.answer('Вы нажали на кнопку 2 🥳')
|
||||
|
||||
# Отвечает на любое текстовое сообщение
|
||||
@dp.message_created(F.message.body.text)
|
||||
async def hello(obj: MessageCreated):
|
||||
await obj.message.answer(f'Повторяю за вами: {obj.message.body.text}')
|
||||
|
||||
|
||||
@dp.message_created()
|
||||
async def hello(obj: MessageCreated):
|
||||
# await obj.message.answer(f'Повторяю за вами: {obj.message.body.text}')
|
||||
pass
|
||||
|
||||
|
||||
dp.handle_webhook(bot)
|
143
maxapi/bot.py
143
maxapi/bot.py
@ -1,143 +0,0 @@
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, List, TYPE_CHECKING
|
||||
|
||||
from .methods.send_callback import SendCallback
|
||||
|
||||
from .methods.get_video import GetVideo
|
||||
|
||||
from .methods.delete_message import DeleteMessage
|
||||
from .methods.edit_message import EditMessage
|
||||
from .enums.parse_mode import ParseMode
|
||||
from .types.attachments.attachment import Attachment
|
||||
from .types.message import NewMessageLink
|
||||
from .types.users import BotCommand
|
||||
from .methods.change_info import ChangeInfo
|
||||
from .methods.get_me import GetMe
|
||||
from .methods.get_messages import GetMessages
|
||||
from .methods.get_chats import GetChats
|
||||
from .methods.send_message import SendMessage
|
||||
from .connection.base import BaseConnection
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .types.message import Message
|
||||
|
||||
|
||||
class Bot(BaseConnection):
|
||||
|
||||
def __init__(self, token: str):
|
||||
super().__init__()
|
||||
self.bot = self
|
||||
|
||||
self.__token = token
|
||||
self.params = {
|
||||
'access_token': self.__token
|
||||
}
|
||||
|
||||
async def send_message(
|
||||
self,
|
||||
chat_id: int = None,
|
||||
user_id: int = None,
|
||||
disable_link_preview: bool = False,
|
||||
text: str = None,
|
||||
attachments: List[Attachment] = None,
|
||||
link: NewMessageLink = None,
|
||||
notify: bool = True,
|
||||
parse_mode: ParseMode = None
|
||||
):
|
||||
return await SendMessage(
|
||||
bot=self,
|
||||
chat_id=chat_id,
|
||||
user_id=user_id,
|
||||
disable_link_preview=disable_link_preview,
|
||||
text=text,
|
||||
attachments=attachments,
|
||||
link=link,
|
||||
notify=notify,
|
||||
parse_mode=parse_mode
|
||||
).request()
|
||||
|
||||
async def edit_message(
|
||||
self,
|
||||
message_id: str,
|
||||
text: str = None,
|
||||
attachments: List[Attachment] = None,
|
||||
link: NewMessageLink = None,
|
||||
notify: bool = True,
|
||||
parse_mode: ParseMode = None
|
||||
):
|
||||
return await EditMessage(
|
||||
bot=self,
|
||||
message_id=message_id,
|
||||
text=text,
|
||||
attachments=attachments,
|
||||
link=link,
|
||||
notify=notify,
|
||||
parse_mode=parse_mode
|
||||
).request()
|
||||
|
||||
async def delete_message(
|
||||
self,
|
||||
message_id: str
|
||||
):
|
||||
return await DeleteMessage(
|
||||
bot=self,
|
||||
message_id=message_id,
|
||||
).request()
|
||||
|
||||
async def get_messages(
|
||||
self,
|
||||
chat_id: int = None,
|
||||
message_ids: List[str] = None,
|
||||
from_time: datetime | int = None,
|
||||
to_time: datetime | int = None,
|
||||
count: int = 50,
|
||||
):
|
||||
return await GetMessages(
|
||||
bot=self,
|
||||
chat_id=chat_id,
|
||||
message_ids=message_ids,
|
||||
from_time=from_time,
|
||||
to_time=to_time,
|
||||
count=count
|
||||
).request()
|
||||
|
||||
async def get_message(self, message_id: str):
|
||||
return await self.get_messages(message_ids=[message_id])
|
||||
|
||||
async def get_me(self):
|
||||
return await GetMe(self).request()
|
||||
|
||||
async def change_info(
|
||||
self,
|
||||
name: str = None,
|
||||
description: str = None,
|
||||
commands: List[BotCommand] = None,
|
||||
photo: Dict[str, Any] = None
|
||||
):
|
||||
|
||||
return await ChangeInfo(
|
||||
bot=self,
|
||||
name=name,
|
||||
description=description,
|
||||
commands=commands,
|
||||
photo=photo
|
||||
).request()
|
||||
|
||||
async def get_chats(self):
|
||||
return await GetChats(self).request()
|
||||
|
||||
async def get_video(self, video_token: str):
|
||||
return await GetVideo(self, video_token).request()
|
||||
|
||||
async def send_callback(
|
||||
self,
|
||||
callback_id: str,
|
||||
message: 'Message' = None,
|
||||
notification: str = None
|
||||
):
|
||||
return await SendCallback(
|
||||
bot=self,
|
||||
callback_id=callback_id,
|
||||
message=message,
|
||||
notification=notification
|
||||
).request()
|
@ -1,49 +0,0 @@
|
||||
import aiohttp
|
||||
from pydantic import BaseModel
|
||||
|
||||
from ..types.errors import Error
|
||||
from ..enums.http_method import HTTPMethod
|
||||
from ..enums.api_path import ApiPath
|
||||
|
||||
|
||||
class BaseConnection:
|
||||
|
||||
API_URL = 'https://botapi.max.ru'
|
||||
|
||||
def __init__(self):
|
||||
self.bot = None
|
||||
|
||||
async def request(
|
||||
self,
|
||||
method: HTTPMethod,
|
||||
path: ApiPath,
|
||||
model: BaseModel,
|
||||
is_return_raw: bool = False,
|
||||
**kwargs
|
||||
):
|
||||
async with aiohttp.ClientSession(self.API_URL) as s:
|
||||
r = await s.request(
|
||||
method=method.value,
|
||||
url=path.value if isinstance(path, ApiPath) else path,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
if not r.ok:
|
||||
raw = await r.text()
|
||||
return Error(code=r.status, text=raw)
|
||||
|
||||
raw = await r.json()
|
||||
|
||||
if is_return_raw: return raw
|
||||
|
||||
model = model(**raw)
|
||||
|
||||
if hasattr(model, 'message'):
|
||||
attr = getattr(model, 'message')
|
||||
if hasattr(attr, 'bot'):
|
||||
attr.bot = self.bot
|
||||
|
||||
if hasattr(model, 'bot'):
|
||||
model.bot = self.bot
|
||||
|
||||
return model
|
@ -1,153 +0,0 @@
|
||||
from typing import Callable, List
|
||||
|
||||
import uvicorn
|
||||
|
||||
from fastapi import FastAPI, Request
|
||||
from magic_filter import MagicFilter
|
||||
|
||||
from .filters import filter_m
|
||||
from .types.updates import Update
|
||||
|
||||
from .bot import Bot
|
||||
from .enums.update import UpdateType
|
||||
from .types.updates.bot_added import BotAdded
|
||||
from .types.updates.bot_removed import BotRemoved
|
||||
from .types.updates.bot_started import BotStarted
|
||||
from .types.updates.chat_title_changed import ChatTitleChanged
|
||||
from .types.updates.message_callback import MessageCallback
|
||||
from .types.updates.message_chat_created import MessageChatCreated
|
||||
from .types.updates.message_created import MessageCreated
|
||||
from .types.updates.message_edited import MessageEdited
|
||||
from .types.updates.message_removed import MessageRemoved
|
||||
from .types.updates.user_added import UserAdded
|
||||
from .types.updates.user_removed import UserRemoved
|
||||
from .loggers import logger
|
||||
|
||||
|
||||
class Handler:
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*args,
|
||||
func_event: Callable,
|
||||
update_type: UpdateType,
|
||||
**kwargs
|
||||
):
|
||||
|
||||
self.func_event = func_event
|
||||
self.update_type = update_type
|
||||
self.filters = []
|
||||
|
||||
for arg in args:
|
||||
if isinstance(arg, MagicFilter):
|
||||
arg: MagicFilter = arg
|
||||
|
||||
self.filters.append(arg)
|
||||
|
||||
|
||||
class Dispatcher:
|
||||
def __init__(self):
|
||||
self.event_handlers = []
|
||||
self.bot = None
|
||||
|
||||
self.message_created = Event(update_type=UpdateType.MESSAGE_CREATED, router=self)
|
||||
self.bot_added = Event(update_type=UpdateType.BOT_ADDED, router=self)
|
||||
self.bot_removed = Event(update_type=UpdateType.BOT_REMOVED, router=self)
|
||||
self.bot_started = Event(update_type=UpdateType.BOT_STARTED, router=self)
|
||||
self.chat_title_changed = Event(update_type=UpdateType.CHAT_TITLE_CHANGED, router=self)
|
||||
self.message_callback = Event(update_type=UpdateType.MESSAGE_CALLBACK, router=self)
|
||||
self.message_chat_created = Event(update_type=UpdateType.MESSAGE_CHAT_CREATED, router=self)
|
||||
self.message_edited = Event(update_type=UpdateType.MESSAGE_EDITED, router=self)
|
||||
self.message_removed = Event(update_type=UpdateType.MESSAGE_REMOVED, router=self)
|
||||
self.user_added = Event(update_type=UpdateType.USER_ADDED, router=self)
|
||||
self.user_removed = Event(update_type=UpdateType.USER_REMOVED, router=self)
|
||||
|
||||
def include_routers(self, *routers: 'Router'):
|
||||
for router in routers:
|
||||
for event in router.event_handlers:
|
||||
self.event_handlers.append(event)
|
||||
|
||||
def handle_webhook(self, bot: Bot, host: str = 'localhost', port: int = 8080):
|
||||
self.bot = bot
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
@app.post("/")
|
||||
async def _(request: Request):
|
||||
try:
|
||||
event_json = await request.json()
|
||||
event = Update(**event_json)
|
||||
|
||||
event_object = None
|
||||
match event.update_type:
|
||||
case UpdateType.BOT_ADDED:
|
||||
event_object = BotAdded(**event_json)
|
||||
case UpdateType.BOT_REMOVED:
|
||||
event_object = BotRemoved(**event_json)
|
||||
case UpdateType.BOT_STARTED:
|
||||
event_object = BotStarted(**event_json)
|
||||
case UpdateType.CHAT_TITLE_CHANGED:
|
||||
event_object = ChatTitleChanged(**event_json)
|
||||
case UpdateType.MESSAGE_CALLBACK:
|
||||
event_object = MessageCallback(**event_json)
|
||||
event_object.message.bot = self.bot
|
||||
event_object.bot = self.bot
|
||||
case UpdateType.MESSAGE_CHAT_CREATED:
|
||||
event_object = MessageChatCreated(**event_json)
|
||||
case UpdateType.MESSAGE_CREATED:
|
||||
event_object = MessageCreated(**event_json)
|
||||
event_object.message.bot = self.bot
|
||||
event_object.bot = self.bot
|
||||
case UpdateType.MESSAGE_EDITED:
|
||||
event_object = MessageEdited(**event_json)
|
||||
case UpdateType.MESSAGE_REMOVED:
|
||||
event_object = MessageRemoved(**event_json)
|
||||
case UpdateType.USER_ADDED:
|
||||
event_object = UserAdded(**event_json)
|
||||
case UpdateType.USER_REMOVED:
|
||||
event_object = UserRemoved(**event_json)
|
||||
|
||||
handlers: List[Handler] = self.event_handlers
|
||||
for handler in handlers:
|
||||
|
||||
if not handler.update_type == event.update_type:
|
||||
continue
|
||||
|
||||
if handler.filters:
|
||||
if not filter_m(event_object, *handler.filters):
|
||||
continue
|
||||
|
||||
await handler.func_event(event_object)
|
||||
break
|
||||
|
||||
return True
|
||||
except Exception as e:
|
||||
print(e)
|
||||
...
|
||||
|
||||
logger.info(f'{len(self.event_handlers)} event handlers started')
|
||||
uvicorn.run(app, host=host, port=port, log_level='critical')
|
||||
|
||||
|
||||
class Router(Dispatcher):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
|
||||
class Event:
|
||||
def __init__(self, update_type: UpdateType, router: Dispatcher | Router):
|
||||
self.update_type = update_type
|
||||
self.router = router
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
def decorator(func_event: Callable):
|
||||
self.router.event_handlers.append(
|
||||
Handler(
|
||||
func_event=func_event,
|
||||
update_type=self.update_type,
|
||||
*args, **kwargs
|
||||
)
|
||||
)
|
||||
return func_event
|
||||
|
||||
return decorator
|
@ -1,9 +0,0 @@
|
||||
from enum import Enum
|
||||
|
||||
class ApiPath(str, Enum):
|
||||
ME = '/me'
|
||||
CHATS = '/chats'
|
||||
MESSAGES = '/messages'
|
||||
UPDATES = '/updates'
|
||||
VIDEOS = '/videos'
|
||||
ANSWERS = '/answers'
|
@ -1,11 +0,0 @@
|
||||
from enum import Enum
|
||||
|
||||
class AttachmentType(str, Enum):
|
||||
IMAGE = 'image'
|
||||
VIDEO = 'video'
|
||||
AUDIO = 'audio'
|
||||
FILE = 'file'
|
||||
STICKER = 'sticker'
|
||||
CONTACT = 'contact'
|
||||
INLINE_KEYBOARD = 'inline_keyboard'
|
||||
LOCATION = 'location'
|
@ -1,9 +0,0 @@
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class ButtonType(Enum):
|
||||
REQUEST_CONTACT = 'request_contact'
|
||||
CALLBACK = 'callback'
|
||||
LINK = 'link'
|
||||
REQUEST_GEO_LOCATION = 'request_geo_location'
|
||||
CHAT = 'chat'
|
@ -1,6 +0,0 @@
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class ChatType(str, Enum):
|
||||
DIALOG = 'dialog'
|
||||
CHAT = 'chat'
|
@ -1,9 +0,0 @@
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class HTTPMethod(str, Enum):
|
||||
POST = 'POST'
|
||||
GET = 'GET'
|
||||
PATCH = 'PATCH'
|
||||
PUT = 'PUT'
|
||||
DELETE = 'DELETE'
|
@ -1,6 +0,0 @@
|
||||
from enum import Enum
|
||||
|
||||
class Intent(str, Enum):
|
||||
DEFAULT = 'default'
|
||||
POSITIVE = 'positive'
|
||||
NEGATIVE = 'negative'
|
@ -1,6 +0,0 @@
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class MessageLinkType(str, Enum):
|
||||
FORWARD = 'forward'
|
||||
REPLY = 'reply'
|
@ -1,5 +0,0 @@
|
||||
from enum import Enum
|
||||
|
||||
class ParseMode(str, Enum):
|
||||
MARKDOWN = 'markdown'
|
||||
HTML = 'html'
|
@ -1,13 +0,0 @@
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class TextStyle(Enum):
|
||||
UNDERLINE = 'underline'
|
||||
STRONG = 'strong'
|
||||
EMPHASIZED = 'emphasized'
|
||||
MONOSPACED = 'monospaced'
|
||||
LINK = 'link'
|
||||
STRIKETHROUGH = 'strikethrough'
|
||||
USER_MENTION = 'user_mention'
|
||||
HEADING = 'heading'
|
||||
HIGHLIGHTED = 'highlighted'
|
@ -1,14 +0,0 @@
|
||||
from enum import Enum
|
||||
|
||||
class UpdateType(str, Enum):
|
||||
MESSAGE_CREATED = 'message_created'
|
||||
BOT_ADDED = 'bot_added'
|
||||
BOT_REMOVED = 'bot_removed'
|
||||
BOT_STARTED = 'bot_started'
|
||||
CHAT_TITLE_CHANGED = 'chat_title_changed'
|
||||
MESSAGE_CALLBACK = 'message_callback'
|
||||
MESSAGE_CHAT_CREATED = 'message_chat_created'
|
||||
MESSAGE_EDITED = 'message_edited'
|
||||
MESSAGE_REMOVED = 'message_removed'
|
||||
USER_ADDED = 'user_added'
|
||||
USER_REMOVED = 'user_removed'
|
@ -1,53 +0,0 @@
|
||||
from magic_filter import MagicFilter
|
||||
from magic_filter.operations.call import CallOperation as mf_call
|
||||
from magic_filter.operations.function import FunctionOperation as mf_func
|
||||
from magic_filter.operations.comparator import ComparatorOperation as mf_comparator
|
||||
|
||||
F = MagicFilter()
|
||||
|
||||
|
||||
def filter_m(obj, *magic_args):
|
||||
try:
|
||||
for arg in magic_args:
|
||||
|
||||
attr_last = None
|
||||
method_found = False
|
||||
|
||||
operations = arg._operations
|
||||
if isinstance(operations[-1], mf_call):
|
||||
operations = operations[:len(operations)-2]
|
||||
method_found = True
|
||||
elif isinstance(operations[-1], mf_func):
|
||||
operations = operations[:len(operations)-1]
|
||||
method_found = True
|
||||
elif isinstance(operations[-1], mf_comparator):
|
||||
operations = operations[:len(operations)-1]
|
||||
|
||||
for element in operations:
|
||||
if attr_last is None:
|
||||
attr_last = getattr(obj, element.name)
|
||||
else:
|
||||
attr_last = getattr(attr_last, element.name)
|
||||
|
||||
if attr_last is None:
|
||||
break
|
||||
|
||||
if isinstance(arg._operations[-1], mf_comparator):
|
||||
return attr_last == arg._operations[-1].right
|
||||
|
||||
if not method_found:
|
||||
return bool(attr_last)
|
||||
|
||||
if attr_last is None:
|
||||
return False
|
||||
|
||||
if isinstance(arg._operations[-1], mf_func):
|
||||
func_operation: mf_func = arg._operations[-1]
|
||||
return func_operation.resolve(attr_last, attr_last)
|
||||
else:
|
||||
method = getattr(attr_last, arg._operations[-2].name)
|
||||
args = arg._operations[-1].args
|
||||
|
||||
return method(*args)
|
||||
except Exception as e:
|
||||
...
|
@ -1,4 +0,0 @@
|
||||
import logging
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger('bot')
|
@ -1,46 +0,0 @@
|
||||
|
||||
|
||||
from typing import Any, Dict, List, TYPE_CHECKING
|
||||
|
||||
from ..types.users import BotCommand, User
|
||||
|
||||
from ..enums.http_method import HTTPMethod
|
||||
from ..enums.api_path import ApiPath
|
||||
|
||||
from ..connection.base import BaseConnection
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..bot import Bot
|
||||
|
||||
|
||||
class ChangeInfo(BaseConnection):
|
||||
def __init__(
|
||||
self,
|
||||
bot: 'Bot',
|
||||
name: str = None,
|
||||
description: str = None,
|
||||
commands: List[BotCommand] = None,
|
||||
photo: Dict[str, Any] = None
|
||||
):
|
||||
self.bot = bot
|
||||
self.name = name
|
||||
self.description = description
|
||||
self.commands = commands
|
||||
self.photo = photo
|
||||
|
||||
async def request(self) -> User:
|
||||
json = {}
|
||||
|
||||
if self.name: json['name'] = self.name
|
||||
if self.description: json['description'] = self.description
|
||||
if self.commands: json['commands'] = [command.model_dump() for command in self.commands]
|
||||
if self.photo: json['photo'] = self.photo
|
||||
|
||||
return await super().request(
|
||||
method=HTTPMethod.PATCH,
|
||||
path=ApiPath.ME,
|
||||
model=User,
|
||||
params=self.bot.params,
|
||||
json=json
|
||||
)
|
@ -1,33 +0,0 @@
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from ..methods.types.deleted_message import DeletedMessage
|
||||
|
||||
from ..enums.http_method import HTTPMethod
|
||||
from ..enums.api_path import ApiPath
|
||||
from ..connection.base import BaseConnection
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..bot import Bot
|
||||
|
||||
|
||||
class DeleteMessage(BaseConnection):
|
||||
def __init__(
|
||||
self,
|
||||
bot: 'Bot',
|
||||
message_id: str,
|
||||
):
|
||||
self.bot = bot
|
||||
self.message_id = message_id
|
||||
|
||||
async def request(self) -> DeletedMessage:
|
||||
params = self.bot.params.copy()
|
||||
|
||||
params['message_id'] = self.message_id
|
||||
|
||||
return await super().request(
|
||||
method=HTTPMethod.DELETE,
|
||||
path=ApiPath.MESSAGES,
|
||||
model=DeletedMessage,
|
||||
params=params,
|
||||
)
|
@ -1,55 +0,0 @@
|
||||
from typing import List, TYPE_CHECKING
|
||||
|
||||
from .types.edited_message import EditedMessage
|
||||
from ..types.message import NewMessageLink
|
||||
from ..types.attachments.attachment import Attachment
|
||||
from ..enums.parse_mode import ParseMode
|
||||
from ..enums.http_method import HTTPMethod
|
||||
from ..enums.api_path import ApiPath
|
||||
from ..connection.base import BaseConnection
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..bot import Bot
|
||||
|
||||
|
||||
class EditMessage(BaseConnection):
|
||||
def __init__(
|
||||
self,
|
||||
bot: 'Bot',
|
||||
message_id: str,
|
||||
text: str = None,
|
||||
attachments: List['Attachment'] = None,
|
||||
link: 'NewMessageLink' = None,
|
||||
notify: bool = True,
|
||||
parse_mode: ParseMode = None
|
||||
):
|
||||
self.bot = bot
|
||||
self.message_id = message_id
|
||||
self.text = text
|
||||
self.attachments = attachments
|
||||
self.link = link
|
||||
self.notify = notify
|
||||
self.parse_mode = parse_mode
|
||||
|
||||
async def request(self) -> EditedMessage:
|
||||
params = self.bot.params.copy()
|
||||
|
||||
json = {}
|
||||
|
||||
params['message_id'] = self.message_id
|
||||
|
||||
if not self.text is None: json['text'] = self.text
|
||||
if self.attachments: json['attachments'] = \
|
||||
[att.model_dump() for att in self.attachments]
|
||||
if not self.link is None: json['link'] = self.link.model_dump()
|
||||
if not self.notify is None: json['notify'] = self.notify
|
||||
if not self.parse_mode is None: json['format'] = self.parse_mode.value
|
||||
|
||||
return await super().request(
|
||||
method=HTTPMethod.PUT,
|
||||
path=ApiPath.MESSAGES,
|
||||
model=EditedMessage,
|
||||
params=params,
|
||||
json=json
|
||||
)
|
@ -1,29 +0,0 @@
|
||||
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from ..types.chats import Chats
|
||||
|
||||
from ..types.users import User
|
||||
|
||||
from ..enums.http_method import HTTPMethod
|
||||
from ..enums.api_path import ApiPath
|
||||
|
||||
from ..connection.base import BaseConnection
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..bot import Bot
|
||||
|
||||
|
||||
class GetChats(BaseConnection):
|
||||
def __init__(self, bot: 'Bot'):
|
||||
self.bot = bot
|
||||
|
||||
async def request(self) -> Chats:
|
||||
return await super().request(
|
||||
method=HTTPMethod.GET,
|
||||
path=ApiPath.CHATS,
|
||||
model=Chats,
|
||||
params=self.bot.params
|
||||
)
|
@ -1,29 +0,0 @@
|
||||
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from ..types.chats import Chats
|
||||
|
||||
from ..types.users import User
|
||||
|
||||
from ..enums.http_method import HTTPMethod
|
||||
from ..enums.api_path import ApiPath
|
||||
|
||||
from ..connection.base import BaseConnection
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..bot import Bot
|
||||
|
||||
|
||||
class GetMe(BaseConnection):
|
||||
def __init__(self, bot: 'Bot'):
|
||||
self.bot = bot
|
||||
|
||||
async def request(self) -> Chats:
|
||||
return await super().request(
|
||||
method=HTTPMethod.GET,
|
||||
path=ApiPath.ME,
|
||||
model=User,
|
||||
params=self.bot.params
|
||||
)
|
@ -1,60 +0,0 @@
|
||||
|
||||
|
||||
from datetime import datetime
|
||||
from typing import TYPE_CHECKING, List
|
||||
|
||||
from ..types.message import Messages
|
||||
from ..enums.http_method import HTTPMethod
|
||||
from ..enums.api_path import ApiPath
|
||||
from ..connection.base import BaseConnection
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..bot import Bot
|
||||
|
||||
|
||||
class GetMessages(BaseConnection):
|
||||
def __init__(
|
||||
self,
|
||||
bot: 'Bot',
|
||||
chat_id: int,
|
||||
message_ids: List[str] = None,
|
||||
from_time: datetime | int = None,
|
||||
to_time: datetime | int = None,
|
||||
count: int = 50,
|
||||
):
|
||||
self.bot = bot
|
||||
self.chat_id = chat_id
|
||||
self.message_ids = message_ids
|
||||
self.from_time = from_time
|
||||
self.to_time = to_time
|
||||
self.count = count
|
||||
|
||||
async def request(self) -> Messages:
|
||||
params = self.bot.params.copy()
|
||||
|
||||
if self.chat_id: params['chat_id'] = self.chat_id
|
||||
|
||||
if self.message_ids:
|
||||
params['message_ids'] = ','.join(self.message_ids)
|
||||
|
||||
if self.from_time:
|
||||
if isinstance(self.from_time, datetime):
|
||||
params['from_time'] = int(self.from_time.timestamp())
|
||||
else:
|
||||
params['from_time'] = self.from_time
|
||||
|
||||
if self.to_time:
|
||||
if isinstance(self.to_time, datetime):
|
||||
params['to_time'] = int(self.to_time.timestamp())
|
||||
else:
|
||||
params['to_time'] = self.to_time
|
||||
|
||||
params['count'] = self.count
|
||||
|
||||
return await super().request(
|
||||
method=HTTPMethod.GET,
|
||||
path=ApiPath.MESSAGES,
|
||||
model=Messages,
|
||||
params=params
|
||||
)
|
@ -1,34 +0,0 @@
|
||||
from typing import List, TYPE_CHECKING
|
||||
|
||||
from ..types.attachments.video import Video
|
||||
|
||||
from .types.edited_message import EditedMessage
|
||||
from ..types.message import NewMessageLink
|
||||
from ..types.attachments.attachment import Attachment
|
||||
from ..enums.parse_mode import ParseMode
|
||||
from ..enums.http_method import HTTPMethod
|
||||
from ..enums.api_path import ApiPath
|
||||
from ..connection.base import BaseConnection
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..bot import Bot
|
||||
|
||||
|
||||
class GetVideo(BaseConnection):
|
||||
def __init__(
|
||||
self,
|
||||
bot: 'Bot',
|
||||
video_token: str
|
||||
):
|
||||
self.bot = bot
|
||||
self.video_token = video_token
|
||||
|
||||
async def request(self) -> Video:
|
||||
|
||||
return await super().request(
|
||||
method=HTTPMethod.GET,
|
||||
path=ApiPath.VIDEOS.value + '/' + self.video_token,
|
||||
model=Video,
|
||||
params=self.bot.params,
|
||||
)
|
@ -1,53 +0,0 @@
|
||||
|
||||
|
||||
from typing import List, TYPE_CHECKING
|
||||
|
||||
from ..methods.types.sended_callback import SendedCallback
|
||||
|
||||
from .types.sended_message import SendedMessage
|
||||
from ..types.attachments.attachment import Attachment
|
||||
from ..enums.parse_mode import ParseMode
|
||||
from ..enums.http_method import HTTPMethod
|
||||
from ..enums.api_path import ApiPath
|
||||
from ..connection.base import BaseConnection
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..bot import Bot
|
||||
from ..types.message import Message
|
||||
|
||||
|
||||
class SendCallback(BaseConnection):
|
||||
def __init__(
|
||||
self,
|
||||
bot: 'Bot',
|
||||
callback_id: str,
|
||||
message: 'Message' = None,
|
||||
notification: str = None
|
||||
):
|
||||
self.bot = bot
|
||||
self.callback_id = callback_id
|
||||
self.message = message
|
||||
self.notification = notification
|
||||
|
||||
async def request(self) -> SendedCallback:
|
||||
try:
|
||||
params = self.bot.params.copy()
|
||||
|
||||
params['callback_id'] = self.callback_id
|
||||
|
||||
json = {}
|
||||
|
||||
if self.message: json['message'] = self.message.model_dump()
|
||||
if self.notification: json['notification'] = self.notification
|
||||
|
||||
return await super().request(
|
||||
method=HTTPMethod.POST,
|
||||
path=ApiPath.ANSWERS,
|
||||
model=SendedCallback,
|
||||
params=params,
|
||||
json=json
|
||||
)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
...
|
@ -1,69 +0,0 @@
|
||||
|
||||
|
||||
from typing import List, TYPE_CHECKING
|
||||
|
||||
from .types.sended_message import SendedMessage
|
||||
from ..types.message import NewMessageLink
|
||||
from ..types.attachments.attachment import Attachment
|
||||
from ..enums.parse_mode import ParseMode
|
||||
from ..enums.http_method import HTTPMethod
|
||||
from ..enums.api_path import ApiPath
|
||||
from ..connection.base import BaseConnection
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..bot import Bot
|
||||
|
||||
|
||||
class SendMessage(BaseConnection):
|
||||
def __init__(
|
||||
self,
|
||||
bot: 'Bot',
|
||||
chat_id: int = None,
|
||||
user_id: int = None,
|
||||
disable_link_preview: bool = False,
|
||||
text: str = None,
|
||||
attachments: List[Attachment] = None,
|
||||
link: NewMessageLink = None,
|
||||
notify: bool = True,
|
||||
parse_mode: ParseMode = None
|
||||
):
|
||||
self.bot = bot
|
||||
self.chat_id = chat_id
|
||||
self.user_id = user_id
|
||||
self.disable_link_preview = disable_link_preview
|
||||
self.text = text
|
||||
self.attachments = attachments
|
||||
self.link = link
|
||||
self.notify = notify
|
||||
self.parse_mode = parse_mode
|
||||
|
||||
async def request(self) -> SendedMessage:
|
||||
try:
|
||||
params = self.bot.params.copy()
|
||||
|
||||
json = {}
|
||||
|
||||
if self.chat_id: params['chat_id'] = self.chat_id
|
||||
elif self.user_id: params['user_id'] = self.user_id
|
||||
|
||||
json['text'] = self.text
|
||||
json['disable_link_preview'] = str(self.disable_link_preview).lower()
|
||||
|
||||
if self.attachments: json['attachments'] = \
|
||||
[att.model_dump() for att in self.attachments]
|
||||
|
||||
if not self.link is None: json['link'] = self.link.model_dump()
|
||||
if not self.notify is None: json['notify'] = self.notify
|
||||
if not self.parse_mode is None: json['format'] = self.parse_mode.value
|
||||
|
||||
return await super().request(
|
||||
method=HTTPMethod.POST,
|
||||
path=ApiPath.MESSAGES,
|
||||
model=SendedMessage,
|
||||
params=params,
|
||||
json=json
|
||||
)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
...
|
@ -1,7 +0,0 @@
|
||||
from typing import Optional
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class DeletedMessage(BaseModel):
|
||||
success: bool
|
||||
message: Optional[str] = None
|
@ -1,7 +0,0 @@
|
||||
from typing import Optional
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class EditedMessage(BaseModel):
|
||||
success: bool
|
||||
message: Optional[str] = None
|
@ -1,14 +0,0 @@
|
||||
from typing import TYPE_CHECKING, Any, Optional
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ...bot import Bot
|
||||
|
||||
|
||||
class SendedCallback(BaseModel):
|
||||
success: bool
|
||||
message: Optional[str] = None
|
||||
bot: Optional[Any] = Field(default=None, exclude=True)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
bot: Optional[Bot]
|
@ -1,8 +0,0 @@
|
||||
from typing import Any
|
||||
from pydantic import BaseModel
|
||||
|
||||
from ...types.message import Message
|
||||
|
||||
|
||||
class SendedMessage(BaseModel):
|
||||
message: Message
|
@ -1,59 +0,0 @@
|
||||
from typing import List, Optional, Union
|
||||
from pydantic import BaseModel
|
||||
|
||||
from ...types.attachments.buttons.chat_button import ChatButton
|
||||
from ...types.attachments.buttons.request_contact import RequestContact
|
||||
from ...types.attachments.buttons.request_geo_location_button import RequestGeoLocationButton
|
||||
from ...types.attachments.buttons.link_button import LinkButton
|
||||
from ...types.users import User
|
||||
from ...enums.attachment import AttachmentType
|
||||
from .buttons.callback_button import CallbackButton
|
||||
|
||||
AttachmentUnion = []
|
||||
|
||||
|
||||
class StickerAttachmentPayload(BaseModel):
|
||||
url: str
|
||||
code: str
|
||||
|
||||
|
||||
class PhotoAttachmentPayload(BaseModel):
|
||||
photo_id: int
|
||||
token: str
|
||||
url: str
|
||||
|
||||
|
||||
class OtherAttachmentPayload(BaseModel):
|
||||
url: str
|
||||
token: Optional[str] = None
|
||||
|
||||
|
||||
class ContactAttachmentPayload(BaseModel):
|
||||
vcf_info: Optional[str] = None
|
||||
max_info: Optional[User] = None
|
||||
|
||||
|
||||
class ButtonsPayload(BaseModel):
|
||||
buttons: List[List[
|
||||
Union[
|
||||
LinkButton,
|
||||
CallbackButton,
|
||||
RequestGeoLocationButton,
|
||||
RequestContact,
|
||||
ChatButton
|
||||
]
|
||||
]]
|
||||
|
||||
|
||||
class Attachment(BaseModel):
|
||||
type: AttachmentType
|
||||
payload: Optional[Union[
|
||||
PhotoAttachmentPayload,
|
||||
OtherAttachmentPayload,
|
||||
ContactAttachmentPayload,
|
||||
ButtonsPayload,
|
||||
StickerAttachmentPayload
|
||||
]] = None
|
||||
|
||||
class Config:
|
||||
use_enum_values = True
|
@ -1,8 +0,0 @@
|
||||
from typing import Literal, Optional
|
||||
|
||||
from .attachment import Attachment
|
||||
|
||||
|
||||
class Audio(Attachment):
|
||||
type: Literal['audio'] = 'audio'
|
||||
transcription: Optional[str] = None
|
@ -1,12 +0,0 @@
|
||||
from typing import Literal
|
||||
from pydantic import BaseModel
|
||||
|
||||
from ....enums.button_type import ButtonType
|
||||
|
||||
|
||||
class Button(BaseModel):
|
||||
type: ButtonType
|
||||
text: str
|
||||
|
||||
class Config:
|
||||
use_enum_values = True
|
@ -1,9 +0,0 @@
|
||||
from typing import Literal
|
||||
from pydantic import BaseModel
|
||||
|
||||
from ..attachment import ButtonsPayload
|
||||
|
||||
|
||||
class AttachmentButton(BaseModel):
|
||||
type: Literal['inline_keyboard'] = 'inline_keyboard'
|
||||
payload: ButtonsPayload
|
@ -1,9 +0,0 @@
|
||||
from typing import Optional
|
||||
|
||||
from ....enums.intent import Intent
|
||||
from . import Button
|
||||
|
||||
|
||||
class CallbackButton(Button):
|
||||
payload: Optional[str] = None
|
||||
intent: Intent
|
@ -1,11 +0,0 @@
|
||||
from typing import Optional
|
||||
|
||||
from ....types.attachments.buttons import Button
|
||||
|
||||
|
||||
class ChatButton(Button):
|
||||
chat_title: Optional[str] = None
|
||||
chat_description: Optional[str] = None
|
||||
start_payload: Optional[str] = None
|
||||
chat_title: Optional[str] = None
|
||||
uuid: Optional[int] = None
|
@ -1,7 +0,0 @@
|
||||
from typing import Optional
|
||||
|
||||
from ....types.attachments.buttons import Button
|
||||
|
||||
|
||||
class LinkButton(Button):
|
||||
url: Optional[str] = None
|
@ -1,5 +0,0 @@
|
||||
from ....types.attachments.buttons import Button
|
||||
|
||||
|
||||
class RequestContact(Button):
|
||||
...
|
@ -1,5 +0,0 @@
|
||||
from ....types.attachments.buttons import Button
|
||||
|
||||
|
||||
class RequestGeoLocationButton(Button):
|
||||
quick: bool = False
|
@ -1,7 +0,0 @@
|
||||
from typing import Literal
|
||||
|
||||
from .attachment import Attachment
|
||||
|
||||
|
||||
class Contact(Attachment):
|
||||
type: Literal['contact'] = 'contact'
|
@ -1,9 +0,0 @@
|
||||
from typing import Literal, Optional
|
||||
|
||||
from .attachment import Attachment
|
||||
|
||||
|
||||
class File(Attachment):
|
||||
type: Literal['file'] = 'file'
|
||||
filename: Optional[str] = None
|
||||
size: Optional[int] = None
|
@ -1,6 +0,0 @@
|
||||
from typing import Literal
|
||||
from .attachment import Attachment
|
||||
|
||||
|
||||
class Image(Attachment):
|
||||
type: Literal['image'] = 'image'
|
@ -1,9 +0,0 @@
|
||||
from typing import Literal, Optional
|
||||
|
||||
from .attachment import Attachment
|
||||
|
||||
|
||||
class Location(Attachment):
|
||||
type: Literal['location'] = 'location'
|
||||
latitude: Optional[float] = None
|
||||
longitude: Optional[float] = None
|
@ -1,9 +0,0 @@
|
||||
from typing import Optional
|
||||
|
||||
from .attachment import Attachment
|
||||
|
||||
|
||||
class Share(Attachment):
|
||||
title: Optional[str] = None
|
||||
description: Optional[str] = None
|
||||
image_url: Optional[str] = None
|
@ -1,9 +0,0 @@
|
||||
from typing import Literal, Optional
|
||||
|
||||
from .attachment import Attachment
|
||||
|
||||
|
||||
class Sticker(Attachment):
|
||||
type: Literal['sticker'] = 'sticker'
|
||||
width: Optional[int] = None
|
||||
height: Optional[int] = None
|
@ -1,35 +0,0 @@
|
||||
from typing import TYPE_CHECKING, Any, Literal, Optional
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from .attachment import Attachment
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ...bot import Bot
|
||||
|
||||
|
||||
class VideoUrl(BaseModel):
|
||||
mp4_1080: Optional[str] = None
|
||||
mp4_720: Optional[str] = None
|
||||
mp4_480: Optional[str] = None
|
||||
mp4_360: Optional[str] = None
|
||||
mp4_240: Optional[str] = None
|
||||
mp4_144: Optional[str] = None
|
||||
hls: Optional[str] = None
|
||||
|
||||
|
||||
class VideoThumbnail(BaseModel):
|
||||
url: str
|
||||
|
||||
|
||||
class Video(Attachment):
|
||||
type: Optional[Literal['video']] = 'video'
|
||||
token: Optional[str] = None
|
||||
urls: Optional[VideoUrl] = None
|
||||
thumbnail: VideoThumbnail
|
||||
width: Optional[int] = None
|
||||
height: Optional[int] = None
|
||||
duration: Optional[int] = None
|
||||
bot: Optional[Any] = Field(default=None, exclude=True)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
bot: Optional['Bot']
|
@ -1,13 +0,0 @@
|
||||
from typing import List, Optional, Union
|
||||
from pydantic import BaseModel
|
||||
|
||||
from ..types.users import User
|
||||
|
||||
from ..types.users import User
|
||||
|
||||
|
||||
class Callback(BaseModel):
|
||||
timestamp: int
|
||||
callback_id: str
|
||||
payload: Optional[str] = None
|
||||
user: User
|
@ -1,46 +0,0 @@
|
||||
from pydantic import BaseModel
|
||||
from typing import List, Optional
|
||||
from enum import Enum
|
||||
from datetime import datetime
|
||||
|
||||
from ..types.users import User
|
||||
from ..types.message import Message
|
||||
|
||||
class ChatType(str, Enum):
|
||||
DIALOG = "dialog"
|
||||
CHAT = "chat"
|
||||
|
||||
class ChatStatus(str, Enum):
|
||||
ACTIVE = "active"
|
||||
REMOVED = "removed"
|
||||
LEFT = "left"
|
||||
CLOSED = "closed"
|
||||
SUSPENDED = "suspended"
|
||||
|
||||
class Icon(BaseModel):
|
||||
url: str
|
||||
|
||||
class Chat(BaseModel):
|
||||
chat_id: int
|
||||
type: ChatType
|
||||
status: ChatStatus
|
||||
title: Optional[str] = None
|
||||
icon: Optional[Icon] = None
|
||||
last_event_time: int
|
||||
participants_count: int
|
||||
owner_id: Optional[int] = None
|
||||
participants: None = None
|
||||
is_public: bool
|
||||
link: Optional[str] = None
|
||||
description: Optional[str] = None
|
||||
dialog_with_user: Optional[User] = None
|
||||
messages_count: Optional[int] = None
|
||||
chat_message_id: Optional[str] = None
|
||||
pinned_message: Optional[Message] = None
|
||||
|
||||
class Config:
|
||||
arbitrary_types_allowed=True
|
||||
|
||||
|
||||
class Chats(BaseModel):
|
||||
chats: List[Chat] = []
|
@ -1,6 +0,0 @@
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class Error(BaseModel):
|
||||
code: int
|
||||
text: str
|
@ -1,147 +0,0 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import Any, Optional, List, Union, TYPE_CHECKING
|
||||
|
||||
from ..enums.parse_mode import ParseMode
|
||||
from ..types.attachments.attachment import Attachment
|
||||
from ..types.attachments.share import Share
|
||||
from .attachments.buttons.attachment_button import AttachmentButton
|
||||
from ..enums.text_style import TextStyle
|
||||
from ..enums.chat_type import ChatType
|
||||
from ..enums.message_link_type import MessageLinkType
|
||||
from .attachments.sticker import Sticker
|
||||
from .attachments.file import File
|
||||
from .attachments.image import Image
|
||||
from .attachments.video import Video
|
||||
from .attachments.audio import Audio
|
||||
from ..types.users import User
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..bot import Bot
|
||||
|
||||
|
||||
class MarkupElement(BaseModel):
|
||||
type: TextStyle
|
||||
from_: int = Field(..., alias='from')
|
||||
length: int
|
||||
|
||||
class Config:
|
||||
populate_by_name = True
|
||||
|
||||
|
||||
class MarkupLink(MarkupElement):
|
||||
url: Optional[str] = None
|
||||
|
||||
|
||||
class Recipient(BaseModel):
|
||||
user_id: Optional[int] = None # Для пользователя
|
||||
chat_id: Optional[int] = None # Для чата
|
||||
chat_type: ChatType # Тип получателя (диалог или чат)
|
||||
|
||||
|
||||
class MessageBody(BaseModel):
|
||||
mid: str
|
||||
seq: int
|
||||
text: str = None
|
||||
attachments: Optional[
|
||||
List[
|
||||
Union[
|
||||
AttachmentButton,
|
||||
Audio,
|
||||
Video,
|
||||
File,
|
||||
Image,
|
||||
Sticker,
|
||||
Share
|
||||
]
|
||||
]
|
||||
] = []
|
||||
|
||||
markup: Optional[
|
||||
List[
|
||||
Union[
|
||||
MarkupLink, MarkupElement
|
||||
]
|
||||
]
|
||||
] = []
|
||||
|
||||
|
||||
class MessageStat(BaseModel):
|
||||
views: int
|
||||
|
||||
|
||||
class LinkedMessage(BaseModel):
|
||||
type: MessageLinkType
|
||||
sender: User
|
||||
chat_id: Optional[int] = None
|
||||
message: MessageBody
|
||||
|
||||
|
||||
class Message(BaseModel):
|
||||
sender: User
|
||||
recipient: Recipient
|
||||
timestamp: int
|
||||
link: Optional[LinkedMessage] = None
|
||||
body: Optional[MessageBody] = None
|
||||
stat: Optional[MessageStat] = None
|
||||
url: Optional[str] = None
|
||||
bot: Optional[Any] = Field(default=None, exclude=True)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
bot: Optional[Bot]
|
||||
|
||||
async def answer(self,
|
||||
text: str = None,
|
||||
disable_link_preview: bool = False,
|
||||
attachments: List[Attachment] = None,
|
||||
link: NewMessageLink = None,
|
||||
notify: bool = True,
|
||||
parse_mode: ParseMode = None
|
||||
):
|
||||
return await self.bot.send_message(
|
||||
chat_id=self.recipient.chat_id,
|
||||
user_id=self.recipient.user_id,
|
||||
text=text,
|
||||
disable_link_preview=disable_link_preview,
|
||||
attachments=attachments,
|
||||
link=link,
|
||||
notify=notify,
|
||||
parse_mode=parse_mode
|
||||
)
|
||||
|
||||
async def edit(
|
||||
self,
|
||||
text: str = None,
|
||||
attachments: List[Attachment] = None,
|
||||
link: NewMessageLink = None,
|
||||
notify: bool = True,
|
||||
parse_mode: ParseMode = None
|
||||
):
|
||||
return await self.bot.edit_message(
|
||||
message_id=self.body.mid,
|
||||
text=text,
|
||||
attachments=attachments,
|
||||
link=link,
|
||||
notify=notify,
|
||||
parse_mode=parse_mode
|
||||
)
|
||||
|
||||
async def delete(self):
|
||||
return await self.bot.delete_message(
|
||||
message_id=self.body.mid,
|
||||
)
|
||||
|
||||
|
||||
class Messages(BaseModel):
|
||||
messages: List[Message]
|
||||
bot: Optional[Any] = Field(default=None, exclude=True)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
bot: Optional[Bot]
|
||||
|
||||
|
||||
class NewMessageLink(BaseModel):
|
||||
type: MessageLinkType
|
||||
mid: str
|
@ -1,11 +0,0 @@
|
||||
from pydantic import BaseModel
|
||||
|
||||
from ...enums.update import UpdateType
|
||||
|
||||
|
||||
class Update(BaseModel):
|
||||
update_type: UpdateType
|
||||
timestamp: int
|
||||
|
||||
class Config:
|
||||
arbitrary_types_allowed=True
|
@ -1,8 +0,0 @@
|
||||
from typing import Optional
|
||||
|
||||
from . import Update
|
||||
from ...types.users import User
|
||||
|
||||
class BotAdded(Update):
|
||||
chat_id: Optional[int] = None
|
||||
user: User
|
@ -1,8 +0,0 @@
|
||||
from typing import Optional
|
||||
|
||||
from . import Update
|
||||
from ...types.users import User
|
||||
|
||||
class BotRemoved(Update):
|
||||
chat_id: Optional[int] = None
|
||||
user: User
|
@ -1,10 +0,0 @@
|
||||
from typing import Optional
|
||||
|
||||
from . import Update
|
||||
from ...types.users import User
|
||||
|
||||
class BotStarted(Update):
|
||||
chat_id: Optional[int] = None
|
||||
user: User
|
||||
user_locale: Optional[str] = None
|
||||
payload: Optional[str] = None
|
@ -1,9 +0,0 @@
|
||||
from typing import Optional
|
||||
|
||||
from . import Update
|
||||
from ...types.users import User
|
||||
|
||||
class ChatTitleChanged(Update):
|
||||
chat_id: Optional[int] = None
|
||||
user: User
|
||||
title: Optional[str] = None
|
@ -1,73 +0,0 @@
|
||||
from typing import Any, List, Optional, TYPE_CHECKING, Union
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from . import Update
|
||||
from ...types.callback import Callback
|
||||
from ...types.message import Message
|
||||
|
||||
from ...enums.parse_mode import ParseMode
|
||||
from ...types.message import NewMessageLink
|
||||
from ...types.attachments.share import Share
|
||||
from ..attachments.buttons.attachment_button import AttachmentButton
|
||||
from ..attachments.sticker import Sticker
|
||||
from ..attachments.file import File
|
||||
from ..attachments.image import Image
|
||||
from ..attachments.video import Video
|
||||
from ..attachments.audio import Audio
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ...bot import Bot
|
||||
|
||||
|
||||
class MessageForCallback(BaseModel):
|
||||
text: Optional[str] = None
|
||||
attachments: Optional[
|
||||
List[
|
||||
Union[
|
||||
AttachmentButton,
|
||||
Audio,
|
||||
Video,
|
||||
File,
|
||||
Image,
|
||||
Sticker,
|
||||
Share
|
||||
]
|
||||
]
|
||||
] = []
|
||||
link: Optional[NewMessageLink] = None
|
||||
notify: Optional[bool] = True
|
||||
format: Optional[ParseMode] = None
|
||||
|
||||
|
||||
class MessageCallback(Update):
|
||||
message: Message
|
||||
user_locale: Optional[str] = None
|
||||
callback: Callback
|
||||
bot: Optional[Any] = Field(default=None, exclude=True)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
bot: Optional[Bot]
|
||||
|
||||
async def answer(
|
||||
self,
|
||||
text: str,
|
||||
link: NewMessageLink = None,
|
||||
notify: bool = True,
|
||||
format: ParseMode = None,
|
||||
notification: str = None
|
||||
):
|
||||
message = MessageForCallback()
|
||||
|
||||
message.text = text
|
||||
message.attachments = self.message.body.attachments
|
||||
message.link = link
|
||||
message.notify = notify
|
||||
message.format = format
|
||||
|
||||
return await self.bot.send_callback(
|
||||
callback_id=self.callback.callback_id,
|
||||
message=message,
|
||||
notification=notification
|
||||
)
|
@ -1,11 +0,0 @@
|
||||
from typing import Optional
|
||||
|
||||
from ...types.chats import Chat
|
||||
|
||||
from . import Update
|
||||
|
||||
class MessageChatCreated(Update):
|
||||
chat: Chat
|
||||
title: Optional[str] = None
|
||||
message_id: Optional[str] = None
|
||||
start_payload: Optional[str] = None
|
@ -1,19 +0,0 @@
|
||||
from __future__ import annotations
|
||||
from typing import Any, Optional, TYPE_CHECKING, ForwardRef
|
||||
|
||||
from pydantic import Field
|
||||
|
||||
from . import Update
|
||||
from ...types.message import Message
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ...bot import Bot
|
||||
|
||||
|
||||
class MessageCreated(Update):
|
||||
message: Message
|
||||
user_locale: Optional[str] = None
|
||||
bot: Optional[Any] = Field(default=None, exclude=True)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
bot: Optional[Bot]
|
@ -1,6 +0,0 @@
|
||||
from . import Update
|
||||
from ...types.message import Message
|
||||
|
||||
|
||||
class MessageEdited(Update):
|
||||
message: Message
|
@ -1,9 +0,0 @@
|
||||
from typing import Optional
|
||||
|
||||
from . import Update
|
||||
|
||||
|
||||
class MessageRemoved(Update):
|
||||
message_id: Optional[str] = None
|
||||
chat_id: Optional[int] = None
|
||||
user_id: Optional[int] = None
|
@ -1,10 +0,0 @@
|
||||
from typing import Optional
|
||||
|
||||
from . import Update
|
||||
from ...types.users import User
|
||||
|
||||
|
||||
class UserAdded(Update):
|
||||
inviter_id: Optional[int] = None
|
||||
chat_id: Optional[int] = None
|
||||
user: User
|
@ -1,10 +0,0 @@
|
||||
from typing import Optional
|
||||
|
||||
from . import Update
|
||||
from ...types.users import User
|
||||
|
||||
|
||||
class UserRemoved(Update):
|
||||
admin_id: Optional[int] = None
|
||||
chat_id: Optional[int] = None
|
||||
user: User
|
@ -1,26 +0,0 @@
|
||||
from pydantic import BaseModel
|
||||
from typing import List, Optional
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class BotCommand(BaseModel):
|
||||
name: str
|
||||
description: Optional[str] = None
|
||||
|
||||
|
||||
class User(BaseModel):
|
||||
user_id: int
|
||||
first_name: str
|
||||
last_name: Optional[str] = None
|
||||
username: Optional[str] = None
|
||||
is_bot: bool
|
||||
last_activity_time: int
|
||||
description: Optional[str] = None
|
||||
avatar_url: Optional[str] = None
|
||||
full_avatar_url: Optional[str] = None
|
||||
commands: Optional[List[BotCommand]] = None
|
||||
|
||||
class Config:
|
||||
json_encoders = {
|
||||
datetime: lambda v: int(v.timestamp() * 1000) # Конвертация datetime в Unix-время (ms)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user