maxapi-python 1.1.13__tar.gz → 1.1.14__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/.github/ISSUE_TEMPLATE/bug_report.md +3 -3
  2. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/.github/workflows/publish.yml +1 -1
  3. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/.gitignore +1 -1
  4. maxapi_python-1.1.14/.pre-commit-config.yaml +41 -0
  5. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/PKG-INFO +1 -1
  6. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/assets/icon.svg +0 -1
  7. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/assets/logo.svg +0 -1
  8. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/docs/assets/icon.svg +0 -1
  9. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/docs/client.md +2 -2
  10. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/docs/examples.md +11 -11
  11. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/examples/example.py +9 -5
  12. maxapi_python-1.1.14/examples/telegram_bridge.py +202 -0
  13. maxapi_python-1.1.14/pyproject.toml +72 -0
  14. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/ruff.toml +1 -1
  15. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/src/pymax/__init__.py +7 -5
  16. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/src/pymax/core.py +20 -54
  17. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/src/pymax/crud.py +10 -9
  18. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/src/pymax/exceptions.py +18 -0
  19. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/src/pymax/files.py +13 -4
  20. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/src/pymax/filters.py +8 -3
  21. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/src/pymax/formatting.py +4 -4
  22. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/src/pymax/interfaces.py +9 -15
  23. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/src/pymax/mixins/auth.py +23 -5
  24. maxapi_python-1.1.14/src/pymax/mixins/channel.py +115 -0
  25. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/src/pymax/mixins/group.py +30 -10
  26. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/src/pymax/mixins/handler.py +15 -14
  27. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/src/pymax/mixins/message.py +79 -32
  28. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/src/pymax/mixins/self.py +4 -2
  29. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/src/pymax/mixins/socket.py +143 -75
  30. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/src/pymax/mixins/telemetry.py +11 -6
  31. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/src/pymax/mixins/user.py +23 -1
  32. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/src/pymax/mixins/websocket.py +82 -39
  33. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/src/pymax/navigation.py +3 -1
  34. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/src/pymax/payloads.py +39 -8
  35. maxapi_python-1.1.14/src/pymax/static/constant.py +26 -0
  36. maxapi_python-1.1.13/src/pymax/static.py → maxapi_python-1.1.14/src/pymax/static/enum.py +12 -31
  37. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/src/pymax/types.py +309 -39
  38. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/src/pymax/utils.py +11 -3
  39. maxapi_python-1.1.13/pyproject.toml +0 -50
  40. maxapi_python-1.1.13/scripts/build.py +0 -47
  41. maxapi_python-1.1.13/src/pymax/mixins/channel.py +0 -25
  42. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/.github/FUNDING.yml +0 -0
  43. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  44. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/.github/ISSUE_TEMPLATE/refactor.md +0 -0
  45. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/.github/pull_request_template.md +0 -0
  46. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/LICENSE +0 -0
  47. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/README.md +0 -0
  48. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/docs/api.md +0 -0
  49. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/docs/index.md +0 -0
  50. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/docs/methods.md +0 -0
  51. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/docs/types.md +0 -0
  52. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/mkdocs.yml +0 -0
  53. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/src/pymax/mixins/__init__.py +0 -0
  54. {maxapi_python-1.1.13 → maxapi_python-1.1.14}/src/pymax/models.py +0 -0
@@ -11,9 +11,9 @@ assignees: ''
11
11
  Что пошло не так?
12
12
 
13
13
  **Шаги для воспроизведения**
14
- 1.
15
- 2.
16
- 3.
14
+ 1.
15
+ 2.
16
+ 3.
17
17
 
18
18
  **Ожидаемый результат**
19
19
  Что должно было произойти
@@ -51,4 +51,4 @@ jobs:
51
51
  env:
52
52
  TOKEN: ${{ secrets.PYPI_API_TOKEN }}
53
53
  run: |
54
- uv publish -t $TOKEN
54
+ uv publish -t $TOKEN
@@ -118,4 +118,4 @@ tests/
118
118
 
119
119
 
120
120
  # Bad dev's requirements
121
- requirements.txt
121
+ requirements.txt
@@ -0,0 +1,41 @@
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v6.0.0
4
+ hooks:
5
+ - id: check-case-conflict
6
+ - id: check-docstring-first
7
+ - id: check-executables-have-shebangs
8
+ - id: check-shebang-scripts-are-executable
9
+ - id: check-yaml
10
+ - id: end-of-file-fixer
11
+ - id: fix-byte-order-marker
12
+ - id: mixed-line-ending
13
+ - id: name-tests-test
14
+ - id: trailing-whitespace
15
+ - repo: https://github.com/psf/black
16
+ rev: 25.9.0
17
+ hooks:
18
+ - id: black
19
+ - repo: https://github.com/csachs/pyproject-flake8
20
+ rev: v7.0.0
21
+ hooks:
22
+ - id: pyproject-flake8
23
+ - repo: https://github.com/pre-commit/mirrors-mypy
24
+ rev: v1.18.2
25
+ hooks:
26
+ - id: mypy
27
+ additional_dependencies:
28
+ - "aiohttp"
29
+ - "sqlalchemy"
30
+ - "sqlmodel"
31
+ - "types-aiofiles"
32
+ - "types-requests"
33
+ exclude: "^examples/"
34
+ - repo: https://github.com/pycqa/isort
35
+ rev: 7.0.0
36
+ hooks:
37
+ - id: isort
38
+ - repo: https://github.com/PyCQA/bandit
39
+ rev: 1.8.6
40
+ hooks:
41
+ - id: bandit
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maxapi-python
3
- Version: 1.1.13
3
+ Version: 1.1.14
4
4
  Summary: Python wrapper для API мессенджера Max
5
5
  Project-URL: Homepage, https://github.com/ink-developer/PyMax
6
6
  Project-URL: Repository, https://github.com/ink-developer/PyMax
@@ -11,4 +11,3 @@
11
11
  <path d="M33.3539 21.0919L33.1508 29.8751L33.0395 34.6974L29.1625 31.8253L24.0121 28.0089L21.5912 26.216L23.4604 24.4816L30.7885 30.0001L30.9223 17.5587L33.4916 15.1779L33.3539 21.0919Z" fill="#2F9872"/>
12
12
  </g>
13
13
  </svg>
14
-
@@ -11,4 +11,3 @@
11
11
  <path d="M33.3539 21.0919L33.1508 29.8751L33.0395 34.6974L29.1625 31.8253L24.0121 28.0089L21.5912 26.216L23.4604 24.4816L30.7885 30.0001L30.9223 17.5587L33.4916 15.1779L33.3539 21.0919Z" fill="#2F9872"/>
12
12
  </g>
13
13
  </svg>
14
-
@@ -11,4 +11,3 @@
11
11
  <path d="M33.3539 21.0919L33.1508 29.8751L33.0395 34.6974L29.1625 31.8253L24.0121 28.0089L21.5912 26.216L23.4604 24.4816L30.7885 30.0001L30.9223 17.5587L33.4916 15.1779L33.3539 21.0919Z" fill="#2F9872"/>
12
12
  </g>
13
13
  </svg>
14
-
@@ -19,7 +19,7 @@
19
19
  client = MaxClient(
20
20
  phone: str,
21
21
  uri: str = Constants.WEBSOCKET_URI.value,
22
- headers: dict[str, Any] | None = Constants.DEFAULT_USER_AGENT.value,
22
+ headers: dict[str, Any] | None = Constants.DEFAULT_USER_AGENT_PAYLOAD.value,
23
23
  token: str | None = None,
24
24
  send_fake_telemetry: bool = True,
25
25
  host: str = Constants.HOST.value,
@@ -35,7 +35,7 @@ client = MaxClient(
35
35
  |----------|-----|----------|---------------|
36
36
  | `phone` | `str` | Номер телефона для авторизации | - |
37
37
  | `uri` | `str` | URI WebSocket сервера | `Constants.WEBSOCKET_URI.value` |
38
- | `headers` | `dict[str, Any] \| None` | Заголовки для соединения | `Constants.DEFAULT_USER_AGENT.value` |
38
+ | `headers` | `dict[str, Any] \| None` | Заголовки для соединения | `Constants.DEFAULT_USER_AGENT_PAYLOAD.value` |
39
39
  | `token` | `str \| None` | Токен авторизации | `None` |
40
40
  | `send_fake_telemetry` | `bool` | Отправка телеметрии | `True` |
41
41
  | `host` | `str` | Хост API сервера | `Constants.HOST.value` |
@@ -8,14 +8,14 @@ from pymax import MaxClient
8
8
 
9
9
  async def main():
10
10
  client = MaxClient(phone="+79001234567")
11
-
11
+
12
12
  @client.on_message
13
13
  async def echo_handler(message):
14
14
  await client.send_message(
15
15
  chat_id=message.chat_id,
16
16
  text=f"Эхо: {message.text}"
17
17
  )
18
-
18
+
19
19
  await client.start()
20
20
 
21
21
  asyncio.run(main())
@@ -29,7 +29,7 @@ from pymax import MaxClient
29
29
 
30
30
  async def main():
31
31
  client = MaxClient(phone="+79001234567")
32
-
32
+
33
33
  # Словарь ключевых слов и ответов
34
34
  auto_replies = {
35
35
  'привет': 'Привет! Как дела?',
@@ -37,11 +37,11 @@ async def main():
37
37
  'спасибо': 'Пожалуйста!',
38
38
  'время': 'Время ответить на ваш вопрос!',
39
39
  }
40
-
40
+
41
41
  @client.on_message
42
42
  async def auto_reply_handler(message):
43
43
  text = message.text.lower()
44
-
44
+
45
45
  for keyword, reply in auto_replies.items():
46
46
  if keyword in text:
47
47
  await client.send_message(
@@ -49,7 +49,7 @@ async def main():
49
49
  text=reply
50
50
  )
51
51
  break
52
-
52
+
53
53
  await client.start()
54
54
 
55
55
  asyncio.run(main())
@@ -63,14 +63,14 @@ from pymax import MaxClient
63
63
 
64
64
  async def main():
65
65
  client = MaxClient(phone="+79001234567")
66
-
66
+
67
67
  # Запрещенные слова
68
68
  forbidden_words = ['спам', 'реклама', 'взлом']
69
-
69
+
70
70
  @client.on_message
71
71
  async def moderation_handler(message):
72
72
  text = message.text.lower()
73
-
73
+
74
74
  for word in forbidden_words:
75
75
  if word in text:
76
76
  # Удаляем сообщение
@@ -78,14 +78,14 @@ async def main():
78
78
  chat_id=message.chat_id,
79
79
  message_id=message.id
80
80
  )
81
-
81
+
82
82
  # Предупреждаем пользователя
83
83
  await client.send_message(
84
84
  chat_id=message.chat_id,
85
85
  text=f"@{message.author.username}, использование запрещенных слов недопустимо!"
86
86
  )
87
87
  break
88
-
88
+
89
89
  await client.start()
90
90
 
91
91
  asyncio.run(main())
@@ -1,16 +1,13 @@
1
1
  import asyncio
2
- import logging
3
2
 
4
- from pymax import MaxClient, Message, SocketMaxClient
5
- from pymax.files import Photo
3
+ from pymax import MaxClient, Message
6
4
  from pymax.filters import Filter
7
- from pymax.static import AttachType
5
+ from pymax.static.enum import AttachType
8
6
 
9
7
  phone = "+1234567890"
10
8
 
11
9
 
12
10
  client = MaxClient(phone=phone, work_dir="cache")
13
- # client = SocketMaxClient(phone=phone, work_dir="cache")
14
11
 
15
12
 
16
13
  @client.on_message(filter=Filter(chat_id=0))
@@ -31,6 +28,13 @@ async def handle_deleted_message(message: Message) -> None:
31
28
  @client.on_start
32
29
  async def handle_start() -> None:
33
30
  print("Client started successfully!")
31
+ history = await client.fetch_history(chat_id=0)
32
+ if history:
33
+ for message in history:
34
+ if message.attaches:
35
+ for attach in message.attaches:
36
+ if attach.type == AttachType.STICKER:
37
+ print(attach.lottie_url)
34
38
  # chat = await client.rework_invite_link(chat_id=0)
35
39
  # print(chat.link)
36
40
  # text = """
@@ -0,0 +1,202 @@
1
+ import asyncio
2
+ import os
3
+ from io import BytesIO
4
+
5
+ import aiohttp
6
+ from aiogram import Bot, Dispatcher, types
7
+ from dotenv import load_dotenv
8
+
9
+ from pymax import Chat, MaxClient, Message, User
10
+ from pymax.types import FileAttach, PhotoAttach, VideoAttach
11
+
12
+ """
13
+ Зависимости:
14
+
15
+ pip install maxapi-python==1.1.13 aiogram==3.22.0 python-dotenv
16
+
17
+ """
18
+
19
+
20
+ """
21
+ В .env нужно указать:
22
+
23
+ PHONE = "+7123456789" # Твой номер для Max
24
+ BOT_TOKEN = "23456789:AAH0cJ3SNzZ2zzD0uF8HOqmxtKpwsKwggM" # Твой токен Telegram-бота
25
+
26
+ """
27
+
28
+ chats = { # В формате айди чата в Max: айди чата в Telegram
29
+ -68690734055662: -1003177746657,
30
+ }
31
+
32
+
33
+ # Создаём зеркальный массив для отправки из Telegram в Max
34
+ chats_telegram = {value: key for key, value in chats.items()}
35
+
36
+
37
+ # Загружаем .env
38
+ load_dotenv(override=True)
39
+
40
+
41
+ # Настройки из .env
42
+ PHONE = os.getenv("PHONE") # Номер телефона Max
43
+ telegram_bot_TOKEN = os.getenv("BOT_TOKEN") # Токен TG-бота
44
+
45
+
46
+ client = MaxClient(phone=PHONE, work_dir="cache")
47
+
48
+
49
+ # Инициализация TG-бота
50
+ telegram_bot = Bot(token=telegram_bot_TOKEN)
51
+ dp = Dispatcher()
52
+
53
+
54
+ # Обработчик входящих сообщений MAX
55
+ @client.on_message()
56
+ async def handle_message(message: Message) -> None:
57
+ tg_id = chats[message.chat_id]
58
+
59
+ sender = await client.get_user(user_id=message.sender)
60
+
61
+ if message.attaches:
62
+ for attach in message.attaches:
63
+ # Проверка на видео
64
+ if isinstance(attach, VideoAttach):
65
+ async with aiohttp.ClientSession() as session:
66
+ try:
67
+ # Получаем видео по айди
68
+ video = await client.get_video_by_id(
69
+ chat_id=message.chat_id,
70
+ message_id=message.id,
71
+ video_id=attach.video_id,
72
+ )
73
+
74
+ # Загружаем видео по URL
75
+ async with session.get(video.url) as response:
76
+ response.raise_for_status() # Проверка на ошибки HTTP
77
+ video_bytes = BytesIO(await response.read())
78
+ video_bytes.name = response.headers.get("X-File-Name")
79
+
80
+ # Отправляем видео через телеграм бота
81
+ await telegram_bot.send_video(
82
+ chat_id=tg_id,
83
+ caption=f"{sender.names[0].name}: {message.text}",
84
+ video=types.BufferedInputFile(
85
+ video_bytes.getvalue(), filename=video_bytes.name
86
+ ),
87
+ )
88
+
89
+ # Очищаем память
90
+ video_bytes.close()
91
+
92
+ except aiohttp.ClientError as e:
93
+ print(f"Ошибка при загрузке видео: {e}")
94
+ except Exception as e:
95
+ print(f"Ошибка при отправке видео: {e}")
96
+
97
+ # Проверка на изображение
98
+ elif isinstance(attach, PhotoAttach):
99
+ async with aiohttp.ClientSession() as session:
100
+ try:
101
+ # Загружаем изображение по URL
102
+ async with session.get(attach.base_url) as response:
103
+ response.raise_for_status() # Проверка на ошибки HTTP
104
+ photo_bytes = BytesIO(await response.read())
105
+ photo_bytes.name = response.headers.get("X-File-Name")
106
+
107
+ # Отправляем фото через телеграм бота
108
+ await telegram_bot.send_photo(
109
+ chat_id=tg_id,
110
+ caption=f"{sender.names[0].name}: {message.text}",
111
+ photo=types.BufferedInputFile(
112
+ photo_bytes.getvalue(), filename=photo_bytes.name
113
+ ),
114
+ )
115
+
116
+ # Очищаем память
117
+ photo_bytes.close()
118
+
119
+ except aiohttp.ClientError as e:
120
+ print(f"Ошибка при загрузке изображения: {e}")
121
+ except Exception as e:
122
+ print(f"Ошибка при отправке фото: {e}")
123
+
124
+ # Проверка на файл
125
+ elif isinstance(attach, FileAttach):
126
+ async with aiohttp.ClientSession() as session:
127
+ try:
128
+ # Получаем файл по айди
129
+ file = await client.get_file_by_id(
130
+ chat_id=message.chat_id,
131
+ message_id=message.id,
132
+ file_id=attach.file_id,
133
+ )
134
+
135
+ # Загружаем файл по URL
136
+ async with session.get(file.url) as response:
137
+ response.raise_for_status() # Проверка на ошибки HTTP
138
+ file_bytes = BytesIO(await response.read())
139
+ file_bytes.name = response.headers.get("X-File-Name")
140
+
141
+ # Отправляем файл через телеграм бота
142
+ await telegram_bot.send_document(
143
+ chat_id=tg_id,
144
+ caption=f"{sender.names[0].name}: {message.text}",
145
+ document=types.BufferedInputFile(
146
+ file_bytes.getvalue(), filename=file_bytes.name
147
+ ),
148
+ )
149
+
150
+ # Очищаем память
151
+ file_bytes.close()
152
+
153
+ except aiohttp.ClientError as e:
154
+ print(f"Ошибка при загрузке файла: {e}")
155
+ except Exception as e:
156
+ print(f"Ошибка при отправке файла: {e}")
157
+ else:
158
+ await telegram_bot.send_message(
159
+ chat_id=tg_id, text=f"{sender.names[0].name}: {message.text}"
160
+ )
161
+
162
+
163
+ # Обработчик запуска клиента, функция выводит все сообщения из чата "Избранное"
164
+ @client.on_start
165
+ async def handle_start() -> None:
166
+ print("Клиент запущен")
167
+
168
+ # Получение истории сообщений
169
+ history = await client.fetch_history(chat_id=0)
170
+ if history:
171
+ for message in history:
172
+ user = await client.get_user(message.sender)
173
+ if user:
174
+ print(f"{user.names[0].name}: {message.text}")
175
+
176
+
177
+ # Обработчик сообщений Telegram
178
+ @dp.message()
179
+ async def handle_message(message: types.Message, bot: Bot) -> None:
180
+ max_id = chats_telegram[message.chat.id]
181
+ await client.send_message(chat_id=max_id, text=message.text, notify=True)
182
+
183
+
184
+ # Раннер ботов
185
+ async def main() -> None:
186
+ # TG-бот в фоне
187
+ telegram_bot_task = asyncio.create_task(dp.start_polling(telegram_bot))
188
+
189
+ try:
190
+ while True: # Не спрашивайте 😃
191
+ await client.start()
192
+
193
+ finally:
194
+ await client.close()
195
+ telegram_bot_task.cancel()
196
+
197
+
198
+ if __name__ == "__main__":
199
+ try:
200
+ asyncio.run(main())
201
+ except KeyboardInterrupt:
202
+ print("Программа остановлена пользователем.")
@@ -0,0 +1,72 @@
1
+ [project]
2
+ name = "maxapi-python"
3
+ version = "1.1.14"
4
+ description = "Python wrapper для API мессенджера Max"
5
+ readme = "README.md"
6
+ requires-python = ">=3.10"
7
+ authors = [{ name = "ink", email = "mail@gmail.com" }]
8
+ license = "MIT"
9
+ keywords = ["max", "messenger", "api", "wrapper", "websocket"]
10
+ classifiers = [
11
+ "Programming Language :: Python :: 3",
12
+ "Operating System :: OS Independent",
13
+ ]
14
+ dependencies = [
15
+ "sqlmodel>=0.0.24",
16
+ "websockets>=15.0",
17
+ "msgpack>=1.1.1",
18
+ "lz4>=4.4.4",
19
+ "aiohttp>=3.12.15",
20
+ "aiofiles>=24.1.0",
21
+ ]
22
+
23
+ [project.urls]
24
+ Homepage = "https://github.com/ink-developer/PyMax"
25
+ Repository = "https://github.com/ink-developer/PyMax"
26
+ Issues = "https://github.com/ink-developer/PyMax/issues"
27
+
28
+ [build-system]
29
+ requires = ["hatchling"]
30
+ build-backend = "hatchling.build"
31
+
32
+ [tool.setuptools.packages.find]
33
+ where = ["src"]
34
+
35
+ [tool.setuptools.package-dir]
36
+ "" = "src"
37
+
38
+ [dependency-groups]
39
+ dev = [
40
+ "mkdocs>=1.6.1",
41
+ "mkdocs-material>=9.6.18",
42
+ "mkdocstrings[python]>=0.30.0",
43
+ "pre-commit>=4.3.0",
44
+ "pydocstring>=0.2.1",
45
+ ]
46
+
47
+ [tool.hatch.build.targets.wheel]
48
+ packages = ["src/pymax"]
49
+
50
+ [tool.pyright]
51
+ venv = ".venv"
52
+ venvPath = "."
53
+
54
+ [tool.black]
55
+ line-length = 79
56
+ target-version = ['py313']
57
+
58
+ [tool.flake8]
59
+ max-line-length = 79
60
+ max-complexity = 10
61
+
62
+ [tool.mypy]
63
+ python_version = "3.13"
64
+ warn_return_any = true
65
+ warn_unused_configs = true
66
+ plugins = ["sqlalchemy.ext.mypy.plugin", "pydantic.mypy"]
67
+
68
+ [tool.isort]
69
+ profile = "black"
70
+ line_length = 79
71
+ multi_line_output = 3
72
+ include_trailing_comma = true
@@ -73,4 +73,4 @@ docstring-code-format = false
73
73
  #
74
74
  # This only has an effect when the `docstring-code-format` setting is
75
75
  # enabled.
76
- docstring-code-line-length = "dynamic"
76
+ docstring-code-line-length = "dynamic"
@@ -3,16 +3,18 @@ Python wrapper для API мессенджера Max
3
3
  """
4
4
 
5
5
  from .core import (
6
- InvalidPhoneError,
7
6
  MaxClient,
8
7
  SocketMaxClient,
8
+ )
9
+ from .exceptions import (
10
+ InvalidPhoneError,
11
+ LoginError,
9
12
  WebSocketNotConnectedError,
10
13
  )
11
- from .static import (
14
+ from .static.enum import (
12
15
  AccessType,
13
16
  AuthType,
14
17
  ChatType,
15
- Constants,
16
18
  DeviceType,
17
19
  ElementType,
18
20
  MessageStatus,
@@ -38,13 +40,14 @@ __all__ = [
38
40
  "Channel",
39
41
  "Chat",
40
42
  "ChatType",
41
- "Constants",
42
43
  "DeviceType",
43
44
  "Dialog",
44
45
  "Element",
45
46
  "ElementType",
46
47
  # Исключения
47
48
  "InvalidPhoneError",
49
+ "LoginError",
50
+ "WebSocketNotConnectedError",
48
51
  # Клиент
49
52
  "MaxClient",
50
53
  "Message",
@@ -53,5 +56,4 @@ __all__ = [
53
56
  "Opcode",
54
57
  "SocketMaxClient",
55
58
  "User",
56
- "WebSocketNotConnectedError",
57
59
  ]