xync-client 0.0.57.dev9__tar.gz → 0.0.57.dev11__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 (112) hide show
  1. {xync_client-0.0.57.dev9/xync_client.egg-info → xync_client-0.0.57.dev11}/PKG-INFO +1 -1
  2. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Abc/Agent.py +3 -2
  3. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Abc/Ex.py +13 -9
  4. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Bybit/agent.py +159 -116
  5. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Bybit/etype/order.py +4 -4
  6. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Htx/etype/ad.py +1 -1
  7. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Htx/ex.py +7 -7
  8. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11/xync_client.egg-info}/PKG-INFO +1 -1
  9. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/.env.sample +0 -0
  10. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/.gitignore +0 -0
  11. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/.pre-commit-config.yaml +0 -0
  12. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/README.md +0 -0
  13. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/makefile +0 -0
  14. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/pyproject.toml +0 -0
  15. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/setup.cfg +0 -0
  16. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/tests/TestAgent.py +0 -0
  17. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/tests/TestAsset.py +0 -0
  18. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/tests/TestEx.py +0 -0
  19. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/tests/TestOrder.py +0 -0
  20. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/tests/_todo_refact/Binance/test_binance.py +0 -0
  21. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/tests/_todo_refact/Bybit/test_bybit.py +0 -0
  22. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/tests/_todo_refact/Bybit/test_bybit_p2p.py +0 -0
  23. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/tests/_todo_refact/Gate/test_gate.py +0 -0
  24. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/tests/_todo_refact/Htx/test_htx_p2p.py +0 -0
  25. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/tests/_todo_refact/Wallet/test_agent.py +0 -0
  26. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/tests/_todo_refact/Wallet/test_ex.py +0 -0
  27. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/tests/_todo_refact/__init__.py +0 -0
  28. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/tests/_todo_refact/_test_ex.py +0 -0
  29. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Abc/Asset.py +0 -0
  30. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Abc/Auth.py +0 -0
  31. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Abc/BaseTest.py +0 -0
  32. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Abc/InAgent.py +0 -0
  33. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Abc/Order.py +0 -0
  34. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Abc/xtype.py +0 -0
  35. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Binance/__init__.py +0 -0
  36. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Binance/binance_async.py +0 -0
  37. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Binance/earn_api.py +0 -0
  38. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Binance/etype/ad.py +0 -0
  39. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Binance/etype/pm.py +0 -0
  40. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Binance/ex.py +0 -0
  41. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Binance/exceptions.py +0 -0
  42. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Binance/sapi.py +0 -0
  43. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Binance/web_c2c.py +0 -0
  44. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/BingX/__init__.py +0 -0
  45. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/BingX/agent.py +0 -0
  46. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/BingX/base.py +0 -0
  47. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/BingX/etype/ad.py +0 -0
  48. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/BingX/etype/pm.py +0 -0
  49. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/BingX/ex.py +0 -0
  50. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/BingX/req.mjs +0 -0
  51. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/BingX/sign.js +0 -0
  52. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/BitGet/__init__.py +0 -0
  53. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/BitGet/agent.py +0 -0
  54. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/BitGet/etype/ad.py +0 -0
  55. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/BitGet/ex.py +0 -0
  56. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/BitPapa/ex.py +0 -0
  57. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Bybit/InAgent.py +0 -0
  58. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Bybit/etype/ad.py +0 -0
  59. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Bybit/etype/cred.py +0 -0
  60. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Bybit/ex.py +0 -0
  61. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Bybit/order.py +0 -0
  62. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Bybit/web_earn.py +0 -0
  63. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Bybit/web_p2p.py +0 -0
  64. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Bybit/ws.py +0 -0
  65. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Gate/etype/ad.py +0 -0
  66. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Gate/ex.py +0 -0
  67. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Gate/premarket.py +0 -0
  68. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Gmail/__init__.py +0 -0
  69. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Htx/agent.py +0 -0
  70. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Htx/earn.py +0 -0
  71. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Htx/etype/__init__.py +0 -0
  72. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Htx/etype/cred.py +0 -0
  73. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Htx/etype/pm.py +0 -0
  74. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Htx/etype/test.py +0 -0
  75. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/KuCoin/etype/ad.py +0 -0
  76. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/KuCoin/etype/pm.py +0 -0
  77. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/KuCoin/ex.py +0 -0
  78. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/KuCoin/web.py +0 -0
  79. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Mexc/etype/ad.py +0 -0
  80. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Mexc/etype/pm.py +0 -0
  81. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Mexc/ex.py +0 -0
  82. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Okx/etype/ad.py +0 -0
  83. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Okx/etype/pm.py +0 -0
  84. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Okx/ex.py +0 -0
  85. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Pms/.gitignore +0 -0
  86. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Pms/Alfa/__init__.py +0 -0
  87. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Pms/Alfa/state.json +0 -0
  88. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Pms/Ozon/__init__.py +0 -0
  89. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Pms/Sber/__init__.py +0 -0
  90. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Pms/Tinkoff/__init__.py +0 -0
  91. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Pms/Tinkoff/state.json +0 -0
  92. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Pms/Volet/__init__.py +0 -0
  93. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Pms/Volet/_todo_req/req.mjs +0 -0
  94. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Pms/Volet/_todo_req/req.py +0 -0
  95. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Pms/Volet/api.py +0 -0
  96. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/Pms/Volet/pl.py +0 -0
  97. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/TgWallet/agent.py +0 -0
  98. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/TgWallet/asset.py +0 -0
  99. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/TgWallet/auth.py +0 -0
  100. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/TgWallet/ex.py +0 -0
  101. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/TgWallet/inAgent.py +0 -0
  102. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/TgWallet/order.py +0 -0
  103. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/TgWallet/pyd.py +0 -0
  104. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/TgWallet/pyro.py +0 -0
  105. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/TgWallet/web.py +0 -0
  106. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/__init__.py +0 -0
  107. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/loader.py +0 -0
  108. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client/pm_unifier.py +0 -0
  109. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client.egg-info/SOURCES.txt +0 -0
  110. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client.egg-info/dependency_links.txt +0 -0
  111. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/xync_client.egg-info/requires.txt +0 -0
  112. {xync_client-0.0.57.dev9 → xync_client-0.0.57.dev11}/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.57.dev9
3
+ Version: 0.0.57.dev11
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,6 +1,7 @@
1
1
  from abc import abstractmethod
2
2
 
3
3
  from pydantic import BaseModel
4
+ from pyro_client.client.file import FileClient
4
5
  from x_client.aiohttp import Client as HttpClient
5
6
  from xync_schema import models
6
7
  from xync_schema.models import OrderStatus, Coin, Cur, Ad, AdStatus, Actor
@@ -11,10 +12,10 @@ from xync_client.Abc.xtype import CredExOut, BaseOrderReq, BaseAdUpdate
11
12
 
12
13
 
13
14
  class BaseAgentClient(HttpClient):
14
- def __init__(self, actor: Actor, headers: dict[str, str] = None, cookies: dict[str, str] = None):
15
+ def __init__(self, actor: Actor, bot: FileClient, headers: dict[str, str] = None, cookies: dict[str, str] = None):
15
16
  self.actor: Actor = actor
16
17
  super().__init__(actor.ex.host_p2p, headers, cookies)
17
- self.ex_client: BaseExClient = self.actor.ex.client(actor)
18
+ self.ex_client: BaseExClient = self.actor.ex.client(bot, actor)
18
19
 
19
20
  # 0: Получшение ордеров в статусе status, по монете coin, в валюте coin, в направлении is_sell: bool
20
21
  @abstractmethod
@@ -234,15 +234,7 @@ class BaseExClient(HttpClient):
234
234
  if not url.startswith("/"):
235
235
  url = "/" + url
236
236
  url = "https://" + self.logo_pre_url + url
237
- if not (file := await models.File.get_or_none(name=url)):
238
- resp = await ss.get(url)
239
- if resp.ok:
240
- byts = await resp.read()
241
- upf, ref = await self.bot.save_doc(byts, resp.content_type)
242
- await sleep(0.34)
243
- typ = FileType[resp.content_type.split("/")[-1]]
244
- file, _ = await models.File.update_or_create({"ref": ref, "size": len(byts), "typ": typ}, name=url)
245
- # fr = await pbot.get_file(file.ref) # check
237
+ return await self.file_upsert(url, ss)
246
238
  return file
247
239
 
248
240
  # Импорт монет (с Coinex-ами) с биржи в бд
@@ -287,6 +279,18 @@ class BaseExClient(HttpClient):
287
279
  await ad_db.pmexs.add(*getattr(ad_pydin, "pmexs_", []))
288
280
  return ad_db
289
281
 
282
+ async def file_upsert(self, url: str, ss: ClientSession = None) -> models.File:
283
+ if not (file := await models.File.get_or_none(name__startswith=url.split("?")[0])):
284
+ ss = ss or self.session
285
+ if (resp := await ss.get(url)).ok:
286
+ byts = await resp.read()
287
+ upf, ref = await self.bot.save_doc(byts, resp.content_type)
288
+ await sleep(0.3)
289
+ typ = FileType[resp.content_type.split("/")[-1]]
290
+ file, _ = await models.File.update_or_create({"ref": ref, "size": len(byts), "typ": typ}, name=url)
291
+ # fr = await pbot.get_file(file.ref) # check
292
+ return file
293
+
290
294
  # async def _proc(self, resp: ClientResponse, data_key: str = None, body: dict | str = None) -> dict | str:
291
295
  # if resp.status in (401, 403):
292
296
  # # proxy = await models.Proxy.filter(valid=True, country__short__not="US").order_by("-updated_at").first()
@@ -11,13 +11,14 @@ import pyotp
11
11
  from asyncpg import ConnectionDoesNotExistError
12
12
  from bybit_p2p import P2P
13
13
  from bybit_p2p._exceptions import FailedRequestError
14
- from tortoise.expressions import F
14
+ from pyro_client.client.file import FileClient
15
+ from tortoise.expressions import F, Q
15
16
  from urllib3.exceptions import ReadTimeoutError
16
17
  from x_model import init_db
17
18
  from xync_schema import models
18
19
  from xync_schema.enums import OrderStatus
19
20
 
20
- from xync_schema.models import Cur, Actor, Cond, Direction, CondSim, Person
21
+ from xync_schema.models import Cur, Actor, Cond, Direction, CondSim, Person, Pmcur
21
22
 
22
23
  from xync_client.Abc.Agent import BaseAgentClient
23
24
  from xync_client.Abc.xtype import BaseOrderReq, FlatDict
@@ -33,7 +34,7 @@ from xync_client.Bybit.etype.order import (
33
34
  Message,
34
35
  Statuses,
35
36
  )
36
- from xync_client.loader import TORM
37
+ from xync_client.loader import TORM, TOKEN
37
38
 
38
39
 
39
40
  class NoMakerException(Exception):
@@ -81,8 +82,8 @@ class AgentClient(BaseAgentClient): # Bybit client
81
82
  cond_sims: dict[int, tuple[int, int]] = {}
82
83
  sim_conds: dict[int, set[int]] = defaultdict(set) # backward
83
84
 
84
- def __init__(self, actor: Actor, **kwargs):
85
- super().__init__(actor, **kwargs)
85
+ def __init__(self, actor: Actor, bot: FileClient, **kwargs):
86
+ super().__init__(actor, bot, **kwargs)
86
87
  self.api = P2P(testnet=False, api_key=actor.agent.auth["key"], api_secret=actor.agent.auth["sec"])
87
88
 
88
89
  """ Private METHs"""
@@ -381,56 +382,79 @@ class AgentClient(BaseAgentClient): # Bybit client
381
382
  },
382
383
  )
383
384
 
384
- async def get_api_orders(self, begin_time: int, end_time: int, status: int, side: int, token_id: str):
385
- lst = self.api.get_orders(
386
- page=1,
387
- size=1000,
388
- # status=status, # 50 - завершено
389
- # tokenId=token_id,
390
- # beginTime=begin_time,
391
- # endTime=end_time,
392
- # side=side, # 1 - продажа, 0 - покупка
393
- )
394
- ords = {o["id"]: OrderItem.model_validate(o) for o in lst}
385
+ async def get_api_orders(
386
+ self, begin_time: int = None, end_time: int = None, status: int = None, side: int = None, token_id: str = None
387
+ ):
388
+ try:
389
+ lst = self.api.get_orders(
390
+ page=1,
391
+ size=30,
392
+ # status=status, # 50 - завершено
393
+ # tokenId=token_id,
394
+ # beginTime=begin_time,
395
+ # endTime=end_time,
396
+ # side=side, # 1 - продажа, 0 - покупка
397
+ )
398
+ except FailedRequestError as e:
399
+ if e.status_code == 10000:
400
+ await sleep(1, await self.get_api_orders(begin_time, end_time, status, side, token_id))
401
+ ords = {int(o["id"]): OrderItem.model_validate(o) for o in lst["result"]["items"]}
395
402
  for oid, o in ords.items():
396
- order = OrderFull.model_validate(self.api.get_order_details(orderId=oid))
397
- ad = Ad(**self.api.get_ad_details(itemId=o.itemId))
398
- if not (
399
- ad_db := await models.Ad.get_or_none(
400
- exid=o.itemId, direction__pairex__ex=self.ex_client.ex
401
- ).prefetch_related("pmex")
402
- ):
403
- dr = await Direction.get(
404
- sell=o["side"],
405
- pairex__ex=self.ex_client.ex,
406
- pairex__pair__coin__ticker=o["tokenId"],
407
- pairex__pair__cur__ticker=o["currencyId"],
408
- )
409
- ad_db, cond_isnew = await self.cond_upsert(ad, order["targetUserName"], dr) # todo: fix realname
410
-
411
- models.CredEx.update_or_create({}, exid=order.confirmedPayTerm.paymentType, ex=self.ex_client.ex)
412
- models.Order.update_or_create(
403
+ fo = self.api.get_order_details(orderId=oid)
404
+ order = OrderFull.model_validate(fo["result"])
405
+ ad = Ad(**self.api.get_ad_details(itemId=order.itemId)["result"])
406
+ maker_name = o.buyerRealName, o.sellerRealName # ad.side
407
+ im_maker = order.makerUserId == o.userId
408
+ taker_id = (o.userId, o.targetUserId)[int(im_maker)]
409
+ taker_nick = (self.actor.name, o.targetNickName)[int(im_maker)]
410
+ ad_db, cond_isnew = await self.cond_upsert(ad, maker_name[ad.side])
411
+ if not ad_db:
412
+ ...
413
+ cred = order.confirmedPayTerm
414
+ if not (credex := await models.CredEx.get_or_none(exid=cred.id, ex=self.ex_client.ex)):
415
+ if not (crd := await models.Cred.get_or_none(pmcur__pm__pmex__exid=cred.paymentType)):
416
+ extr = cred.bankName or cred.branchName or cred.qrcode or cred.payMessage or cred.paymentExt1
417
+ crd = await models.Cred.create(
418
+ detail=cred.accountNo,
419
+ pmcur=await Pmcur.get(pm__pmex__exid=cred.paymentType, cur__ticker=ad.currencyId),
420
+ person=ad_db.maker.person,
421
+ name=cred.realName,
422
+ extra=extr,
423
+ )
424
+ credex = await models.CredEx.create(exid=cred.id, ex=self.ex_client.ex, cred=crd)
425
+ taker_person, _ = await Person.get_or_create(name=maker_name[::-1][ad.side])
426
+ taker, _ = await Actor.get_or_create(
427
+ {"name": taker_nick}, person=taker_person, ex=self.ex_client.ex, exid=taker_id
428
+ )
429
+ order_db, _ = await models.Order.update_or_create(
413
430
  {
414
431
  "amount": o.amount,
415
432
  "status": OrderStatus[Statuses(o.status).name],
416
- "created_at": o.createDate,
417
- "payed_at": order.transferDate,
418
- "confirmed_at": order.updateDate, # todo: check
419
- "cred": order.confirmedPayTerm,
420
- # "taker": order.updateDate,
433
+ "created_at": int(o.createDate[:-3]),
434
+ "payed_at": int(order.transferDate[:-3]),
435
+ "confirmed_at": int(order.updateDate[:-3]), # todo: check
436
+ "cred_id": credex.cred_id,
437
+ "taker": taker,
421
438
  },
422
439
  exid=o.id,
423
440
  ad=ad_db,
424
441
  )
425
- msgs = [Message.model_validate(m) for m in self.api.get_chat_messages(orderId=oid, size=200)]
426
- [
442
+ dmsgs = self.api.get_chat_messages(orderId=oid, size=200)["result"]["result"][::-1]
443
+ if ad.remark != dmsgs.pop(0)["message"]:
444
+ logging.exception(ad.remark)
445
+ msgs = [Message.model_validate(m) for m in dmsgs if m["msgType"] in (1, 2, 7, 8)]
446
+ msgs_db = [
427
447
  models.Msg(
448
+ order=order_db,
428
449
  read=m.isRead,
429
- txt=m.message,
450
+ to_maker=m.userId != order.makerUserId,
451
+ **({"txt": m.message} if m.msgType == 1 else {"file": await self.ex_client.file_upsert(m.message)}),
452
+ sent_at=int(m.createDate[:-3]),
430
453
  )
431
454
  for m in msgs
432
455
  ]
433
- models.Msg.bulk_create([models.Msg])
456
+ _ = await models.Msg.bulk_create(msgs_db, ignore_conflicts=True)
457
+ ...
434
458
 
435
459
  async def mad_upd(self, mad: Ad, attrs: dict, cxids: list[str]):
436
460
  if not [setattr(mad, k, v) for k, v in attrs.items() if getattr(mad, k) != v]:
@@ -634,43 +658,42 @@ class AgentClient(BaseAgentClient): # Bybit client
634
658
 
635
659
  async def cond_upsert(self, ad: Ad, rname: str = None, dr: Direction = None) -> tuple[models.Ad, bool]:
636
660
  sim = None
637
- # если точно такого условия еще нет в бд
661
+ # если точно такое условие уже есть в бд, ниче делать не надо
638
662
  if not (cleaned := clean(ad.remark)) or cleaned in {oc[0] for oc in self.all_conds.values()}:
639
663
  return None, False
640
- # если такая объява уже есть, просто заменяем текст ее условия
641
- if ad_db := await models.Ad.get_or_none(exid=ad.id).prefetch_related("cond__ads__maker"):
664
+ # если эта объява уже есть в бд
665
+ if ad_db := await models.Ad.get_or_none(exid=ad.id).prefetch_related("cond__ads__maker", "maker__person"):
642
666
  # у измененного условия этой объявы есть другие объявы?
643
667
  if rest_ads := set(ad_db.cond.ads) - {ad_db}:
668
+ # другие объявы этого условия принадлежат другим юзерам
644
669
  if rest_uids := {ra.maker_id for ra in rest_ads} - {ad_db.maker_id}:
645
- # todo: дописать проверку на измененность этого условия в других ads
646
- logging.exception("у измененного cond этой ad есть другие ads где оно не изменилось", rest_uids)
647
- if cond := await Cond.get_or_none(raw_txt=cleaned):
648
- if not rest_ads:
649
- self.all_conds.pop(ad_db.cond_id)
650
- await ad_db.cond.delete()
651
- ad_db.cond_id = cond.id
652
- await ad_db.save()
653
- else:
654
- if rest_ads and rest_uids:
655
- logging.error(rest_uids)
656
- # щас переписывается условие во всех объявах даже если они разных юзеров
657
- ad_db.cond.last_ver = ad_db.cond.raw_txt
658
- ad_db.cond.raw_txt = cleaned
659
- uids = {ra.maker.exid for ra in ad_db.cond.ads}
660
- self.all_conds[ad_db.cond_id] = cleaned, uids
661
- await ad_db.cond.save()
670
+ # создадим новое условие и присвоим его только текущей объяве
671
+ new_cond = await Cond.create(raw_txt=cleaned)
672
+ await self.sim_new(new_cond.id, get_sim(cleaned, ad_db.cond.raw_txt), ad_db.cond_id)
673
+ ad_db.cond_id = new_cond.id
674
+ self.all_conds[ad_db.cond_id] = cleaned, {ad_db.maker.exid}
675
+ await ad_db.save()
676
+ return ad_db, True
677
+ # проверка на всякий что точно нет такого условия
678
+ if new_cond := await Cond.get_or_none(raw_txt=cleaned):
679
+ logging.exception("!!!!!!!!!", rest_uids)
680
+ # если других объяв со старым условием этой обявы нет, либо они все этого же юзера
681
+ # обновляем условие (в тч во всех ЕГО объявах)
682
+ ad_db.cond.last_ver = ad_db.cond.raw_txt
683
+ ad_db.cond.raw_txt = cleaned
684
+ self.all_conds[ad_db.cond_id] = cleaned, {ad_db.maker.exid}
685
+ await ad_db.cond.save()
686
+ await self.sim_upd(ad_db.cond_id, cleaned)
662
687
  return ad_db, False
663
688
 
664
689
  # находим все старые тексты похожие на 90% и более
665
- if sim_connds := {
690
+ if _sims := {
666
691
  old_cid: (txt, sim)
667
692
  for old_cid, (txt, uids) in self.all_conds.items()
668
- if len(cleaned) > 15
669
- and ad.userId not in uids
670
- and (sim := int((SequenceMatcher(None, cleaned, txt).ratio() - 0.9) * 10_000)) > 0
693
+ if len(cleaned) > 15 and ad.userId not in uids and (sim := get_sim(cleaned, txt))
671
694
  }:
672
695
  # если есть, берем самый похожий из них
673
- old_cid, (txt, sim) = max(sim_connds.items(), key=lambda x: x[1])
696
+ old_cid, (txt, sim) = max(_sims.items(), key=lambda x: x[1][1])
674
697
  old_ads = await models.Ad.filter(cond_id=old_cid, maker__exid=int(ad.userId)).prefetch_related("cond")
675
698
  for old_ad in old_ads:
676
699
  # и у этого чела есть объява с почти таким же текстом
@@ -682,37 +705,50 @@ class AgentClient(BaseAgentClient): # Bybit client
682
705
  # но это не она, значит у него есть другая объява с похожим, но чуть отличающимся текстом
683
706
  logging.warning(f"ad#{ad.id}-cond#{old_cid} txt updated:\n{txt}\n|\n|\nV\n{cleaned}")
684
707
 
685
- cond = await Cond.create(raw_txt=cleaned)
686
- self.all_conds[cond.id] = cond.raw_txt, {ad.userId}
687
- act_df = {"name": ad.nickName}
708
+ new_cond = await Cond.create(raw_txt=cleaned)
709
+ self.all_conds[new_cond.id] = new_cond.raw_txt, {ad.userId}
710
+ act_df = {}
711
+ if int(ad.userId) != self.actor.exid:
712
+ act_df |= {"name": ad.nickName}
688
713
  if rname:
689
- act_df |= {"person": await Person.get_or_create(name=rname)}
714
+ act_df |= {"person": (await Person.get_or_create(name=rname))[0]}
690
715
  actor, _ = await Actor.update_or_create(act_df, exid=ad.userId, ex=self.ex_client.ex)
691
716
  ad_db = await models.Ad.create(
692
717
  price=ad.price,
693
718
  amount=float(ad.quantity) * float(ad.price),
694
719
  min_fiat=ad.minAmount,
695
720
  max_fiat=ad.maxAmount,
696
- cond=cond,
721
+ cond=new_cond,
697
722
  exid=int(ad.id),
698
723
  direction=dr
699
724
  or await Direction.get(
700
725
  sell=ad.side,
701
726
  pairex__ex=self.ex_client.ex,
702
727
  pairex__pair__coin__ticker=ad.tokenId,
703
- pairex__pair__cur__ticker=ad.currency,
728
+ pairex__pair__cur__ticker=ad.currencyId,
704
729
  ),
705
730
  maker=actor,
706
731
  )
707
732
 
708
- if sim and sim_connds: # если нашелся похожий текст у другого юзера, добавим связь с % похожести
709
- await CondSim.update_or_create({"similarity": sim, "cond_rel_id": old_cid}, cond_id=cond.id)
710
- self.cond_sims[cond.id] = old_cid, sim
711
- self.sim_conds[old_cid].add(cond.id)
733
+ # если нашелся похожий текст у другого юзера, добавим связь с % похожести
734
+ if sim:
735
+ await self.sim_new(new_cond.id, sim, old_cid)
712
736
 
713
- await ad_db.fetch_related("cond")
737
+ await ad_db.fetch_related("cond", "maker__person")
714
738
  return ad_db, True
715
739
 
740
+ async def sim_new(self, new_cid: int, sim: int, old_cid: int):
741
+ if not sim:
742
+ return None
743
+ return await CondSim.create(cond_id=new_cid, similarity=sim, cond_rel_id=old_cid)
744
+
745
+ async def sim_upd(self, cid: int, new_txt: int):
746
+ for sim_db in (_sims := await CondSim.filter(Q(join_type="OR", cond_id=cid, cond_rel_id=cid))):
747
+ (op,) = {sim_db.cond_id, sim_db.cond_rel_id} - {cid}
748
+ op_cond = await Cond[op]
749
+ sim_db.similarity = get_sim(new_txt, op_cond.raw_txt)
750
+ await sim_db.save()
751
+
716
752
  #
717
753
  # async def cond_upsert(
718
754
  # self, ad: Ad, rname: str = None, dr: Direction = None, cid: int = 0
@@ -806,6 +842,11 @@ class AgentClient(BaseAgentClient): # Bybit client
806
842
  await self.cond_upsert(ad, dr=dr, cid=ad_db.cond_id)
807
843
 
808
844
 
845
+ def get_sim(s1, s2) -> int:
846
+ sim = int((SequenceMatcher(None, s1, s2).ratio() - 0.9) * 10_000)
847
+ return sim if sim > 0 else 0
848
+
849
+
809
850
  def detailed_diff(str1, str2):
810
851
  matcher = SequenceMatcher(None, str1, str2)
811
852
  result = []
@@ -864,45 +905,47 @@ async def main():
864
905
  actor = (
865
906
  await models.Actor.filter(ex_id=9, agent__isnull=False).prefetch_related("ex", "agent", "person__user").first()
866
907
  )
867
- cl: AgentClient = actor.client()
868
- # await cl.ex_client.set_pmcurexs(cookies=actor.agent.auth["cookies"]) # 617 -> 639
869
- # await cl.set_creds()
870
- usdt = await models.Coinex.get(coin__ticker="USDT", ex=cl.actor.ex).prefetch_related("coin")
871
- btc = await models.Coinex.get(coin__ticker="BTC", ex=cl.actor.ex).prefetch_related("coin")
872
- eth = await models.Coinex.get(coin__ticker="ETH", ex=cl.actor.ex).prefetch_related("coin")
873
- usdc = await models.Coinex.get(coin__ticker="USDC", ex=cl.actor.ex).prefetch_related("coin")
874
- rub = await models.Curex.get(cur__ticker="RUB", ex=cl.actor.ex).prefetch_related("cur")
875
- # await models.Direction.get(
876
- # pairex__ex=cl.actor.ex, pairex__pair__coin__ticker="USDT", pairex__pair__cur__ticker="RUB", sell=True
877
- # )
878
- # await cl.set_creds()
879
- # await cl.actual_cond()
880
- await gather(
881
- cl.battle(usdt, rub, False, ["volet"], 79.97), # гонка в стакане покупки - мы продаем
882
- cl.battle(usdt, rub, True, ["volet"], 79.9), # гонка в стакане продажи - мы покупаем
883
- cl.battle(eth, rub, False, ["volet"], 206_000),
884
- cl.battle(eth, rub, True, ["volet"], 200_000),
885
- cl.battle(btc, rub, False, ["volet"], 8_500_000),
886
- cl.battle(btc, rub, True, ["volet"], 8_400_000),
887
- cl.battle(usdc, rub, False, ["volet"], 80.5),
888
- cl.battle(usdc, rub, True, ["volet"], 79),
889
- cl.take(usdt, rub, False, ceil=80.5, volume=360),
890
- cl.take(usdt, rub, True, ceil=80.5, volume=360),
891
- )
908
+ async with FileClient(TOKEN) as b:
909
+ cl: AgentClient = actor.client(b)
910
+ # await cl.ex_client.set_pmcurexs(cookies=actor.agent.auth["cookies"]) # 617 -> 639
911
+ # await cl.set_creds()
912
+ usdt = await models.Coinex.get(coin__ticker="USDT", ex=cl.actor.ex).prefetch_related("coin")
913
+ btc = await models.Coinex.get(coin__ticker="BTC", ex=cl.actor.ex).prefetch_related("coin")
914
+ eth = await models.Coinex.get(coin__ticker="ETH", ex=cl.actor.ex).prefetch_related("coin")
915
+ usdc = await models.Coinex.get(coin__ticker="USDC", ex=cl.actor.ex).prefetch_related("coin")
916
+ rub = await models.Curex.get(cur__ticker="RUB", ex=cl.actor.ex).prefetch_related("cur")
917
+ # await models.Direction.get(
918
+ # pairex__ex=cl.actor.ex, pairex__pair__coin__ticker="USDT", pairex__pair__cur__ticker="RUB", sell=True
919
+ # )
920
+ # await cl.set_creds()
921
+ await cl.get_api_orders()
922
+ # await cl.actual_cond()
923
+ await gather(
924
+ cl.battle(usdt, rub, False, ["volet"], 79.97), # гонка в стакане покупки - мы продаем
925
+ cl.battle(usdt, rub, True, ["volet"], 79.9), # гонка в стакане продажи - мы покупаем
926
+ cl.battle(eth, rub, False, ["volet"], 206_000),
927
+ cl.battle(eth, rub, True, ["volet"], 200_000),
928
+ cl.battle(btc, rub, False, ["volet"], 8_500_000),
929
+ cl.battle(btc, rub, True, ["volet"], 8_400_000),
930
+ cl.battle(usdc, rub, False, ["volet"], 80.5),
931
+ cl.battle(usdc, rub, True, ["volet"], 79),
932
+ cl.take(usdt, rub, False, ceil=80.5, volume=360),
933
+ cl.take(usdt, rub, True, ceil=80.5, volume=360),
934
+ )
892
935
 
893
- bor = BaseOrderReq(
894
- ad_id="1861440060199632896",
895
- # asset_amount=40,
896
- fiat_amount=3000,
897
- amount_is_fiat=True,
898
- is_sell=False,
899
- cur_exid=rub.exid,
900
- coin_exid=usdt.exid,
901
- coin_scale=usdt.coin.scale,
902
- )
903
- res: OrderResp = await cl.order_request(bor)
904
- await cl.cancel_order(res.orderId)
905
- await cl.close()
936
+ bor = BaseOrderReq(
937
+ ad_id="1861440060199632896",
938
+ # asset_amount=40,
939
+ fiat_amount=3000,
940
+ amount_is_fiat=True,
941
+ is_sell=False,
942
+ cur_exid=rub.exid,
943
+ coin_exid=usdt.exid,
944
+ coin_scale=usdt.coin.scale,
945
+ )
946
+ res: OrderResp = await cl.order_request(bor)
947
+ await cl.cancel_order(res.orderId)
948
+ await cl.close()
906
949
 
907
950
 
908
951
  if __name__ == "__main__":
@@ -105,7 +105,7 @@ class PaymentConfigVo(BaseModel):
105
105
  addTips: str
106
106
  itemTips: str
107
107
  online: int
108
- items: list[str]
108
+ items: list[dict[str, str | bool]]
109
109
 
110
110
 
111
111
  class PaymentTerm(BaseModel):
@@ -236,7 +236,7 @@ class OrderFull(OrderItem):
236
236
  needSellerExamineCancel: bool
237
237
  couponCurrencyAmount: str
238
238
  totalCurrencyAmount: str
239
- usedCoupon: Literal[1, 2] # bool: 1: used, 2: no used
239
+ usedCoupon: bool # bool: 1: used, 2: no used
240
240
  couponTokenId: str
241
241
  couponQuantity: str
242
242
  completedOrderAppealCount: int
@@ -262,12 +262,12 @@ class Message(BaseModel):
262
262
  msgCode: int
263
263
  createDate: str
264
264
  isRead: Literal[0, 1] # int: 1: read, 0: unread
265
- contentType: Literal["text", "pic", "pdf", "video"]
265
+ contentType: Literal["str", "pic", "pdf", "video"]
266
266
  roleType: str
267
267
  userId: str
268
268
  orderId: str
269
269
  msgUuid: str
270
270
  nickName: str
271
- read: str
271
+ read: Literal[0, 1]
272
272
  fileName: str
273
273
  onlyForCustomer: int
@@ -1,7 +1,7 @@
1
1
  from typing import Literal
2
2
 
3
3
  from pydantic import BaseModel
4
- from xync_schema.types import BaseAd
4
+ from xync_schema.xtype import BaseAd
5
5
 
6
6
 
7
7
  class TradeRule(BaseModel):
@@ -4,7 +4,7 @@ from collections import defaultdict
4
4
  from msgspec import convert
5
5
  from pyro_client.client.file import FileClient
6
6
  from x_model import init_db
7
- from xync_schema import models, types
7
+ from xync_schema import models, xtype
8
8
  from xync_schema.models import Ex, Cur
9
9
  from xync_schema.enums import PmType
10
10
 
@@ -51,7 +51,7 @@ class ExClient(BaseExClient):
51
51
 
52
52
  async def ads(
53
53
  self, coin_exid: int, cur_exid: int, is_sell: bool, pm_exids: list[str] = None, amount: int = None
54
- ) -> list[types.BaseAd]:
54
+ ) -> list[xtype.BaseAd]:
55
55
  params = {
56
56
  "coinId": coin_exid,
57
57
  "currency": cur_exid,
@@ -70,7 +70,7 @@ class ExClient(BaseExClient):
70
70
  ads = [ad.Resp(**a) for a in res]
71
71
  return ads
72
72
 
73
- async def ad(self, ad_id: int) -> types.BaseAd:
73
+ async def ad(self, ad_id: int) -> xtype.BaseAd:
74
74
  pass
75
75
 
76
76
  # 20: Get all pms
@@ -99,7 +99,7 @@ class ExClient(BaseExClient):
99
99
  return pmsd
100
100
 
101
101
  # 21: Get all: currency,pay,allCountry,coin
102
- async def curs(self) -> dict[int, types.CurEx]:
102
+ async def curs(self) -> dict[int, xtype.CurEx]:
103
103
  self.session.headers["client-type"] = "web"
104
104
  curs: list[dict] = (await self.data)["currency"]
105
105
  cmap: dict[str, int] = {c["nameShort"]: c["currencyId"] for c in curs}
@@ -108,7 +108,7 @@ class ExClient(BaseExClient):
108
108
  for c in res:
109
109
  for q in c["quoteAsset"]:
110
110
  cursd[q["name"]] = max(cursd.get(q["name"], 0), float(q["minAmount"]))
111
- return {exid: types.CurEx(exid=exid, ticker=tkr, minimum=cursd.get(tkr)) for tkr, exid in cmap.items()}
111
+ return {exid: xtype.CurEx(exid=exid, ticker=tkr, minimum=cursd.get(tkr)) for tkr, exid in cmap.items()}
112
112
 
113
113
  # 22: Список платежных методов по каждой валюте
114
114
  async def cur_pms_map(self) -> dict[int, set[int]]:
@@ -117,13 +117,13 @@ class ExClient(BaseExClient):
117
117
  return {c["currencyId"]: set(c["supportPayments"]) - wrong_pms for c in res["currency"] if c["supportPayments"]}
118
118
 
119
119
  # 23: Список торгуемых монет
120
- async def coins(self) -> dict[int, types.CoinEx]:
120
+ async def coins(self) -> dict[int, xtype.CoinEx]:
121
121
  self.session.headers["client-type"] = "web"
122
122
  coins: list[dict] = (await self.data)["coin"]
123
123
  res = (await self._get("/-/x/otc/v1/trade/fast/config/list?side=buy&tradeMode=c2c_simple"))["data"]
124
124
  coinsl: list[str] = [c["cryptoAsset"]["name"] for c in res]
125
125
  return {
126
- c["coinId"]: types.CoinEx(exid=c["coinId"], ticker=c["coinCode"], scale=c["showPrecision"])
126
+ c["coinId"]: xtype.CoinEx(exid=c["coinId"], ticker=c["coinCode"], scale=c["showPrecision"])
127
127
  for c in coins
128
128
  if c["coinCode"] in coinsl
129
129
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xync-client
3
- Version: 0.0.57.dev9
3
+ Version: 0.0.57.dev11
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