maxapi-python 1.1.5__py3-none-any.whl → 1.1.7__py3-none-any.whl

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maxapi-python
3
- Version: 1.1.5
3
+ Version: 1.1.7
4
4
  Summary: Python wrapper для API мессенджера Max
5
5
  Project-URL: Homepage, https://github.com/noxzion/PyMax
6
6
  Project-URL: Repository, https://github.com/noxzion/PyMax
@@ -7,22 +7,22 @@ pymax/filters.py,sha256=fxC3Bl5AqrB8BSdN-CtiLWucbHCRA2IODpsOy2NagGU,1471
7
7
  pymax/interfaces.py,sha256=_D6iMQI74Gdtl6-HMoE1acRFRHeITgOZPVFpt5pvoow,2394
8
8
  pymax/models.py,sha256=PsPGbOkERxesZZltjNrmqhOfRcO44Is2ThbEToREcB8,201
9
9
  pymax/navigation.py,sha256=16c1_FZrw24uFlP6W5-F8OrEQE73bkQA3HSFqTdBtgo,5725
10
- pymax/payloads.py,sha256=t-6xM3s8laQqBWyVdcQNV080sjfRsOtbQ-o6CKpAh20,4087
10
+ pymax/payloads.py,sha256=494RYjE3AjRbIrme1hcb2q5WNNcoZF13elqJeSVOW0Q,4158
11
11
  pymax/static.py,sha256=wwSV1ue5s5buqWz6TvCzjzN2ZWI-wITposTRvcS151g,4738
12
- pymax/types.py,sha256=2huOPuGxwka_6s-Fw-7KbeAAoiFJrB7e07ArBKIRA6w,19020
12
+ pymax/types.py,sha256=jaqhh-G2xMVVhpRCqRFat5BecPqNcZIROEGr6YICPFE,19158
13
13
  pymax/utils.py,sha256=F2TdoWfSwDLeh2uIcMIE_GTdXd7hU7gWti2i5P727bA,1364
14
14
  pymax/mixins/__init__.py,sha256=-PSMwTVioS-VTy-EGfV-epaKFLy58R4N2b-rX6wJf-M,649
15
15
  pymax/mixins/auth.py,sha256=vTNSZ6AunvDIMPQAvgYozpIZaCWMYiMDiabCBI7Sm6c,3079
16
16
  pymax/mixins/channel.py,sha256=Stnf63GPtlQnsMPVEC9P0oardEOz50I4DCXN5H5s1SM,823
17
17
  pymax/mixins/group.py,sha256=NFdq6VExTKR80tE9XzVBjuG_eRMKEdYSm2HZop5yPYE,7809
18
18
  pymax/mixins/handler.py,sha256=I1iNPaEgpvFnphaxV6liLwVaBCJ8sN6-h7908-_tPFk,2104
19
- pymax/mixins/message.py,sha256=GtwhoZaX2JPadhE9wq7M0YHBV1V2jbBIFwtQVIWP8sY,12896
19
+ pymax/mixins/message.py,sha256=sIDNpLfCPCPJNq9kZNbNTSnAIs810WI4-E9VpJeGcRU,13386
20
20
  pymax/mixins/self.py,sha256=V0gbkY3jfX9fnd7v06n4_s7P3HTPcS1KNPqUzA0vNi8,1169
21
21
  pymax/mixins/socket.py,sha256=UNMU1Fh9J3xDV76J2Mx8bVHXo0gcS81qocOw8MM0XXs,15643
22
22
  pymax/mixins/telemetry.py,sha256=0sQl6kvFVxobLthNAPNS9LzMrwwzZFA1xmOnvfiHWos,3522
23
- pymax/mixins/user.py,sha256=U-epgvLruTDHBCrLDE0N0iWeOypGE1_SU8cKD3TE90U,3045
23
+ pymax/mixins/user.py,sha256=VgAylqEeWMzgPaScakozZ1Wx0NwEnwVJLt1DtUbWaoM,4276
24
24
  pymax/mixins/websocket.py,sha256=L958bXTYh6U89jnmd0VWIUVtmJweUVFOMqjEuH8jWGo,10079
25
- maxapi_python-1.1.5.dist-info/METADATA,sha256=k2lznWoJb4fgMJg_abFlOXE064a5_eZjbMDknokgZh8,5930
26
- maxapi_python-1.1.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
27
- maxapi_python-1.1.5.dist-info/licenses/LICENSE,sha256=oe-AGp86WMKawV4KmqF28Q0m-kGAhPfAOPrEUm4MnVw,1064
28
- maxapi_python-1.1.5.dist-info/RECORD,,
25
+ maxapi_python-1.1.7.dist-info/METADATA,sha256=WRYdT7ZWOChOvAnNW6R5TK-gu8Q71MC46jL9j5fmBP0,5930
26
+ maxapi_python-1.1.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
27
+ maxapi_python-1.1.7.dist-info/licenses/LICENSE,sha256=oe-AGp86WMKawV4KmqF28Q0m-kGAhPfAOPrEUm4MnVw,1064
28
+ maxapi_python-1.1.7.dist-info/RECORD,,
pymax/mixins/message.py CHANGED
@@ -10,16 +10,16 @@ from pymax.payloads import (
10
10
  DeleteMessagePayload,
11
11
  EditMessagePayload,
12
12
  FetchHistoryPayload,
13
+ GetFilePayload,
14
+ GetVideoPayload,
13
15
  PinMessagePayload,
14
16
  ReplyLink,
15
17
  SendMessagePayload,
16
18
  SendMessagePayloadMessage,
17
19
  UploadPhotoPayload,
18
- GetVideoPayload,
19
- GetFilePayload,
20
20
  )
21
21
  from pymax.static import AttachType, Opcode
22
- from pymax.types import Attach, Message, FileRequest, VideoRequest
22
+ from pymax.types import Attach, FileRequest, Message, VideoRequest
23
23
 
24
24
 
25
25
  class MessageMixin(ClientProtocol):
@@ -143,7 +143,6 @@ class MessageMixin(ClientProtocol):
143
143
  data = await self._send_and_wait(opcode=Opcode.MSG_SEND, payload=payload)
144
144
  if error := data.get("payload", {}).get("error"):
145
145
  self.logger.error("Send message error: %s", error)
146
- print(data)
147
146
  return None
148
147
  msg = Message.from_dict(data["payload"]) if data.get("payload") else None
149
148
  self.logger.debug("send_message result: %r", msg)
@@ -286,12 +285,11 @@ class MessageMixin(ClientProtocol):
286
285
  self.logger.exception("Fetch history failed")
287
286
  return None
288
287
 
289
-
290
288
  async def get_video_by_id(
291
289
  self,
292
290
  chat_id: int,
293
291
  message_id: int,
294
- video_id: str,
292
+ video_id: int,
295
293
  ) -> VideoRequest | None:
296
294
  """
297
295
  Получает видео
@@ -307,33 +305,37 @@ class MessageMixin(ClientProtocol):
307
305
  url (str): Ссылка на видео
308
306
  """
309
307
  try:
310
- self.logger.info(
311
- "Getting video_id=%s message_id=%s", video_id, message_id
312
- )
308
+ self.logger.info("Getting video_id=%s message_id=%s", video_id, message_id)
313
309
 
314
- payload = GetVideoPayload(
315
- chat_id=chat_id,
316
- message_id=message_id,
317
- video_id=video_id
318
- ).model_dump(by_alias=True)
310
+ if self.is_connected and self._socket is not None:
311
+ payload = GetVideoPayload(
312
+ chat_id=chat_id, message_id=message_id, video_id=video_id
313
+ ).model_dump(by_alias=True)
314
+ else:
315
+ payload = GetVideoPayload(
316
+ chat_id=chat_id, message_id=str(message_id), video_id=video_id
317
+ ).model_dump(by_alias=True)
319
318
 
320
319
  data = await self._send_and_wait(opcode=Opcode.VIDEO_PLAY, payload=payload)
321
320
 
322
321
  if error := data.get("payload", {}).get("error"):
323
322
  self.logger.error("Get video error: %s", error)
324
-
325
- video = VideoRequest.from_dict(data["payload"]) if data.get("payload") else None
326
- self.logger.debug(" result: %r", video)
323
+ return
324
+
325
+ video = (
326
+ VideoRequest.from_dict(data["payload"]) if data.get("payload") else None
327
+ )
328
+ self.logger.debug("result: %r", video)
327
329
  return video
328
330
  except Exception:
329
331
  self.logger.exception("Get video error")
330
332
  return None
331
-
333
+
332
334
  async def get_file_by_id(
333
335
  self,
334
336
  chat_id: int,
335
337
  message_id: int,
336
- file_id: str,
338
+ file_id: int,
337
339
  ) -> FileRequest | None:
338
340
  """
339
341
  Получает файл
@@ -348,20 +350,28 @@ class MessageMixin(ClientProtocol):
348
350
  url (str): Ссылка на скачивание файла
349
351
  """
350
352
  try:
351
- self.logger.info(
352
- "Getting file_id=%s message_id=%s", file_id, message_id
353
+ self.logger.info("Getting file_id=%s message_id=%s", file_id, message_id)
354
+ if self.is_connected and self._socket is not None:
355
+ payload = GetFilePayload(
356
+ chat_id=chat_id, message_id=message_id, file_id=file_id
357
+ ).model_dump(by_alias=True)
358
+ else:
359
+ payload = GetFilePayload(
360
+ chat_id=chat_id, message_id=str(message_id), file_id=file_id
361
+ ).model_dump(by_alias=True)
362
+ data = await self._send_and_wait(
363
+ opcode=Opcode.FILE_DOWNLOAD, payload=payload
353
364
  )
354
- payload = GetFilePayload(
355
- chat_id=chat_id,
356
- message_id=message_id,
357
- file_id=file_id
358
- ).model_dump(by_alias=True)
359
- data = await self._send_and_wait(opcode=Opcode.FILE_DOWNLOAD, payload=payload)
365
+
360
366
  if error := data.get("payload", {}).get("error"):
361
367
  self.logger.error("Get file error: %s", error)
362
- file = FileRequest.from_dict(data["payload"]) if data.get("payload") else None
368
+ return
369
+
370
+ file = (
371
+ FileRequest.from_dict(data["payload"]) if data.get("payload") else None
372
+ )
363
373
  self.logger.debug(" result: %r", file)
364
374
  return file
365
375
  except Exception:
366
376
  self.logger.exception("Get video error")
367
- return None
377
+ return None
pymax/mixins/user.py CHANGED
@@ -1,5 +1,5 @@
1
1
  from pymax.interfaces import ClientProtocol
2
- from pymax.payloads import FetchContactsPayload
2
+ from pymax.payloads import FetchContactsPayload, SearchByPhonePayload
3
3
  from pymax.static import Opcode
4
4
  from pymax.types import User
5
5
 
@@ -80,3 +80,38 @@ class UserMixin(ClientProtocol):
80
80
  except Exception:
81
81
  self.logger.exception("Fetch users failed")
82
82
  return []
83
+
84
+ async def search_by_phone(self, phone: str) -> User | None:
85
+ """
86
+ Ищет пользователя по номеру телефона.
87
+
88
+ Args:
89
+ phone (str): Номер телефона.
90
+
91
+ Returns:
92
+ User | None: Объект User или None при ошибке.
93
+ """
94
+ try:
95
+ self.logger.info("Searching user by phone: %s", phone)
96
+
97
+ payload = SearchByPhonePayload(phone=phone).model_dump(by_alias=True)
98
+
99
+ data = await self._send_and_wait(
100
+ opcode=Opcode.CONTACT_INFO_BY_PHONE, payload=payload
101
+ )
102
+ if error := data.get("payload", {}).get("error"):
103
+ self.logger.error("Search by phone error: %s", error)
104
+ return None
105
+
106
+ user = (
107
+ User.from_dict(data["payload"]["contact"])
108
+ if data.get("payload")
109
+ else None
110
+ )
111
+ if user:
112
+ self._users[user.id] = user
113
+ self.logger.debug("Found user by phone: %s", user)
114
+ return user
115
+ except Exception:
116
+ self.logger.exception("Search by phone failed")
117
+ return None
pymax/payloads.py CHANGED
@@ -194,12 +194,18 @@ class NavigationEventPayload(CamelModel):
194
194
  class NavigationPayload(CamelModel):
195
195
  events: list[NavigationEventPayload]
196
196
 
197
+
197
198
  class GetVideoPayload(CamelModel):
198
199
  chat_id: int
199
- message_id: str
200
+ message_id: int | str
200
201
  video_id: int
201
202
 
203
+
202
204
  class GetFilePayload(CamelModel):
203
205
  chat_id: int
204
- message_id: str
206
+ message_id: str | int
205
207
  file_id: int
208
+
209
+
210
+ class SearchByPhonePayload(CamelModel):
211
+ phone: str
pymax/types.py CHANGED
@@ -181,7 +181,7 @@ class FileRequest:
181
181
  return cls(
182
182
  unsafe=data["unsafe"],
183
183
  url=data["url"],
184
- )
184
+ )
185
185
 
186
186
 
187
187
  class VideoRequest:
@@ -197,15 +197,16 @@ class VideoRequest:
197
197
 
198
198
  @classmethod
199
199
  def from_dict(cls, data: dict[str, Any]) -> "VideoRequest":
200
-
201
- listdata = list(data.values()) # Костыль
202
-
200
+ # listdata = list(data.values()) # Костыль ✅
201
+ url = [v for k, v in data.items() if k not in ("EXTERNAL", "cache")][
202
+ 0
203
+ ] # Еще больший костыль ✅
203
204
  return cls(
204
205
  external=data["EXTERNAL"],
205
206
  cache=data["cache"],
206
- url=listdata[2],
207
- )
208
-
207
+ url=url,
208
+ )
209
+
209
210
 
210
211
  class Me:
211
212
  def __init__(