fpx-engine 0.7.6__tar.gz → 0.7.7__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.
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/PKG-INFO +15 -12
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/README.md +14 -11
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/_api/_client.py +10 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/classes/account/account.py +36 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/classes/account/subclasses/profile.py +2 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/main.py +23 -1
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/middlewares/_request_engine.py +2 -2
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/utils/errors.py +7 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx_engine.egg-info/PKG-INFO +15 -12
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/pyproject.toml +1 -1
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/LICENSE +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/__init__.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/_parsers/__init__.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/_parsers/_base.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/_parsers/_category.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/_parsers/_chats.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/_parsers/_lots.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/_parsers/_orders.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/_parsers/_profile.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/classes/account/subclasses/addons.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/classes/account/subclasses/category.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/classes/account/subclasses/chat.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/classes/account/subclasses/editor.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/classes/account/subclasses/lot.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/classes/account/subclasses/order.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/classes/account/subclasses/review.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/classes/runner/runner.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/classes/runner/subclasses/_category.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/classes/runner/subclasses/_chat.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/classes/runner/subclasses/_order.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/classes/runner/subclasses/_review.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/classes/runner/subclasses/router.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/fsm/__init__.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/fsm/fsm.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/models/__init__.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/models/account.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/models/chat.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/models/lots.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/py.typed +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/services/__init__.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/utils/dependencies.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/utils/storage/__init__.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/utils/storage/base.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/utils/storage/file.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/utils/storage/memory.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx/utils/storage/redis.py +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx_engine.egg-info/SOURCES.txt +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx_engine.egg-info/dependency_links.txt +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx_engine.egg-info/requires.txt +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/fpx_engine.egg-info/top_level.txt +0 -0
- {fpx_engine-0.7.6 → fpx_engine-0.7.7}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fpx-engine
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.7
|
|
4
4
|
Summary: Автоматизация работы с FunPay
|
|
5
5
|
Author-email: Be My Code <gettofarmila@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/bymyforge/fpx
|
|
@@ -36,17 +36,20 @@ Dynamic: license-file
|
|
|
36
36
|
|
|
37
37
|
<p align="center">
|
|
38
38
|
<a href="https://github.com/bymyforge/fpx" target="_blank">
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
39
|
+
<img src="https://img.shields.io/badge/GitHub-temp_inactive-lightgrey?style=for-the-badge&logo=github&logoColor=white" alt="GitHub (temp inactive)">
|
|
40
|
+
</a>
|
|
41
|
+
<a href="https://gitlab.com/funpayx/fpx" target="_blank">
|
|
42
|
+
<img src="https://img.shields.io/badge/GitLab-FC6D26?style=for-the-badge&logo=gitlab&logoColor=white" alt="GitLab">
|
|
43
|
+
</a>
|
|
44
|
+
<a href="https://fpx.readthedocs.io/ru/latest/" target="_blank">
|
|
45
|
+
<img src="https://img.shields.io/badge/Документация-00b0ff?style=for-the-badge&logo=read-the-docs&logoColor=white" alt="Read the Docs">
|
|
46
|
+
</a>
|
|
47
|
+
<a href="https://t.me/fpx_engine" target="_blank">
|
|
48
|
+
<img src="https://img.shields.io/badge/Телеграм_Чат-26A5E4?style=for-the-badge&logo=telegram&logoColor=white" alt="Телеграм Чат">
|
|
49
|
+
</a>
|
|
50
|
+
<a href="https://pypi.org/project/fpx-engine/" target="_blank">
|
|
51
|
+
<img src="https://img.shields.io/badge/PyPI-3775A9?style=for-the-badge&logo=pypi&logoColor=white" alt="PyPI">
|
|
52
|
+
</a>
|
|
50
53
|
</p>
|
|
51
54
|
|
|
52
55
|
---
|
|
@@ -11,17 +11,20 @@
|
|
|
11
11
|
|
|
12
12
|
<p align="center">
|
|
13
13
|
<a href="https://github.com/bymyforge/fpx" target="_blank">
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
14
|
+
<img src="https://img.shields.io/badge/GitHub-temp_inactive-lightgrey?style=for-the-badge&logo=github&logoColor=white" alt="GitHub (temp inactive)">
|
|
15
|
+
</a>
|
|
16
|
+
<a href="https://gitlab.com/funpayx/fpx" target="_blank">
|
|
17
|
+
<img src="https://img.shields.io/badge/GitLab-FC6D26?style=for-the-badge&logo=gitlab&logoColor=white" alt="GitLab">
|
|
18
|
+
</a>
|
|
19
|
+
<a href="https://fpx.readthedocs.io/ru/latest/" target="_blank">
|
|
20
|
+
<img src="https://img.shields.io/badge/Документация-00b0ff?style=for-the-badge&logo=read-the-docs&logoColor=white" alt="Read the Docs">
|
|
21
|
+
</a>
|
|
22
|
+
<a href="https://t.me/fpx_engine" target="_blank">
|
|
23
|
+
<img src="https://img.shields.io/badge/Телеграм_Чат-26A5E4?style=for-the-badge&logo=telegram&logoColor=white" alt="Телеграм Чат">
|
|
24
|
+
</a>
|
|
25
|
+
<a href="https://pypi.org/project/fpx-engine/" target="_blank">
|
|
26
|
+
<img src="https://img.shields.io/badge/PyPI-3775A9?style=for-the-badge&logo=pypi&logoColor=white" alt="PyPI">
|
|
27
|
+
</a>
|
|
25
28
|
</p>
|
|
26
29
|
|
|
27
30
|
---
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import json
|
|
2
|
+
import secrets
|
|
2
3
|
|
|
3
4
|
|
|
4
5
|
class FunPayClient:
|
|
@@ -6,6 +7,15 @@ class FunPayClient:
|
|
|
6
7
|
self._account = account
|
|
7
8
|
self.client = http_client
|
|
8
9
|
|
|
10
|
+
async def refresh_session_cookies(self) -> dict:
|
|
11
|
+
objects = [{"type": "chat_counter", "id": "0", "tag": secrets.token_hex(4), "data": False}]
|
|
12
|
+
payload = {"objects": json.dumps(objects)}
|
|
13
|
+
headers = {"X-Requested-With": "XMLHttpRequest"}
|
|
14
|
+
|
|
15
|
+
r = await self.client.request("POST", "/runner/", data=payload, headers=headers)
|
|
16
|
+
|
|
17
|
+
return r
|
|
18
|
+
|
|
9
19
|
async def get_chats_page(self) -> str:
|
|
10
20
|
r = await self._account._request_engine.execute("GET", "/chat/")
|
|
11
21
|
return r.text
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import re
|
|
1
3
|
from dataclasses import dataclass, field
|
|
2
4
|
from typing import Optional
|
|
3
5
|
|
|
@@ -14,6 +16,7 @@ from fpx.classes.account.subclasses.order import OrderManager
|
|
|
14
16
|
from fpx.classes.account.subclasses.profile import ProfileManager
|
|
15
17
|
from fpx.classes.account.subclasses.review import ReviewManager
|
|
16
18
|
from fpx.middlewares._request_engine import RequestEngine
|
|
19
|
+
from fpx.utils.errors import FpxRefreshCookieError
|
|
17
20
|
|
|
18
21
|
|
|
19
22
|
@dataclass
|
|
@@ -62,3 +65,36 @@ class Account:
|
|
|
62
65
|
|
|
63
66
|
result = await self._client.upload_image(image_data)
|
|
64
67
|
return result["fileId"]
|
|
68
|
+
|
|
69
|
+
async def _refresh_cookies(self):
|
|
70
|
+
cookies = await self._client.refresh_session_cookies()
|
|
71
|
+
headers = cookies.headers
|
|
72
|
+
MAX_AGE_RE = re.compile(r"max-age=(\d+)", re.IGNORECASE)
|
|
73
|
+
for raw_cookie in headers.get_list("set-cookie"):
|
|
74
|
+
if raw_cookie.startswith("golden_seal="):
|
|
75
|
+
match = MAX_AGE_RE.search(raw_cookie)
|
|
76
|
+
return int(match.group(1)) if match else None
|
|
77
|
+
return None
|
|
78
|
+
|
|
79
|
+
async def refresh_cookies_cycle(self):
|
|
80
|
+
"""
|
|
81
|
+
Обновление gseal и PHPSESSID.
|
|
82
|
+
Запускает цикл обновления куков.
|
|
83
|
+
Сам внутри обновляет куки каждую неделю.
|
|
84
|
+
|
|
85
|
+
Raises:
|
|
86
|
+
FpxRefreshCookieError: Ошибка обновления куков
|
|
87
|
+
"""
|
|
88
|
+
while True:
|
|
89
|
+
ex_time = None
|
|
90
|
+
atts = 0
|
|
91
|
+
while ex_time is None:
|
|
92
|
+
try:
|
|
93
|
+
ex_time = await self._refresh_cookies()
|
|
94
|
+
except Exception as e:
|
|
95
|
+
atts += 1
|
|
96
|
+
if atts > 3:
|
|
97
|
+
raise FpxRefreshCookieError(f"Ошибка обновления куков: {e}")
|
|
98
|
+
if ex_time is None:
|
|
99
|
+
await asyncio.sleep(15)
|
|
100
|
+
await asyncio.sleep(ex_time)
|
|
@@ -157,6 +157,8 @@ class ProfileManager:
|
|
|
157
157
|
html = await self._account._client.get_finance_page()
|
|
158
158
|
step = "парсинг данных"
|
|
159
159
|
balance = self._account._parser.parse_finanses(html)
|
|
160
|
+
except fpx_err.FpxAuthError:
|
|
161
|
+
raise
|
|
160
162
|
except Exception as e:
|
|
161
163
|
raise fpx_err.FpxGetProfileError(f"При сборе баланса, выполняя {step} произошла ошибка: {e}")
|
|
162
164
|
return balance
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import asyncio
|
|
1
2
|
import re
|
|
2
3
|
|
|
3
4
|
import httpx
|
|
@@ -15,6 +16,11 @@ class FunPayTools:
|
|
|
15
16
|
def __init__(
|
|
16
17
|
self, gkey: str, gseal: str | None = None, storage: BaseStorage | None = None, proxy=None, http_client=None
|
|
17
18
|
):
|
|
19
|
+
if gseal or gseal is None:
|
|
20
|
+
print(
|
|
21
|
+
"ВАЖНО: С выхода релиза 0.8.0 аргумент gseal будет удалён, теперь он подставляется "
|
|
22
|
+
"автоматически, просьба не передавать аргумент gseal во избежание проблем."
|
|
23
|
+
)
|
|
18
24
|
if not gkey:
|
|
19
25
|
raise FpxAuthError("gkey и gseal не могут быть None.")
|
|
20
26
|
if not GKEY_PATTERN.match(gkey):
|
|
@@ -22,7 +28,9 @@ class FunPayTools:
|
|
|
22
28
|
if gseal:
|
|
23
29
|
if not GSEAL_PATTERN.match(gseal):
|
|
24
30
|
raise FpxAuthError("Неверный формат gseal, перепроверь его.")
|
|
25
|
-
self._cookies = {"golden_key": gkey, "
|
|
31
|
+
self._cookies = {"golden_key": gkey, "locale": "ru"}
|
|
32
|
+
if gseal:
|
|
33
|
+
self._cookies["golden_seal"] = gseal
|
|
26
34
|
self._headers = {
|
|
27
35
|
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:120.0) Gecko/20100101 Firefox/120.0",
|
|
28
36
|
"Accept-Language": "ru-RU,ru;q=0.9",
|
|
@@ -58,14 +66,28 @@ class FunPayTools:
|
|
|
58
66
|
self.account._request_engine.runner = self.runner
|
|
59
67
|
self.storage = storage or MemoryStorage()
|
|
60
68
|
self.runner.storage = self.storage
|
|
69
|
+
self._refresh_task: asyncio.Task | None = None
|
|
70
|
+
|
|
71
|
+
try:
|
|
72
|
+
loop = asyncio.get_running_loop()
|
|
73
|
+
self._refresh_task = loop.create_task(self.account.refresh_cookies_cycle())
|
|
74
|
+
except RuntimeError:
|
|
75
|
+
pass
|
|
61
76
|
|
|
62
77
|
async def __aenter__(self):
|
|
78
|
+
self._refresh_task = asyncio.create_task(self.account.refresh_cookies_cycle())
|
|
63
79
|
return self
|
|
64
80
|
|
|
65
81
|
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
66
82
|
await self.shutdown()
|
|
67
83
|
|
|
68
84
|
async def shutdown(self):
|
|
85
|
+
if self._refresh_task and not self._refresh_task.done():
|
|
86
|
+
self._refresh_task.cancel()
|
|
87
|
+
try:
|
|
88
|
+
await self._refresh_task
|
|
89
|
+
except asyncio.CancelledError:
|
|
90
|
+
pass
|
|
69
91
|
if hasattr(self, "runner") and self.runner.is_running:
|
|
70
92
|
self.runner.is_running = False
|
|
71
93
|
if self._client and not self._client.is_closed:
|
|
@@ -15,8 +15,6 @@ class RequestEngine:
|
|
|
15
15
|
attempts = 3
|
|
16
16
|
backoff = 1.5 # множитель времени ожидания
|
|
17
17
|
if method.upper() in ("POST", "PUT", "DELETE"):
|
|
18
|
-
if "golden_seal" in self._client.cookies:
|
|
19
|
-
raise fpx_err.FpxAbsentGoldenSeal()
|
|
20
18
|
if "data" not in kwargs:
|
|
21
19
|
kwargs["data"] = {}
|
|
22
20
|
if "headers" not in kwargs:
|
|
@@ -48,6 +46,8 @@ class RequestEngine:
|
|
|
48
46
|
sleep_time = backoff ** float(attempt)
|
|
49
47
|
await asyncio.sleep(sleep_time)
|
|
50
48
|
continue
|
|
49
|
+
if response.url == "https://funpay.com/account/login":
|
|
50
|
+
raise fpx_err.FpxAuthError("Неверный gkey, обнови свои куки.")
|
|
51
51
|
return response
|
|
52
52
|
except httpx.ReadTimeout as e:
|
|
53
53
|
if method.upper() == "GET":
|
|
@@ -42,6 +42,13 @@ class FpxHandlerError(FpxError):
|
|
|
42
42
|
# аккаунт
|
|
43
43
|
|
|
44
44
|
|
|
45
|
+
class FpxRefreshCookieError(FpxAccountError):
|
|
46
|
+
"""Ошибка обновления куков"""
|
|
47
|
+
|
|
48
|
+
def __init__(self, message="Ошибка обновления куков"):
|
|
49
|
+
super().__init__(message)
|
|
50
|
+
|
|
51
|
+
|
|
45
52
|
class FpxAbsentGoldenSeal(FpxAccountError):
|
|
46
53
|
"""Для POST запроса обязателен gseal."""
|
|
47
54
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fpx-engine
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.7
|
|
4
4
|
Summary: Автоматизация работы с FunPay
|
|
5
5
|
Author-email: Be My Code <gettofarmila@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/bymyforge/fpx
|
|
@@ -36,17 +36,20 @@ Dynamic: license-file
|
|
|
36
36
|
|
|
37
37
|
<p align="center">
|
|
38
38
|
<a href="https://github.com/bymyforge/fpx" target="_blank">
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
39
|
+
<img src="https://img.shields.io/badge/GitHub-temp_inactive-lightgrey?style=for-the-badge&logo=github&logoColor=white" alt="GitHub (temp inactive)">
|
|
40
|
+
</a>
|
|
41
|
+
<a href="https://gitlab.com/funpayx/fpx" target="_blank">
|
|
42
|
+
<img src="https://img.shields.io/badge/GitLab-FC6D26?style=for-the-badge&logo=gitlab&logoColor=white" alt="GitLab">
|
|
43
|
+
</a>
|
|
44
|
+
<a href="https://fpx.readthedocs.io/ru/latest/" target="_blank">
|
|
45
|
+
<img src="https://img.shields.io/badge/Документация-00b0ff?style=for-the-badge&logo=read-the-docs&logoColor=white" alt="Read the Docs">
|
|
46
|
+
</a>
|
|
47
|
+
<a href="https://t.me/fpx_engine" target="_blank">
|
|
48
|
+
<img src="https://img.shields.io/badge/Телеграм_Чат-26A5E4?style=for-the-badge&logo=telegram&logoColor=white" alt="Телеграм Чат">
|
|
49
|
+
</a>
|
|
50
|
+
<a href="https://pypi.org/project/fpx-engine/" target="_blank">
|
|
51
|
+
<img src="https://img.shields.io/badge/PyPI-3775A9?style=for-the-badge&logo=pypi&logoColor=white" alt="PyPI">
|
|
52
|
+
</a>
|
|
50
53
|
</p>
|
|
51
54
|
|
|
52
55
|
---
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|