xync-client 0.0.93.dev1__tar.gz → 0.0.93.dev17__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.
- {xync_client-0.0.93.dev1/xync_client.egg-info → xync_client-0.0.93.dev17}/PKG-INFO +1 -1
- xync_client-0.0.93.dev17/index.html +397 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/tests/TestEx.py +23 -9
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Abc/InAgent.py +3 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Abc/PmAgent.py +5 -5
- xync_client-0.0.93.dev17/xync_client/Bybit/InAgent.py +242 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Bybit/agent.py +113 -91
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Bybit/etype/order.py +12 -7
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Pms/Ozon/__init__.py +5 -2
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Pms/Payeer/__init__.py +13 -7
- xync_client-0.0.93.dev17/xync_client/Pms/Payeer/api.py +25 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Pms/Payeer/login.py +7 -4
- xync_client-0.0.93.dev17/xync_client/Pms/Sber/__init__.py +123 -0
- xync_client-0.0.93.dev17/xync_client/Pms/Sber/utils.py +48 -0
- xync_client-0.0.93.dev17/xync_client/Pms/Tinkoff/__init__.py +135 -0
- xync_client-0.0.93.dev17/xync_client/Pms/Xync/__main__.py +536 -0
- xync_client-0.0.93.dev17/xync_client/Pms/Xync/ed.py +156 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17/xync_client.egg-info}/PKG-INFO +1 -1
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client.egg-info/SOURCES.txt +5 -0
- xync_client-0.0.93.dev1/xync_client/Bybit/InAgent.py +0 -123
- xync_client-0.0.93.dev1/xync_client/Pms/Sber/__init__.py +0 -164
- xync_client-0.0.93.dev1/xync_client/Pms/Tinkoff/__init__.py +0 -117
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/.env.sample +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/.gitignore +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/.pre-commit-config.yaml +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/README.md +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/__init__.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/makefile +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/pyproject.toml +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/setup.cfg +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/tests/TestAgent.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/tests/TestAsset.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/tests/TestOrder.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/tests/_todo_refact/Binance/test_binance.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/tests/_todo_refact/Bybit/test_bybit.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/tests/_todo_refact/Bybit/test_bybit_p2p.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/tests/_todo_refact/Gate/test_gate.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/tests/_todo_refact/Wallet/test_agent.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/tests/_todo_refact/Wallet/test_ex.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/tests/_todo_refact/__init__.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/tests/_todo_refact/_test_ex.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Abc/Agent.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Abc/Asset.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Abc/Auth.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Abc/BaseTest.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Abc/Ex.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Abc/Exception.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Abc/Order.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Abc/xtype.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Binance/__init__.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Binance/binance_async.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Binance/earn_api.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Binance/etype/ad.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Binance/etype/pm.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Binance/ex.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Binance/exceptions.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Binance/sapi.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Binance/web_c2c.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/BingX/__init__.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/BingX/agent.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/BingX/base.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/BingX/etype/ad.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/BingX/etype/pm.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/BingX/ex.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/BingX/req.mjs +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/BingX/sign.js +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/BitGet/__init__.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/BitGet/agent.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/BitGet/etype/ad.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/BitGet/ex.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/BitPapa/ex.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Bybit/etype/ad.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Bybit/etype/cred.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Bybit/ex.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Bybit/order.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Bybit/web_earn.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Bybit/web_p2p.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Bybit/ws.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Gate/etype/ad.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Gate/ex.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Gate/premarket.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Gmail/__init__.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Htx/agent.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Htx/earn.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Htx/etype/__init__.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Htx/etype/ad.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Htx/etype/cred.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Htx/etype/pm.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Htx/etype/test.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Htx/ex.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/KuCoin/etype/ad.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/KuCoin/etype/pm.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/KuCoin/ex.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/KuCoin/web.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Mexc/etype/ad.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Mexc/etype/pm.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Mexc/ex.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Okx/etype/ad.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Okx/etype/pm.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Okx/ex.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Pms/.gitignore +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Pms/Alfa/__init__.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Pms/Alfa/state.json +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Pms/MTS/__init__.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Pms/Payeer/.gitignore +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Pms/Volet/__init__.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Pms/Volet/_todo_req/req.mjs +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Pms/Volet/_todo_req/req.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Pms/Volet/api.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Pms/Volet/pl.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Pms/Yandex/__init__.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/TgWallet/agent.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/TgWallet/asset.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/TgWallet/auth.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/TgWallet/ex.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/TgWallet/inAgent.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/TgWallet/order.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/TgWallet/pyd.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/TgWallet/pyro.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/TgWallet/web.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/__init__.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/loader.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/pm_unifier.py +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client.egg-info/dependency_links.txt +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client.egg-info/requires.txt +0 -0
- {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="ru">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>QR Scanner Mini App</title>
|
|
7
|
+
<script src="https://telegram.org/js/telegram-web-app.js"></script>
|
|
8
|
+
<style>
|
|
9
|
+
body {
|
|
10
|
+
margin: 0;
|
|
11
|
+
padding: 20px;
|
|
12
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
13
|
+
background-color: var(--tg-theme-bg-color, #ffffff);
|
|
14
|
+
color: var(--tg-theme-text-color, #000000);
|
|
15
|
+
display: flex;
|
|
16
|
+
flex-direction: column;
|
|
17
|
+
align-items: center;
|
|
18
|
+
justify-content: center;
|
|
19
|
+
min-height: 100vh;
|
|
20
|
+
box-sizing: border-box;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.container {
|
|
24
|
+
text-align: center;
|
|
25
|
+
max-width: 300px;
|
|
26
|
+
width: 100%;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.title {
|
|
30
|
+
font-size: 24px;
|
|
31
|
+
font-weight: bold;
|
|
32
|
+
margin-bottom: 20px;
|
|
33
|
+
color: var(--tg-theme-text-color, #000000);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.scan-button {
|
|
37
|
+
background: var(--tg-theme-button-color, #3390ec);
|
|
38
|
+
color: var(--tg-theme-button-text-color, #ffffff);
|
|
39
|
+
border: none;
|
|
40
|
+
padding: 15px 30px;
|
|
41
|
+
font-size: 16px;
|
|
42
|
+
border-radius: 8px;
|
|
43
|
+
cursor: pointer;
|
|
44
|
+
width: 100%;
|
|
45
|
+
margin-bottom: 20px;
|
|
46
|
+
transition: opacity 0.2s;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.scan-button:hover {
|
|
50
|
+
opacity: 0.8;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.scan-button:disabled {
|
|
54
|
+
opacity: 0.5;
|
|
55
|
+
cursor: not-allowed;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.result-container {
|
|
59
|
+
background: var(--tg-theme-secondary-bg-color, #f4f4f4);
|
|
60
|
+
border-radius: 8px;
|
|
61
|
+
padding: 15px;
|
|
62
|
+
margin-top: 20px;
|
|
63
|
+
text-align: left;
|
|
64
|
+
word-break: break-all;
|
|
65
|
+
max-height: 200px;
|
|
66
|
+
overflow-y: auto;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.result-title {
|
|
70
|
+
font-weight: bold;
|
|
71
|
+
margin-bottom: 10px;
|
|
72
|
+
color: var(--tg-theme-text-color, #000000);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.result-text {
|
|
76
|
+
font-family: monospace;
|
|
77
|
+
font-size: 14px;
|
|
78
|
+
line-height: 1.4;
|
|
79
|
+
color: var(--tg-theme-text-color, #000000);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.error {
|
|
83
|
+
color: #ff3b30;
|
|
84
|
+
margin-top: 10px;
|
|
85
|
+
font-size: 14px;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.info {
|
|
89
|
+
color: var(--tg-theme-hint-color, #999999);
|
|
90
|
+
font-size: 14px;
|
|
91
|
+
margin-bottom: 20px;
|
|
92
|
+
}
|
|
93
|
+
</style>
|
|
94
|
+
</head>
|
|
95
|
+
<body>
|
|
96
|
+
<div class="container">
|
|
97
|
+
<h1 class="title">QR Сканер</h1>
|
|
98
|
+
<p class="info">Нажмите кнопку для сканирования QR-кода</p>
|
|
99
|
+
|
|
100
|
+
<button class="scan-button" id="scanButton">
|
|
101
|
+
📱 Сканировать QR-код
|
|
102
|
+
</button>
|
|
103
|
+
|
|
104
|
+
<div id="result" style="display: none;">
|
|
105
|
+
<div class="result-container">
|
|
106
|
+
<div class="result-title">Результат сканирования:</div>
|
|
107
|
+
<div class="result-text" id="resultText"></div>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
|
|
111
|
+
<div id="debug" class="result-container" style="display: block; background: #e8f4fd; border: 1px solid #3390ec;">
|
|
112
|
+
<div class="result-title">Отладочная информация:</div>
|
|
113
|
+
<div class="result-text" id="debugText">Инициализация...</div>
|
|
114
|
+
</div>
|
|
115
|
+
|
|
116
|
+
<div id="error" class="error" style="display: none;"></div>
|
|
117
|
+
</div>
|
|
118
|
+
|
|
119
|
+
<script>
|
|
120
|
+
// Проверяем доступность Telegram Web App API
|
|
121
|
+
let tg = null;
|
|
122
|
+
let isTelegramEnvironment = false;
|
|
123
|
+
|
|
124
|
+
try {
|
|
125
|
+
if (window.Telegram && window.Telegram.WebApp) {
|
|
126
|
+
tg = window.Telegram.WebApp;
|
|
127
|
+
isTelegramEnvironment = true;
|
|
128
|
+
|
|
129
|
+
// Настройка темы и интерфейса
|
|
130
|
+
tg.ready();
|
|
131
|
+
tg.expand();
|
|
132
|
+
} else {
|
|
133
|
+
// Создаем заглушку для тестирования вне Telegram
|
|
134
|
+
tg = {
|
|
135
|
+
themeParams: {
|
|
136
|
+
bg_color: '#ffffff',
|
|
137
|
+
text_color: '#000000',
|
|
138
|
+
button_color: '#3390ec',
|
|
139
|
+
button_text_color: '#ffffff'
|
|
140
|
+
},
|
|
141
|
+
showScanQrPopup: function(params) {
|
|
142
|
+
// Имитация сканирования для тестирования
|
|
143
|
+
setTimeout(() => {
|
|
144
|
+
const mockQRData = 'https://example.com/test-qr-data-' + Date.now();
|
|
145
|
+
// Имитируем событие qrTextReceived
|
|
146
|
+
if (this.eventHandlers && this.eventHandlers['qrTextReceived']) {
|
|
147
|
+
this.eventHandlers['qrTextReceived'].forEach(handler => {
|
|
148
|
+
handler({ data: mockQRData });
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}, 2000);
|
|
152
|
+
},
|
|
153
|
+
sendData: function(data) {
|
|
154
|
+
console.log('Mock sendData:', data);
|
|
155
|
+
},
|
|
156
|
+
onEvent: function(event, callback) {
|
|
157
|
+
console.log('Mock onEvent:', event);
|
|
158
|
+
if (!this.eventHandlers) this.eventHandlers = {};
|
|
159
|
+
if (!this.eventHandlers[event]) this.eventHandlers[event] = [];
|
|
160
|
+
this.eventHandlers[event].push(callback);
|
|
161
|
+
},
|
|
162
|
+
offEvent: function(event, callback) {
|
|
163
|
+
console.log('Mock offEvent:', event);
|
|
164
|
+
if (this.eventHandlers && this.eventHandlers[event]) {
|
|
165
|
+
const index = this.eventHandlers[event].indexOf(callback);
|
|
166
|
+
if (index > -1) {
|
|
167
|
+
this.eventHandlers[event].splice(index, 1);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
} catch (error) {
|
|
174
|
+
console.error('Ошибка инициализации Telegram Web App:', error);
|
|
175
|
+
addDebugInfo = function(msg) { console.log(msg); };
|
|
176
|
+
// Используем заглушку
|
|
177
|
+
tg = {
|
|
178
|
+
themeParams: {},
|
|
179
|
+
showScanQrPopup: null,
|
|
180
|
+
sendData: function() {},
|
|
181
|
+
onEvent: function() {}
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Инициализируем функцию отладки если она еще не определена
|
|
186
|
+
if (typeof addDebugInfo === 'undefined') {
|
|
187
|
+
addDebugInfo = function(msg) { console.log(msg); };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Применяем тему Telegram
|
|
191
|
+
if (tg && tg.themeParams) {
|
|
192
|
+
document.body.style.backgroundColor = tg.themeParams.bg_color || '#ffffff';
|
|
193
|
+
document.body.style.color = tg.themeParams.text_color || '#000000';
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Элементы DOM
|
|
197
|
+
const scanButton = document.getElementById('scanButton');
|
|
198
|
+
const resultDiv = document.getElementById('result');
|
|
199
|
+
const resultText = document.getElementById('resultText');
|
|
200
|
+
const errorDiv = document.getElementById('error');
|
|
201
|
+
const debugDiv = document.getElementById('debug');
|
|
202
|
+
const debugText = document.getElementById('debugText');
|
|
203
|
+
|
|
204
|
+
// Функция для добавления отладочной информации
|
|
205
|
+
function addDebugInfo(message) {
|
|
206
|
+
const timestamp = new Date().toLocaleTimeString();
|
|
207
|
+
debugText.innerHTML += `<br>[${timestamp}] ${message}`;
|
|
208
|
+
debugDiv.scrollTop = debugDiv.scrollHeight;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Функция для показа ошибки
|
|
212
|
+
function showError(message) {
|
|
213
|
+
errorDiv.textContent = message;
|
|
214
|
+
errorDiv.style.display = 'block';
|
|
215
|
+
resultDiv.style.display = 'none';
|
|
216
|
+
addDebugInfo(`ОШИБКА: ${message}`);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Функция для показа результата
|
|
220
|
+
function showResult(data) {
|
|
221
|
+
resultText.textContent = data;
|
|
222
|
+
resultDiv.style.display = 'block';
|
|
223
|
+
errorDiv.style.display = 'none';
|
|
224
|
+
addDebugInfo(`РЕЗУЛЬТАТ ОТОБРАЖЕН: "${data}"`);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Функция сканирования QR-кода
|
|
228
|
+
function scanQRCode() {
|
|
229
|
+
addDebugInfo('Начало сканирования...');
|
|
230
|
+
|
|
231
|
+
// Скрываем предыдущие результаты и ошибки
|
|
232
|
+
resultDiv.style.display = 'none';
|
|
233
|
+
errorDiv.style.display = 'none';
|
|
234
|
+
|
|
235
|
+
// Блокируем кнопку во время сканирования
|
|
236
|
+
scanButton.disabled = true;
|
|
237
|
+
scanButton.textContent = '🔍 Сканирование...';
|
|
238
|
+
|
|
239
|
+
try {
|
|
240
|
+
// Проверяем доступность API
|
|
241
|
+
if (!tg || !tg.showScanQrPopup) {
|
|
242
|
+
if (isTelegramEnvironment) {
|
|
243
|
+
throw new Error('QR сканер недоступен в этой версии Telegram');
|
|
244
|
+
} else {
|
|
245
|
+
throw new Error('Приложение должно запускаться в Telegram');
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
addDebugInfo('API доступен, открываем сканер...');
|
|
250
|
+
|
|
251
|
+
// Устанавливаем обработчики событий ДО открытия сканера
|
|
252
|
+
const handleQrText = function(data) {
|
|
253
|
+
addDebugInfo(`Получено событие qrTextReceived: ${JSON.stringify(data)}`);
|
|
254
|
+
|
|
255
|
+
let qrData = null;
|
|
256
|
+
|
|
257
|
+
// Пробуем разные форматы данных
|
|
258
|
+
if (typeof data === 'string') {
|
|
259
|
+
qrData = data;
|
|
260
|
+
} else if (data && data.data) {
|
|
261
|
+
qrData = data.data;
|
|
262
|
+
} else if (data && typeof data === 'object') {
|
|
263
|
+
qrData = JSON.stringify(data);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if (qrData) {
|
|
267
|
+
// Сразу закрываем сканер при успешном распознавании
|
|
268
|
+
addDebugInfo('Закрываем сканер после успешного распознавания...');
|
|
269
|
+
if (tg.closeScanQrPopup) {
|
|
270
|
+
try {
|
|
271
|
+
tg.closeScanQrPopup();
|
|
272
|
+
addDebugInfo('Сканер закрыт программно');
|
|
273
|
+
} catch (e) {
|
|
274
|
+
addDebugInfo(`Ошибка закрытия сканера: ${e.message}`);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
showResult(qrData);
|
|
279
|
+
|
|
280
|
+
// Отправляем данные обратно в Telegram
|
|
281
|
+
if (isTelegramEnvironment && tg.sendData) {
|
|
282
|
+
try {
|
|
283
|
+
tg.sendData(JSON.stringify({
|
|
284
|
+
action: 'qr_scanned',
|
|
285
|
+
data: qrData,
|
|
286
|
+
timestamp: Date.now()
|
|
287
|
+
}));
|
|
288
|
+
addDebugInfo('Данные отправлены в Telegram');
|
|
289
|
+
} catch (e) {
|
|
290
|
+
addDebugInfo(`Ошибка отправки данных: ${e.message}`);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
} else {
|
|
294
|
+
showError('QR-код не содержит данных или данные в неизвестном формате');
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Разблокируем кнопку
|
|
298
|
+
scanButton.disabled = false;
|
|
299
|
+
scanButton.textContent = '📱 Сканировать QR-код';
|
|
300
|
+
|
|
301
|
+
// Удаляем обработчик
|
|
302
|
+
if (tg.offEvent) {
|
|
303
|
+
tg.offEvent('qrTextReceived', handleQrText);
|
|
304
|
+
}
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
const handleScanClosed = function() {
|
|
308
|
+
addDebugInfo('Сканер закрыт пользователем');
|
|
309
|
+
|
|
310
|
+
// НЕ сбрасываем результат если он уже есть
|
|
311
|
+
if (resultDiv.style.display !== 'block') {
|
|
312
|
+
// Только если результата нет, показываем отмену
|
|
313
|
+
showError('Сканирование отменено');
|
|
314
|
+
} else {
|
|
315
|
+
// Если результат есть, просто скрываем ошибку
|
|
316
|
+
errorDiv.style.display = 'none';
|
|
317
|
+
addDebugInfo('Результат сохранен после закрытия сканера');
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
scanButton.disabled = false;
|
|
321
|
+
scanButton.textContent = '📱 Сканировать QR-код';
|
|
322
|
+
|
|
323
|
+
if (tg.offEvent) {
|
|
324
|
+
tg.offEvent('qrTextReceived', handleQrText);
|
|
325
|
+
tg.offEvent('scanQrPopupClosed', handleScanClosed);
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
// Устанавливаем обработчики
|
|
330
|
+
tg.onEvent('qrTextReceived', handleQrText);
|
|
331
|
+
tg.onEvent('scanQrPopupClosed', handleScanClosed);
|
|
332
|
+
|
|
333
|
+
addDebugInfo('Обработчики событий установлены');
|
|
334
|
+
|
|
335
|
+
// Открываем сканер QR-кода
|
|
336
|
+
tg.showScanQrPopup({
|
|
337
|
+
text: 'Наведите камеру на QR-код'
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
addDebugInfo('Сканер открыт, ждем сканирования...');
|
|
341
|
+
|
|
342
|
+
// Добавляем таймаут на случай зависания
|
|
343
|
+
setTimeout(() => {
|
|
344
|
+
if (scanButton.disabled) {
|
|
345
|
+
addDebugInfo('Таймаут: сканирование длится более 30 секунд');
|
|
346
|
+
scanButton.disabled = false;
|
|
347
|
+
scanButton.textContent = '📱 Сканировать QR-код';
|
|
348
|
+
}
|
|
349
|
+
}, 30000);
|
|
350
|
+
|
|
351
|
+
} catch (error) {
|
|
352
|
+
addDebugInfo(`Исключение в scanQRCode: ${error.message}`);
|
|
353
|
+
showError('Ошибка: ' + error.message);
|
|
354
|
+
|
|
355
|
+
// Разблокируем кнопку
|
|
356
|
+
scanButton.disabled = false;
|
|
357
|
+
scanButton.textContent = '📱 Сканировать QR-код';
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// Обработчик события для кнопки сканирования
|
|
362
|
+
scanButton.addEventListener('click', scanQRCode);
|
|
363
|
+
|
|
364
|
+
// Обработчик закрытия сканера (если пользователь отменил)
|
|
365
|
+
if (isTelegramEnvironment && tg.onEvent) {
|
|
366
|
+
tg.onEvent('scanQrPopupClosed', function() {
|
|
367
|
+
console.log('Сканер QR-кода закрыт');
|
|
368
|
+
// Разблокируем кнопку если сканер был закрыт
|
|
369
|
+
scanButton.disabled = false;
|
|
370
|
+
scanButton.textContent = '📱 Сканировать QR-код';
|
|
371
|
+
|
|
372
|
+
// Показываем сообщение о том, что сканирование отменено
|
|
373
|
+
showError('Сканирование отменено');
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// Проверяем поддержку QR сканера при загрузке
|
|
378
|
+
window.addEventListener('load', function() {
|
|
379
|
+
addDebugInfo(`Среда Telegram: ${isTelegramEnvironment}`);
|
|
380
|
+
addDebugInfo(`Версия WebApp: ${tg.version || 'неизвестно'}`);
|
|
381
|
+
addDebugInfo(`Platform: ${tg.platform || 'неизвестно'}`);
|
|
382
|
+
addDebugInfo(`showScanQrPopup доступен: ${!!tg.showScanQrPopup}`);
|
|
383
|
+
addDebugInfo(`onEvent доступен: ${!!tg.onEvent}`);
|
|
384
|
+
|
|
385
|
+
if (!isTelegramEnvironment) {
|
|
386
|
+
addDebugInfo('⚠️ Тестовый режим - имитация сканирования через 2 секунды');
|
|
387
|
+
} else if (!tg.showScanQrPopup) {
|
|
388
|
+
showError('QR сканер не поддерживается в этой версии Telegram. Обновите приложение.');
|
|
389
|
+
scanButton.disabled = true;
|
|
390
|
+
addDebugInfo('QR сканер недоступен');
|
|
391
|
+
} else {
|
|
392
|
+
addDebugInfo('✅ QR сканер готов к работе');
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
</script>
|
|
396
|
+
</body>
|
|
397
|
+
</html>
|
|
@@ -7,8 +7,8 @@ from xync_schema.xtype import BaseAd
|
|
|
7
7
|
|
|
8
8
|
from xync_client.Abc.BaseTest import BaseTest
|
|
9
9
|
from xync_schema.enums import ExStatus, ExType, ExAction
|
|
10
|
-
from xync_schema.models import Ex, ExStat, Curex, Coinex
|
|
11
|
-
|
|
10
|
+
# from xync_schema.models import Ex, ExStat, Curex, Coinex, Race, Ad
|
|
11
|
+
from xync_schema import models
|
|
12
12
|
from xync_client.Abc.Ex import BaseExClient
|
|
13
13
|
from xync_client.loader import TOKEN
|
|
14
14
|
|
|
@@ -29,7 +29,7 @@ class TestEx(BaseTest):
|
|
|
29
29
|
async def test_set_coins(self, clients: list[BaseExClient]):
|
|
30
30
|
for client in clients:
|
|
31
31
|
await client.set_coins()
|
|
32
|
-
t, _ = await ExStat.update_or_create({"ok": True}, ex=client.ex, action=ExAction.set_coins)
|
|
32
|
+
t, _ = await models.ExStat.update_or_create({"ok": True}, ex=client.ex, action=ExAction.set_coins)
|
|
33
33
|
assert t.ok, "Coins not set"
|
|
34
34
|
logging.info(f"{client.ex.name}: {ExAction.set_coins.name} - ok")
|
|
35
35
|
|
|
@@ -37,7 +37,7 @@ class TestEx(BaseTest):
|
|
|
37
37
|
async def test_set_curs(self, clients: list[BaseExClient]):
|
|
38
38
|
for client in clients:
|
|
39
39
|
await client.set_curs()
|
|
40
|
-
t, _ = await ExStat.update_or_create({"ok": True}, ex=client.ex, action=ExAction.set_curs)
|
|
40
|
+
t, _ = await models.ExStat.update_or_create({"ok": True}, ex=client.ex, action=ExAction.set_curs)
|
|
41
41
|
assert t.ok, "Curs not set"
|
|
42
42
|
logging.info(f"{client.ex.name}: {ExAction.set_curs.name} - ok")
|
|
43
43
|
|
|
@@ -45,7 +45,7 @@ class TestEx(BaseTest):
|
|
|
45
45
|
async def test_set_pms(self, clients: list[BaseExClient]):
|
|
46
46
|
for client in clients:
|
|
47
47
|
await client.set_pms()
|
|
48
|
-
t, _ = await ExStat.update_or_create({"ok": True}, ex=client.ex, action=ExAction.set_pms)
|
|
48
|
+
t, _ = await models.ExStat.update_or_create({"ok": True}, ex=client.ex, action=ExAction.set_pms)
|
|
49
49
|
assert t.ok, "Pms not set"
|
|
50
50
|
logging.info(f"{client.ex.name}: {ExAction.set_pms.name} - ok")
|
|
51
51
|
|
|
@@ -53,7 +53,7 @@ class TestEx(BaseTest):
|
|
|
53
53
|
async def test_set_pairs(self, clients: list[BaseExClient]):
|
|
54
54
|
for client in clients:
|
|
55
55
|
await client.set_pairs()
|
|
56
|
-
t, _ = await ExStat.update_or_create({"ok": True}, ex=client.ex, action=ExAction.set_pairs)
|
|
56
|
+
t, _ = await models.ExStat.update_or_create({"ok": True}, ex=client.ex, action=ExAction.set_pairs)
|
|
57
57
|
assert t.ok, "Pairs not set"
|
|
58
58
|
logging.info(f"{client.ex.name}: {ExAction.set_pairs.name} - ok")
|
|
59
59
|
|
|
@@ -105,10 +105,24 @@ class TestEx(BaseTest):
|
|
|
105
105
|
# 24
|
|
106
106
|
async def test_ads(self, clients: list[BaseExClient]):
|
|
107
107
|
for client in clients:
|
|
108
|
-
cur = await Curex.filter(cur__ticker="EUR", ex=client.ex).first().values_list("exid", flat=True)
|
|
109
|
-
coin = await Coinex.filter(coin__ticker="USDT", ex=client.ex).first().values_list("exid", flat=True)
|
|
108
|
+
cur = await models.Curex.filter(cur__ticker="EUR", ex=client.ex).first().values_list("exid", flat=True)
|
|
109
|
+
coin = await models.Coinex.filter(coin__ticker="USDT", ex=client.ex).first().values_list("exid", flat=True)
|
|
110
110
|
ads: list[BaseAd] = await client.ads(coin, cur, False)
|
|
111
111
|
ok = self.is_list_of_objects(ads, BaseAd)
|
|
112
|
-
t, _ = await ExStat.update_or_create({"ok": ok}, ex=client.ex, action=ExAction.ads)
|
|
112
|
+
t, _ = await models.ExStat.update_or_create({"ok": ok}, ex=client.ex, action=ExAction.ads)
|
|
113
113
|
assert t.ok, "No ads"
|
|
114
114
|
logging.info(f"{client.ex.name}: {ExAction.ads.name} - ok")
|
|
115
|
+
|
|
116
|
+
async def test_race(self):
|
|
117
|
+
races = await models.Race.all().prefetch_related("road__ad")
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
# price_dict = {race.id: race.road.ad.price for race in races}
|
|
122
|
+
# print(price_dict)
|
|
123
|
+
# sorted_dict = dict(sorted(price_dict.items(), key=lambda x: x[1]))
|
|
124
|
+
# print(sorted_dict)
|
|
125
|
+
# for race in races:
|
|
126
|
+
# print(f"{race.id}: {race.road.ad.price}")
|
|
127
|
+
# for race in races:
|
|
128
|
+
# print(race.id)
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
from abc import abstractmethod
|
|
2
2
|
|
|
3
3
|
from pyro_client.client.file import FileClient
|
|
4
|
+
from xync_client.Abc.PmAgent import PmAgentClient
|
|
4
5
|
from xync_schema.models import Actor
|
|
5
6
|
|
|
6
7
|
from xync_client.Abc.Agent import BaseAgentClient
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
class BaseInAgentClient:
|
|
11
|
+
pmacs: dict[int, PmAgentClient] = {}
|
|
12
|
+
|
|
10
13
|
def __init__(self, actor: Actor, bot: FileClient):
|
|
11
14
|
self.agent_client: BaseAgentClient = actor.client(bot)
|
|
12
15
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
from abc import abstractmethod, ABCMeta
|
|
2
2
|
from asyncio import get_running_loop
|
|
3
|
+
from decimal import Decimal
|
|
3
4
|
from enum import StrEnum
|
|
4
5
|
|
|
5
6
|
from playwright.async_api import Page, Playwright
|
|
6
7
|
from pyro_client.client.file import FileClient
|
|
7
|
-
|
|
8
8
|
from xync_client.loader import TOKEN
|
|
9
9
|
from xync_schema.enums import UserStatus
|
|
10
10
|
from xync_schema.models import PmAgent, User
|
|
@@ -41,8 +41,8 @@ class PmAgentClient(metaclass=ABCMeta):
|
|
|
41
41
|
await self.bot.send(f"No active users with agent for {self.norm}!", self.uid)
|
|
42
42
|
raise Exception(f"No active users for {self.norm}!")
|
|
43
43
|
|
|
44
|
-
browser = await pw.chromium.launch(channel="chrome", headless=not headed)
|
|
45
|
-
context = await browser.new_context(storage_state=self.agent.state)
|
|
44
|
+
self.browser = await pw.chromium.launch(channel="chrome", headless=not headed)
|
|
45
|
+
context = await self.browser.new_context(storage_state=self.agent.state)
|
|
46
46
|
self.page = await context.new_page()
|
|
47
47
|
await self.page.goto(self.pages.SEND) # Оптимистично переходим сразу на страницу отправки
|
|
48
48
|
if self.page.url.startswith(self.pages.LOGIN): # Если перебросило на страницу логина
|
|
@@ -57,7 +57,7 @@ class PmAgentClient(metaclass=ABCMeta):
|
|
|
57
57
|
|
|
58
58
|
async def _idle(self): # todo: не мешать другим процессам, обновлять на другой вкладке?
|
|
59
59
|
while (await User.get(username_id=self.uid)).status >= UserStatus.ACTIVE:
|
|
60
|
-
await self.page.wait_for_timeout(
|
|
60
|
+
await self.page.wait_for_timeout(30 * 1000)
|
|
61
61
|
await self.page.reload()
|
|
62
62
|
await self.bot.send(self.norm + " stoped", self.uid)
|
|
63
63
|
await self.stop()
|
|
@@ -79,7 +79,7 @@ class PmAgentClient(metaclass=ABCMeta):
|
|
|
79
79
|
async def send(self, dest, amount: int, cur: str) -> tuple[int, bytes]: ...
|
|
80
80
|
|
|
81
81
|
@abstractmethod # проверка поступления определенной суммы за последние пол часа (минимум), return точную сумму
|
|
82
|
-
async def check_in(self, amount: int, cur: str, tid: str | int = None) -> float | None: ...
|
|
82
|
+
async def check_in(self, amount: int | Decimal | float, cur: str, tid: str | int = None) -> float | None: ...
|
|
83
83
|
|
|
84
84
|
@abstractmethod # видео входа в аккаунт, и переход в историю поступлений за последние сутки (минимум)
|
|
85
85
|
async def proof(self) -> bytes: ...
|