xync-client 0.0.43.dev15__tar.gz → 0.0.43.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 (105) hide show
  1. {xync_client-0.0.43.dev15/xync_client.egg-info → xync_client-0.0.43.dev17}/PKG-INFO +1 -1
  2. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Bybit/agent.py +77 -43
  3. xync_client-0.0.43.dev15/xync_client/Pms/Volet/volet.py → xync_client-0.0.43.dev17/xync_client/Pms/Volet/__init__.py +2 -2
  4. xync_client-0.0.43.dev17/xync_client/pyro.py +121 -0
  5. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17/xync_client.egg-info}/PKG-INFO +1 -1
  6. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client.egg-info/SOURCES.txt +2 -1
  7. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/.env.sample +0 -0
  8. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/.gitignore +0 -0
  9. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/.pre-commit-config.yaml +0 -0
  10. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/README.md +0 -0
  11. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/makefile +0 -0
  12. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/pyproject.toml +0 -0
  13. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/setup.cfg +0 -0
  14. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/tests/TestAgent.py +0 -0
  15. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/tests/TestAsset.py +0 -0
  16. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/tests/TestEx.py +0 -0
  17. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/tests/TestOrder.py +0 -0
  18. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/tests/_todo_refact/Binance/test_binance.py +0 -0
  19. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/tests/_todo_refact/Bybit/test_bybit.py +0 -0
  20. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/tests/_todo_refact/Bybit/test_bybit_p2p.py +0 -0
  21. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/tests/_todo_refact/Gate/test_gate.py +0 -0
  22. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/tests/_todo_refact/Htx/test_htx_p2p.py +0 -0
  23. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/tests/_todo_refact/Wallet/test_agent.py +0 -0
  24. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/tests/_todo_refact/Wallet/test_ex.py +0 -0
  25. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/tests/_todo_refact/__init__.py +0 -0
  26. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/tests/_todo_refact/_test_ex.py +0 -0
  27. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Abc/Agent.py +0 -0
  28. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Abc/Asset.py +0 -0
  29. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Abc/AuthTrait.py +0 -0
  30. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Abc/Base.py +0 -0
  31. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Abc/BaseTest.py +0 -0
  32. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Abc/Ex.py +0 -0
  33. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Abc/InAgent.py +0 -0
  34. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Abc/Order.py +0 -0
  35. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Abc/types.py +0 -0
  36. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Binance/__init__.py +0 -0
  37. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Binance/binance_async.py +0 -0
  38. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Binance/earn_api.py +0 -0
  39. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Binance/etype/ad.py +0 -0
  40. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Binance/etype/pm.py +0 -0
  41. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Binance/ex.py +0 -0
  42. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Binance/exceptions.py +0 -0
  43. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Binance/sapi.py +0 -0
  44. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Binance/web_c2c.py +0 -0
  45. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/BingX/__init__.py +0 -0
  46. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/BingX/agent.py +0 -0
  47. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/BingX/base.py +0 -0
  48. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/BingX/etype/ad.py +0 -0
  49. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/BingX/etype/pm.py +0 -0
  50. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/BingX/ex.py +0 -0
  51. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/BingX/req.mjs +0 -0
  52. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/BingX/sign.js +0 -0
  53. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/BitGet/__init__.py +0 -0
  54. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/BitGet/agent.py +0 -0
  55. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/BitGet/etype/ad.py +0 -0
  56. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/BitGet/ex.py +0 -0
  57. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/BitGet/req.mjs +0 -0
  58. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/BitPapa/ex.py +0 -0
  59. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Bybit/InAgent.py +0 -0
  60. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Bybit/etype/ad.py +0 -0
  61. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Bybit/etype/cred.py +0 -0
  62. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Bybit/etype/order.py +0 -0
  63. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Bybit/ex.py +0 -0
  64. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Bybit/web_earn.py +0 -0
  65. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Bybit/web_p2p.py +0 -0
  66. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Bybit/ws.py +0 -0
  67. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Gate/etype/ad.py +0 -0
  68. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Gate/ex.py +0 -0
  69. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Gate/premarket.py +0 -0
  70. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Htx/agent.py +0 -0
  71. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Htx/earn.py +0 -0
  72. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Htx/etype/__init__.py +0 -0
  73. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Htx/etype/ad.py +0 -0
  74. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Htx/etype/cred.py +0 -0
  75. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Htx/etype/pm.py +0 -0
  76. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Htx/etype/test.py +0 -0
  77. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Htx/ex.py +0 -0
  78. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/KuCoin/etype/ad.py +0 -0
  79. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/KuCoin/etype/pm.py +0 -0
  80. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/KuCoin/ex.py +0 -0
  81. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/KuCoin/web.py +0 -0
  82. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Mexc/etype/ad.py +0 -0
  83. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Mexc/etype/pm.py +0 -0
  84. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Mexc/ex.py +0 -0
  85. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Okx/etype/ad.py +0 -0
  86. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Okx/etype/pm.py +0 -0
  87. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Okx/ex.py +0 -0
  88. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Pms/Volet/_todo_req/req.mjs +0 -0
  89. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Pms/Volet/_todo_req/req.py +0 -0
  90. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/Pms/Volet/api.py +0 -0
  91. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/TgWallet/agent.py +0 -0
  92. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/TgWallet/asset.py +0 -0
  93. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/TgWallet/auth.py +0 -0
  94. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/TgWallet/ex.py +0 -0
  95. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/TgWallet/inAgent.py +0 -0
  96. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/TgWallet/order.py +0 -0
  97. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/TgWallet/pyd.py +0 -0
  98. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/TgWallet/pyro.py +0 -0
  99. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/TgWallet/web.py +0 -0
  100. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/__init__.py +0 -0
  101. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/loader.py +0 -0
  102. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client/pm_unifier.py +0 -0
  103. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client.egg-info/dependency_links.txt +0 -0
  104. {xync_client-0.0.43.dev15 → xync_client-0.0.43.dev17}/xync_client.egg-info/requires.txt +0 -0
  105. {xync_client-0.0.43.dev15 → xync_client-0.0.43.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.43.dev15
3
+ Version: 0.0.43.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
@@ -1,11 +1,14 @@
1
+ import logging
1
2
  from asyncio import run, sleep, gather
2
3
  from enum import IntEnum
3
4
  from http.client import HTTPException
4
- from math import floor
5
5
  from typing import Literal
6
6
 
7
7
  import pyotp
8
+ from asyncpg import ConnectionDoesNotExistError
8
9
  from bybit_p2p import P2P
10
+ from bybit_p2p._exceptions import FailedRequestError
11
+ from urllib3.exceptions import ReadTimeoutError
9
12
  from x_model import init_db
10
13
  from xync_schema import models
11
14
 
@@ -174,10 +177,9 @@ class AgentClient(BaseAgentClient): # Bybit client
174
177
  res = await self._post("/fiat/otc/maker/work-config/switch", data)
175
178
  return res
176
179
 
177
- async def ads(self, coin: models.Coin, cur: models.Cur, is_sell: bool, pms: list[models.Pm]) -> list[Ad]:
180
+ async def ads(self, coin: models.Coin, cur: models.Cur, is_sell: bool, pmexs: list[models.Pmex]) -> list[Ad]:
178
181
  coinex = await models.Coinex.get(ex=self.ex, coin=coin)
179
182
  curex = await models.Curex.get(ex=self.ex, cur=cur)
180
- pmexs = await models.Pmex.filter(ex=self.ex, pm_id__in=[pm.id for pm in pms])
181
183
  return await self.ex_client.ads(coinex.exid, curex.exid, is_sell, [pmex.exid for pmex in pmexs])
182
184
 
183
185
  def online_ads(self) -> str:
@@ -362,43 +364,56 @@ class AgentClient(BaseAgentClient): # Bybit client
362
364
  coin: models.Coin,
363
365
  cur: models.Cur,
364
366
  is_sell: bool,
365
- pms: list[models.Pm],
367
+ pms: dict[models.Pmex, models.CredEx],
366
368
  amount: float,
367
369
  ceil: float,
368
370
  place: int = 1,
369
371
  ):
370
- k = (-1) ** int(is_sell)
371
- pays: list[str] = []
372
+ k = (-1) ** int(is_sell) # on_buy=1, on_sell=-1
372
373
  while self.actor.person.user.status > 0:
373
- ads: list[Ad] = await self.ads(coin, cur, is_sell, pms)
374
+ ads: list[Ad] = await self.ads(coin, cur, is_sell, list(pms.keys()))
374
375
  idiot_maker_filter(ads, ceil, k)
375
376
  cur_plc = [i for i, ad in enumerate(ads) if int(ad.accountId) == self.actor.exid][0]
376
- if cur_plc > place:
377
- cad: Ad = ads[place]
378
- mad: Ad = ads.pop(cur_plc)
379
- if not pays: # cached
380
- pays += await models.CredEx.filter(
381
- cred__pmcur__pm__pmexs__exid__in=mad.payments, cred__pmcur__pm__pmexs__ex_id=self.ex.id
382
- ).values_list("exid", flat=True)
383
- cprice = float(cad.price)
384
- if (cprice - ceil) * k > 0:
385
- rprice = cprice
386
- else:
387
- rprice = float(ads[cur_plc].price)
388
- step = 0.01 if cad.recentExecuteRate > mad.recentExecuteRate else 0
389
- mew_price = str(round(rprice - k * step, cur.scale))
390
- if mad.price == mew_price:
391
- print(end="V" if is_sell else "A", flush=True)
392
- await sleep(2)
393
- continue
394
- mad.price = mew_price
395
- mad.quantity = str(floor(amount))
396
- req = AdUpdateRequest.model_validate({**mad.model_dump(), "paymentIds": [str(p) for p in pays]})
397
- _res = self.ad_upd(req)
398
- print("-" if is_sell else "+", end=req.price, flush=True)
399
- else:
377
+ mad: Ad = ads.pop(cur_plc)
378
+ # чью цену будем обгонять, предыдущей или слещующей объявы?
379
+ cad: Ad = ads[place] if cur_plc > place else ads[cur_plc]
380
+ # а цена обгоняемой объявы не выше нашего потолка?
381
+ if (float(cad.price) - ceil) * k < 0:
382
+ # тогда берем следующую
383
+ cad = ads[cur_plc]
384
+ cprice = float(cad.price)
385
+ new_price = round(cprice - k * step(mad, cad), cur.scale)
386
+ if mad.price == f"%.{cur.scale}f" % new_price:
400
387
  print(end="v" if is_sell else "^", flush=True)
401
- await sleep(3)
388
+ await sleep(2)
389
+ continue
390
+ if cad.priceType: # Если цена конкурента плавающая, то повышаем себе не цену, а %
391
+ mad.premium = str(round(float(cad.premium) - k * step(mad, cad), 2))
392
+ mad.priceType = cad.priceType
393
+ mad.price = str(new_price)
394
+ mad.quantity = str(round(amount, coin.scale))
395
+ mad.maxAmount = str(2_000_000)
396
+ req = AdUpdateRequest.model_validate(
397
+ {**mad.model_dump(), "paymentIds": [str(p.exid) for p in pms.values()]}
398
+ )
399
+ try:
400
+ _res = self.ad_upd(req)
401
+ except FailedRequestError:
402
+ # logging.error(e.message)
403
+ await sleep(51)
404
+ except (ReadTimeoutError, ConnectionDoesNotExistError):
405
+ logging.warning("Connection failed. Restarting..")
406
+ print("-" if is_sell else "+", end=req.price, flush=True)
407
+ await sleep(40)
408
+
409
+
410
+ def step(mad, cad) -> float:
411
+ return (
412
+ 0.01
413
+ if cad.recentExecuteRate > mad.recentExecuteRate
414
+ or (cad.recentExecuteRate == mad.recentExecuteRate and cad.recentOrderNum > mad.recentOrderNum)
415
+ else 0
416
+ )
402
417
 
403
418
 
404
419
  def idiot_maker_filter(ads: list[Ad], ceil: float, k: Literal[-1, 1]):
@@ -412,6 +427,13 @@ def listen(data: dict):
412
427
  print(data)
413
428
 
414
429
 
430
+ async def get_creds(norms: list[str], ex_id: int) -> dict[models.Pmex, models.CredEx]:
431
+ return {
432
+ await models.Pmex.get(ex_id=ex_id, pm__norm=n): await models.CredEx.get(ex_id=ex_id, cred__pmcur__pm__norm=n)
433
+ for n in norms
434
+ }
435
+
436
+
415
437
  async def main():
416
438
  _ = await init_db(PG_DSN, models, True)
417
439
  actor = (
@@ -419,15 +441,27 @@ async def main():
419
441
  )
420
442
  cl: AgentClient = actor.client()
421
443
  # await cl.ex_client.set_pmcurexs(cookies=actor.agent.auth["cookies"]) # 607 -> 629
422
- coin = await models.Coin.get(ticker="USDT")
423
- cur = await models.Cur.get(ticker="RUB")
424
- volet = await models.Pm.get(norm="volet")
425
- asset = await models.Asset.filter(addr__actor=actor, addr__coin=coin).first()
426
- asset.free - (asset.freeze or 0) - (asset.lock or 0)
444
+ usdt = await models.Coin.get(ticker="USDT")
445
+ btc = await models.Coin.get(ticker="BTC")
446
+ eth = await models.Coin.get(ticker="ETH")
447
+ rub = await models.Cur.get(ticker="RUB")
448
+ # await models.Direction.get(
449
+ # pairex__ex=cl.ex, pairex__pair__coin__ticker="USDT", pairex__pair__cur__ticker="RUB", sell=True
450
+ # )
451
+ usdt_asset = await models.Asset.get(addr__actor=actor, addr__coin=usdt)
452
+ btc_asset = await models.Asset.get(addr__actor=actor, addr__coin=btc)
453
+ eth_asset = await models.Asset.get(addr__actor=actor, addr__coin=eth)
454
+ creds = await get_creds(["volet"], 9)
455
+ volet = await models.Fiat.get(cred_id=list(creds.values())[0].cred_id)
456
+ usdt_amount = usdt_asset.free - (usdt_asset.freeze or 0) - (usdt_asset.lock or 0)
457
+ btc_asset.free - (btc_asset.freeze or 0) - (btc_asset.lock or 0)
458
+ eth_asset.free - (eth_asset.freeze or 0) - (eth_asset.lock or 0)
427
459
  # await cl.set_creds()
428
460
  await gather(
429
- cl.battle(coin, cur, False, [volet], 235, 86.9, 0),
430
- cl.battle(coin, cur, True, [volet], 65, 82.1, 0),
461
+ cl.battle(usdt, rub, False, creds, usdt_amount, 85.39, 0), # гонка в стакане покупки - мы продаем
462
+ cl.battle(usdt, rub, True, creds, volet.amount / 82, 82, 0), # гонка в стакане продажи - мы покупаем
463
+ cl.battle(eth, rub, True, creds, volet.amount / 144_000, 144_000, 0),
464
+ cl.battle(btc, rub, True, creds, volet.amount / 7_600_000, 7_600_000, 0),
431
465
  )
432
466
 
433
467
  bor = BaseOrderReq(
@@ -436,12 +470,12 @@ async def main():
436
470
  fiat_amount=3000,
437
471
  amount_is_fiat=True,
438
472
  is_sell=False,
439
- cur_exid=cur.ticker,
440
- coin_exid=coin.ticker,
441
- coin_scale=coin.scale,
473
+ cur_exid=rub.ticker,
474
+ coin_exid=usdt.ticker,
475
+ coin_scale=usdt.scale,
442
476
  )
443
477
  res: OrderResp = await cl.order_request(bor)
444
- cl.cancel_order(res.orderId)
478
+ await cl.cancel_order(res.orderId)
445
479
  await cl.close()
446
480
 
447
481
 
@@ -55,7 +55,7 @@ async def report(uid: int, byts: bytes, msg: str, exc: bool = True):
55
55
  raise Exception(msg)
56
56
 
57
57
 
58
- class VoletAgent:
58
+ class Client:
59
59
  agent: PmAgent
60
60
  pbot: PyroClient
61
61
  page: Page
@@ -246,7 +246,7 @@ async def _test(uid: int, dest: str, amount):
246
246
  from xync_schema import models
247
247
 
248
248
  _ = await init_db(PG_DSN, models, True)
249
- va = VoletAgent(uid)
249
+ va = Client(uid)
250
250
  try:
251
251
  await va.start(True)
252
252
  await va.send(dest, amount)
@@ -0,0 +1,121 @@
1
+ from asyncio import run, sleep
2
+ from io import BytesIO
3
+
4
+ from aiogram import Bot
5
+ from pyrogram import Client
6
+ from pyrogram.errors import UserNotParticipant
7
+ from pyrogram.raw.functions.messages import UploadMedia
8
+ from pyrogram.raw.functions.photos import GetUserPhotos
9
+ from pyrogram.raw.functions.upload import GetFile
10
+ from pyrogram.raw.types import (
11
+ InputPeerSelf,
12
+ InputMediaUploadedDocument,
13
+ MessageMediaDocument,
14
+ InputMediaUploadedPhoto,
15
+ MessageMediaPhoto,
16
+ InputDocumentFileLocation,
17
+ InputPhotoFileLocation,
18
+ )
19
+ from pyrogram.raw.types.photos import Photos
20
+ from pyrogram.raw.types.upload import File
21
+ from pyrogram.types import Chat, ChatPrivileges
22
+ from x_model import init_db
23
+ from xync_client.loader import TG_API_ID, TG_API_HASH, PG_DSN
24
+ from xync_schema import models
25
+ from xync_schema.models import User
26
+
27
+
28
+ class PyroClient:
29
+ max_privs = ChatPrivileges(
30
+ can_manage_chat=True, # default
31
+ can_delete_messages=True,
32
+ can_delete_stories=True, # Channels only
33
+ can_manage_video_chats=True, # Groups and supergroups only
34
+ can_restrict_members=True,
35
+ can_promote_members=True,
36
+ can_change_info=True,
37
+ can_post_messages=True, # Channels only
38
+ can_post_stories=True, # Channels only
39
+ can_edit_messages=True, # Channels only
40
+ can_edit_stories=True, # Channels only
41
+ can_invite_users=True,
42
+ can_pin_messages=True, # Groups and supergroups only
43
+ can_manage_topics=True, # Supergroups only
44
+ is_anonymous=True,
45
+ )
46
+
47
+ def __init__(self, ub: User | Bot):
48
+ auth = {"bot_token": ub.token} if isinstance(ub, Bot) else {"session_string": ub.sess}
49
+ self.app: Client = Client(str(ub.id), TG_API_ID, TG_API_HASH, **auth, in_memory=True)
50
+
51
+ @staticmethod
52
+ def ref_enc(ph_id: int, access_hash: int, ref: bytes) -> bytes:
53
+ return ph_id.to_bytes(8, "big") + access_hash.to_bytes(8, "big", signed=True) + ref
54
+
55
+ @staticmethod
56
+ def ref_dec(full_ref: bytes) -> tuple[int, int, bytes]:
57
+ pid, ah = int.from_bytes(full_ref[:8], "big"), int.from_bytes(full_ref[8:16], "big", signed=True)
58
+ return pid, ah, full_ref[16:]
59
+
60
+ async def create_orders_forum(self, uid: str | int) -> tuple[int, bool]:
61
+ chat: Chat = await self.app.create_supergroup("Xync Orders", "Xync Orders")
62
+ if not (await self.app.toggle_forum_topics(chat_id=chat.id, enabled=True)):
63
+ await self.app.delete_channel(chat.id)
64
+ await chat.leave()
65
+ raise Exception(f"Chat {chat.id} for {self.app.me.username} not converted to forum")
66
+ await chat.add_members(["XyncNetBot"]) # , "xync_bot"
67
+ await chat.promote_member("XyncNetBot", self.max_privs)
68
+ added = await chat.add_members([uid])
69
+ try:
70
+ await sleep(1, await chat.get_member(uid))
71
+ except UserNotParticipant:
72
+ added = False
73
+ # await chat.leave()
74
+ return chat.id, added
75
+
76
+ async def get_user_photos(self, uid: str | int) -> Photos:
77
+ try:
78
+ peer = await self.app.resolve_peer(uid)
79
+ except Exception as e:
80
+ raise e
81
+ return await self.app.invoke(GetUserPhotos(user_id=peer, offset=0, limit=1, max_id=-1))
82
+
83
+ async def send_img(self, txt: str, byts: bytes, uid="me"):
84
+ return await self.app.send_photo(uid, BytesIO(byts), txt)
85
+
86
+ async def save_file(self, byts: bytes, ctype: str) -> tuple[MessageMediaDocument, bytes]:
87
+ in_file = await self.app.save_file(BytesIO(byts))
88
+ imud = InputMediaUploadedDocument(file=in_file, mime_type=ctype, attributes=[])
89
+ upf: MessageMediaDocument = await self.app.invoke(UploadMedia(peer=InputPeerSelf(), media=imud))
90
+ return upf, (
91
+ upf.document.id.to_bytes(8, "big")
92
+ + upf.document.access_hash.to_bytes(8, "big", signed=True)
93
+ + upf.document.file_reference
94
+ )
95
+
96
+ async def save_photo(self, file: bytes) -> tuple[MessageMediaPhoto, bytes]:
97
+ in_file = await self.app.save_file(BytesIO(file))
98
+ upm = UploadMedia(peer=InputPeerSelf(), media=InputMediaUploadedPhoto(file=in_file))
99
+ upp: MessageMediaPhoto = await self.app.invoke(upm)
100
+ return upp, self.ref_enc(upp.photo.id, upp.photo.access_hash, upp.photo.file_reference)
101
+
102
+ async def get_file(self, fid: bytes) -> File:
103
+ pid, ah, ref = self.ref_dec(fid)
104
+ loc = InputDocumentFileLocation(id=pid, access_hash=ah, file_reference=ref, thumb_size="x")
105
+ return await self.app.invoke(GetFile(location=loc, offset=0, limit=512 * 1024))
106
+
107
+ async def get_photo(self, fid: bytes, st: str) -> File:
108
+ pid, ah, ref = self.ref_dec(fid)
109
+ loc = InputPhotoFileLocation(id=pid, access_hash=ah, file_reference=ref, thumb_size=st)
110
+ return await self.app.invoke(GetFile(location=loc, offset=0, limit=512 * 1024))
111
+
112
+
113
+ async def main():
114
+ _ = await init_db(PG_DSN, models, True)
115
+ user: User = await User.filter(sess__isnull=False, status__gt=0, pm_agent__pm__norm="volet").first()
116
+ pcl = PyroClient(user)
117
+ await pcl.create_orders_forum(user.id)
118
+
119
+
120
+ if __name__ == "__main__":
121
+ run(main())
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xync-client
3
- Version: 0.0.43.dev15
3
+ Version: 0.0.43.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
@@ -20,6 +20,7 @@ tests/_todo_refact/Wallet/test_ex.py
20
20
  xync_client/__init__.py
21
21
  xync_client/loader.py
22
22
  xync_client/pm_unifier.py
23
+ xync_client/pyro.py
23
24
  xync_client.egg-info/PKG-INFO
24
25
  xync_client.egg-info/SOURCES.txt
25
26
  xync_client.egg-info/dependency_links.txt
@@ -87,8 +88,8 @@ xync_client/Mexc/etype/pm.py
87
88
  xync_client/Okx/ex.py
88
89
  xync_client/Okx/etype/ad.py
89
90
  xync_client/Okx/etype/pm.py
91
+ xync_client/Pms/Volet/__init__.py
90
92
  xync_client/Pms/Volet/api.py
91
- xync_client/Pms/Volet/volet.py
92
93
  xync_client/Pms/Volet/_todo_req/req.mjs
93
94
  xync_client/Pms/Volet/_todo_req/req.py
94
95
  xync_client/TgWallet/agent.py