Skip to content
This repository was archived by the owner on Feb 11, 2026. It is now read-only.

Commit ed55732

Browse files
Merge pull request #32 from MaxApiTeam/dev/1.2.2
Dev/1.2.2
2 parents e1c8eaf + c9c2946 commit ed55732

10 files changed

Lines changed: 324 additions & 36 deletions

File tree

.github/workflows/tests.yml

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,41 @@ uv add -U maxapi-python
5454

5555
## Быстрый старт
5656

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+
5792
### Базовый пример использования
5893

5994
```python

examples/test.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
from pymax import MaxClient
44
from pymax.payloads import UserAgentPayload
55

6-
ua = UserAgentPayload(device_type="WEB")
6+
ua = UserAgentPayload(device_type="DESKTOP", app_version="25.12.13")
77

88
client = MaxClient(
9-
phone="+79911111111",
9+
phone="+79116290861",
1010
work_dir="cache",
1111
headers=ua,
1212
)

pyproject.toml

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "maxapi-python"
3-
version = "1.2.1"
3+
version = "1.2.2"
44
description = "Python wrapper для API мессенджера Max"
55
readme = "README.md"
66
requires-python = ">=3.10"
@@ -36,7 +36,25 @@ where = ["src"]
3636
[tool.setuptools.package-dir]
3737
"" = "src"
3838

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+
3949
[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+
]
4058
dev = [
4159
"furo>=2025.9.25",
4260
"ghp-import>=2.1.0",
@@ -46,6 +64,10 @@ dev = [
4664
"pre-commit>=4.3.0",
4765
"pydocstring>=0.2.1",
4866
"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",
4971
]
5072

5173
[tool.hatch.build.targets.wheel]
@@ -74,3 +96,33 @@ profile = "black"
7496
line_length = 79
7597
multi_line_output = 3
7698
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+
]

pytest.ini

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,26 @@
11
[pytest]
2+
3+
asyncio_mode = auto
4+
25
testpaths = tests
6+
37
python_files = test_*.py
48
python_classes = Test*
59
python_functions = test_*
6-
addopts = -v --tb=short
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

redocs/source/clients.rst

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,28 @@ MaxClient
2020
logger=None, # Пользовательский логгер
2121
)
2222
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+
2345
Основные методы:
2446

2547
.. code-block:: python

src/pymax/core.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ async def start(self) -> None:
295295
if self._token is None:
296296
await self._login()
297297

298-
await self._sync()
298+
await self._sync(self.user_agent)
299299

300300
await self._post_login_tasks(sync=False)
301301

0 commit comments

Comments
 (0)