### Retrieve user, chat, and history data Source: https://github.com/dayforce/pymax/blob/master/redocs/source/quickstart.md Examples for fetching user profiles, chat information, and message history using the client instance. ```python from pymax.types import Message, User, Chat from pymax.filters import Filters # Get user info @client.on_message() async def get_user_info(message: Message) -> None: user: User | None = await client.get_user(message.sender) if user: name = user.names[0].first_name if user.names else "Неизвестно" await client.send_message(chat_id=message.chat_id, text=f"Привет, {name}!") # Get chat info @client.on_message() async def get_chat_info(message: Message) -> None: chat: Chat | None = await client.get_chat(message.chat_id) if chat: await client.send_message(chat_id=message.chat_id, text=f"Название чата: {chat.title}") # Fetch history @client.on_message(Filters.text("история")) async def fetch_history(message: Message) -> None: history = await client.fetch_history(chat_id=message.chat_id, limit=10) text = "Последние 10 сообщений:\n" for msg in history: text += f"- {msg.text}\n" await client.send_message(chat_id=message.chat_id, text=text) ``` -------------------------------- ### Install PyMax from Source Source: https://github.com/dayforce/pymax/blob/master/redocs/source/installation.md Installs the PyMax library from its source code repository for development or testing the latest version. This involves cloning the repository and then installing using pip or uv. ```bash git clone https://github.com/MaxApiTeam/PyMax.git cd PyMax pip install -e . ``` ```bash git clone https://github.com/MaxApiTeam/PyMax.git cd PyMax uv sync ``` -------------------------------- ### Build a Command Handler Source: https://github.com/dayforce/pymax/blob/master/redocs/source/examples.md Demonstrates how to parse and execute commands starting with a prefix. Supports static string responses and dynamic function-based responses. ```python import asyncio from pymax import MaxClient from datetime import datetime from pymax.filters import Filters client = MaxClient(phone="+79001234567") commands = { "/привет": "Привет! 👋", "/помощь": "Доступные команды: /привет, /время, /помощь", "/время": lambda: f"Время: {datetime.now().strftime('%H:%M:%S')} ⏰", } @client.on_message() async def handle_command(message): if not message.text or not message.text.startswith("/"): return command = message.text.split()[0] if command in commands: response = commands[command] if callable(response): response = response() await client.send_message( chat_id=message.chat_id, text=response ) asyncio.run(client.start()) ``` -------------------------------- ### Send files as attachments Source: https://github.com/dayforce/pymax/blob/master/redocs/source/quickstart.md Shows how to create a File object and send it as an attachment within a message. ```python from pymax.filters import Filters from pymax.files import File from pymax.types import Message @client.on_message(Filters.text("файл")) async def send_file(message: Message) -> None: file = File(path="document.pdf") await client.send_message( chat_id=message.chat_id, text="Вот документ", attachment=file ) ``` -------------------------------- ### PyMax Simple Assistant - Python Source: https://github.com/dayforce/pymax/blob/master/redocs/source/quickstart.md This Python script demonstrates a basic assistant using the PyMax library. It sets up a client, defines handlers for starting the client, periodic tasks, and specific text messages ('привет', 'помощь', 'время'). It requires the 'pymax' library and 'asyncio'. The script takes a phone number and a working directory for caching as input. ```python import asyncio from pymax import MaxClient from pymax.filters import Filters from pymax.types import Message, User client = MaxClient( phone="+79001234567", work_dir="./cache" ) @client.on_start() async def on_start() -> None: print(f"Помощник запущен! ID: {client.me.id}") await client.send_message( chat_id=123456, text="Я запустился!", notify=False ) @client.task(minutes=1) async def status_check() -> None: """Проверка статуса каждую минуту""" print("Помощник все еще работает!") @client.on_message(Filters.text("привет")) async def hello(message: Message) -> None: user: User | None = await client.get_user(message.sender) name = user.names[0].first_name if user and user.names else "друг" await client.send_message( chat_id=message.chat_id, text=f"Привет, {name}! 👋" ) @client.on_message(Filters.text("помощь")) async def help_command(message: Message) -> None: help_text = """Доступные команды: - привет — приветствие - помощь — показать эту справку - время — текущее время """ await client.send_message( chat_id=message.chat_id, text=help_text ) @client.on_message(Filters.text("время")) async def time_command(message: Message) -> None: from datetime import datetime current_time = datetime.now().strftime("%H:%M:%S") await client.send_message( chat_id=message.chat_id, text=f"Текущее время: {current_time} ⏰" ) if __name__ == "__main__": asyncio.run(client.start()) ``` -------------------------------- ### async start() Source: https://github.com/dayforce/pymax/blob/master/redocs/source/clients.md Starts the client, connects to the WebSocket, performs user authorization if necessary, and initiates the background loop. Includes a secure reconnect-loop if reconnect is enabled. ```APIDOC ## async start() ### Description Starts the client, connects to the WebSocket, performs user authorization if necessary, and initiates the background loop. Includes a secure reconnect-loop if reconnect is enabled. ### Returns - **None** (None) ``` -------------------------------- ### Install PyMax using uv Source: https://github.com/dayforce/pymax/blob/master/redocs/source/installation.md Installs the PyMax library using the uv package manager, which is recommended for its speed. It can be added directly or by updating the pyproject.toml file. ```bash uv add maxapi-python ``` ```toml [project] dependencies = [ "maxapi-python>=1.0.0", ] ``` -------------------------------- ### Verify PyMax Installation Source: https://github.com/dayforce/pymax/blob/master/redocs/source/installation.md A Python code snippet to verify that the PyMax library has been installed correctly by importing it and printing its version. ```python import pymax print(pymax.__version__) ``` -------------------------------- ### Troubleshoot Dependency Errors Source: https://github.com/dayforce/pymax/blob/master/redocs/source/installation.md Suggests reinstalling the PyMax library with the '--force-reinstall' option to resolve dependency issues. ```bash pip install --force-reinstall -U maxapi-python ``` -------------------------------- ### Troubleshoot ImportError: No module named 'pymax' Source: https://github.com/dayforce/pymax/blob/master/redocs/source/installation.md Provides a solution for the 'ImportError: No module named 'pymax'' by suggesting the installation command. ```bash pip install -U maxapi-python ``` -------------------------------- ### Install PyMax using pip Source: https://github.com/dayforce/pymax/blob/master/redocs/source/installation.md Installs the PyMax library using the pip package manager. It can be installed globally or within a virtual environment. ```bash pip install -U maxapi-python ``` ```bash python -m venv venv source venv/bin/activate # На Windows: venv\Scripts\activate pip install -U maxapi-python ``` -------------------------------- ### Manage Files and Attachments Source: https://github.com/dayforce/pymax/blob/master/redocs/source/examples.md Shows how to detect incoming file attachments and how to send local files as attachments using the File class. ```python import asyncio from pymax import MaxClient from pymax.files import File from pymax.static.enum import AttachType from pymax.filters import Filters client = MaxClient(phone="+79001234567") @client.on_message() async def handle_files(message): if not message.attaches: return for attach in message.attaches: if attach.type == AttachType.PHOTO: print("Получено фото!") print(f"URL: {attach.base_url}") @client.on_message(Filters.text("файл")) async def send_file(message): file = File(path="document.pdf") await client.send_message( chat_id=message.chat_id, text="Вот файл", attachment=file ) asyncio.run(client.start()) ``` -------------------------------- ### Handle client events Source: https://github.com/dayforce/pymax/blob/master/redocs/source/quickstart.md Registers handlers for lifecycle events such as client startup, message deletion, and chat updates. ```python from pymax.types import Message, Chat @client.on_start() async def startup() -> None: print(f"Клиент запущен! ID: {client.me.id}") @client.on_message_delete() async def message_deleted(message: Message) -> None: print(f"Сообщение удалено: {message.id}") @client.on_chat_update() async def chat_changed(chat: Chat) -> None: print(f"Чат обновлен: {chat.title}") ``` -------------------------------- ### Troubleshoot Old Python Version Source: https://github.com/dayforce/pymax/blob/master/redocs/source/installation.md Provides guidance on updating Python to version 3.10 or newer if an older version is detected. ```bash python --version ``` -------------------------------- ### Install PyMax library Source: https://github.com/dayforce/pymax/blob/master/redocs/source/index.md Commands to install the PyMax library using standard pip or the uv package manager. ```bash pip install -U maxapi-python ``` ```bash uv add -U maxapi-python ``` -------------------------------- ### Register User with Code Source: https://github.com/dayforce/pymax/blob/master/redocs/source/clients.md Completes a custom registration flow by sending a verification code and saving the user's token. The 'start' parameter controls whether post-login tasks are initiated. ```python await client.register_with_code(temp_token=temp_token, code=code, first_name=first_name, last_name=last_name, start=True) ``` -------------------------------- ### Event Handlers Source: https://github.com/dayforce/pymax/blob/master/API_DOCUMENTATION.md Examples of how to use decorators to handle incoming events from the Max messenger. ```APIDOC ## Event Handlers Use decorators to process incoming data: ```python @client.on_message() async def handler(msg: Message): print(f"Новое сообщение: {msg.text}") @client.on_message_edit() async def handler(msg: Message): print(f"Сообщение изменено: {msg.text}") @client.on_reaction_change() def handler(message_id, chat_id, reaction_info): print(f"Реакции изменились в чате {chat_id}") ``` ``` -------------------------------- ### Initialize SocketMaxClient for login Source: https://github.com/dayforce/pymax/blob/master/redocs/source/clients.md Initialize SocketMaxClient for logging in with a phone number. Requires the phone number, a working directory for cache, and user agent headers. The start() method will prompt for a confirmation code. ```python from pymax import SocketMaxClient from pymax.payloads import UserAgentPayload # Для входа по номеру телефона client = SocketMaxClient( phone="+79001234567", work_dir="./cache", headers=UserAgentPayload(device_type="DESKTOP"), ) await client.start() # Потребуется ввести код подтверждения ``` -------------------------------- ### Initialize SocketMaxClient for new user registration Source: https://github.com/dayforce/pymax/blob/master/redocs/source/clients.md Initialize SocketMaxClient for registering a new user. Set the 'registration' flag to True and provide the user's first and last name along with phone number and headers. The start() method will prompt for a confirmation code. ```python from pymax import SocketMaxClient from pymax.payloads import UserAgentPayload client = SocketMaxClient( phone="+79001234567", registration=True, # Флаг регистрации first_name="Иван", last_name="Петров", headers=UserAgentPayload(device_type="DESKTOP"), ) await client.start() # Потребуется ввести код подтверждения ``` -------------------------------- ### Filter incoming messages Source: https://github.com/dayforce/pymax/blob/master/redocs/source/quickstart.md Demonstrates how to use message filters to restrict event handling to specific chat IDs or specific text content. ```python from pymax.filters import Filters from pymax.types import Message # Only from a specific chat @client.on_message(Filters.chat(123456)) async def handle_chat(message: Message) -> None: await client.send_message( chat_id=message.chat_id, text="Это из моего чата!" ) # Only with specific text @client.on_message(Filters.text("привет")) async def greet(message: Message) -> None: await client.send_message( chat_id=message.chat_id, text="И тебе привет!" ) ``` -------------------------------- ### Create an Echo Bot with MaxClient Source: https://github.com/dayforce/pymax/blob/master/redocs/source/quickstart.md Initializes a MaxClient instance and registers an asynchronous message handler to echo incoming text messages back to the sender. ```python import asyncio from pymax import MaxClient from pymax.types import Message client = MaxClient(phone="+79001234567") @client.on_message() async def echo(message: Message) -> None: if message.text: await client.send_message( chat_id=message.chat_id, text=f"Echo: {message.text}" ) if __name__ == "__main__": asyncio.run(client.start()) ``` -------------------------------- ### Add New Method Example (Python) Source: https://github.com/dayforce/pymax/blob/master/CONTRIBUTING.md Demonstrates how to add a new asynchronous method to a PyMax mixin. It shows the process of defining a payload using Pydantic models and sending it via `_send_and_wait` with a specified opcode. ```python async def my_new_method(self, param: str): payload = MyPayload(p=param).model_dump(by_alias=True) return await self._send_and_wait(opcode=Opcode.SOME_OP, payload=payload) ``` -------------------------------- ### Remove PyMax using pip or uv Source: https://github.com/dayforce/pymax/blob/master/redocs/source/installation.md Commands to uninstall the PyMax library from the system using either pip or uv. ```bash pip uninstall maxapi-python ``` ```bash uv remove maxapi-python ``` -------------------------------- ### Use PyMax as a Context Manager Source: https://github.com/dayforce/pymax/blob/master/redocs/source/examples.md Demonstrates the use of the 'async with' statement to manage the lifecycle of the PyMax client. This automatically handles connection and synchronization states. ```python import asyncio from pymax import MaxClient client = MaxClient(phone="+79001234567") async def main(): async with client: # Клиент автоматически подключён и синхронизирован await client.send_message( chat_id=123456, text="Контекстный менеджер работает!" ) # Блокировать и ждать событий await client.idle() asyncio.run(main()) ``` -------------------------------- ### Implement a Greeter Bot Source: https://github.com/dayforce/pymax/blob/master/redocs/source/examples.md This bot greets new users in a specific chat by retrieving their profile information. It uses filters to restrict the greeting to a specific chat ID. ```python import asyncio from pymax import MaxClient from pymax.filters import Filters client = MaxClient(phone="+79001234567") @client.on_message(Filters.chat(123)) async def greet(message): user = await client.get_user(message.sender) if user and user.names: name = user.names[0].first_name await client.send_message( chat_id=message.chat_id, text=f"Привет, {name}! 👋" ) @client.on_start async def on_start(): print(f"Greeter запущен! ID: {client.me.id}") asyncio.run(client.start()) ``` -------------------------------- ### Set Client Startup Handler in PyMax Source: https://github.com/dayforce/pymax/blob/master/redocs/source/decorators.md Sets a handler function or coroutine that is executed when the client starts. This handler does not accept any arguments and returns the registered handler. ```python def on_start(handler): """ Sets a handler function or coroutine that is executed when the client starts. Parameters: handler (Callable[[], Any | Awaitable[Any]]): The function or coroutine to execute on client start. Returns: Callable[[], Any | Awaitable[Any]]: The registered handler. """ pass ``` -------------------------------- ### Implement basic bot functionality Source: https://github.com/dayforce/pymax/blob/master/README.md A complete example showing how to handle incoming messages, send replies, add reactions, and fetch chat history using the MaxClient. ```python import asyncio from pymax import MaxClient, Message from pymax.filters import Filters client = MaxClient( phone="+1234567890", work_dir="cache", ) @client.on_message(Filters.chat(0)) async def on_message(msg: Message) -> None: print(f"[{msg.sender}] {msg.text}") await client.send_message( chat_id=msg.chat_id, text="Привет, я бот на PyMax!", ) await client.add_reaction( chat_id=msg.chat_id, message_id=str(msg.id), reaction="👍", ) @client.on_start async def on_start() -> None: print(f"Клиент запущен. Ваш ID: {client.me.id}") history = await client.fetch_history(chat_id=0) for m in history: print(f"- {m.text}") async def main(): await client.start() if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### Implement Auto-Reply Logic with PyMax Source: https://github.com/dayforce/pymax/blob/master/redocs/source/examples.md Demonstrates how to listen for incoming messages and trigger automated responses based on keyword matching. It uses a dictionary mapping to define triggers and their corresponding replies. ```python import asyncio from pymax import MaxClient from pymax.filters import Filters client = MaxClient(phone="+79001234567") auto_replies = { "привет": "И тебе привет! 👋", "как дела": "Спасибо, отлично! 😊", "спасибо": "Пожалуйста! 🙏", "пока": "До свидания! 👋", } @client.on_message() async def auto_reply(message): if not message.text: return text_lower = message.text.lower() for trigger, response in auto_replies.items(): if trigger in text_lower: await client.send_message( chat_id=message.chat_id, text=response ) return asyncio.run(client.start()) ``` -------------------------------- ### Schedule Messages with PyMax Source: https://github.com/dayforce/pymax/blob/master/redocs/source/examples.md Shows how to run background tasks alongside the PyMax client to send messages at specific times. It utilizes an infinite loop with asyncio.sleep to check the current time. ```python import asyncio from datetime import datetime, timedelta client = MaxClient(phone="+79001234567") async def scheduled_sender(): while True: now = datetime.now() # Отправить сообщение в 12:00 if now.hour == 12 and now.minute == 0: await client.send_message( chat_id=123456, text="🕐 Обеденный перерыв!", notify=False ) await asyncio.sleep(60) # Не отправлять дважды в одну минуту await asyncio.sleep(1) @client.on_start async def on_start(): asyncio.create_task(scheduled_sender()) asyncio.run(client.start()) ``` -------------------------------- ### Create an Echo Bot with PyMax Source: https://github.com/dayforce/pymax/blob/master/redocs/source/examples.md A basic bot implementation that listens for incoming messages and replies with an echoed version of the original text. It utilizes the MaxClient class and an asynchronous message handler. ```python import asyncio from pymax import MaxClient client = MaxClient(phone="+79001234567") @client.on_message() async def echo(message): if message.text: await client.send_message( chat_id=message.chat_id, text=f"Echo: {message.text}" ) asyncio.run(client.start()) ``` -------------------------------- ### Track Message Statistics Source: https://github.com/dayforce/pymax/blob/master/redocs/source/examples.md Tracks the number of messages sent by each user and provides a command to display the top 5 most active users. ```python import asyncio from collections import defaultdict from pymax import MaxClient from pymax.filters import Filters client = MaxClient(phone="+79001234567") user_messages = defaultdict(int) @client.on_message() async def count_messages(message): user_messages[message.sender] += 1 @client.on_message(Filters.text("статистика")) async def show_stats(message): top = sorted(user_messages.items(), key=lambda x: x[1], reverse=True)[:5] text = "📊 Топ активные:\n" for user_id, count in top: user = await client.get_user(user_id) name = user.names[0].first_name if user and user.names else "Неизвестно" text += f"{name}: {count}\n" await client.send_message( chat_id=message.chat_id, text=text ) asyncio.run(client.start()) ``` -------------------------------- ### Combine PyMax Filters Source: https://github.com/dayforce/pymax/blob/master/redocs/source/examples.md Illustrates how to use logical operators (AND, OR, NOT) with PyMax filters to create complex message handling conditions. This allows for precise control over which messages trigger specific functions. ```python import asyncio from pymax import MaxClient from pymax.filters import Filters client = MaxClient(phone="+79001234567") # AND - оба условия должны быть верны @client.on_message(Filters.chat(123456) & Filters.text("важное")) async def important_in_chat(message): await client.send_message( chat_id=message.chat_id, text="Это важно в нашем чате!" ) # OR - одно из условий должно быть верно @client.on_message(Filters.chat(123456) | Filters.chat(789012)) async def in_my_chats(message): print("Это в одном из моих чатов") # NOT - условие должно быть неверно @client.on_message(~Filters.text("реклама")) async def not_ads(message): print("Это не реклама") asyncio.run(client.start()) ``` -------------------------------- ### Develop a Broadcast Bot Source: https://github.com/dayforce/pymax/blob/master/redocs/source/examples.md Allows the bot to send a message to all chats it is a member of. It filters for a specific trigger word and iterates through the client's chat list. ```python import asyncio from pymax import MaxClient from pymax.filters import Filters client = MaxClient(phone="+79001234567") @client.on_message(Filters.text("рассылка")) async def broadcast(message): text = message.text.replace("рассылка ", "") for chat in client.chats: try: await client.send_message( chat_id=chat.id, text=text, notify=False ) except Exception as e: print(f"Ошибка в чате {chat.title}: {e}") await client.send_message( chat_id=message.chat_id, text="✅ Рассылка завершена" ) asyncio.run(client.start()) ``` -------------------------------- ### Run Tests with Pytest (Bash) Source: https://github.com/dayforce/pymax/blob/master/CONTRIBUTING.md Command to execute all tests within the PyMax project using the pytest framework. This is a crucial step before committing any changes to ensure code quality and stability. ```bash pytest ``` -------------------------------- ### Dynamic User-Agent Management Source: https://github.com/dayforce/pymax/blob/master/ANALYSIS.md To avoid detection, bots should use a diverse set of User-Agents reflecting actual browser and application versions. PyMax allows setting `UserAgentPayload`, but maintaining an up-to-date database of these payloads is crucial. The example shows how a User-Agent might be structured. ```python class UserAgentPayload: def __init__(self, user_agent, os, platform): self.user_agent = user_agent self.os = os self.platform = platform # Example of a dynamic User-Agent payload # This should be selected randomly from a large, updated list chrome_win_ua = UserAgentPayload( user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', os='Windows 10', platform='PC' ) # In a real scenario, you would have a list of these and pick one: # user_agents = [chrome_win_ua, firefox_mac_ua, ...] # selected_ua = random.choice(user_agents) # client = MaxClient(user_agent_payload=selected_ua) ``` -------------------------------- ### Handle Errors in PyMax Handlers Source: https://github.com/dayforce/pymax/blob/master/redocs/source/examples.md Provides a robust pattern for error handling within message handlers using try-except blocks and Python's logging module. This ensures that runtime exceptions do not crash the bot process. ```python import asyncio import logging from pymax import MaxClient logging.basicConfig(level=logging.INFO) logger = logging.getLogger("bot") client = MaxClient(phone="+79001234567", logger=logger) @client.on_message() async def safe_handler(message): try: if not message.text: return result = await client.send_message( chat_id=message.chat_id, text=f"Получено: {message.text}" ) logger.info(f"Сообщение отправлено в чат {message.chat_id}") except Exception as e: logger.error(f"Ошибка в обработчике: {e}") asyncio.run(client.start()) ``` -------------------------------- ### Initialize MaxClient Source: https://github.com/dayforce/pymax/blob/master/redocs/source/clients.md Configure the MaxClient instance with phone number, cache directory, and connection settings. ```python from pymax import MaxClient client = MaxClient( phone="+79001234567", # Номер телефона (обязательно) work_dir="./cache", # Папка для кэша сессии reconnect=True, # Автоматическое переподключение send_fake_telemetry=True, # Отправлять телеметрию logger=None, # Пользовательский логгер ) ``` -------------------------------- ### Max Client Initialization Source: https://github.com/dayforce/pymax/blob/master/redocs/source/clients.md Configuration and initialization of the Max client. ```APIDOC ## MaxClient ### Description The main client for interacting with the Max service via WebSocket API. ### Method Not applicable (class definition) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example None ### Response #### Success Response (200) None #### Response Example None ``` -------------------------------- ### MaxClient Initialization Source: https://github.com/dayforce/pymax/blob/master/redocs/source/clients.md Configuration and initialization parameters for the MaxClient class. ```APIDOC ## MaxClient Initialization ### Description Parameters required to initialize the MaxClient instance. ### Parameters - **phone** (str) - Required - Phone number for the session. - **work_dir** (str) - Optional - Directory for session cache. - **reconnect** (bool) - Optional - Enable automatic reconnection. - **send_fake_telemetry** (bool) - Optional - Enable telemetry simulation. - **logger** (logging.Logger) - Optional - Custom logger instance. ``` -------------------------------- ### Use MaxClient as Context Manager Source: https://github.com/dayforce/pymax/blob/master/redocs/source/clients.md Manage client connection lifecycle automatically using the async context manager. ```python async with MaxClient(phone="+79001234567") as client: # Клиент автоматически подключён await client.send_message(chat_id=123456, text="Привет!") # Клиент автоматически закроется ``` -------------------------------- ### Convert String to Lowercase Source: https://github.com/dayforce/pymax/blob/master/redocs/source/types.md Use lower() to get a copy of the string with all characters converted to lowercase. ```python s = 'Hello World' s.lower() ``` -------------------------------- ### Authenticate with Max API Source: https://github.com/dayforce/pymax/blob/master/README.md Demonstrates how to initialize the client with different device types. The device_type parameter in UserAgentPayload determines the authentication method (DESKTOP for phone number, WEB for QR code). ```python from pymax import SocketMaxClient from pymax.payloads import UserAgentPayload ua = UserAgentPayload(device_type="DESKTOP", app_version="25.12.13") client = SocketMaxClient( phone="+79111111111", work_dir="cache", headers=ua, ) ``` ```python from pymax import MaxClient from pymax.payloads import UserAgentPayload ua = UserAgentPayload(device_type="WEB", app_version="25.12.13") client = MaxClient( phone="+7911111111", work_dir="cache", headers=ua, ) ``` -------------------------------- ### Event Handlers Source: https://github.com/dayforce/pymax/blob/master/redocs/source/clients.md Set up handlers for various events like chat updates, new messages, message edits, deletions, raw data reception, reaction changes, and client startup. ```APIDOC ## Event Handlers ### `on_chat_update(handler)` * **Description**: Sets a handler for chat information updates. * **Parameters**: * **handler** (Callable[[Chat], Any | Awaitable[Any]]) - A function or coroutine that accepts a `Chat` object. * **Returns**: The installed handler. ### `on_message(filter=None)` * **Description**: Decorator to register a handler for incoming messages. Can filter messages based on criteria. * **Parameters**: * **filter** (BaseFilter[[Message]] | None) - Filter for processing messages. Defaults to None. * **Returns**: A decorator for the handler function. ### `on_message_delete(filter=None)` * **Description**: Decorator to set up a handler for deleted messages. * **Parameters**: * **filter** (BaseFilter[[Message]] | None) - Filter for processing deleted messages. Defaults to None. * **Returns**: A decorator for the handler function. ### `on_message_edit(filter=None)` * **Description**: Decorator to set up a handler for edited messages. * **Parameters**: * **filter** (BaseFilter[[Message]] | None) - Filter for processing edited messages. Defaults to None. * **Returns**: A decorator for the handler function. ### `on_raw_receive(handler)` * **Description**: Sets a handler for receiving raw data from the server. * **Parameters**: * **handler** (Callable[[dict[str, Any]], Any | Awaitable[Any]]) - A function or coroutine that accepts raw data as a dictionary. * **Returns**: The installed handler. ### `on_reaction_change(handler)` * **Description**: Sets a handler for message reaction changes. * **Parameters**: * **handler** (Callable[[str, int, ReactionInfo], Any | Awaitable[Any]]) - A function or coroutine accepting message ID, chat ID, and `ReactionInfo`. * **Returns**: The installed handler. ### `on_start(handler)` * **Description**: Sets a handler that is called when the client starts. * **Parameters**: * **handler** (Callable[[], Any | Awaitable[Any]]) - A function or coroutine with no arguments. * **Returns**: The installed handler. ``` -------------------------------- ### Find Highest Index of Substring Source: https://github.com/dayforce/pymax/blob/master/redocs/source/types.md Use rfind() to find the highest index where a substring is found within the string. Returns -1 if the substring is not found. Optional start and end arguments can specify a slice. ```python s = 'hello world hello' s.rfind('hello') ``` ```python s = 'hello world hello' s.rfind('test') ``` -------------------------------- ### Partition String by Separator Source: https://github.com/dayforce/pymax/blob/master/redocs/source/types.md Use partition() to split a string into three parts based on the first occurrence of a separator: the part before, the separator itself, and the part after. Returns the original string and two empty strings if the separator is not found. ```python s = 'hello world hello' s.partition('world') ``` ```python s = 'hello world' s.partition('test') ``` -------------------------------- ### String Justification and Padding Source: https://github.com/dayforce/pymax/blob/master/redocs/source/types.md Methods for aligning strings within a specified width. ```APIDOC ## ljust(width, fillchar=' ') ### Description Return a left-justified string of length width. Padding is done using the specified fill character (default is a space). ### Method N/A (String method) ### Endpoint N/A ## rjust(width, fillchar=' ') ### Description Return a right-justified string of length width. Padding is done using the specified fill character (default is a space). ### Method N/A (String method) ### Endpoint N/A ``` -------------------------------- ### Handle and Send Messages Source: https://github.com/dayforce/pymax/blob/master/redocs/source/guides.md Demonstrates how to listen for incoming messages using decorators and perform actions like sending, replying, editing, or deleting messages. ```python from pymax.types import Message @client.on_message() async def handle_message(message: Message) -> None: message.id message.chat_id message.sender message.text message.type message.status message.timestamp message.attaches # Sending messages await client.send_message(chat_id=123456, text="Привет!") await client.send_message(chat_id=123456, text="Важное!", notify=True) # Replying async def reply_to_message(message: Message) -> None: await client.send_message(chat_id=message.chat_id, text="Ответ", reply_to=message.id) # Edit/Delete await client.edit_message(chat_id=123456, message_id=msg_id, text="Новый текст") await client.delete_message(chat_id=123456, message_ids=[msg_id], for_me=False) ``` -------------------------------- ### async update_folder(folder_id, title, chat_include=None, filters=None, options=None) Source: https://github.com/dayforce/pymax/blob/master/redocs/source/clients.md Updates the parameters of an existing folder. ```APIDOC ## async update_folder(folder_id, title, chat_include=None, filters=None, options=None) ### Description Updates the parameters of an existing folder. ### Parameters #### Request Body - **folder_id** (str) - Required - Identifier of the folder. - **title** (str) - Required - Title of the folder. - **chat_include** (list[int]) - Optional - List of chat IDs to include. - **filters** (list[Any]) - Optional - List of filters. - **options** (list[Any]) - Optional - List of options. ### Response #### Success Response (200) - **FolderUpdate** (object) - Returns a FolderUpdate object or None. ``` -------------------------------- ### Adding Typing Status Indicator Source: https://github.com/dayforce/pymax/blob/master/ANALYSIS.md The `send_message` method should optionally send a 'typing' status indicator before delivering a message, especially for longer texts. This enhances the human-like behavior of the bot. The example shows a placeholder for sending such an event. ```python async def send_message_with_typing(message): if len(message) > 50: # Example condition for long messages # Send 'typing' event # await client.send_typing_indicator() print("Sent typing indicator.") await asyncio.sleep(random.uniform(0.5, 1.5)) # Simulate typing time # Send the actual message # await client.send_message(message) print(f"Sent message: {message}") # Example usage: # asyncio.run(send_message_with_typing("This is a very long message that should trigger the typing indicator.")) ``` -------------------------------- ### Configure Automatic Reconnection Source: https://github.com/dayforce/pymax/blob/master/redocs/source/clients.md Enable automatic reconnection for the client instance. ```python client = MaxClient(phone="+79001234567", reconnect=True) # Клиент автоматически переподключится при разрыве соединения await client.start() ``` -------------------------------- ### v1.2.3 - New Features and Methods Source: https://github.com/dayforce/pymax/blob/master/redocs/source/release_notes_archive.md Details the new functionalities and methods introduced in version 1.2.3, including profile photo uploads, resolving groups by link, contact message support, and accessing the client's contact list. ```APIDOC ## v1.2.3 (December 24, 2025) ### New Features * **Profile photo upload**: Profiles can now be updated with a new photo via the `change_profile()` method. * **Resolve groups by link**: Groups can now be resolved (retrieved) directly by their link using the `resolve_group_by_link()` method. * **Contact support in messages**: Messages now support contact attachments with contact information (ContactAttach). * **Client contact list**: The client now maintains a list of all user contacts via the `client.contacts` property. ### New Methods * `MaxClient.resolve_group_by_link(link: str) -> Chat | None` * Resolves a group by its link. Returns the group chat object or None if not found. * `MaxClient.change_profile(first_name, last_name, description, photo)` * Changes the current user's profile information, including uploading a new photo. ### New Types * `ContactAttach` * Represents a contact in a message. Contains contact information (ID, first name, last name, photo). ### Modified Types * `Message` * Now supports `ContactAttach` type attachments in the `attaches` list. * `Names` * Improved for handling various user name formats. * `StickerAttach` * Improved representation of stickers in messages. * `Photo` * Improved for handling profile photos. * `AttachType` * Added `CONTACT` value for contacts. ### New Parameters * `MaxClient.contacts: list[User]` * List of the current user's contacts. ``` -------------------------------- ### Utility and Search Methods Source: https://github.com/dayforce/pymax/blob/master/redocs/source/types.md Methods for creating translation tables and searching for substrings. ```APIDOC ## Utility and Search Methods ### maketrans() - **Description**: Static method to return a translation table for str.translate(). ### rfind(sub) - **Description**: Return the highest index where substring sub is found, or -1 on failure. ``` -------------------------------- ### Streaming Large Files for Memory Efficiency Source: https://github.com/dayforce/pymax/blob/master/ANALYSIS.md In `message.py`, loading entire video files into memory (`await video.read()`) can cause `MemoryError` for large files. The recommendation is to use file streaming for all file types to handle large uploads efficiently. The example demonstrates reading a file in chunks. ```python async def upload_video_streamed(file_path, chunk_size=8192): with open(file_path, 'rb') as f: while True: chunk = f.read(chunk_size) if not chunk: break # Process chunk (e.g., send over network) # await send_chunk(chunk) await asyncio.sleep(0.01) # Simulate async operation # Example usage: # await upload_video_streamed('large_video.mp4') ``` -------------------------------- ### String Partitioning Source: https://github.com/dayforce/pymax/blob/master/redocs/source/types.md Methods for splitting a string into three parts based on a separator. ```APIDOC ## partition(sep,) ### Description Partition the string into three parts using the given separator. This will search for the separator in the string. If the separator is found, returns a 3-tuple containing the part before the separator, the separator itself, and the part after it. If the separator is not found, returns a 3-tuple containing the original string and two empty strings. ### Method N/A (String method) ### Endpoint N/A ## rpartition(sep,) ### Description Partition the string into three parts using the given separator. This will search for the separator in the string, starting at the end. If the separator is found, returns a 3-tuple containing the part before the separator, the separator itself, and the part after it. If the separator is not found, returns a 3-tuple containing two empty strings and the original string. ### Method N/A (String method) ### Endpoint N/A ``` -------------------------------- ### String Transformation and Joining Source: https://github.com/dayforce/pymax/blob/master/redocs/source/types.md Methods for transforming strings and joining them. ```APIDOC ## join(iterable,) ### Description Concatenate any number of strings. The string whose method is called is inserted in between each given string. The result is returned as a new string. ### Method N/A (String method) ### Endpoint N/A ### Request Example ```python '.'.join(['ab', 'pq', 'rs']) ``` ### Response Example ``` ab.pq.rs ``` ## lower() ### Description Return a copy of the string converted to lowercase. ### Method N/A (String method) ### Endpoint N/A ``` -------------------------------- ### Access MaxClient Properties Source: https://github.com/dayforce/pymax/blob/master/redocs/source/clients.md Retrieve client state and metadata using available properties. ```python client.me # Информация о себе (Me) client.is_connected # Статус подключения (bool) client.chats # Список всех чатов (list[Chat]) client.dialogs # Список диалогов (list[Dialog]) client.channels # Список каналов (list[Channel]) client.phone # Номер телефона (str) client.token # Токен сессии (str | None) client.contacts # Список контактов (list[User]) ``` -------------------------------- ### fetch_users Source: https://github.com/dayforce/pymax/blob/master/redocs/source/clients.md Loads user information from the server and adds them to the internal cache. ```APIDOC ## fetch_users ### Description Requests user data by IDs and caches them. ### Parameters - **user_ids** (list[int]) - Required - Список идентификаторов пользователей. ### Response - **list[User]** - Список загруженных объектов User. ``` -------------------------------- ### get_folders Source: https://github.com/dayforce/pymax/blob/master/redocs/source/clients.md Retrieves the list of all user folders. ```APIDOC ## get_folders ### Description Gets user folders. ### Parameters - **folder_sync** (int) - Optional - Синхронизационный маркер. ### Response - **FolderList** - Объект FolderList. ``` -------------------------------- ### task(seconds, minutes=0, hours=0) Source: https://github.com/dayforce/pymax/blob/master/redocs/source/clients.md Decorator for scheduling periodic tasks within the client. ```APIDOC ## task(seconds, minutes=0, hours=0) ### Description Decorator for scheduling periodic tasks. ### Parameters #### Query Parameters - **seconds** (float) - Required - Interval in seconds. - **minutes** (float) - Optional - Interval in minutes. Default is 0. - **hours** (float) - Optional - Interval in hours. Default is 0. ### Returns - **Callable** - Decorator for the handler function. ``` -------------------------------- ### Channel and Group Management Source: https://github.com/dayforce/pymax/blob/master/redocs/source/clients.md Methods for interacting with channels and groups. ```APIDOC ## POST /invite_users_to_channel ### Description Invites users to a channel. ### Method POST ### Parameters #### Request Body - **chat_id** (int) - Required - Channel ID. - **user_ids** (list[int]) - Required - List of user IDs. - **show_history** (bool) - Optional - Alert flag. Defaults to True. ## POST /join_channel ### Description Joins a channel via a link. ### Method POST ### Parameters #### Request Body - **link** (str) - Required - Channel link. ## GET /load_members ### Description Loads members of a channel with pagination support. ### Method GET ### Parameters #### Query Parameters - **chat_id** (int) - Required - Channel ID. - **marker** (int) - Optional - Pagination marker. - **count** (int) - Optional - Number of members to load. ``` -------------------------------- ### v1.2.4 - New Features and Methods Source: https://github.com/dayforce/pymax/blob/master/redocs/source/release_notes_archive.md Details the new functionalities and methods introduced in version 1.2.4, such as enhanced file type support, automatic read receipts, session name customization, and retrieving web app version. ```APIDOC ## v1.2.4 (December 30, 2025) ### New Features * **Support for various file types in File and Photo classes**: `Photo`, `File`, and `Video` classes now support bytes, allowing direct loading of files from memory. * **Automatic sending of read receipts**: The client now automatically sends read receipts to the service for improved synchronization. * **`session_name` parameter for session management**: The `session_name` parameter allows specifying a custom filename for saving the session. * **Get current web application version**: New method `get_current_web_version()` in utilities to retrieve the current Max web application version. * **Improved User-Agent generation**: Uses the `ua-generator` library for more realistic User-Agent strings and device parameters. ### New Methods * `read_message(chat_id: int, message_id: int) -> ReadState` * Marks a message as read. Returns a `ReadState` object with status information. * `pymax.utils.MixinsUtils.get_current_web_version() -> str | None` * Retrieves the current Max web application version from the source. Returns the version in "XX.XX.XX" format or None. ### Modified Methods * `MaxClient.start()` * Improved reconnection loop logic using `asyncio.Event` for cleaner termination. * Fixed state handling during disconnection and reconnection. * `MaxClient.close()` * Simplified client closing logic. Now uses `asyncio.Event` for stop signaling. ### New Parameters * `MaxClient._\_init_\_(session_name: str = "session.db")` * Allows specifying a custom session database filename. ### Modified Types * `BaseFile` * Now supports bytes via the `raw` parameter in all subclasses. * `Photo` * Added `name` parameter for explicit filename specification when working with bytes. * Improved file extension validation. * `File` * Added support for bytes via the `raw` parameter. * Improved filename handling. * `Video` * Added support for bytes via the `raw` parameter. * Improved video file handling. ### Fixes and Improvements * Added `device_type` validation for `MaxClient` (supports only WEB) and `SocketMaxClient` (supports ANDROID, IOS, DESKTOP). * Improved WebSocket error handling on disconnection. * Added `ua-generator` option for more realistic device parameter generation. * Updated application version to 25.12.14. * Improved handling of message delivery notifications. * Fixed issues with async task termination when closing the client. ### Dependencies * Added new dependencies: * `ua-generator>=2.0.19` - for generating realistic User-Agent strings and device parameters. ``` -------------------------------- ### Manage Users and Profiles Source: https://github.com/dayforce/pymax/blob/master/redocs/source/guides.md Covers retrieving user profiles, extracting names, and accessing the current user's own account information. ```python from pymax.types import User, Me user: User | None = await client.get_user(user_id=789012) def get_user_name(user: User | None) -> str: if not user or not user.names: return "Неизвестно" name = user.names[0] return f"{name.first_name} {name.last_name}" if name.last_name else name.first_name @client.on_start async def on_start() -> None: me: Me | None = client.me if me: print(f"Мой ID: {me.id}") ```