maxapi-python 1.1.12__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 (56) hide show
  1. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/.github/ISSUE_TEMPLATE/bug_report.md +3 -3
  2. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/.github/workflows/publish.yml +1 -1
  3. {maxapi_python-1.1.12 → 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.12 → maxapi_python-1.1.14}/LICENSE +1 -1
  6. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/PKG-INFO +20 -20
  7. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/README.md +15 -15
  8. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/assets/icon.svg +0 -1
  9. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/assets/logo.svg +0 -1
  10. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/docs/assets/icon.svg +0 -1
  11. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/docs/client.md +2 -2
  12. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/docs/examples.md +11 -11
  13. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/docs/index.md +2 -2
  14. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/examples/example.py +24 -10
  15. maxapi_python-1.1.14/examples/telegram_bridge.py +202 -0
  16. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/mkdocs.yml +1 -1
  17. maxapi_python-1.1.14/pyproject.toml +72 -0
  18. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/ruff.toml +1 -1
  19. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/src/pymax/__init__.py +8 -6
  20. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/src/pymax/core.py +20 -48
  21. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/src/pymax/crud.py +10 -9
  22. maxapi_python-1.1.14/src/pymax/exceptions.py +66 -0
  23. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/src/pymax/files.py +13 -4
  24. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/src/pymax/filters.py +8 -3
  25. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/src/pymax/formatting.py +4 -4
  26. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/src/pymax/interfaces.py +15 -15
  27. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/src/pymax/mixins/auth.py +23 -5
  28. maxapi_python-1.1.14/src/pymax/mixins/channel.py +115 -0
  29. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/src/pymax/mixins/group.py +30 -10
  30. maxapi_python-1.1.14/src/pymax/mixins/handler.py +114 -0
  31. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/src/pymax/mixins/message.py +79 -32
  32. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/src/pymax/mixins/self.py +4 -2
  33. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/src/pymax/mixins/socket.py +169 -66
  34. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/src/pymax/mixins/telemetry.py +11 -6
  35. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/src/pymax/mixins/user.py +23 -1
  36. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/src/pymax/mixins/websocket.py +112 -44
  37. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/src/pymax/navigation.py +3 -1
  38. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/src/pymax/payloads.py +39 -8
  39. maxapi_python-1.1.14/src/pymax/static/constant.py +26 -0
  40. maxapi_python-1.1.12/src/pymax/static.py → maxapi_python-1.1.14/src/pymax/static/enum.py +14 -35
  41. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/src/pymax/types.py +310 -40
  42. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/src/pymax/utils.py +11 -3
  43. maxapi_python-1.1.12/pyproject.toml +0 -50
  44. maxapi_python-1.1.12/scripts/build.py +0 -47
  45. maxapi_python-1.1.12/src/pymax/exceptions.py +0 -29
  46. maxapi_python-1.1.12/src/pymax/mixins/channel.py +0 -25
  47. maxapi_python-1.1.12/src/pymax/mixins/handler.py +0 -61
  48. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/.github/FUNDING.yml +0 -0
  49. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  50. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/.github/ISSUE_TEMPLATE/refactor.md +0 -0
  51. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/.github/pull_request_template.md +0 -0
  52. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/docs/api.md +0 -0
  53. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/docs/methods.md +0 -0
  54. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/docs/types.md +0 -0
  55. {maxapi_python-1.1.12 → maxapi_python-1.1.14}/src/pymax/mixins/__init__.py +0 -0
  56. {maxapi_python-1.1.12 → 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
  MIT License
2
2
 
3
- Copyright (c) 2025 noxzion
3
+ Copyright (c) 2025 ink-developer
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maxapi-python
3
- Version: 1.1.12
3
+ Version: 1.1.14
4
4
  Summary: Python wrapper для API мессенджера Max
5
- Project-URL: Homepage, https://github.com/noxzion/PyMax
6
- Project-URL: Repository, https://github.com/noxzion/PyMax
7
- Project-URL: Issues, https://github.com/noxzion/PyMax/issues
8
- Author-email: noxzion <mail@gmail.com>
5
+ Project-URL: Homepage, https://github.com/ink-developer/PyMax
6
+ Project-URL: Repository, https://github.com/ink-developer/PyMax
7
+ Project-URL: Issues, https://github.com/ink-developer/PyMax/issues
8
+ Author-email: ink <mail@gmail.com>
9
9
  License-Expression: MIT
10
10
  License-File: LICENSE
11
11
  Keywords: api,max,messenger,websocket,wrapper
@@ -37,7 +37,7 @@ Description-Content-Type: text/markdown
37
37
 
38
38
  ---
39
39
  > ⚠️ **Дисклеймер**
40
- >
40
+ >
41
41
  > * Это **неофициальная** библиотека для работы с внутренним API Max.
42
42
  > * Использование может **нарушать условия предоставления услуг** сервиса.
43
43
  > * **Вы используете её исключительно на свой страх и риск.**
@@ -94,7 +94,7 @@ async def handle_message(message: Message) -> None:
94
94
  @client.on_start
95
95
  async def handle_start() -> None:
96
96
  print("Клиент запущен")
97
-
97
+
98
98
  # Получение истории сообщений
99
99
  history = await client.fetch_history(chat_id=0)
100
100
  if history:
@@ -105,38 +105,38 @@ async def handle_start() -> None:
105
105
 
106
106
  async def main() -> None:
107
107
  await client.start()
108
-
108
+
109
109
  # Работа с чатами
110
110
  for chat in client.chats:
111
111
  print(f"Чат: {chat.title}")
112
-
112
+
113
113
  # Отправка сообщения
114
114
  message = await client.send_message(
115
- "Привет от PyMax!",
116
- chat.id,
115
+ "Привет от PyMax!",
116
+ chat.id,
117
117
  notify=True
118
118
  )
119
-
119
+
120
120
  # Редактирование сообщения
121
121
  await asyncio.sleep(2)
122
122
  await client.edit_message(
123
- chat.id,
124
- message.id,
123
+ chat.id,
124
+ message.id,
125
125
  "Привет от PyMax! (отредактировано)"
126
126
  )
127
-
127
+
128
128
  # Удаление сообщения
129
129
  await asyncio.sleep(2)
130
130
  await client.delete_message(chat.id, [message.id], for_me=False)
131
-
131
+
132
132
  # Работа с диалогами
133
133
  for dialog in client.dialogs:
134
134
  print(f"Диалог: {dialog.last_message.text}")
135
-
135
+
136
136
  # Работа с каналами
137
137
  for channel in client.channels:
138
138
  print(f"Канал: {channel.title}")
139
-
139
+
140
140
  await client.close()
141
141
 
142
142
  if __name__ == "__main__":
@@ -145,7 +145,7 @@ if __name__ == "__main__":
145
145
 
146
146
  ## Документация
147
147
 
148
- [WIP](https://noxzion.github.io/)
148
+ [WIP](https://ink-developer.github.io/)
149
149
 
150
150
  ## Лицензия
151
151
 
@@ -157,7 +157,7 @@ if __name__ == "__main__":
157
157
 
158
158
  ## Авторы
159
159
 
160
- - **[noxzion](https://github.com/noxzion)** — Оригинальный автор проекта
160
+ - **[ink-developer](https://github.com/ink-developer)** — Оригинальный автор проекта
161
161
  - **[ink](https://github.com/ink-developer)** — Главный разработчик, исследование API и его документация
162
162
 
163
163
  ## Контрибьюторы
@@ -15,7 +15,7 @@
15
15
 
16
16
  ---
17
17
  > ⚠️ **Дисклеймер**
18
- >
18
+ >
19
19
  > * Это **неофициальная** библиотека для работы с внутренним API Max.
20
20
  > * Использование может **нарушать условия предоставления услуг** сервиса.
21
21
  > * **Вы используете её исключительно на свой страх и риск.**
@@ -72,7 +72,7 @@ async def handle_message(message: Message) -> None:
72
72
  @client.on_start
73
73
  async def handle_start() -> None:
74
74
  print("Клиент запущен")
75
-
75
+
76
76
  # Получение истории сообщений
77
77
  history = await client.fetch_history(chat_id=0)
78
78
  if history:
@@ -83,38 +83,38 @@ async def handle_start() -> None:
83
83
 
84
84
  async def main() -> None:
85
85
  await client.start()
86
-
86
+
87
87
  # Работа с чатами
88
88
  for chat in client.chats:
89
89
  print(f"Чат: {chat.title}")
90
-
90
+
91
91
  # Отправка сообщения
92
92
  message = await client.send_message(
93
- "Привет от PyMax!",
94
- chat.id,
93
+ "Привет от PyMax!",
94
+ chat.id,
95
95
  notify=True
96
96
  )
97
-
97
+
98
98
  # Редактирование сообщения
99
99
  await asyncio.sleep(2)
100
100
  await client.edit_message(
101
- chat.id,
102
- message.id,
101
+ chat.id,
102
+ message.id,
103
103
  "Привет от PyMax! (отредактировано)"
104
104
  )
105
-
105
+
106
106
  # Удаление сообщения
107
107
  await asyncio.sleep(2)
108
108
  await client.delete_message(chat.id, [message.id], for_me=False)
109
-
109
+
110
110
  # Работа с диалогами
111
111
  for dialog in client.dialogs:
112
112
  print(f"Диалог: {dialog.last_message.text}")
113
-
113
+
114
114
  # Работа с каналами
115
115
  for channel in client.channels:
116
116
  print(f"Канал: {channel.title}")
117
-
117
+
118
118
  await client.close()
119
119
 
120
120
  if __name__ == "__main__":
@@ -123,7 +123,7 @@ if __name__ == "__main__":
123
123
 
124
124
  ## Документация
125
125
 
126
- [WIP](https://noxzion.github.io/)
126
+ [WIP](https://ink-developer.github.io/)
127
127
 
128
128
  ## Лицензия
129
129
 
@@ -135,7 +135,7 @@ if __name__ == "__main__":
135
135
 
136
136
  ## Авторы
137
137
 
138
- - **[noxzion](https://github.com/noxzion)** — Оригинальный автор проекта
138
+ - **[ink-developer](https://github.com/ink-developer)** — Оригинальный автор проекта
139
139
  - **[ink](https://github.com/ink-developer)** — Главный разработчик, исследование API и его документация
140
140
 
141
141
  ## Контрибьюторы
@@ -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())
@@ -39,6 +39,6 @@ uv add -U maxapi-python
39
39
 
40
40
  ## Ссылки
41
41
 
42
- - [GitHub](https://github.com/noxzion/PyMax)
42
+ - [GitHub](https://github.com/ink-developer/PyMax)
43
43
  - [PyPI](https://pypi.org/project/pymax/)
44
- - [Issues](https://github.com/noxzion/PyMax/issues)
44
+ - [Issues](https://github.com/ink-developer/PyMax/issues)
@@ -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))
@@ -18,9 +15,26 @@ async def handle_message(message: Message) -> None:
18
15
  print(str(message.sender) + ": " + message.text)
19
16
 
20
17
 
18
+ @client.on_message_edit()
19
+ async def handle_edited_message(message: Message) -> None:
20
+ print(f"Edited message in chat {message.chat_id}: {message.text}")
21
+
22
+
23
+ @client.on_message_delete()
24
+ async def handle_deleted_message(message: Message) -> None:
25
+ print(f"Deleted message in chat {message.chat_id}: {message.id}")
26
+
27
+
21
28
  @client.on_start
22
29
  async def handle_start() -> None:
23
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)
24
38
  # chat = await client.rework_invite_link(chat_id=0)
25
39
  # print(chat.link)
26
40
  # text = """
@@ -78,12 +92,12 @@ async def handle_start() -> None:
78
92
  # print(client.me.names[0].first_name)
79
93
  # user = await client.get_user(client.me.id)
80
94
 
81
- photo1 = Photo(path="tests/test.jpeg")
82
- photo2 = Photo(path="tests/test.jpg")
95
+ # photo1 = Photo(path="tests/test.jpeg")
96
+ # photo2 = Photo(path="tests/test.jpg")
83
97
 
84
- await client.send_message(
85
- "Hello with photo!", chat_id=0, photos=[photo1, photo2], notify=True
86
- )
98
+ # await client.send_message(
99
+ # "Hello with photo!", chat_id=0, photos=[photo1, photo2], notify=True
100
+ # )
87
101
 
88
102
 
89
103
  if __name__ == "__main__":
@@ -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("Программа остановлена пользователем.")
@@ -150,6 +150,6 @@ markdown_extensions:
150
150
  extra:
151
151
  social:
152
152
  - icon: fontawesome/brands/github
153
- link: https://github.com/noxzion/PyMax
153
+ link: https://github.com/ink-developer/PyMax
154
154
  - icon: fontawesome/brands/python
155
155
  link: https://pypi.org/project/maxapi-python