xync-client 0.0.145__tar.gz → 0.0.147__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.
Potentially problematic release.
This version of xync-client might be problematic. Click here for more details.
- {xync_client-0.0.145/xync_client.egg-info → xync_client-0.0.147}/PKG-INFO +1 -1
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Abc/Agent.py +2 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Abc/PmAgent.py +1 -1
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Abc/xtype.py +3 -1
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Bybit/InAgent.py +16 -11
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Bybit/agent.py +101 -47
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Bybit/etype/order.py +34 -16
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Gmail/__init__.py +16 -3
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Pms/Payeer/__init__.py +7 -5
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Pms/Volet/__init__.py +1 -1
- {xync_client-0.0.145 → xync_client-0.0.147/xync_client.egg-info}/PKG-INFO +1 -1
- {xync_client-0.0.145 → xync_client-0.0.147}/.env.sample +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/.gitignore +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/.pre-commit-config.yaml +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/README.md +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/__init__.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/makefile +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/pyproject.toml +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/setup.cfg +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/tests/TestAgent.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/tests/TestAsset.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/tests/TestEx.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/tests/TestOrder.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/tests/_todo_refact/Binance/test_binance.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/tests/_todo_refact/Bybit/test_bybit.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/tests/_todo_refact/Bybit/test_bybit_p2p.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/tests/_todo_refact/Gate/test_gate.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/tests/_todo_refact/Wallet/test_agent.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/tests/_todo_refact/Wallet/test_ex.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/tests/_todo_refact/__init__.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/tests/_todo_refact/_test_ex.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Abc/Asset.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Abc/Auth.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Abc/BaseTest.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Abc/Ex.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Abc/Exception.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Abc/HasAbotUid.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Abc/InAgent.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Abc/Order.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Binance/__init__.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Binance/binance_async.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Binance/earn_api.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Binance/etype/ad.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Binance/etype/pm.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Binance/ex.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Binance/exceptions.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Binance/sapi.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Binance/web_c2c.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/BingX/__init__.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/BingX/agent.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/BingX/base.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/BingX/etype/ad.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/BingX/etype/pm.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/BingX/ex.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/BingX/req.mjs +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/BingX/sign.js +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/BitGet/__init__.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/BitGet/agent.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/BitGet/etype/ad.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/BitGet/ex.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/BitPapa/ex.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Bybit/etype/ad.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Bybit/etype/cred.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Bybit/ex.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Bybit/order.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Bybit/web_earn.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Bybit/web_p2p.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Bybit/ws.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Gate/etype/ad.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Gate/ex.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Gate/premarket.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Htx/agent.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Htx/earn.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Htx/etype/__init__.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Htx/etype/ad.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Htx/etype/cred.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Htx/etype/pm.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Htx/etype/test.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Htx/ex.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/KuCoin/etype/ad.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/KuCoin/etype/pm.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/KuCoin/ex.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/KuCoin/web.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Mexc/etype/ad.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Mexc/etype/pm.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Mexc/ex.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Okx/etype/ad.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Okx/etype/pm.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Okx/ex.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Pms/.gitignore +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Pms/Alfa/__init__.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Pms/Alfa/state.json +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Pms/MTS/__init__.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Pms/Ozon/__init__.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Pms/Payeer/.gitignore +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Pms/Payeer/api.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Pms/Payeer/login.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Pms/Sber/__init__.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Pms/Sber/utils.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Pms/Tinkoff/__init__.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Pms/Volet/_todo_req/req.mjs +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Pms/Volet/_todo_req/req.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Pms/Volet/api.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Pms/Volet/pl.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Pms/Xync/__main__.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Pms/Xync/ed.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/Pms/Yandex/__init__.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/TgWallet/agent.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/TgWallet/asset.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/TgWallet/auth.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/TgWallet/ex.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/TgWallet/inAgent.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/TgWallet/order.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/TgWallet/pyd.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/TgWallet/pyro.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/TgWallet/web.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/__init__.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/details.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/loader.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client/pm_unifier.py +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client.egg-info/SOURCES.txt +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client.egg-info/dependency_links.txt +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client.egg-info/requires.txt +0 -0
- {xync_client-0.0.145 → xync_client-0.0.147}/xync_client.egg-info/top_level.txt +0 -0
|
@@ -10,6 +10,7 @@ from xync_schema.xtype import BaseAd
|
|
|
10
10
|
|
|
11
11
|
from xync_client.Abc.Ex import BaseExClient
|
|
12
12
|
from xync_client.Abc.xtype import CredExOut, BaseOrderReq, BaseAdUpdate
|
|
13
|
+
from xync_client.Gmail import GmClient
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
class BaseAgentClient(HttpClient):
|
|
@@ -28,6 +29,7 @@ class BaseAgentClient(HttpClient):
|
|
|
28
29
|
self.fbot = fbot
|
|
29
30
|
self.agent: Agent = agent
|
|
30
31
|
self.actor: Actor = agent.actor
|
|
32
|
+
self.gmail = GmClient(agent.actor.person.user)
|
|
31
33
|
super().__init__(self.actor.ex.host_p2p, headers, cookies)
|
|
32
34
|
self.ex_client: BaseExClient = self.actor.ex.client(fbot)
|
|
33
35
|
|
|
@@ -32,7 +32,7 @@ class PmAgentClient(HasAbotUid, metaclass=ABCMeta):
|
|
|
32
32
|
ubot: FileClient | UserClient = None
|
|
33
33
|
page: Page
|
|
34
34
|
pages: type(StrEnum) = Pages
|
|
35
|
-
last_active: datetime =
|
|
35
|
+
last_active: datetime = now()
|
|
36
36
|
with_userbot: bool = False
|
|
37
37
|
_is_started: bool = False
|
|
38
38
|
|
|
@@ -53,7 +53,9 @@ class BaseOrderReq(BaseModel):
|
|
|
53
53
|
asset_amount: float | None = None
|
|
54
54
|
fiat_amount: float | None = None
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
pm_id: int = (None,)
|
|
57
|
+
|
|
58
|
+
# todo: mv from base to special ex class
|
|
57
59
|
amount_is_fiat: bool = True
|
|
58
60
|
is_sell: bool = None
|
|
59
61
|
cur_exid: int | str = None
|
|
@@ -77,7 +77,7 @@ class InAgentClient(BaseInAgentClient):
|
|
|
77
77
|
while resp := await websocket.recv():
|
|
78
78
|
if data := json.loads(resp):
|
|
79
79
|
upd, order_db = None, None
|
|
80
|
-
logging.info(f" {
|
|
80
|
+
logging.info(f" {now().strftime('%H:%M:%S')} upd: {data.get('topic')}:{data.get('type')}")
|
|
81
81
|
match data.get("topic"):
|
|
82
82
|
case "OTC_ORDER_STATUS":
|
|
83
83
|
match data["type"]:
|
|
@@ -108,10 +108,11 @@ class InAgentClient(BaseInAgentClient):
|
|
|
108
108
|
if not (pmacdx := await self.get_pma_by_cdex(order)):
|
|
109
109
|
continue
|
|
110
110
|
pma, cdx = pmacdx
|
|
111
|
-
am, tid = pma.check_in(
|
|
111
|
+
am, tid = await pma.check_in(
|
|
112
112
|
Decimal(order.amount),
|
|
113
113
|
cdx.cred.pmcur.cur.ticker,
|
|
114
|
-
|
|
114
|
+
# todo: почему в московском час.поясе?
|
|
115
|
+
datetime.fromtimestamp(float(order.transferDate) / 1000),
|
|
115
116
|
)
|
|
116
117
|
if not tid:
|
|
117
118
|
logging.info(
|
|
@@ -142,9 +143,13 @@ class InAgentClient(BaseInAgentClient):
|
|
|
142
143
|
if (
|
|
143
144
|
o["amount"] == order.amount
|
|
144
145
|
and o["id"] != upd.id
|
|
145
|
-
and int(order.createDate)
|
|
146
|
-
|
|
147
|
-
#
|
|
146
|
+
and int(order.createDate)
|
|
147
|
+
< int(o["createDate"]) + 15 * 60 * 1000
|
|
148
|
+
# get full_order from o, and cred or pm from full_order:
|
|
149
|
+
and self.agent_client.api.get_order_details(orderId=o["id"])[
|
|
150
|
+
"result"
|
|
151
|
+
]["paymentTermList"][0]["accountNo"]
|
|
152
|
+
== order.paymentTermList[0].accountNo
|
|
148
153
|
)
|
|
149
154
|
]
|
|
150
155
|
curex = await models.CurEx.get(
|
|
@@ -155,7 +160,7 @@ class InAgentClient(BaseInAgentClient):
|
|
|
155
160
|
cred_id=order_db.cred_id,
|
|
156
161
|
amount=int(float(order.amount) * 10**curex.scale),
|
|
157
162
|
status__not_in=[OrderStatus.completed, OrderStatus.canceled],
|
|
158
|
-
created_at__gt=now() - timedelta(
|
|
163
|
+
created_at__gt=now() - timedelta(minutes=15),
|
|
159
164
|
)
|
|
160
165
|
if pos or pos_db:
|
|
161
166
|
await self.agent_client.ex_client.bot.send(
|
|
@@ -169,10 +174,10 @@ class InAgentClient(BaseInAgentClient):
|
|
|
169
174
|
# !!! ОТПРАВЛЯЕМ ДЕНЬГИ !!!
|
|
170
175
|
self.agent_client.api.release_assets(orderId=upd.id)
|
|
171
176
|
logging.info(
|
|
172
|
-
f"Order {order.id} created, paid before #{tid}:{am} at {order.createDate}, and RELEASED at {
|
|
177
|
+
f"Order {order.id} created, paid before #{tid}:{am} at {order.createDate}, and RELEASED at {now()}"
|
|
173
178
|
)
|
|
174
179
|
elif upd.side == 1: # я покупатель - ждем мою оплату
|
|
175
|
-
continue # logging.warning(f"Order {order.id} PAID at {
|
|
180
|
+
continue # logging.warning(f"Order {order.id} PAID at {now()}: {int_am}")
|
|
176
181
|
else:
|
|
177
182
|
...
|
|
178
183
|
# todo: check is always canceling
|
|
@@ -416,7 +421,7 @@ async def main():
|
|
|
416
421
|
actor__person__user__status=UserStatus.ACTIVE,
|
|
417
422
|
actor__person__user__pm_agents__isnull=False,
|
|
418
423
|
)
|
|
419
|
-
.prefetch_related("actor__ex", "
|
|
424
|
+
.prefetch_related("actor__ex", "actor__person__user__gmail")
|
|
420
425
|
.first()
|
|
421
426
|
)
|
|
422
427
|
pm_agents = await models.PmAgent.filter(
|
|
@@ -434,7 +439,7 @@ async def main():
|
|
|
434
439
|
# payeer_cl = Client(actor.person.user.username_id)
|
|
435
440
|
for pma in pm_agents:
|
|
436
441
|
pcl: PmAgentClient = pma.client(bbot)
|
|
437
|
-
cl.pmacs[pma.pm_id] = await pcl.start(await async_playwright().start(),
|
|
442
|
+
cl.pmacs[pma.pm_id] = await pcl.start(await async_playwright().start(), False)
|
|
438
443
|
try:
|
|
439
444
|
_ = await cl.start_listen()
|
|
440
445
|
except Exception as e:
|
|
@@ -31,7 +31,7 @@ from xync_schema.enums import OrderStatus
|
|
|
31
31
|
from xync_schema.models import Actor, Cond, CondSim, PmCur, PairSide, Agent
|
|
32
32
|
|
|
33
33
|
from xync_client.Abc.Agent import BaseAgentClient
|
|
34
|
-
from xync_client.Abc.xtype import
|
|
34
|
+
from xync_client.Abc.xtype import FlatDict, BaseOrderReq
|
|
35
35
|
from xync_client.Bybit.etype.ad import AdPostRequest, AdUpdateRequest, Ad, AdStatus
|
|
36
36
|
from xync_client.Bybit.etype.cred import CredEpyd
|
|
37
37
|
from xync_client.Bybit.etype.order import (
|
|
@@ -43,6 +43,8 @@ from xync_client.Bybit.etype.order import (
|
|
|
43
43
|
OrderFull,
|
|
44
44
|
Message,
|
|
45
45
|
Status,
|
|
46
|
+
OrderSellRequest,
|
|
47
|
+
TakeAdReq,
|
|
46
48
|
)
|
|
47
49
|
from xync_client.loader import TORM, NET_TOKEN, PAY_TOKEN
|
|
48
50
|
|
|
@@ -273,20 +275,39 @@ class AgentClient(BaseAgentClient): # Bybit client
|
|
|
273
275
|
security_risk_token = data["result"]["securityRiskToken"]
|
|
274
276
|
return security_risk_token
|
|
275
277
|
|
|
276
|
-
def _check_2fa(self, risk_token):
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
278
|
+
async def _check_2fa(self, risk_token) -> int:
|
|
279
|
+
cres = await self._post("/user/public/risk/components", {"risk_token": risk_token})
|
|
280
|
+
if cres["ret_msg"] != "success":
|
|
281
|
+
raise HTTPException("get")
|
|
282
|
+
cres = cres["result"]["component_list"]
|
|
283
|
+
res = await self._post(
|
|
284
|
+
"/user/public/risk/verify",
|
|
285
|
+
{
|
|
286
|
+
"risk_token": risk_token,
|
|
287
|
+
"component_list": {c["component_id"]: self.__get_2fa(c["component_id"]) for c in cres},
|
|
288
|
+
},
|
|
284
289
|
)
|
|
285
290
|
if res["ret_msg"] != "success":
|
|
286
|
-
|
|
287
|
-
sleep(5)
|
|
288
|
-
self._check_2fa(risk_token)
|
|
289
|
-
return res
|
|
291
|
+
logging.error("Wrong 2fa, wait 5 secs and retry..")
|
|
292
|
+
await sleep(5)
|
|
293
|
+
await self._check_2fa(risk_token)
|
|
294
|
+
return res["ret_code"]
|
|
295
|
+
|
|
296
|
+
async def __get_2fa(self, typ: Literal["google2fa", "email_verify", "payment_password_verify"], rt: str = None):
|
|
297
|
+
if typ == "google2fa":
|
|
298
|
+
bybit_secret = self.agent.auth["2fa"]
|
|
299
|
+
totp = pyotp.TOTP(bybit_secret)
|
|
300
|
+
return totp.now()
|
|
301
|
+
elif typ == "email_verify":
|
|
302
|
+
res = await self._post("/user/public/risk/send/code", {"risk_token": rt, "component_id": "email_verify"})
|
|
303
|
+
if res["ret_msg"] != "success":
|
|
304
|
+
return self.gmail.bybit_code()
|
|
305
|
+
elif cool_down := int(res["result"]["cool_down"]):
|
|
306
|
+
await sleep(cool_down)
|
|
307
|
+
return self.gmail.bybit_code()
|
|
308
|
+
elif typ == "payment_password_verify":
|
|
309
|
+
return self.agent.auth["pass"]
|
|
310
|
+
raise Exception("2fa fail")
|
|
290
311
|
|
|
291
312
|
def _post_ad(self, risk_token: str):
|
|
292
313
|
self.create_ad_body.update({"securityRiskToken": risk_token})
|
|
@@ -340,27 +361,56 @@ class AgentClient(BaseAgentClient): # Bybit client
|
|
|
340
361
|
data = self.api.remove_ad(itemId=ad_id)
|
|
341
362
|
return data
|
|
342
363
|
|
|
343
|
-
async def
|
|
344
|
-
|
|
345
|
-
if
|
|
346
|
-
|
|
347
|
-
|
|
364
|
+
async def __preorder_request(self, ad_id: int) -> PreOrderResp:
|
|
365
|
+
res = await self._post("/fiat/otc/item/simple", data={"item_id": str(ad_id)})
|
|
366
|
+
if res["ret_code"] == 0:
|
|
367
|
+
res = res["result"]
|
|
368
|
+
return PreOrderResp.model_validate(res)
|
|
369
|
+
|
|
370
|
+
async def __order_request_build(self, por: PreOrderResp, br: BaseOrderReq) -> OrderRequest:
|
|
348
371
|
req = OrderRequest(
|
|
349
|
-
itemId=
|
|
372
|
+
itemId=por.id,
|
|
350
373
|
tokenId=br.coin_exid,
|
|
351
374
|
currencyId=br.cur_exid,
|
|
352
|
-
side=
|
|
353
|
-
amount=str(br.fiat_amount
|
|
354
|
-
curPrice=
|
|
355
|
-
quantity=str(
|
|
356
|
-
flag="amount"
|
|
375
|
+
side="1" if br.is_sell else "0",
|
|
376
|
+
amount=str(br.fiat_amount),
|
|
377
|
+
curPrice=por.curPrice,
|
|
378
|
+
quantity=str(round(br.fiat_amount / float(por.price), br.coin_scale)),
|
|
379
|
+
flag="amount",
|
|
380
|
+
# paymentType="51",
|
|
381
|
+
# paymentId="20399134",
|
|
382
|
+
# online="0"
|
|
357
383
|
)
|
|
384
|
+
if br.is_sell:
|
|
385
|
+
credex = await models.CredEx.get(
|
|
386
|
+
cred__person_id=self.actor.person_id,
|
|
387
|
+
pmcur__pm__pmexs__exid=por.payments[0],
|
|
388
|
+
pmcur__pm__pmexs__ex_id=self.ex_client.ex.id,
|
|
389
|
+
pmcur__cur_id=br.cur_exid,
|
|
390
|
+
)
|
|
391
|
+
req = OrderSellRequest(**req.model_dump(), paymentType=por.payments[0], paymentId=str(credex.exid))
|
|
392
|
+
return req
|
|
393
|
+
|
|
394
|
+
async def _order_request(self, bor: BaseOrderReq) -> OrderResp:
|
|
395
|
+
por: PreOrderResp = await self.__preorder_request(bor.ad_id)
|
|
396
|
+
req: OrderRequest | OrderSellRequest = await self.__order_request_build(por, bor)
|
|
358
397
|
# вот непосредственно сам запрос на ордер
|
|
359
|
-
|
|
398
|
+
return await self.__order_create(req, bor)
|
|
399
|
+
|
|
400
|
+
async def __order_create(self, req: OrderRequest | OrderSellRequest, bor: BaseOrderReq) -> OrderResp:
|
|
401
|
+
res: dict = await self._post("/fiat/otc/order/create", data=req.model_dump())
|
|
360
402
|
if res["ret_code"] == 0:
|
|
361
|
-
|
|
403
|
+
resp = OrderResp.model_validate(res["result"])
|
|
362
404
|
elif res["ret_code"] == 912120030 or res["ret_msg"] == "The price has changed, please try again later.":
|
|
363
|
-
|
|
405
|
+
resp = await self._order_request(bor)
|
|
406
|
+
if not resp.orderId and resp.needSecurityRisk:
|
|
407
|
+
if rc := await self._check_2fa(resp.securityRiskToken):
|
|
408
|
+
await self.bbot.send(self.actor.person.user.username_id, f"Bybit 2fa: {rc}")
|
|
409
|
+
raise Exception(f"Bybit 2fa: {rc}")
|
|
410
|
+
# еще раз уже с токеном
|
|
411
|
+
req.securityRiskToken = resp.securityRiskToken
|
|
412
|
+
resp = await self.__order_create(req, bor)
|
|
413
|
+
return resp
|
|
364
414
|
|
|
365
415
|
async def cancel_order(self, order_id: str) -> bool:
|
|
366
416
|
cr = CancelOrderReq(orderId=order_id)
|
|
@@ -546,7 +596,7 @@ class AgentClient(BaseAgentClient): # Bybit client
|
|
|
546
596
|
to = ((odb.payed_at or odb.created_at) + timedelta(minutes=180 + 30)).isoformat(sep=" ").split("+")[0]
|
|
547
597
|
tsa = [
|
|
548
598
|
t
|
|
549
|
-
for tid, t in self.hist.items()
|
|
599
|
+
for tid, t in (self.hist.items() if self.hist else [])
|
|
550
600
|
if (ecredex.accountNo == t["to"] and t["from"] != "@merchant" and frm < t["date"] < to)
|
|
551
601
|
]
|
|
552
602
|
buyer_person = (
|
|
@@ -1185,6 +1235,20 @@ class AgentClient(BaseAgentClient): # Bybit client
|
|
|
1185
1235
|
|
|
1186
1236
|
self.tree = tree
|
|
1187
1237
|
|
|
1238
|
+
async def take_ad(self, req: TakeAdReq):
|
|
1239
|
+
ad: Ad = Ad.model_validate(self.api.get_ad_details(itemId=req.ad_id))
|
|
1240
|
+
bor = BaseOrderReq(
|
|
1241
|
+
ad_id=str(ad.id),
|
|
1242
|
+
fiat_amount=req.amount,
|
|
1243
|
+
is_sell=bool(ad.side),
|
|
1244
|
+
cur_exid=ad.currencyId,
|
|
1245
|
+
coin_exid=ad.tokenId,
|
|
1246
|
+
coin_scale=ad.token.scale,
|
|
1247
|
+
pm_id=req.pm_id,
|
|
1248
|
+
)
|
|
1249
|
+
resp: OrderResp = await self._order_request(bor)
|
|
1250
|
+
return resp
|
|
1251
|
+
|
|
1188
1252
|
|
|
1189
1253
|
def ms2utc(msk_ts_str: str):
|
|
1190
1254
|
return datetime.fromtimestamp(int(msk_ts_str) / 1000, timezone(timedelta(hours=3), name="MSK"))
|
|
@@ -1262,20 +1326,20 @@ async def main():
|
|
|
1262
1326
|
else: # параметры гонки изменены
|
|
1263
1327
|
...
|
|
1264
1328
|
|
|
1265
|
-
|
|
1329
|
+
agent = (
|
|
1266
1330
|
await models.Agent.filter(actor__ex_id=4, auth__isnull=False, active=True)
|
|
1267
|
-
.prefetch_related("actor__ex", "
|
|
1331
|
+
.prefetch_related("actor__ex", "actor__person__user__gmail")
|
|
1268
1332
|
.first()
|
|
1269
1333
|
)
|
|
1270
1334
|
filebot = FileClient(NET_TOKEN)
|
|
1271
1335
|
await filebot.start()
|
|
1272
1336
|
# b.add_handler(MessageHandler(cond_start_handler, command("cond")))
|
|
1273
|
-
cl: AgentClient =
|
|
1337
|
+
cl: AgentClient = agent.client(filebot, XyncBot(PAY_TOKEN, cn))
|
|
1274
1338
|
|
|
1275
1339
|
# await cl.ex_client.set_pairs()
|
|
1276
1340
|
# await cl.ex_client.set_pms()
|
|
1277
|
-
|
|
1278
|
-
|
|
1341
|
+
await cl.set_creds()
|
|
1342
|
+
await cl.export_my_ads()
|
|
1279
1343
|
|
|
1280
1344
|
# создание гонок по мои активным объявам:
|
|
1281
1345
|
# for ma in cl.my_ads():
|
|
@@ -1323,7 +1387,7 @@ async def main():
|
|
|
1323
1387
|
# )
|
|
1324
1388
|
# await cl.get_api_orders() # 43, 1741294800000, 1749157199999)
|
|
1325
1389
|
|
|
1326
|
-
races = await models.Race.filter(started=True).prefetch_related(
|
|
1390
|
+
races = await models.Race.filter(started=True, road__ad__maker_id=agent.actor_id).prefetch_related(
|
|
1327
1391
|
"road__ad__pair_side__pair__cur",
|
|
1328
1392
|
"road__ad__pms",
|
|
1329
1393
|
)
|
|
@@ -1335,20 +1399,10 @@ async def main():
|
|
|
1335
1399
|
# cl.get_api_orders(), # 10, 1738357200000, 1742504399999
|
|
1336
1400
|
)
|
|
1337
1401
|
except Exception as e:
|
|
1338
|
-
await filebot.send("🤬Bybit agent CRASHED!!!🤬", actor.person.user.username_id)
|
|
1339
|
-
await filebot.send(e.__repr__(), actor.person.user.username_id)
|
|
1402
|
+
await filebot.send("🤬Bybit agent CRASHED!!!🤬", agent.actor.person.user.username_id)
|
|
1403
|
+
await filebot.send(e.__repr__(), agent.actor.person.user.username_id)
|
|
1340
1404
|
raise e
|
|
1341
|
-
|
|
1342
|
-
# ad_id="1861440060199632896",
|
|
1343
|
-
# # asset_amount=40,
|
|
1344
|
-
# fiat_amount=3000,
|
|
1345
|
-
# amount_is_fiat=True,
|
|
1346
|
-
# is_sell=False,
|
|
1347
|
-
# cur_exid=rub.exid,
|
|
1348
|
-
# coin_exid=usdt.exid,
|
|
1349
|
-
# coin_scale=usdt.coin.scale,
|
|
1350
|
-
# )
|
|
1351
|
-
# res: OrderResp = await cl.order_request(bor)
|
|
1405
|
+
|
|
1352
1406
|
# await cl.cancel_order(res.orderId)
|
|
1353
1407
|
await filebot.stop()
|
|
1354
1408
|
await cl.close()
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
from datetime import datetime
|
|
2
1
|
from enum import IntEnum
|
|
3
2
|
from typing import Literal
|
|
4
3
|
|
|
@@ -45,6 +44,12 @@ class StatusApi(IntEnum):
|
|
|
45
44
|
waiting_for_objection = 110
|
|
46
45
|
|
|
47
46
|
|
|
47
|
+
class TakeAdReq(BaseModel):
|
|
48
|
+
ad_id: int | str
|
|
49
|
+
amount: float
|
|
50
|
+
pm_id: int = None
|
|
51
|
+
|
|
52
|
+
|
|
48
53
|
class OrderRequest(BaseModel):
|
|
49
54
|
class Side(IntEnum):
|
|
50
55
|
BUY = 0
|
|
@@ -60,33 +65,46 @@ class OrderRequest(BaseModel):
|
|
|
60
65
|
flag: Literal["amount", "quantity"]
|
|
61
66
|
version: str = "1.0"
|
|
62
67
|
securityRiskToken: str = ""
|
|
68
|
+
isFromAi: bool = False
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class OrderSellRequest(OrderRequest):
|
|
72
|
+
paymentId: str
|
|
73
|
+
paymentType: str
|
|
63
74
|
|
|
64
75
|
|
|
65
76
|
class PreOrderResp(BaseModel):
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
77
|
+
id: str # bigint
|
|
78
|
+
price: str # float .cur.scale
|
|
79
|
+
lastQuantity: str # float .coin.scale
|
|
80
|
+
curPrice: str # hex 32
|
|
81
|
+
lastPrice: str # float .cur.scale # future
|
|
82
|
+
isOnline: bool
|
|
83
|
+
lastLogoutTime: str # timestamp(0)+0
|
|
73
84
|
payments: list[str] # list[int]
|
|
74
85
|
status: Literal[10, 20]
|
|
75
|
-
paymentTerms: list
|
|
76
|
-
paymentPeriod: Literal[15]
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
86
|
+
paymentTerms: list # empty
|
|
87
|
+
paymentPeriod: Literal[15, 30, 60]
|
|
88
|
+
totalAmount: str # float .cur.scale
|
|
89
|
+
minAmount: str # float .cur.scale
|
|
90
|
+
maxAmount: str # float .cur.scale
|
|
91
|
+
minQuantity: str # float .coin.scale
|
|
92
|
+
maxQuantity: str # float .coin.scale
|
|
93
|
+
itemPriceAvailableTime: str # timestamp(0)+0
|
|
94
|
+
itemPriceValidTime: Literal["45000"]
|
|
83
95
|
itemType: Literal["ORIGIN"]
|
|
96
|
+
shareItem: bool # False
|
|
84
97
|
|
|
85
98
|
|
|
86
99
|
class OrderResp(BaseModel):
|
|
87
100
|
orderId: str
|
|
88
101
|
isNeedConfirm: bool
|
|
102
|
+
confirmId: str = ""
|
|
89
103
|
success: bool
|
|
104
|
+
securityRiskToken: str = ""
|
|
105
|
+
riskTokenType: Literal["challenge"] = None
|
|
106
|
+
riskVersion: Literal["1", "2"] = None
|
|
107
|
+
needSecurityRisk: bool
|
|
90
108
|
isBulkOrder: bool
|
|
91
109
|
confirmed: str = None
|
|
92
110
|
delayTime: str
|
|
@@ -92,8 +92,8 @@ class GmClient(HasAbotUid):
|
|
|
92
92
|
|
|
93
93
|
return {"id": message_id, "subject": subject, "from": from_email, "date": date, "body": body}
|
|
94
94
|
|
|
95
|
-
async def
|
|
96
|
-
if email := self._get_last_email("
|
|
95
|
+
async def volet_confirm(self, amount: float, dt: datetime):
|
|
96
|
+
if email := self._get_last_email("noreply@volet.com", "Please Confirm Withdrawal"): # "Volet.com"
|
|
97
97
|
date = datetime.strptime(email["date"].split(",")[1].split(" +")[0], "%d %b %Y %H:%M:%S")
|
|
98
98
|
if match := re.search(r"Amount: <b>([\d.]+) [A-Z]{3}</b>", email["body"]):
|
|
99
99
|
amt = float(match.group(1))
|
|
@@ -107,6 +107,19 @@ class GmClient(HasAbotUid):
|
|
|
107
107
|
await self.receive("А нет запросов от волета")
|
|
108
108
|
return False
|
|
109
109
|
|
|
110
|
+
async def bybit_code(self, dt: datetime) -> str | None:
|
|
111
|
+
if email := self._get_last_email("Bybit", "[Bybit]Security Code for Your Bybit Account"):
|
|
112
|
+
date = datetime.strptime(email["date"].split(",")[1].split(" +")[0], "%d %b %Y %H:%M:%S")
|
|
113
|
+
if match := re.search(r'<span style="font-size:28pt;color:#ff9c2e">(\d{6})</span>', email["body"]):
|
|
114
|
+
code = match.group(1)
|
|
115
|
+
|
|
116
|
+
if email and date > dt and code:
|
|
117
|
+
get(f"https://account.volet.com/verify/{code}")
|
|
118
|
+
return code
|
|
119
|
+
|
|
120
|
+
await self.receive("А нет запросов от волета")
|
|
121
|
+
return None
|
|
122
|
+
|
|
110
123
|
|
|
111
124
|
async def _test():
|
|
112
125
|
from x_model import init_db
|
|
@@ -115,7 +128,7 @@ async def _test():
|
|
|
115
128
|
|
|
116
129
|
gm = await Gmail.get(id=1).prefetch_related("user__username")
|
|
117
130
|
gmc = GmClient(gm)
|
|
118
|
-
await gmc.
|
|
131
|
+
await gmc.volet_confirm(amount=90, dt=datetime.now())
|
|
119
132
|
|
|
120
133
|
|
|
121
134
|
if __name__ == "__main__":
|
|
@@ -22,6 +22,7 @@ from playwright.async_api import async_playwright, Playwright, Error
|
|
|
22
22
|
|
|
23
23
|
# noinspection PyProtectedMember
|
|
24
24
|
from playwright._impl._errors import TimeoutError
|
|
25
|
+
from tortoise.timezone import now
|
|
25
26
|
from xync_bot import XyncBot
|
|
26
27
|
from xync_schema.models import TopUp, TopUpAble, PmAgent, Transfer
|
|
27
28
|
|
|
@@ -139,7 +140,7 @@ class Client(PmAgentClient):
|
|
|
139
140
|
async def send(self, t: Transfer) -> tuple[str, bytes] | float:
|
|
140
141
|
dest, cur = t.order.cred.detail, t.order.cred.pmcur.cur.ticker
|
|
141
142
|
amount = round(t.order.amount * 10**-t.order.cred.pmcur.cur.scale, t.order.cred.pmcur.cur.scale)
|
|
142
|
-
self.last_active =
|
|
143
|
+
self.last_active = now()
|
|
143
144
|
page = self.page
|
|
144
145
|
if not page.url.startswith(self.pages.SEND):
|
|
145
146
|
try:
|
|
@@ -181,7 +182,7 @@ class Client(PmAgentClient):
|
|
|
181
182
|
await page.click(f".history-id-{trans_num} a.link")
|
|
182
183
|
sleep(1)
|
|
183
184
|
receipt = await page.query_selector(".ui-dialog.ui-corner-all")
|
|
184
|
-
return trans_num, await receipt.screenshot(path=f"tmp/{trans_num}.png")
|
|
185
|
+
return trans_num, receipt and await receipt.screenshot(path=f"tmp/{trans_num}.png")
|
|
185
186
|
else:
|
|
186
187
|
await self.receive("Payeer хз", photo=await self.page.screenshot())
|
|
187
188
|
return -1
|
|
@@ -192,10 +193,10 @@ class Client(PmAgentClient):
|
|
|
192
193
|
)
|
|
193
194
|
return has_amount
|
|
194
195
|
|
|
195
|
-
def check_in(
|
|
196
|
+
async def check_in(
|
|
196
197
|
self, amount: Decimal | int | float, cur: str, dt: datetime = None, tid: str | int = None
|
|
197
198
|
) -> tuple[Decimal | None, int | None]:
|
|
198
|
-
history = self.api.history(type="incoming",
|
|
199
|
+
history = self.api.history(type="incoming", count=10)
|
|
199
200
|
if tid:
|
|
200
201
|
return (t := history.get(tid)) and Decimal(t["creditedAmount"])
|
|
201
202
|
ts: list[dict] = [
|
|
@@ -204,7 +205,8 @@ class Client(PmAgentClient):
|
|
|
204
205
|
if (
|
|
205
206
|
amount <= Decimal(h["creditedAmount"]) <= ceil(amount)
|
|
206
207
|
and h["creditedCurrency"] == cur
|
|
207
|
-
|
|
208
|
+
# todo: wrong tz
|
|
209
|
+
and datetime.fromisoformat(h["date"]) > dt - timedelta(minutes=3) # +180(tz)-5
|
|
208
210
|
)
|
|
209
211
|
]
|
|
210
212
|
if not (t := ts and ts[0]):
|
|
@@ -174,7 +174,7 @@ class Client(PmAgentClient):
|
|
|
174
174
|
elif self.agent.user.username.session:
|
|
175
175
|
if not (code := await self.wait_for_code(volet_bot_id, topic, hg)):
|
|
176
176
|
if 1: # todo: Is mail_confirm required?
|
|
177
|
-
if _mcr := await self.gmail.
|
|
177
|
+
if _mcr := await self.gmail.volet_confirm(amount, t.updated_at):
|
|
178
178
|
...
|
|
179
179
|
# todo: click Continue
|
|
180
180
|
if not (code := await self.wait_for_code(volet_bot_id, topic, hg)):
|
|
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
|
|
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
|
|
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
|