xync-client 0.0.144__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.

Files changed (125) hide show
  1. {xync_client-0.0.144/xync_client.egg-info → xync_client-0.0.147}/PKG-INFO +1 -1
  2. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Abc/Agent.py +21 -5
  3. xync_client-0.0.147/xync_client/Abc/HasAbotUid.py +10 -0
  4. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Abc/InAgent.py +5 -3
  5. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Abc/PmAgent.py +34 -23
  6. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Abc/xtype.py +3 -1
  7. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Bybit/InAgent.py +55 -33
  8. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Bybit/agent.py +110 -53
  9. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Bybit/etype/order.py +34 -16
  10. xync_client-0.0.147/xync_client/Gmail/__init__.py +137 -0
  11. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Pms/Payeer/__init__.py +37 -28
  12. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Pms/Payeer/login.py +6 -2
  13. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Pms/Volet/__init__.py +80 -61
  14. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Pms/Volet/api.py +5 -4
  15. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/loader.py +1 -0
  16. {xync_client-0.0.144 → xync_client-0.0.147/xync_client.egg-info}/PKG-INFO +1 -1
  17. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client.egg-info/SOURCES.txt +1 -0
  18. xync_client-0.0.144/xync_client/Gmail/__init__.py +0 -116
  19. {xync_client-0.0.144 → xync_client-0.0.147}/.env.sample +0 -0
  20. {xync_client-0.0.144 → xync_client-0.0.147}/.gitignore +0 -0
  21. {xync_client-0.0.144 → xync_client-0.0.147}/.pre-commit-config.yaml +0 -0
  22. {xync_client-0.0.144 → xync_client-0.0.147}/README.md +0 -0
  23. {xync_client-0.0.144 → xync_client-0.0.147}/__init__.py +0 -0
  24. {xync_client-0.0.144 → xync_client-0.0.147}/makefile +0 -0
  25. {xync_client-0.0.144 → xync_client-0.0.147}/pyproject.toml +0 -0
  26. {xync_client-0.0.144 → xync_client-0.0.147}/setup.cfg +0 -0
  27. {xync_client-0.0.144 → xync_client-0.0.147}/tests/TestAgent.py +0 -0
  28. {xync_client-0.0.144 → xync_client-0.0.147}/tests/TestAsset.py +0 -0
  29. {xync_client-0.0.144 → xync_client-0.0.147}/tests/TestEx.py +0 -0
  30. {xync_client-0.0.144 → xync_client-0.0.147}/tests/TestOrder.py +0 -0
  31. {xync_client-0.0.144 → xync_client-0.0.147}/tests/_todo_refact/Binance/test_binance.py +0 -0
  32. {xync_client-0.0.144 → xync_client-0.0.147}/tests/_todo_refact/Bybit/test_bybit.py +0 -0
  33. {xync_client-0.0.144 → xync_client-0.0.147}/tests/_todo_refact/Bybit/test_bybit_p2p.py +0 -0
  34. {xync_client-0.0.144 → xync_client-0.0.147}/tests/_todo_refact/Gate/test_gate.py +0 -0
  35. {xync_client-0.0.144 → xync_client-0.0.147}/tests/_todo_refact/Wallet/test_agent.py +0 -0
  36. {xync_client-0.0.144 → xync_client-0.0.147}/tests/_todo_refact/Wallet/test_ex.py +0 -0
  37. {xync_client-0.0.144 → xync_client-0.0.147}/tests/_todo_refact/__init__.py +0 -0
  38. {xync_client-0.0.144 → xync_client-0.0.147}/tests/_todo_refact/_test_ex.py +0 -0
  39. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Abc/Asset.py +0 -0
  40. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Abc/Auth.py +0 -0
  41. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Abc/BaseTest.py +0 -0
  42. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Abc/Ex.py +0 -0
  43. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Abc/Exception.py +0 -0
  44. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Abc/Order.py +0 -0
  45. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Binance/__init__.py +0 -0
  46. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Binance/binance_async.py +0 -0
  47. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Binance/earn_api.py +0 -0
  48. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Binance/etype/ad.py +0 -0
  49. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Binance/etype/pm.py +0 -0
  50. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Binance/ex.py +0 -0
  51. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Binance/exceptions.py +0 -0
  52. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Binance/sapi.py +0 -0
  53. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Binance/web_c2c.py +0 -0
  54. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/BingX/__init__.py +0 -0
  55. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/BingX/agent.py +0 -0
  56. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/BingX/base.py +0 -0
  57. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/BingX/etype/ad.py +0 -0
  58. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/BingX/etype/pm.py +0 -0
  59. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/BingX/ex.py +0 -0
  60. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/BingX/req.mjs +0 -0
  61. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/BingX/sign.js +0 -0
  62. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/BitGet/__init__.py +0 -0
  63. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/BitGet/agent.py +0 -0
  64. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/BitGet/etype/ad.py +0 -0
  65. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/BitGet/ex.py +0 -0
  66. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/BitPapa/ex.py +0 -0
  67. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Bybit/etype/ad.py +0 -0
  68. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Bybit/etype/cred.py +0 -0
  69. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Bybit/ex.py +0 -0
  70. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Bybit/order.py +0 -0
  71. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Bybit/web_earn.py +0 -0
  72. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Bybit/web_p2p.py +0 -0
  73. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Bybit/ws.py +0 -0
  74. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Gate/etype/ad.py +0 -0
  75. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Gate/ex.py +0 -0
  76. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Gate/premarket.py +0 -0
  77. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Htx/agent.py +0 -0
  78. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Htx/earn.py +0 -0
  79. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Htx/etype/__init__.py +0 -0
  80. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Htx/etype/ad.py +0 -0
  81. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Htx/etype/cred.py +0 -0
  82. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Htx/etype/pm.py +0 -0
  83. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Htx/etype/test.py +0 -0
  84. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Htx/ex.py +0 -0
  85. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/KuCoin/etype/ad.py +0 -0
  86. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/KuCoin/etype/pm.py +0 -0
  87. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/KuCoin/ex.py +0 -0
  88. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/KuCoin/web.py +0 -0
  89. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Mexc/etype/ad.py +0 -0
  90. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Mexc/etype/pm.py +0 -0
  91. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Mexc/ex.py +0 -0
  92. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Okx/etype/ad.py +0 -0
  93. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Okx/etype/pm.py +0 -0
  94. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Okx/ex.py +0 -0
  95. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Pms/.gitignore +0 -0
  96. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Pms/Alfa/__init__.py +0 -0
  97. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Pms/Alfa/state.json +0 -0
  98. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Pms/MTS/__init__.py +0 -0
  99. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Pms/Ozon/__init__.py +0 -0
  100. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Pms/Payeer/.gitignore +0 -0
  101. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Pms/Payeer/api.py +0 -0
  102. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Pms/Sber/__init__.py +0 -0
  103. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Pms/Sber/utils.py +0 -0
  104. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Pms/Tinkoff/__init__.py +0 -0
  105. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Pms/Volet/_todo_req/req.mjs +0 -0
  106. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Pms/Volet/_todo_req/req.py +0 -0
  107. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Pms/Volet/pl.py +0 -0
  108. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Pms/Xync/__main__.py +0 -0
  109. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Pms/Xync/ed.py +0 -0
  110. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/Pms/Yandex/__init__.py +0 -0
  111. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/TgWallet/agent.py +0 -0
  112. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/TgWallet/asset.py +0 -0
  113. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/TgWallet/auth.py +0 -0
  114. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/TgWallet/ex.py +0 -0
  115. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/TgWallet/inAgent.py +0 -0
  116. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/TgWallet/order.py +0 -0
  117. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/TgWallet/pyd.py +0 -0
  118. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/TgWallet/pyro.py +0 -0
  119. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/TgWallet/web.py +0 -0
  120. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/__init__.py +0 -0
  121. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/details.py +0 -0
  122. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client/pm_unifier.py +0 -0
  123. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client.egg-info/dependency_links.txt +0 -0
  124. {xync_client-0.0.144 → xync_client-0.0.147}/xync_client.egg-info/requires.txt +0 -0
  125. {xync_client-0.0.144 → xync_client-0.0.147}/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.144
3
+ Version: 0.0.147
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
@@ -3,19 +3,35 @@ from abc import abstractmethod
3
3
  from pydantic import BaseModel
4
4
  from pyro_client.client.file import FileClient
5
5
  from x_client.aiohttp import Client as HttpClient
6
+ from xync_bot import XyncBot
6
7
  from xync_schema import models
7
- from xync_schema.models import OrderStatus, Coin, Cur, Ad, AdStatus, Actor
8
+ from xync_schema.models import OrderStatus, Coin, Cur, Ad, AdStatus, Actor, Agent
8
9
  from xync_schema.xtype import BaseAd
9
10
 
10
11
  from xync_client.Abc.Ex import BaseExClient
11
12
  from xync_client.Abc.xtype import CredExOut, BaseOrderReq, BaseAdUpdate
13
+ from xync_client.Gmail import GmClient
12
14
 
13
15
 
14
16
  class BaseAgentClient(HttpClient):
15
- def __init__(self, actor: Actor, bot: FileClient, headers: dict[str, str] = None, cookies: dict[str, str] = None):
16
- self.actor: Actor = actor
17
- super().__init__(actor.ex.host_p2p, headers, cookies)
18
- self.ex_client: BaseExClient = self.actor.ex.client(bot)
17
+ bbot: XyncBot
18
+ fbot: FileClient
19
+
20
+ def __init__(
21
+ self,
22
+ agent: Agent,
23
+ fbot: FileClient,
24
+ bbot: XyncBot,
25
+ headers: dict[str, str] = None,
26
+ cookies: dict[str, str] = None,
27
+ ):
28
+ self.bbot = bbot
29
+ self.fbot = fbot
30
+ self.agent: Agent = agent
31
+ self.actor: Actor = agent.actor
32
+ self.gmail = GmClient(agent.actor.person.user)
33
+ super().__init__(self.actor.ex.host_p2p, headers, cookies)
34
+ self.ex_client: BaseExClient = self.actor.ex.client(fbot)
19
35
 
20
36
  # 0: Получшение ордеров в статусе status, по монете coin, в валюте coin, в направлении is_sell: bool
21
37
  @abstractmethod
@@ -0,0 +1,10 @@
1
+ from PGram import Bot
2
+ from aiogram.types import Message
3
+
4
+
5
+ class HasAbotUid:
6
+ abot: Bot
7
+ uid: int
8
+
9
+ async def receive(self, text: str, photo: bytes = None, video: bytes = None) -> Message:
10
+ return await self.abot.send(self.uid, txt=text, photo=photo, video=video)
@@ -1,8 +1,10 @@
1
1
  from abc import abstractmethod
2
2
 
3
3
  from pyro_client.client.file import FileClient
4
+ from xync_bot import XyncBot
5
+
4
6
  from xync_client.Abc.PmAgent import PmAgentClient
5
- from xync_schema.models import Actor
7
+ from xync_schema.models import Agent
6
8
 
7
9
  from xync_client.Abc.Agent import BaseAgentClient
8
10
 
@@ -10,8 +12,8 @@ from xync_client.Abc.Agent import BaseAgentClient
10
12
  class BaseInAgentClient:
11
13
  pmacs: dict[int, PmAgentClient] = {}
12
14
 
13
- def __init__(self, actor: Actor, bot: FileClient):
14
- self.agent_client: BaseAgentClient = actor.client(bot)
15
+ def __init__(self, agent: Agent, fbot: FileClient, bbot: XyncBot):
16
+ self.agent_client: BaseAgentClient = agent.client(fbot, bbot)
15
17
 
16
18
  @abstractmethod
17
19
  async def start_listen(self) -> bool: ...
@@ -4,52 +4,57 @@ from datetime import datetime, timedelta
4
4
  from decimal import Decimal
5
5
  from enum import StrEnum
6
6
 
7
- from playwright.async_api import Page, Playwright
7
+ from PGram import Bot
8
+ from playwright.async_api import Page, Playwright, Browser
8
9
  from pyro_client.client.file import FileClient
9
10
  from pyro_client.client.user import UserClient
11
+ from tortoise.timezone import now
10
12
 
11
- from xync_client.loader import NET_TOKEN
12
13
  from xync_schema.enums import UserStatus
13
- from xync_schema.models import PmAgent, User
14
+ from xync_schema.models import PmAgent, User, Transfer
15
+
16
+ from xync_client.Abc.HasAbotUid import HasAbotUid
14
17
 
15
18
 
16
19
  class LoginFailedException(Exception): ...
17
20
 
18
21
 
19
- class PmAgentClient(metaclass=ABCMeta):
22
+ class PmAgentClient(HasAbotUid, metaclass=ABCMeta):
20
23
  class Pages(StrEnum):
21
24
  base = "https://host"
22
25
  LOGIN = base + "login"
23
26
  SEND = base + "send"
24
27
  OTP_LOGIN = base + "login/otp"
25
28
 
29
+ browser: Browser
26
30
  norm: str
27
31
  agent: PmAgent
28
- bot: FileClient | UserClient
32
+ ubot: FileClient | UserClient = None
29
33
  page: Page
30
34
  pages: type(StrEnum) = Pages
31
- last_page: int = 0
32
- last_active: datetime = datetime.now()
35
+ last_active: datetime = now()
36
+ with_userbot: bool = False
33
37
  _is_started: bool = False
34
38
 
35
- async def start(self, pw: Playwright, headed: bool = False, userbot: bool = False) -> "PmAgentClient":
36
- bot = FileClient(NET_TOKEN)
37
- self.bot = UserClient(self.uid, bot) if userbot else bot
38
- await self.bot.start()
39
+ async def start(self, pw: Playwright, headed: bool = False) -> "PmAgentClient":
40
+ if self.with_userbot:
41
+ self.ubot = UserClient(self.uid)
42
+ await self.ubot.start()
39
43
 
40
44
  self.browser = await pw.chromium.launch(
41
- channel="chromium" if headed else "chromium-headless-shell", headless=not headed
45
+ channel="chrome-beta" if headed else "chromium-headless-shell", headless=not headed
42
46
  )
47
+ # noinspection PyTypeChecker
43
48
  context = await self.browser.new_context(storage_state=self.agent.state)
44
49
  self.page = await context.new_page()
45
- await self.page.goto(self.pages.SEND) # Оптимистично переходим сразу на страницу отправки
50
+ await self.page.goto(self.pages.SEND, wait_until="commit") # Оптимистично переходим сразу на страницу отправки
46
51
  if self.page.url.startswith(self.pages.LOGIN): # Если перебросило на страницу логина
47
52
  await self._login() # Логинимся
48
53
  if not self.page.url.startswith(self.pages.SEND): # Если в итоге не удалось попасть на отправку
49
- await self.bot.send(self.norm + " not logged in!", self.uid, photo=await self.page.screenshot())
54
+ await self.receive(self.norm + " not logged in!", photo=await self.page.screenshot())
50
55
  raise LoginFailedException(f"User {self.agent.user_id} has not logged in")
51
56
  loop = get_running_loop()
52
- self.last_active = datetime.now()
57
+ self.last_active = now()
53
58
  loop.create_task(self._idle()) # Бесконечно пасёмся в фоне на странице отправки, что бы куки не протухли
54
59
  self._is_started = True
55
60
  return self
@@ -59,18 +64,21 @@ class PmAgentClient(metaclass=ABCMeta):
59
64
  async def _idle(self): # todo: не мешать другим процессам, обновлять на другой вкладке?
60
65
  while (await User.get(username_id=self.uid)).status >= UserStatus.ACTIVE:
61
66
  await self.page.wait_for_timeout(30 * 1000)
62
- if self.last_active < datetime.now() - timedelta(minutes=1):
63
- await self.page.reload()
64
- self.last_active = datetime.now()
65
- await self.bot.send(self.norm + " stoped", self.uid)
67
+ if self.last_active < now() - timedelta(minutes=1):
68
+ await self.page.reload(wait_until="commit")
69
+ self.last_active = now()
70
+ await self.receive(self.norm + " stoped")
66
71
  await self.stop()
67
72
 
68
73
  async def stop(self):
69
74
  # save state
75
+ # noinspection PyTypeChecker
70
76
  self.agent.state = await self.page.context.storage_state()
71
77
  await self.agent.save()
72
78
  # closing
73
- await self.bot.stop()
79
+ await self.abot.stop()
80
+ if self.ubot:
81
+ await self.ubot.stop()
74
82
  await self.page.context.close()
75
83
  await self.page.context.browser.close()
76
84
  self._is_started = False
@@ -79,15 +87,18 @@ class PmAgentClient(metaclass=ABCMeta):
79
87
  async def _login(self): ...
80
88
 
81
89
  @abstractmethod
82
- async def send(self, dest, amount: int, cur: str) -> tuple[int, bytes, float]: ...
90
+ async def send(self, t: Transfer) -> tuple[int, bytes] | float: ...
83
91
 
84
92
  @abstractmethod # проверка поступления определенной суммы за последние пол часа (минимум), return точную сумму
85
- async def check_in(self, amount: int | Decimal | float, cur: str, tid: str | int = None) -> float | None: ...
93
+ async def check_in(
94
+ self, amount: int | Decimal | float, cur: str, dt: datetime, tid: str | int = None
95
+ ) -> float | None: ...
86
96
 
87
97
  @abstractmethod # видео входа в аккаунт, и переход в историю поступлений за последние сутки (минимум)
88
98
  async def proof(self) -> bytes: ...
89
99
 
90
- def __init__(self, agent: PmAgent):
100
+ def __init__(self, agent: PmAgent, abot: Bot):
91
101
  self.agent = agent
102
+ self.abot = abot
92
103
  self.uid = agent.user.username_id
93
104
  self.norm = agent.pm.norm
@@ -53,7 +53,9 @@ class BaseOrderReq(BaseModel):
53
53
  asset_amount: float | None = None
54
54
  fiat_amount: float | None = None
55
55
 
56
- # todo: mv from to base to special ex class
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
@@ -1,6 +1,7 @@
1
1
  import json
2
2
  import logging
3
3
  import re
4
+ import traceback
4
5
  from datetime import datetime, timezone, timedelta
5
6
  from uuid import uuid4
6
7
 
@@ -14,6 +15,7 @@ from pyro_client.client.file import FileClient
14
15
  from tortoise.exceptions import IntegrityError
15
16
  from tortoise.timezone import now
16
17
  from tortoise.transactions import in_transaction
18
+ from xync_bot import XyncBot
17
19
 
18
20
  from xync_client.Abc.PmAgent import PmAgentClient
19
21
  from xync_schema import models
@@ -28,7 +30,7 @@ from xync_client.Bybit.etype.order import (
28
30
  OrderFull,
29
31
  StatusApi,
30
32
  )
31
- from xync_client.loader import NET_TOKEN
33
+ from xync_client.loader import NET_TOKEN, PAY_TOKEN
32
34
  from xync_client.Abc.InAgent import BaseInAgentClient
33
35
  from xync_client.Bybit.agent import AgentClient
34
36
 
@@ -39,7 +41,7 @@ class InAgentClient(BaseInAgentClient):
39
41
  async def start_listen(self):
40
42
  t = await self.agent_client.ott()
41
43
  ts = int(float(t["time_now"]) * 1000)
42
- await self.ws_prv(self.agent_client.actor.agent.auth["deviceId"], t["result"], ts)
44
+ await self.ws_prv(self.agent_client.agent.auth["deviceId"], t["result"], ts)
43
45
 
44
46
  # 3N: [T] - Уведомление об одобрении запроса на сделку
45
47
  async def request_accepted_notify(self) -> int: ... # id
@@ -75,7 +77,7 @@ class InAgentClient(BaseInAgentClient):
75
77
  while resp := await websocket.recv():
76
78
  if data := json.loads(resp):
77
79
  upd, order_db = None, None
78
- logging.info(f" {datetime.now().strftime('%H:%M:%S')} upd: {data.get('topic')}:{data.get('type')}")
80
+ logging.info(f" {now().strftime('%H:%M:%S')} upd: {data.get('topic')}:{data.get('type')}")
79
81
  match data.get("topic"):
80
82
  case "OTC_ORDER_STATUS":
81
83
  match data["type"]:
@@ -96,20 +98,21 @@ class InAgentClient(BaseInAgentClient):
96
98
  # сразу уменьшаем доступный остаток монеты/валюты
97
99
  await self.money_upd(order_db)
98
100
  if upd.side: # я покупатель - ждем мою оплату
99
- dest = order.paymentTermList[0].accountNo
100
- if not re.match(r"^([PpРр])\d{7,10}\b", dest):
101
+ _dest = order.paymentTermList[0].accountNo
102
+ if not re.match(r"^([PpРр])\d{7,10}\b", _dest):
101
103
  continue
102
104
  await order_db.fetch_related("ad__pair_side__pair", "cred__pmcur__cur")
103
- await self.send_payment(order_db, dest)
105
+ await self.send_payment(order_db)
104
106
  case StatusApi.wait_for_buyer:
105
107
  if upd.side == 0: # ждем когда покупатель оплатит
106
108
  if not (pmacdx := await self.get_pma_by_cdex(order)):
107
109
  continue
108
110
  pma, cdx = pmacdx
109
- am, tid = pma.check_in(
111
+ am, tid = await pma.check_in(
110
112
  Decimal(order.amount),
111
113
  cdx.cred.pmcur.cur.ticker,
112
- datetime.fromtimestamp(float(order.createDate) / 1000),
114
+ # todo: почему в московском час.поясе?
115
+ datetime.fromtimestamp(float(order.transferDate) / 1000),
113
116
  )
114
117
  if not tid:
115
118
  logging.info(
@@ -140,9 +143,13 @@ class InAgentClient(BaseInAgentClient):
140
143
  if (
141
144
  o["amount"] == order.amount
142
145
  and o["id"] != upd.id
143
- and o.paymentTermList[0].accountNo
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"]
144
152
  == order.paymentTermList[0].accountNo
145
- and int(order.createDate) < int(o["createDate"]) + 3600 * 000
146
153
  )
147
154
  ]
148
155
  curex = await models.CurEx.get(
@@ -153,7 +160,7 @@ class InAgentClient(BaseInAgentClient):
153
160
  cred_id=order_db.cred_id,
154
161
  amount=int(float(order.amount) * 10**curex.scale),
155
162
  status__not_in=[OrderStatus.completed, OrderStatus.canceled],
156
- created_at__gt=now() - timedelta(hours=1),
163
+ created_at__gt=now() - timedelta(minutes=15),
157
164
  )
158
165
  if pos or pos_db:
159
166
  await self.agent_client.ex_client.bot.send(
@@ -167,10 +174,10 @@ class InAgentClient(BaseInAgentClient):
167
174
  # !!! ОТПРАВЛЯЕМ ДЕНЬГИ !!!
168
175
  self.agent_client.api.release_assets(orderId=upd.id)
169
176
  logging.info(
170
- f"Order {order.id} created, paid before #{tid}:{am} at {order.createDate}, and RELEASED at {datetime.now()}"
177
+ f"Order {order.id} created, paid before #{tid}:{am} at {order.createDate}, and RELEASED at {now()}"
171
178
  )
172
179
  elif upd.side == 1: # я покупатель - ждем мою оплату
173
- continue # logging.warning(f"Order {order.id} PAID at {datetime.now()}: {int_am}")
180
+ continue # logging.warning(f"Order {order.id} PAID at {now()}: {int_am}")
174
181
  else:
175
182
  ...
176
183
  # todo: check is always canceling
@@ -245,7 +252,10 @@ class InAgentClient(BaseInAgentClient):
245
252
  if not upd.message:
246
253
  ...
247
254
  if im_buyer and (g := re.match(r"^[PpРр]\d{7,10}\b", upd.message)):
248
- await self.send_payment(order_db, g.group())
255
+ if not order_db.cred.detail.startswith(dest := g.group()):
256
+ order_db.cred.detail = dest
257
+ await order_db.save()
258
+ await self.send_payment(order_db)
249
259
  case "READ":
250
260
  upd = Read.model_validate(data["data"])
251
261
  # if upd.status not in (StatusWs.created, StatusWs.canceled, 10, StatusWs.completed):
@@ -318,7 +328,7 @@ class InAgentClient(BaseInAgentClient):
318
328
  await fiat.save(update_fields=["amount"])
319
329
  logging.info(f"Order #{order_db.id} {order_db.status.name}. Fiat: {fiat.amount}, Asset: {ass.free}")
320
330
 
321
- async def send_payment(self, order_db: models.Order, dest):
331
+ async def send_payment(self, order_db: models.Order):
322
332
  if order_db.status != OrderStatus.created:
323
333
  return
324
334
  fmt_am = round(order_db.amount * 10**-2, 2)
@@ -335,19 +345,23 @@ class InAgentClient(BaseInAgentClient):
335
345
  # проверяем не отправляли ли мы уже перевод по этому ордеру
336
346
  if t := await models.Transfer.get_or_none(order=order_db, amount=order_db.amount):
337
347
  await pma.bot.send(
338
- f"Order# {order_db.exid}: Double send {fmt_am}{cur} to {dest} #{t.pmid}!",
348
+ f"Order# {order_db.exid}: Double send {fmt_am}{cur} to {order_db.cred.detail} #{t.pmid}!",
339
349
  self.agent_client.actor.person.user.username_id,
340
350
  )
341
- raise Exception(f"Order# {order_db.exid}: Double send {fmt_am}{cur} to {dest} #{t.pmid}!")
351
+ raise Exception(
352
+ f"Order# {order_db.exid}: Double send {fmt_am}{cur} to {order_db.cred.detail} #{t.pmid}!"
353
+ )
342
354
 
343
355
  # ставим в бд статус "оплачен"
344
356
  order_db.status = OrderStatus.paid
345
357
  order_db.payed_at = datetime.now(timezone.utc)
346
358
  await order_db.save()
347
- # отправляем деньги
348
- tid, img, rest_amount = await pma.send(dest=dest, amount=fmt_am, cur=cur)
349
359
  # создаем перевод в бд
350
- t, _ = await models.Transfer.update_or_create({"order": order_db, "amount": order_db.amount}, pmid=tid)
360
+ t = models.Transfer(order=order_db, amount=order_db.amount, updated_at=now())
361
+ # отправляем деньги
362
+ tid, img = await pma.send(t)
363
+ t.pmid = tid
364
+ await t.save()
351
365
  await self.send_receipt(str(order_db.exid), tid) # отправляем продавцу чек
352
366
  logging.info(f"Order {order_db.exid} PAID at {datetime.now()}: {fmt_am}!")
353
367
 
@@ -396,33 +410,41 @@ async def main():
396
410
  from x_model import init_db
397
411
  from xync_client.loader import TORM
398
412
 
399
- _ = await init_db(TORM, True)
413
+ cn = await init_db(TORM, True)
400
414
  logging.basicConfig(level=logging.INFO)
401
415
 
402
- actor = (
403
- await models.Actor.filter(
404
- ex_id=4,
405
- agent__auth__isnull=False,
406
- person__user__status=UserStatus.ACTIVE,
407
- person__user__pm_agents__isnull=False,
416
+ agent = (
417
+ await models.Agent.filter(
418
+ actor__ex_id=4,
419
+ active=True,
420
+ auth__isnull=False,
421
+ actor__person__user__status=UserStatus.ACTIVE,
422
+ actor__person__user__pm_agents__isnull=False,
408
423
  )
409
- .prefetch_related("ex", "agent", "person__user__pm_agents__user", "person__user__pm_agents__pm")
424
+ .prefetch_related("actor__ex", "actor__person__user__gmail")
410
425
  .first()
411
426
  )
427
+ pm_agents = await models.PmAgent.filter(
428
+ active=True,
429
+ auth__isnull=False,
430
+ user__status=UserStatus.ACTIVE,
431
+ ).prefetch_related("pm", "user__gmail")
432
+
433
+ bbot = XyncBot(PAY_TOKEN, cn)
412
434
 
413
435
  async with FileClient(NET_TOKEN) as b:
414
436
  b: FileClient
415
- cl: InAgentClient = actor.in_client(b)
437
+ cl: InAgentClient = agent.in_client(b, bbot)
416
438
  # await cl.agent_client.export_my_ads()
417
439
  # payeer_cl = Client(actor.person.user.username_id)
418
- for pma in actor.person.user.pm_agents:
419
- pcl = pma.client()
440
+ for pma in pm_agents:
441
+ pcl: PmAgentClient = pma.client(bbot)
420
442
  cl.pmacs[pma.pm_id] = await pcl.start(await async_playwright().start(), False)
421
443
  try:
422
444
  _ = await cl.start_listen()
423
445
  except Exception as e:
424
- await b.send("😱Bybit InAgent CRASHED!!!😱", actor.person.user.username_id)
425
- await b.send(e.__repr__(), actor.person.user.username_id)
446
+ await b.send("😱Bybit InAgent CRASHED!!!😱", agent.actor.person.user.username_id)
447
+ await b.send(f"```\n{''.join(traceback.format_exception(e))}\n```", agent.actor.person.user.username_id)
426
448
  await cl.agent_client.close()
427
449
 
428
450