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.
Files changed (126) hide show
  1. {xync_client-0.0.93.dev1/xync_client.egg-info → xync_client-0.0.93.dev17}/PKG-INFO +1 -1
  2. xync_client-0.0.93.dev17/index.html +397 -0
  3. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/tests/TestEx.py +23 -9
  4. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Abc/InAgent.py +3 -0
  5. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Abc/PmAgent.py +5 -5
  6. xync_client-0.0.93.dev17/xync_client/Bybit/InAgent.py +242 -0
  7. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Bybit/agent.py +113 -91
  8. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Bybit/etype/order.py +12 -7
  9. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Pms/Ozon/__init__.py +5 -2
  10. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Pms/Payeer/__init__.py +13 -7
  11. xync_client-0.0.93.dev17/xync_client/Pms/Payeer/api.py +25 -0
  12. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Pms/Payeer/login.py +7 -4
  13. xync_client-0.0.93.dev17/xync_client/Pms/Sber/__init__.py +123 -0
  14. xync_client-0.0.93.dev17/xync_client/Pms/Sber/utils.py +48 -0
  15. xync_client-0.0.93.dev17/xync_client/Pms/Tinkoff/__init__.py +135 -0
  16. xync_client-0.0.93.dev17/xync_client/Pms/Xync/__main__.py +536 -0
  17. xync_client-0.0.93.dev17/xync_client/Pms/Xync/ed.py +156 -0
  18. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17/xync_client.egg-info}/PKG-INFO +1 -1
  19. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client.egg-info/SOURCES.txt +5 -0
  20. xync_client-0.0.93.dev1/xync_client/Bybit/InAgent.py +0 -123
  21. xync_client-0.0.93.dev1/xync_client/Pms/Sber/__init__.py +0 -164
  22. xync_client-0.0.93.dev1/xync_client/Pms/Tinkoff/__init__.py +0 -117
  23. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/.env.sample +0 -0
  24. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/.gitignore +0 -0
  25. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/.pre-commit-config.yaml +0 -0
  26. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/README.md +0 -0
  27. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/__init__.py +0 -0
  28. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/makefile +0 -0
  29. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/pyproject.toml +0 -0
  30. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/setup.cfg +0 -0
  31. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/tests/TestAgent.py +0 -0
  32. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/tests/TestAsset.py +0 -0
  33. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/tests/TestOrder.py +0 -0
  34. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/tests/_todo_refact/Binance/test_binance.py +0 -0
  35. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/tests/_todo_refact/Bybit/test_bybit.py +0 -0
  36. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/tests/_todo_refact/Bybit/test_bybit_p2p.py +0 -0
  37. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/tests/_todo_refact/Gate/test_gate.py +0 -0
  38. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/tests/_todo_refact/Wallet/test_agent.py +0 -0
  39. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/tests/_todo_refact/Wallet/test_ex.py +0 -0
  40. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/tests/_todo_refact/__init__.py +0 -0
  41. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/tests/_todo_refact/_test_ex.py +0 -0
  42. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Abc/Agent.py +0 -0
  43. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Abc/Asset.py +0 -0
  44. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Abc/Auth.py +0 -0
  45. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Abc/BaseTest.py +0 -0
  46. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Abc/Ex.py +0 -0
  47. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Abc/Exception.py +0 -0
  48. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Abc/Order.py +0 -0
  49. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Abc/xtype.py +0 -0
  50. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Binance/__init__.py +0 -0
  51. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Binance/binance_async.py +0 -0
  52. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Binance/earn_api.py +0 -0
  53. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Binance/etype/ad.py +0 -0
  54. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Binance/etype/pm.py +0 -0
  55. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Binance/ex.py +0 -0
  56. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Binance/exceptions.py +0 -0
  57. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Binance/sapi.py +0 -0
  58. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Binance/web_c2c.py +0 -0
  59. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/BingX/__init__.py +0 -0
  60. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/BingX/agent.py +0 -0
  61. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/BingX/base.py +0 -0
  62. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/BingX/etype/ad.py +0 -0
  63. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/BingX/etype/pm.py +0 -0
  64. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/BingX/ex.py +0 -0
  65. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/BingX/req.mjs +0 -0
  66. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/BingX/sign.js +0 -0
  67. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/BitGet/__init__.py +0 -0
  68. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/BitGet/agent.py +0 -0
  69. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/BitGet/etype/ad.py +0 -0
  70. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/BitGet/ex.py +0 -0
  71. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/BitPapa/ex.py +0 -0
  72. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Bybit/etype/ad.py +0 -0
  73. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Bybit/etype/cred.py +0 -0
  74. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Bybit/ex.py +0 -0
  75. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Bybit/order.py +0 -0
  76. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Bybit/web_earn.py +0 -0
  77. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Bybit/web_p2p.py +0 -0
  78. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Bybit/ws.py +0 -0
  79. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Gate/etype/ad.py +0 -0
  80. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Gate/ex.py +0 -0
  81. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Gate/premarket.py +0 -0
  82. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Gmail/__init__.py +0 -0
  83. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Htx/agent.py +0 -0
  84. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Htx/earn.py +0 -0
  85. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Htx/etype/__init__.py +0 -0
  86. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Htx/etype/ad.py +0 -0
  87. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Htx/etype/cred.py +0 -0
  88. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Htx/etype/pm.py +0 -0
  89. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Htx/etype/test.py +0 -0
  90. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Htx/ex.py +0 -0
  91. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/KuCoin/etype/ad.py +0 -0
  92. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/KuCoin/etype/pm.py +0 -0
  93. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/KuCoin/ex.py +0 -0
  94. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/KuCoin/web.py +0 -0
  95. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Mexc/etype/ad.py +0 -0
  96. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Mexc/etype/pm.py +0 -0
  97. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Mexc/ex.py +0 -0
  98. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Okx/etype/ad.py +0 -0
  99. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Okx/etype/pm.py +0 -0
  100. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Okx/ex.py +0 -0
  101. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Pms/.gitignore +0 -0
  102. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Pms/Alfa/__init__.py +0 -0
  103. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Pms/Alfa/state.json +0 -0
  104. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Pms/MTS/__init__.py +0 -0
  105. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Pms/Payeer/.gitignore +0 -0
  106. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Pms/Volet/__init__.py +0 -0
  107. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Pms/Volet/_todo_req/req.mjs +0 -0
  108. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Pms/Volet/_todo_req/req.py +0 -0
  109. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Pms/Volet/api.py +0 -0
  110. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Pms/Volet/pl.py +0 -0
  111. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/Pms/Yandex/__init__.py +0 -0
  112. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/TgWallet/agent.py +0 -0
  113. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/TgWallet/asset.py +0 -0
  114. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/TgWallet/auth.py +0 -0
  115. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/TgWallet/ex.py +0 -0
  116. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/TgWallet/inAgent.py +0 -0
  117. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/TgWallet/order.py +0 -0
  118. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/TgWallet/pyd.py +0 -0
  119. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/TgWallet/pyro.py +0 -0
  120. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/TgWallet/web.py +0 -0
  121. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/__init__.py +0 -0
  122. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/loader.py +0 -0
  123. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client/pm_unifier.py +0 -0
  124. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client.egg-info/dependency_links.txt +0 -0
  125. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client.egg-info/requires.txt +0 -0
  126. {xync_client-0.0.93.dev1 → xync_client-0.0.93.dev17}/xync_client.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xync-client
3
- Version: 0.0.93.dev1
3
+ Version: 0.0.93.dev17
4
4
  Author-email: Mike Artemiev <mixartemev@gmail.com>
5
5
  Project-URL: Homepage, https://gitlab.com/XyncNet/client
6
6
  Project-URL: Repository, https://gitlab.com/XyncNet/client
@@ -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 * 1000)
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: ...