maxapi-python 1.1.21__tar.gz → 1.2.2__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.
- maxapi_python-1.2.2/.github/workflows/tests.yml +153 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/.gitignore +1 -1
- maxapi_python-1.1.21/README.md → maxapi_python-1.2.2/PKG-INFO +66 -0
- maxapi_python-1.1.21/PKG-INFO → maxapi_python-1.2.2/README.md +36 -22
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/examples/example.py +2 -6
- maxapi_python-1.2.2/examples/test.py +20 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/pyproject.toml +54 -1
- maxapi_python-1.2.2/pytest.ini +26 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/redocs/source/clients.rst +22 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/src/pymax/core.py +14 -152
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/src/pymax/crud.py +1 -1
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/src/pymax/formatting.py +4 -6
- maxapi_python-1.2.2/src/pymax/interfaces.py +256 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/src/pymax/mixins/auth.py +162 -20
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/src/pymax/mixins/socket.py +30 -43
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/src/pymax/mixins/websocket.py +7 -16
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/src/pymax/payloads.py +29 -14
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/src/pymax/static/constant.py +2 -2
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/src/pymax/static/enum.py +4 -0
- maxapi_python-1.1.21/pytest.ini +0 -6
- maxapi_python-1.1.21/src/pymax/interfaces.py +0 -122
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/.coderabbit.yaml +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/.github/FUNDING.yml +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/.github/ISSUE_TEMPLATE/refactor.md +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/.github/pull_request_template.md +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/.github/workflows/publish.yml +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/.pre-commit-config.yaml +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/LICENSE +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/assets/icon.svg +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/assets/logo.svg +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/examples/flt_test.py +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/examples/large_file_upload.py +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/examples/reg.py +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/examples/telegram_bridge.py +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/mkdocs.yml +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/redocs/Makefile +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/redocs/build.sh +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/redocs/make.bat +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/redocs/source/_static/logo.svg +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/redocs/source/conf.py +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/redocs/source/decorators.rst +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/redocs/source/examples.rst +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/redocs/source/guides.rst +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/redocs/source/index.rst +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/redocs/source/installation.rst +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/redocs/source/quickstart.rst +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/redocs/source/types.rst +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/ruff.toml +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/src/pymax/__init__.py +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/src/pymax/exceptions.py +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/src/pymax/files.py +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/src/pymax/filters.py +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/src/pymax/formatter.py +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/src/pymax/mixins/__init__.py +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/src/pymax/mixins/channel.py +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/src/pymax/mixins/group.py +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/src/pymax/mixins/handler.py +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/src/pymax/mixins/message.py +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/src/pymax/mixins/scheduler.py +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/src/pymax/mixins/self.py +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/src/pymax/mixins/telemetry.py +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/src/pymax/mixins/user.py +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/src/pymax/mixins/utils.py +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/src/pymax/models.py +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/src/pymax/navigation.py +0 -0
- {maxapi_python-1.1.21 → maxapi_python-1.2.2}/src/pymax/types.py +0 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
#on:
|
|
4
|
+
# push:
|
|
5
|
+
# branches: [ main, develop ]
|
|
6
|
+
# pull_request:
|
|
7
|
+
# branches: [ main, develop ]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
fail-fast: false
|
|
14
|
+
matrix:
|
|
15
|
+
python-version: ['3.10', '3.11', '3.12', '3.13']
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- name: Checkout repository
|
|
19
|
+
uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
22
|
+
uses: actions/setup-python@v5
|
|
23
|
+
with:
|
|
24
|
+
python-version: ${{ matrix.python-version }}
|
|
25
|
+
|
|
26
|
+
- name: Cache pip packages
|
|
27
|
+
uses: actions/cache@v4
|
|
28
|
+
with:
|
|
29
|
+
path: ~/.cache/pip
|
|
30
|
+
key: ${{ runner.os }}-pip-${{ hashFiles('**/pyproject.toml') }}
|
|
31
|
+
restore-keys: |
|
|
32
|
+
${{ runner.os }}-pip-
|
|
33
|
+
|
|
34
|
+
- name: Install runtime + test tools
|
|
35
|
+
run: |
|
|
36
|
+
python -m pip install --upgrade pip
|
|
37
|
+
# Устанавливаем package (runtime deps)
|
|
38
|
+
pip install -e "."
|
|
39
|
+
# Явно ставим инструменты для тестов/линта, чтобы они были доступны в runner
|
|
40
|
+
pip install pytest pytest-asyncio pytest-cov pytest-timeout flake8 mypy
|
|
41
|
+
|
|
42
|
+
- name: Lint with flake8
|
|
43
|
+
run: |
|
|
44
|
+
flake8 src/pymax tests \
|
|
45
|
+
--count \
|
|
46
|
+
--select=E9,F63,F7,F82 \
|
|
47
|
+
--show-source \
|
|
48
|
+
--statistics
|
|
49
|
+
flake8 src/pymax tests \
|
|
50
|
+
--count \
|
|
51
|
+
--exit-zero \
|
|
52
|
+
--max-complexity=10 \
|
|
53
|
+
--max-line-length=79 \
|
|
54
|
+
--statistics
|
|
55
|
+
continue-on-error: true
|
|
56
|
+
|
|
57
|
+
- name: Type check with mypy
|
|
58
|
+
run: |
|
|
59
|
+
mypy src/pymax \
|
|
60
|
+
--ignore-missing-imports \
|
|
61
|
+
--no-error-summary
|
|
62
|
+
continue-on-error: true
|
|
63
|
+
|
|
64
|
+
- name: Run unit tests
|
|
65
|
+
run: |
|
|
66
|
+
pytest -m "not mockserver" \
|
|
67
|
+
--cov=src/pymax \
|
|
68
|
+
--cov-report=xml \
|
|
69
|
+
--cov-report=term-missing
|
|
70
|
+
|
|
71
|
+
- name: Upload coverage to Codecov
|
|
72
|
+
uses: codecov/codecov-action@v4
|
|
73
|
+
with:
|
|
74
|
+
files: coverage.xml
|
|
75
|
+
flags: unittests
|
|
76
|
+
name: codecov-umbrella
|
|
77
|
+
fail_ci_if_error: false
|
|
78
|
+
|
|
79
|
+
- name: Archive pytest cache
|
|
80
|
+
if: always()
|
|
81
|
+
uses: actions/upload-artifact@v4
|
|
82
|
+
with:
|
|
83
|
+
name: pytest-cache-${{ matrix.python-version }}
|
|
84
|
+
path: .pytest_cache/
|
|
85
|
+
retention-days: 5
|
|
86
|
+
|
|
87
|
+
integration-tests:
|
|
88
|
+
runs-on: ubuntu-latest
|
|
89
|
+
|
|
90
|
+
steps:
|
|
91
|
+
- name: Checkout repository (with submodules)
|
|
92
|
+
uses: actions/checkout@v4
|
|
93
|
+
with:
|
|
94
|
+
submodules: recursive
|
|
95
|
+
|
|
96
|
+
- name: Set up Python
|
|
97
|
+
uses: actions/setup-python@v5
|
|
98
|
+
with:
|
|
99
|
+
python-version: '3.13'
|
|
100
|
+
|
|
101
|
+
- name: Install runtime + test tools (integration)
|
|
102
|
+
run: |
|
|
103
|
+
python -m pip install --upgrade pip
|
|
104
|
+
pip install -e "."
|
|
105
|
+
pip install pytest pytest-asyncio pytest-cov pytest-timeout flake8 mypy
|
|
106
|
+
|
|
107
|
+
- name: Set up Go
|
|
108
|
+
uses: actions/setup-go@v5
|
|
109
|
+
with:
|
|
110
|
+
go-version: '1.22'
|
|
111
|
+
|
|
112
|
+
- name: Start MockServer
|
|
113
|
+
run: |
|
|
114
|
+
git clone https://github.com/fresh-milkshake/gomax-prerelease.git
|
|
115
|
+
cd gomax-prerelease/mockserver
|
|
116
|
+
go mod download
|
|
117
|
+
go run cmd/server/main.go &
|
|
118
|
+
sleep 3
|
|
119
|
+
|
|
120
|
+
- name: Run integration tests
|
|
121
|
+
run: |
|
|
122
|
+
pytest -m mockserver -v --tb=short
|
|
123
|
+
continue-on-error: true
|
|
124
|
+
env:
|
|
125
|
+
MOCKSERVER_WS_URL: ws://localhost:8080/
|
|
126
|
+
MOCKSERVER_HTTP_URL: http://localhost:8080
|
|
127
|
+
|
|
128
|
+
code-quality:
|
|
129
|
+
runs-on: ubuntu-latest
|
|
130
|
+
|
|
131
|
+
steps:
|
|
132
|
+
- name: Checkout repository
|
|
133
|
+
uses: actions/checkout@v4
|
|
134
|
+
|
|
135
|
+
- name: Set up Python
|
|
136
|
+
uses: actions/setup-python@v5
|
|
137
|
+
with:
|
|
138
|
+
python-version: '3.13'
|
|
139
|
+
|
|
140
|
+
- name: Install dependencies + quality tools
|
|
141
|
+
run: |
|
|
142
|
+
python -m pip install --upgrade pip
|
|
143
|
+
pip install -e "."
|
|
144
|
+
# black/isort/pylint используются только в этом job
|
|
145
|
+
pip install black isort pylint
|
|
146
|
+
|
|
147
|
+
- name: Check code formatting with black
|
|
148
|
+
run: black --check src/pymax tests
|
|
149
|
+
continue-on-error: true
|
|
150
|
+
|
|
151
|
+
- name: Check import sorting with isort
|
|
152
|
+
run: isort --check-only src/pymax tests
|
|
153
|
+
continue-on-error: true
|
|
@@ -116,7 +116,7 @@ cache/
|
|
|
116
116
|
# Keep lockfiles and important configs tracked? If you want to track specific lockfiles,
|
|
117
117
|
# remove them from this .gitignore (for example: remove poetry.lock or uv.lock).
|
|
118
118
|
tests2/
|
|
119
|
-
tests
|
|
119
|
+
tests
|
|
120
120
|
|
|
121
121
|
|
|
122
122
|
# Bad dev's requirements
|
|
@@ -1,3 +1,33 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: maxapi-python
|
|
3
|
+
Version: 1.2.2
|
|
4
|
+
Summary: Python wrapper для API мессенджера Max
|
|
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
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: api,max,messenger,websocket,wrapper
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Requires-Python: >=3.10
|
|
15
|
+
Requires-Dist: aiofiles>=24.1.0
|
|
16
|
+
Requires-Dist: aiohttp>=3.12.15
|
|
17
|
+
Requires-Dist: lz4>=4.4.4
|
|
18
|
+
Requires-Dist: msgpack>=1.1.1
|
|
19
|
+
Requires-Dist: qrcode>=8.2
|
|
20
|
+
Requires-Dist: sqlmodel>=0.0.24
|
|
21
|
+
Requires-Dist: websockets>=15.0
|
|
22
|
+
Provides-Extra: test
|
|
23
|
+
Requires-Dist: flake8; extra == 'test'
|
|
24
|
+
Requires-Dist: mypy; extra == 'test'
|
|
25
|
+
Requires-Dist: pytest-asyncio>=0.24.0; extra == 'test'
|
|
26
|
+
Requires-Dist: pytest-cov>=5.0.0; extra == 'test'
|
|
27
|
+
Requires-Dist: pytest-timeout>=2.1.0; extra == 'test'
|
|
28
|
+
Requires-Dist: pytest>=8.0.0; extra == 'test'
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
1
31
|
<p align="center">
|
|
2
32
|
<img src="assets/logo.svg" alt="PyMax" width="400">
|
|
3
33
|
</p>
|
|
@@ -13,6 +43,7 @@
|
|
|
13
43
|
<img src="https://img.shields.io/badge/packaging-uv-D7FF64.svg" alt="Packaging">
|
|
14
44
|
</p>
|
|
15
45
|
|
|
46
|
+
|
|
16
47
|
---
|
|
17
48
|
> ⚠️ **Дисклеймер**
|
|
18
49
|
>
|
|
@@ -53,6 +84,41 @@ uv add -U maxapi-python
|
|
|
53
84
|
|
|
54
85
|
## Быстрый старт
|
|
55
86
|
|
|
87
|
+
### Аутентификация (`device_type`)
|
|
88
|
+
|
|
89
|
+
> [!IMPORTANT]
|
|
90
|
+
> Параметр `device_type` в `UserAgentPayload` **критически важен** для выбора способа авторизации:
|
|
91
|
+
|
|
92
|
+
**Вход по номеру телефона (DESKTOP):**
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
from pymax import MaxClient
|
|
96
|
+
from pymax.payloads import UserAgentPayload
|
|
97
|
+
|
|
98
|
+
ua = UserAgentPayload(device_type="DESKTOP", app_version="25.12.13")
|
|
99
|
+
|
|
100
|
+
client = MaxClient(
|
|
101
|
+
phone="+79111111111",
|
|
102
|
+
work_dir="cache",
|
|
103
|
+
headers=ua,
|
|
104
|
+
)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**Вход через QR-код (WEB)** — токен совместим с веб-версией Max:
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
from pymax import MaxClient
|
|
111
|
+
from pymax.payloads import UserAgentPayload
|
|
112
|
+
|
|
113
|
+
ua = UserAgentPayload(device_type="WEB", app_version="25.12.13")
|
|
114
|
+
|
|
115
|
+
client = MaxClient(
|
|
116
|
+
phone="+7911111111",
|
|
117
|
+
work_dir="cache",
|
|
118
|
+
headers=ua,
|
|
119
|
+
)
|
|
120
|
+
```
|
|
121
|
+
|
|
56
122
|
### Базовый пример использования
|
|
57
123
|
|
|
58
124
|
```python
|
|
@@ -1,25 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: maxapi-python
|
|
3
|
-
Version: 1.1.21
|
|
4
|
-
Summary: Python wrapper для API мессенджера Max
|
|
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
|
-
License-Expression: MIT
|
|
10
|
-
License-File: LICENSE
|
|
11
|
-
Keywords: api,max,messenger,websocket,wrapper
|
|
12
|
-
Classifier: Operating System :: OS Independent
|
|
13
|
-
Classifier: Programming Language :: Python :: 3
|
|
14
|
-
Requires-Python: >=3.10
|
|
15
|
-
Requires-Dist: aiofiles>=24.1.0
|
|
16
|
-
Requires-Dist: aiohttp>=3.12.15
|
|
17
|
-
Requires-Dist: lz4>=4.4.4
|
|
18
|
-
Requires-Dist: msgpack>=1.1.1
|
|
19
|
-
Requires-Dist: sqlmodel>=0.0.24
|
|
20
|
-
Requires-Dist: websockets>=15.0
|
|
21
|
-
Description-Content-Type: text/markdown
|
|
22
|
-
|
|
23
1
|
<p align="center">
|
|
24
2
|
<img src="assets/logo.svg" alt="PyMax" width="400">
|
|
25
3
|
</p>
|
|
@@ -35,6 +13,7 @@ Description-Content-Type: text/markdown
|
|
|
35
13
|
<img src="https://img.shields.io/badge/packaging-uv-D7FF64.svg" alt="Packaging">
|
|
36
14
|
</p>
|
|
37
15
|
|
|
16
|
+
|
|
38
17
|
---
|
|
39
18
|
> ⚠️ **Дисклеймер**
|
|
40
19
|
>
|
|
@@ -75,6 +54,41 @@ uv add -U maxapi-python
|
|
|
75
54
|
|
|
76
55
|
## Быстрый старт
|
|
77
56
|
|
|
57
|
+
### Аутентификация (`device_type`)
|
|
58
|
+
|
|
59
|
+
> [!IMPORTANT]
|
|
60
|
+
> Параметр `device_type` в `UserAgentPayload` **критически важен** для выбора способа авторизации:
|
|
61
|
+
|
|
62
|
+
**Вход по номеру телефона (DESKTOP):**
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from pymax import MaxClient
|
|
66
|
+
from pymax.payloads import UserAgentPayload
|
|
67
|
+
|
|
68
|
+
ua = UserAgentPayload(device_type="DESKTOP", app_version="25.12.13")
|
|
69
|
+
|
|
70
|
+
client = MaxClient(
|
|
71
|
+
phone="+79111111111",
|
|
72
|
+
work_dir="cache",
|
|
73
|
+
headers=ua,
|
|
74
|
+
)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**Вход через QR-код (WEB)** — токен совместим с веб-версией Max:
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
from pymax import MaxClient
|
|
81
|
+
from pymax.payloads import UserAgentPayload
|
|
82
|
+
|
|
83
|
+
ua = UserAgentPayload(device_type="WEB", app_version="25.12.13")
|
|
84
|
+
|
|
85
|
+
client = MaxClient(
|
|
86
|
+
phone="+7911111111",
|
|
87
|
+
work_dir="cache",
|
|
88
|
+
headers=ua,
|
|
89
|
+
)
|
|
90
|
+
```
|
|
91
|
+
|
|
78
92
|
### Базовый пример использования
|
|
79
93
|
|
|
80
94
|
```python
|
|
@@ -44,9 +44,7 @@ async def handle_start() -> None:
|
|
|
44
44
|
messages = []
|
|
45
45
|
from_time = int(time() * 1000)
|
|
46
46
|
while len(messages) < max_messages:
|
|
47
|
-
r = await client.fetch_history(
|
|
48
|
-
chat_id=chat_id, from_time=from_time, backward=30
|
|
49
|
-
)
|
|
47
|
+
r = await client.fetch_history(chat_id=chat_id, from_time=from_time, backward=30)
|
|
50
48
|
if not r:
|
|
51
49
|
break
|
|
52
50
|
from_time = r[0].time
|
|
@@ -131,9 +129,7 @@ async def handle_start() -> None:
|
|
|
131
129
|
|
|
132
130
|
@client.on_message()
|
|
133
131
|
async def handle_message(message: Message) -> None:
|
|
134
|
-
print(
|
|
135
|
-
f"New message in chat {message.chat_id} from {message.sender}: {message.text}"
|
|
136
|
-
)
|
|
132
|
+
print(f"New message in chat {message.chat_id} from {message.sender}: {message.text}")
|
|
137
133
|
# if message.link and message.link.message.attaches:
|
|
138
134
|
# for attach in message.link.message.attaches:
|
|
139
135
|
# print(f"Link attach type: {attach.type}")
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
|
|
3
|
+
from pymax import MaxClient
|
|
4
|
+
from pymax.payloads import UserAgentPayload
|
|
5
|
+
|
|
6
|
+
ua = UserAgentPayload(device_type="DESKTOP", app_version="25.12.13")
|
|
7
|
+
|
|
8
|
+
client = MaxClient(
|
|
9
|
+
phone="+79116290861",
|
|
10
|
+
work_dir="cache",
|
|
11
|
+
headers=ua,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@client.on_start
|
|
16
|
+
async def on_start() -> None:
|
|
17
|
+
print(f"MaxClient started as {client.me.names[0].first_name}!")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
asyncio.run(client.start())
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "maxapi-python"
|
|
3
|
-
version = "1.
|
|
3
|
+
version = "1.2.2"
|
|
4
4
|
description = "Python wrapper для API мессенджера Max"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.10"
|
|
@@ -18,6 +18,7 @@ dependencies = [
|
|
|
18
18
|
"lz4>=4.4.4",
|
|
19
19
|
"aiohttp>=3.12.15",
|
|
20
20
|
"aiofiles>=24.1.0",
|
|
21
|
+
"qrcode>=8.2",
|
|
21
22
|
]
|
|
22
23
|
|
|
23
24
|
[project.urls]
|
|
@@ -35,7 +36,25 @@ where = ["src"]
|
|
|
35
36
|
[tool.setuptools.package-dir]
|
|
36
37
|
"" = "src"
|
|
37
38
|
|
|
39
|
+
[project.optional-dependencies]
|
|
40
|
+
test = [
|
|
41
|
+
"pytest>=8.0.0",
|
|
42
|
+
"pytest-asyncio>=0.24.0",
|
|
43
|
+
"pytest-cov>=5.0.0",
|
|
44
|
+
"pytest-timeout>=2.1.0",
|
|
45
|
+
"flake8",
|
|
46
|
+
"mypy",
|
|
47
|
+
]
|
|
48
|
+
|
|
38
49
|
[dependency-groups]
|
|
50
|
+
test = [
|
|
51
|
+
"pytest>=8.0.0",
|
|
52
|
+
"pytest-asyncio>=0.24.0",
|
|
53
|
+
"pytest-cov>=5.0.0",
|
|
54
|
+
"pytest-timeout>=2.1.0",
|
|
55
|
+
"flake8",
|
|
56
|
+
"mypy",
|
|
57
|
+
]
|
|
39
58
|
dev = [
|
|
40
59
|
"furo>=2025.9.25",
|
|
41
60
|
"ghp-import>=2.1.0",
|
|
@@ -45,6 +64,10 @@ dev = [
|
|
|
45
64
|
"pre-commit>=4.3.0",
|
|
46
65
|
"pydocstring>=0.2.1",
|
|
47
66
|
"sphinx>=8.1.3",
|
|
67
|
+
"pytest>=8.0.0",
|
|
68
|
+
"pytest-asyncio>=0.24.0",
|
|
69
|
+
"pytest-cov>=5.0.0",
|
|
70
|
+
"pytest-timeout>=2.1.0",
|
|
48
71
|
]
|
|
49
72
|
|
|
50
73
|
[tool.hatch.build.targets.wheel]
|
|
@@ -73,3 +96,33 @@ profile = "black"
|
|
|
73
96
|
line_length = 79
|
|
74
97
|
multi_line_output = 3
|
|
75
98
|
include_trailing_comma = true
|
|
99
|
+
|
|
100
|
+
[tool.pytest.ini_options]
|
|
101
|
+
asyncio_mode = "auto"
|
|
102
|
+
testpaths = ["tests"]
|
|
103
|
+
python_files = ["test_*.py"]
|
|
104
|
+
python_classes = ["Test*"]
|
|
105
|
+
python_functions = ["test_*"]
|
|
106
|
+
addopts = "-v --tb=short --strict-markers"
|
|
107
|
+
markers = [
|
|
108
|
+
"asyncio: marker for asyncio tests",
|
|
109
|
+
"mockserver: marker for MockServer integration tests",
|
|
110
|
+
"integration: marker for integration tests",
|
|
111
|
+
"slow: marker for slow tests",
|
|
112
|
+
]
|
|
113
|
+
|
|
114
|
+
[tool.coverage.run]
|
|
115
|
+
source = ["src/pymax"]
|
|
116
|
+
branch = true
|
|
117
|
+
|
|
118
|
+
[tool.coverage.report]
|
|
119
|
+
exclude_lines = [
|
|
120
|
+
"pragma: no cover",
|
|
121
|
+
"def __repr__",
|
|
122
|
+
"raise AssertionError",
|
|
123
|
+
"raise NotImplementedError",
|
|
124
|
+
"if __name__ == .__main__.:",
|
|
125
|
+
"if TYPE_CHECKING:",
|
|
126
|
+
"class .*\\bProtocol\\):",
|
|
127
|
+
"@(abc\\.)?abstractmethod",
|
|
128
|
+
]
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
[pytest]
|
|
2
|
+
|
|
3
|
+
asyncio_mode = auto
|
|
4
|
+
|
|
5
|
+
testpaths = tests
|
|
6
|
+
|
|
7
|
+
python_files = test_*.py
|
|
8
|
+
python_classes = Test*
|
|
9
|
+
python_functions = test_*
|
|
10
|
+
|
|
11
|
+
addopts =
|
|
12
|
+
-v
|
|
13
|
+
--tb=short
|
|
14
|
+
--strict-markers
|
|
15
|
+
-ra
|
|
16
|
+
--color=yes
|
|
17
|
+
|
|
18
|
+
markers =
|
|
19
|
+
asyncio: асинхронные тесты
|
|
20
|
+
mockserver: интеграционные тесты с MockServer
|
|
21
|
+
integration: интеграционные тесты
|
|
22
|
+
slow: медленные тесты
|
|
23
|
+
unit: модульные тесты
|
|
24
|
+
skip_ci: пропустить в CI
|
|
25
|
+
|
|
26
|
+
timeout = 30
|
|
@@ -20,6 +20,28 @@ MaxClient
|
|
|
20
20
|
logger=None, # Пользовательский логгер
|
|
21
21
|
)
|
|
22
22
|
|
|
23
|
+
.. warning::
|
|
24
|
+
|
|
25
|
+
Параметр ``device_type`` в ``UserAgentPayload`` **критически важен** для выбора способа авторизации:
|
|
26
|
+
|
|
27
|
+
**DESKTOP** — вход по номеру телефона:
|
|
28
|
+
|
|
29
|
+
.. code-block:: python
|
|
30
|
+
|
|
31
|
+
from pymax.payloads import UserAgentPayload
|
|
32
|
+
|
|
33
|
+
ua = UserAgentPayload(device_type="DESKTOP", app_version="25.12.13")
|
|
34
|
+
client = MaxClient(phone="+79111111111", headers=ua)
|
|
35
|
+
|
|
36
|
+
**WEB** — вход через QR-код; токен совместим с веб-версией Max:
|
|
37
|
+
|
|
38
|
+
.. code-block:: python
|
|
39
|
+
|
|
40
|
+
from pymax.payloads import UserAgentPayload
|
|
41
|
+
|
|
42
|
+
ua = UserAgentPayload(device_type="WEB", app_version="25.12.13")
|
|
43
|
+
client = MaxClient(phone="+79111111111", headers=ua)
|
|
44
|
+
|
|
23
45
|
Основные методы:
|
|
24
46
|
|
|
25
47
|
.. code-block:: python
|