Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions docs/api/client-config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,3 @@ Client Config

.. autoclass:: ExtraConfig
:members:

.. autofunction:: configure_logging
17 changes: 6 additions & 11 deletions docs/client.rst
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ Client
work_dir="cache",
session_name="account.db",
extra_config=ExtraConfig(
log_level="INFO",
reconnect=True,
reconnect_delay=3,
),
Expand All @@ -85,7 +84,7 @@ Client
Имя файла сессии внутри ``work_dir``.

``extra_config``
Настройки соединения, логов, reconnect, token, device/user-agent и sync.
Настройки соединения, reconnect, token, device/user-agent и sync.

Тип устройства
---------------
Expand Down Expand Up @@ -259,17 +258,13 @@ Debug-логи
Debug-логи показывают handshake, login, входящие события, API-ошибки,
причины reconnect и детали upload. Начинайте диагностику с них.

.. code-block:: python

from pymax import Client, ExtraConfig
PyMax не настраивает логирование самостоятельно. Включите debug-логи
стандартными средствами Python до создания клиента:

client = Client(
phone="+79990000000",
extra_config=ExtraConfig(log_level="DEBUG"),
)
.. code-block:: python

Можно также вызвать ``configure_logging("DEBUG")`` до создания клиента, но
обычно достаточно ``ExtraConfig(log_level="DEBUG")``.
import logging
logging.basicConfig(level=logging.DEBUG)

Группы методов клиента
----------------------
Expand Down
28 changes: 2 additions & 26 deletions docs/faq.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ FAQ

Проверьте, что ``await client.start()`` действительно запущен, handler
зарегистрирован до запуска клиента, аккаунт видит нужный чат, а соединение не
упало. Для диагностики включите ``log_level="DEBUG"`` и временно добавьте
``on_raw``.
упало. Для диагностики включите ``logging.basicConfig(level=logging.DEBUG)``
и временно добавьте ``on_raw``.

Почему handler не вызывается?
-----------------------------
Expand Down Expand Up @@ -58,30 +58,6 @@ Max не всегда присылает полный объект сообще
Если удалить файл сессии, PyMax создает новую сессию и снова запускает
авторизацию.

Как включить debug-логи?
------------------------

.. code-block:: python

from pymax import Client, ExtraConfig

client = Client(
phone="+79990000000",
extra_config=ExtraConfig(log_level="DEBUG"),
)

Как отключить reconnect?
------------------------

.. code-block:: python

from pymax import Client, ExtraConfig

client = Client(
phone="+79990000000",
extra_config=ExtraConfig(reconnect=False),
)

Что делать, если upload файла падает?
-------------------------------------

Expand Down
14 changes: 5 additions & 9 deletions docs/troubleshooting.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,13 @@ Troubleshooting
Базовая диагностика
-------------------

Начинайте с debug-логов:
Начинайте с debug-логов. PyMax не настраивает логирование самостоятельно —
включите их до создания клиента:

.. code-block:: python

from pymax import Client, ExtraConfig

client = Client(
phone="+79990000000",
work_dir="cache",
extra_config=ExtraConfig(log_level="DEBUG"),
)
import logging
logging.basicConfig(level=logging.DEBUG)

Если событие не распознается, добавьте raw-handler:

Expand Down Expand Up @@ -110,5 +106,5 @@ Reconnect
консольный provider. В UI-приложениях передайте собственный async-provider.

``remove_2fa()`` не отключает пароль
Метод требует текущий пароль 2FA. Включите ``DEBUG``-логи и проверьте, что
Метод требует текущий пароль 2FA. Включите debug-логи и проверьте, что
сервер принял проверку пароля и запрос отключения.
2 changes: 0 additions & 2 deletions src/pymax/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
from .dispatch import EventType, Router
from .exceptions import ApiError, PyMaxError, UploadError
from .files import File, Photo, Video
from .logging import configure_logging
from .routers import ClientRouter, WebRouter
from .types import Chat, Message, MessageDeleteEvent, Profile, User
from .types.domain.sync import SyncOverrides, SyncState
Expand Down Expand Up @@ -54,5 +53,4 @@
"WebClient",
"WebRouter",
"__version__",
"configure_logging",
)
52 changes: 39 additions & 13 deletions src/pymax/api/chats/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ def _remove_cached_chat(self, chat_id: int) -> None:
if self.app.chats is None:
return

self.app.chats = [chat for chat in self.app.chats if chat.id != chat_id]
self.app.chats = [
chat for chat in self.app.chats if chat.id != chat_id
]

@staticmethod
def _process_chat_join_link(link: str) -> str | None:
Expand Down Expand Up @@ -151,7 +153,9 @@ async def invite_users_to_channel(
user_ids: list[int],
show_history: bool = True,
) -> Chat | None:
return await self.invite_users_to_group(chat_id, user_ids, show_history)
return await self.invite_users_to_group(
chat_id, user_ids, show_history
)

async def remove_users_from_group(
self,
Expand Down Expand Up @@ -195,7 +199,9 @@ async def change_group_settings(
),
)

response = await self.app.invoke(Opcode.CHAT_UPDATE, frame.to_payload())
response = await self.app.invoke(
Opcode.CHAT_UPDATE, frame.to_payload()
)
chat = parse_payload_item_model(response, ChatPayloadKey.CHAT, Chat)
if chat:
self._cache_chat(chat)
Expand All @@ -212,7 +218,9 @@ async def change_group_profile(
description=description,
)

response = await self.app.invoke(Opcode.CHAT_UPDATE, frame.to_payload())
response = await self.app.invoke(
Opcode.CHAT_UPDATE, frame.to_payload()
)
chat = parse_payload_item_model(response, ChatPayloadKey.CHAT, Chat)
if chat:
self._cache_chat(chat)
Expand Down Expand Up @@ -244,7 +252,9 @@ async def resolve_group_by_link(self, link: str) -> Chat | None:

async def rework_invite_link(self, chat_id: int) -> Chat:
frame = ReworkInviteLinkPayload(chat_id=chat_id)
response = await self.app.invoke(Opcode.CHAT_UPDATE, frame.to_payload())
response = await self.app.invoke(
Opcode.CHAT_UPDATE, frame.to_payload()
)
chat = require_payload_item_model(response, ChatPayloadKey.CHAT, Chat)
return self._cache_chat(chat)

Expand All @@ -254,12 +264,18 @@ async def get_chats(self, chat_ids: list[int]) -> list[Chat]:
for chat_id in chat_ids
if (chat := self._get_cached_chat(chat_id)) is not None
}
missed_chat_ids = [chat_id for chat_id in chat_ids if chat_id not in cached]
missed_chat_ids = [
chat_id for chat_id in chat_ids if chat_id not in cached
]

if missed_chat_ids:
frame = GetChatInfoPayload(chat_ids=missed_chat_ids)
response = await self.app.invoke(Opcode.CHAT_INFO, frame.to_payload())
for chat in parse_payload_list(response, ChatPayloadKey.CHATS, Chat):
response = await self.app.invoke(
Opcode.CHAT_INFO, frame.to_payload()
)
for chat in parse_payload_list(
response, ChatPayloadKey.CHATS, Chat
):
chat = self._cache_chat(chat)
cached[chat.id] = chat

Expand All @@ -286,14 +302,20 @@ async def fetch_chats(self, marker: int | None = None) -> list[Chat]:

chats = [
self._cache_chat(chat)
for chat in parse_payload_list(response, ChatPayloadKey.CHATS, Chat)
for chat in parse_payload_list(
response, ChatPayloadKey.CHATS, Chat
)
]
return chats

async def get_join_requests(self, chat_id: int, count: int = 100) -> list[Member]:
async def get_join_requests(
self, chat_id: int, count: int = 100
) -> list[Member]:
frame = FetchJoinRequests(chat_id=chat_id, count=count)

response = await self.app.invoke(Opcode.CHAT_MEMBERS, frame.to_payload())
response = await self.app.invoke(
Opcode.CHAT_MEMBERS, frame.to_payload()
)

return bind_api_model(
self.app,
Expand All @@ -313,7 +335,9 @@ async def confirm_join_requests(
operation=ChatMemberOperation.ADD,
)

response = await self.app.invoke(Opcode.CHAT_MEMBERS_UPDATE, frame.to_payload())
response = await self.app.invoke(
Opcode.CHAT_MEMBERS_UPDATE, frame.to_payload()
)

chat = parse_payload_item_model(response, ChatPayloadKey.CHAT, Chat)
if chat:
Expand Down Expand Up @@ -345,7 +369,9 @@ async def decline_join_requests(
operation=ChatMemberOperation.REMOVE,
)

response = await self.app.invoke(Opcode.CHAT_MEMBERS_UPDATE, frame.to_payload())
response = await self.app.invoke(
Opcode.CHAT_MEMBERS_UPDATE, frame.to_payload()
)

chat = parse_payload_item_model(response, ChatPayloadKey.CHAT, Chat)
if chat:
Expand Down
2 changes: 1 addition & 1 deletion src/pymax/api/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class CamelModel(BaseModel):
model_config = ConfigDict(
alias_generator=to_camel,
populate_by_name=True,
arbitrary_types_allowed=True
arbitrary_types_allowed=True,
)

def to_payload(self) -> dict:
Expand Down
1 change: 0 additions & 1 deletion src/pymax/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ def _build_config(
port=self.extra_config.port,
use_ssl=self.extra_config.use_ssl,
request_timeout=self.extra_config.request_timeout,
log_level=self.extra_config.log_level,
telemetry=self.extra_config.telemetry,
sync=self.extra_config.sync,
store=self.extra_config.store,
Expand Down
6 changes: 3 additions & 3 deletions src/pymax/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
)
from pymax.connection import ConnectionManager
from pymax.connection.readers import TCPReader
from pymax.logging import configure_logging, get_logger
from pymax.logging import get_logger
from pymax.protocol.tcp import TcpProtocol
from pymax.protocol.tcp.framing import TcpPacketFramer
from pymax.transport.tcp import TCPTransport
Expand Down Expand Up @@ -54,9 +54,9 @@ def __init__(
self.session_name = session_name
self.work_dir = work_dir

configure_logging(self.extra_config.log_level)
logger.debug(
"creating client phone_set=%s session=%s work_dir=%s proxy_set=%s reconnect=%s",
"creating client phone_set=%s session=%s "
"work_dir=%s proxy_set=%s reconnect=%s",
bool(phone),
self.session_name,
self.work_dir,
Expand Down
6 changes: 3 additions & 3 deletions src/pymax/client_web.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from pymax.auth.qr import QrAuthFlow
from pymax.connection import ConnectionManager
from pymax.connection.readers import WSReader
from pymax.logging import configure_logging, get_logger
from pymax.logging import get_logger
from pymax.protocol.ws import WsProtocol
from pymax.transport.websocket import WebSocketTransport

Expand Down Expand Up @@ -42,9 +42,9 @@ def __init__(
self.session_name = session_name
self.work_dir = work_dir

configure_logging(self.extra_config.log_level)
logger.debug(
"creating web client session=%s work_dir=%s proxy_set=%s reconnect=%s",
"creating web client session=%s work_dir=%s "
"proxy_set=%s reconnect=%s",
self.session_name,
self.work_dir,
bool(self.extra_config.proxy),
Expand Down
6 changes: 1 addition & 5 deletions src/pymax/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ class ClientConfig(BaseModel):

protocol_version: int = 10
request_timeout: float = 30.0
log_level: str = "INFO"
telemetry: bool = False

store: StoreProtocol | None = None
Expand All @@ -117,7 +116,7 @@ def ensure_config(self) -> None:
class ExtraConfig(BaseModel):
"""Дополнительные настройки ``Client`` и ``WebClient``.

Используйте ``ExtraConfig`` для token-логина, debug-логов, reconnect,
Используйте ``ExtraConfig`` для token-логина, reconnect,
пользовательского device/user-agent и переопределения sync-state.

Args:
Expand All @@ -134,7 +133,6 @@ class ExtraConfig(BaseModel):
user_agent: Полностью заданный user-agent payload.
mt_instance_id: Instance ID устройства.
request_timeout: Timeout API-запросов в секундах.
log_level: Уровень логов ``pymax``.
telemetry: Отправлять telemetry-события Max.
sync: Переопределения sync-маркеров для login.

Expand All @@ -146,7 +144,6 @@ class ExtraConfig(BaseModel):
client = Client(
phone="+79990000000",
extra_config=ExtraConfig(
log_level="DEBUG",
reconnect=False,
sync=SyncOverrides(chats_sync=-1),
),
Expand All @@ -171,7 +168,6 @@ class ExtraConfig(BaseModel):
mt_instance_id: str = Field(default_factory=lambda: str(uuid4()))

request_timeout: float = 30.0
log_level: str = "INFO"
telemetry: bool = True

store: StoreProtocol | None = None
Expand Down
Loading
Loading