xync-client 0.0.141__py3-none-any.whl → 0.0.155__py3-none-any.whl

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.
@@ -11,17 +11,22 @@ from os import urandom
11
11
  from time import sleep
12
12
  from urllib.parse import urlencode
13
13
 
14
+ from PGram import Bot
14
15
  from asyncpg.pgproto.pgproto import timedelta
15
16
  from cryptography.hazmat.primitives import padding
16
17
  from cryptography.hazmat.primitives.ciphers import Cipher
17
18
  from cryptography.hazmat.primitives.ciphers.algorithms import AES
18
19
  from cryptography.hazmat.primitives.ciphers.modes import CBC
19
20
  from payeer_api import PayeerAPI
20
- from playwright.async_api import async_playwright, Playwright, Error
21
+ from playwright.async_api import async_playwright, Playwright, Error, Browser
22
+
23
+ # noinspection PyProtectedMember
21
24
  from playwright._impl._errors import TimeoutError
22
- from xync_schema.models import TopUp, TopUpAble, PmAgent
25
+ from tortoise.timezone import now
26
+ from xync_bot import XyncBot
27
+ from xync_schema.models import TopUp, TopUpAble, PmAgent, Transfer
23
28
 
24
- from xync_client.loader import TORM
29
+ from xync_client.loader import TORM, PAY_TOKEN
25
30
 
26
31
  from xync_client.Abc.PmAgent import PmAgentClient
27
32
  from xync_client.Pms.Payeer.login import login
@@ -64,9 +69,10 @@ class Client(PmAgentClient):
64
69
  norm: str = "payeer"
65
70
  pages: type(StrEnum) = Pages
66
71
  api: PayeerAPI
72
+ with_userbot: bool = False
67
73
 
68
- def __init__(self, agent: PmAgent):
69
- super().__init__(agent)
74
+ def __init__(self, agent: PmAgent, browser: Browser, abot: XyncBot):
75
+ super().__init__(agent, browser, abot)
70
76
  if api_id := self.agent.auth.get("api_id"):
71
77
  self.api = PayeerAPI(self.agent.auth["email"], api_id, self.agent.auth["api_sec"])
72
78
 
@@ -74,7 +80,7 @@ class Client(PmAgentClient):
74
80
  await login(self.agent)
75
81
  for cookie in self.agent.state["cookies"]:
76
82
  await self.page.context.add_cookies([cookie])
77
- await self.page.goto(self.pages.SEND)
83
+ await self.page.goto(self.pages.SEND, wait_until="commit")
78
84
 
79
85
  @staticmethod
80
86
  def form_redirect(topup: TopUp) -> tuple[str, dict | None]:
@@ -131,20 +137,22 @@ class Client(PmAgentClient):
131
137
  "ts": datetime.strptime(ti["dateCreate"], "%d.%m.%Y %H:%M:%S") - timedelta(hours=3),
132
138
  }
133
139
 
134
- async def send(self, dest: str, amount: int, cur: str) -> tuple[int, bytes, int] | int:
135
- self.last_active = datetime.now()
140
+ async def send(self, t: Transfer) -> tuple[str, bytes] | float:
141
+ dest, cur = t.order.cred.detail, t.order.cred.pmcur.cur.ticker
142
+ amount = round(t.order.amount * 10**-t.order.cred.pmcur.cur.scale, t.order.cred.pmcur.cur.scale)
143
+ self.last_active = now()
136
144
  page = self.page
137
145
  if not page.url.startswith(self.pages.SEND):
138
146
  try:
139
- await page.goto(self.pages.SEND)
147
+ await page.goto(self.pages.SEND, wait_until="commit")
140
148
  except (TimeoutError, Error):
141
149
  await login(self.agent)
142
150
  for cookie in self.agent.state["cookies"]:
143
151
  await page.context.add_cookies([cookie])
144
152
  sleep(0.5)
145
- await page.goto("https://payeer.com/en/account/send/")
153
+ await page.goto("https://payeer.com/en/account/send/", wait_until="commit")
146
154
  has_amount = float(self.api.get_balance()[cur]["DOSTUPNO"])
147
- if float(amount) <= has_amount:
155
+ if amount <= has_amount:
148
156
  sleep(0.1)
149
157
  await page.locator('input[name="param_ACCOUNT_NUMBER"]').fill(dest)
150
158
  await page.locator("select[name=curr_receive]").select_option(value=cur)
@@ -166,42 +174,42 @@ class Client(PmAgentClient):
166
174
  except TimeoutError as _:
167
175
  logging.error("Repeat!")
168
176
  sleep(0.5)
169
- return await self.send(dest, amount, cur)
177
+ return await self.send(t)
170
178
  if await page.locator('.note_txt:has-text("successfully completed")').count():
171
179
  transaction = await page.locator(".note_txt").all_text_contents()
172
- trans_num = int(transaction[0].replace("Transaction #", "").split()[0])
173
- await page.goto("https://payeer.com/ru/account/history/")
180
+ trans_num = transaction[0].replace("Transaction #", "").split()[0]
181
+ await page.goto("https://payeer.com/ru/account/history/", wait_until="commit")
174
182
  await page.click(f".history-id-{trans_num} a.link")
175
183
  sleep(1)
176
184
  receipt = await page.query_selector(".ui-dialog.ui-corner-all")
177
- return trans_num, await receipt.screenshot(path=f"tmp/{trans_num}.png"), int(has_amount - amount)
185
+ return trans_num, receipt and await receipt.screenshot(path=f"tmp/{trans_num}.png")
178
186
  else:
179
- await self.bot.send("Payeer хз", self.uid, photo=await self.page.screenshot())
187
+ await self.receive("Payeer хз", photo=await self.page.screenshot())
180
188
  return -1
181
189
  else:
182
- await self.bot.send(
190
+ await self.receive(
183
191
  f"Payeer no have {amount}, only {has_amount}{cur} to {dest}",
184
- self.uid,
185
192
  photo=await self.page.screenshot(),
186
193
  )
187
194
  return has_amount
188
195
 
189
- def check_in(
190
- self, amount: Decimal | int | float, cur: str, tme: datetime = None, tid: str | int = None
196
+ async def check_in(
197
+ self, amount: Decimal | int | float, cur: str, dt: datetime = None, tid: str | int = None
191
198
  ) -> tuple[Decimal | None, int | None]:
192
- history = self.api.history(type="incoming", append=tid, count=3)
199
+ history = self.api.history(type="incoming", count=10)
193
200
  if tid:
194
201
  return (t := history.get(tid)) and Decimal(t["creditedAmount"])
195
- t = [
202
+ ts: list[dict] = [
196
203
  h
197
204
  for h in history.values()
198
205
  if (
199
206
  amount <= Decimal(h["creditedAmount"]) <= ceil(amount)
200
207
  and h["creditedCurrency"] == cur
201
- and datetime.fromisoformat(h["date"]) > tme - timedelta(minutes=1)
208
+ # todo: wrong tz
209
+ and datetime.fromisoformat(h["date"]) > dt - timedelta(minutes=3) # +180(tz)-5
202
210
  )
203
211
  ]
204
- if not (t := t and t[0]):
212
+ if not (t := ts and ts[0]):
205
213
  return None, None
206
214
  return (
207
215
  amount <= (am := Decimal(t["creditedAmount"])) <= ceil(amount) and t["creditedCurrency"] == cur
@@ -219,7 +227,8 @@ async def main(uid: int):
219
227
  )
220
228
  if not agent:
221
229
  raise Exception(f"No active user #{uid} with agent for volet!")
222
- pyr = agent.client()
230
+ abot = Bot(PAY_TOKEN)
231
+ pyr = agent.client(abot)
223
232
  playwright: Playwright = await async_playwright().start()
224
233
  try:
225
234
  dest, amount, cur = "P79619335", 4, "RUB"
@@ -236,14 +245,14 @@ async def main(uid: int):
236
245
  res = pyr.check_in(3, cur, datetime.now())
237
246
 
238
247
  if len(res) > 1 and isinstance(res[1], bytes):
239
- await pyr.bot.send(f"Transaction #{res[0]}", uid, photo=res[1])
248
+ await pyr.receive(f"Transaction #{res[0]}", photo=res[1])
240
249
  elif res[0] > 0:
241
- await pyr.bot.send(f"Sreen of transaction #{res[0]} failed", uid, photo=await pyr.page.screenshot())
250
+ await pyr.receive(f"Sreen of transaction #{res[0]} failed", photo=await pyr.page.screenshot())
242
251
  else:
243
- await pyr.bot.send(f"Sending {amount} {cur} to {dest} FAILED", uid, photo=await pyr.page.screenshot())
252
+ await pyr.receive(f"Sending {amount} {cur} to {dest} FAILED", photo=await pyr.page.screenshot())
244
253
 
245
254
  except TimeoutError as te:
246
- await pyr.bot.send(repr(te), uid, photo=await pyr.page.screenshot())
255
+ await pyr.receive(repr(te), photo=await pyr.page.screenshot())
247
256
  raise te
248
257
  # finally:
249
258
  # await pyr.stop()
@@ -12,7 +12,7 @@ async def login(agent: PmAgent):
12
12
  options.add_argument("--disable-blink-features=AutomationControlled")
13
13
  options.add_argument("--no-sandbox")
14
14
  options.add_argument("--disable-dev-shm-usage")
15
- options.add_argument("--headless=new") # for Chrome >= 109
15
+ # options.add_argument("--headless=new") # for Chrome >= 109
16
16
  options.add_argument("--disable-renderer-backgrounding")
17
17
  options.add_argument("--disable-background-timer-throttling")
18
18
  options.add_argument("--disable-backgrounding-occluded-windows")
@@ -28,7 +28,11 @@ async def login(agent: PmAgent):
28
28
  options.add_argument("--window-size=1920,1080")
29
29
  options.add_argument("--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
30
30
 
31
- driver = uc.Chrome(options=options, headless=True)
31
+ driver = uc.Chrome(
32
+ options=options,
33
+ headless=False,
34
+ browser_executable_path="/Applications/Google Chrome Beta.app/Contents/MacOS/Google Chrome Beta",
35
+ )
32
36
  wait = WebDriverWait(driver, timeout=10)
33
37
  try:
34
38
  driver.get("https://payeer.com/en/auth")
@@ -1,23 +1,28 @@
1
1
  import logging
2
2
  import re
3
- from asyncio import run, ensure_future
3
+ from asyncio import run
4
+ from datetime import datetime
4
5
  from decimal import Decimal
5
6
  from enum import StrEnum
6
7
  from hashlib import sha256
7
8
 
8
- from playwright.async_api import async_playwright, Page, Locator, Position, Playwright # , FloatRect
9
+ from PGram import Bot
10
+ from playwright.async_api import async_playwright, Page, Locator, Position, Playwright, Browser # , FloatRect
9
11
  from pyotp import TOTP
10
12
 
11
13
  # noinspection PyProtectedMember
12
14
  from playwright._impl._errors import TimeoutError
13
15
  from pyro_client.client.user import UserClient
14
16
  from pyrogram.handlers import MessageHandler
17
+ from tortoise.timezone import now
18
+ from xync_schema import models
15
19
  from xync_schema.enums import UserStatus
16
- from xync_schema.models import Cur, User, PmAgent, Cred, PmCur, Fiat, TopUp
20
+ from xync_schema.models import Cur, User, PmAgent, Cred, PmCur, Fiat, TopUp, Transfer
17
21
 
18
22
  from xync_client.Abc.PmAgent import PmAgentClient
19
23
  from xync_client.Gmail import GmClient
20
24
  from xync_client.Pms.Volet.api import APIClient
25
+ from xync_client.loader import PAY_TOKEN
21
26
 
22
27
 
23
28
  class CaptchaException(Exception): ...
@@ -58,24 +63,28 @@ class Client(PmAgentClient):
58
63
  # HOME = base + "pages/transaction"
59
64
  SEND = base + "pages/transfer/wallet"
60
65
 
61
- async def check_in(self, amount: int | Decimal | float, cur: str, tid: str | int = None) -> float | None:
62
- pass
66
+ async def check_in(
67
+ self, amount: int | Decimal | float, cur: str, dt: datetime, tid: str | int = None
68
+ ) -> float | None:
69
+ return await (self.api.check_by_id(tid) if tid else self.api.check_by_amount(amount, cur))
63
70
 
64
71
  async def proof(self) -> bytes:
65
72
  pass
66
73
 
67
74
  uid: int
68
75
  agent: PmAgent
69
- bot: UserClient
76
+ abot: Bot
77
+ ubot: UserClient
70
78
  api: APIClient
71
79
  page: Page
72
80
  gmail: GmClient
73
81
  norm: str = "payeer"
74
82
  pages: type(StrEnum) = Pages
83
+ with_userbot: bool = True
75
84
 
76
- def __init__(self, agent: PmAgent):
77
- super().__init__(agent)
78
- self.gmail = GmClient(self.uid)
85
+ def __init__(self, agent: PmAgent, browser: Browser, abot: Bot):
86
+ super().__init__(agent, browser, abot)
87
+ self.gmail = GmClient(agent.user)
79
88
  self.api = APIClient(self.agent.auth["api"], self.agent.auth["password"], self.agent.auth["login"])
80
89
 
81
90
  @staticmethod
@@ -113,77 +122,92 @@ class Client(PmAgentClient):
113
122
  "ts": t["updatedTime"],
114
123
  }
115
124
 
116
- async def start(self, pw: Playwright, headed: bool = False):
117
- ensure_future(self.gmail.start(pw, True))
118
- return await super().start(pw, True, True)
119
-
120
125
  async def wait_for_code(self, uid: int, topic: str, hg: tuple[MessageHandler, int]) -> str:
121
- code = await self.bot.wait_from(uid, topic, hg)
126
+ code = await self.ubot.wait_from(uid, topic, hg)
122
127
  return code and code[-6:]
123
128
 
124
129
  async def _login(self):
125
130
  ll = self.page.locator("input#j_username")
126
- await ll.fill("mixartemev@gmail.com")
127
- await self.page.locator("input#j_password").fill("mixfixX98")
128
- await self.page.wait_for_timeout(200)
131
+ await ll.fill(self.agent.auth["login"])
132
+ await self.page.locator("input#j_password").fill(self.agent.auth["password"])
133
+ await self.page.wait_for_timeout(300)
129
134
  await ll.click()
135
+ await ll.press(key="ArrowLeft")
136
+ await ll.blur()
130
137
  volet_bot_id, topic = 243630567, "otp_login"
131
138
  await self.page.locator("input#loginToAdvcashButton", has_text="log in").hover()
132
- hg = self.bot.subscribe_for(volet_bot_id, topic) # 243630567 - is volet bot
139
+ hg = self.ubot.subscribe_for(volet_bot_id, topic)
133
140
  await self.page.locator("input#loginToAdvcashButton:not([disabled])", has_text="log in").click()
134
141
  await self.page.wait_for_url(self.pages.OTP_LOGIN)
135
142
  if not (code := await self.wait_for_code(volet_bot_id, topic, hg)):
136
- await self.bot.receive("no login code", photo=await self.page.screenshot())
143
+ await self.ubot.receive("no login code", photo=await self.page.screenshot())
137
144
  raise NoCodeException(self.agent.user_id)
138
145
  await self.page.locator("input#otpId").fill(code)
139
146
  await self.page.click("input#checkOtpButton")
140
- await self.page.wait_for_url(self.pages.SEND)
147
+ await self.page.wait_for_url(self.pages.SEND, wait_until="domcontentloaded")
148
+ # save state
149
+ # noinspection PyTypeChecker
150
+ self.agent.state = await self.page.context.storage_state()
151
+ await self.agent.save()
141
152
 
142
- async def send(self, dest: str, amount: float, cur: str) -> tuple[int, bytes, float]:
153
+ async def send(self, t: Transfer) -> tuple[str, bytes] | float:
154
+ dest, cur = t.order.cred.detail, t.order.cred.pmcur.cur.ticker
155
+ amount = round(t.order.amount * 10**-t.order.cred.pmcur.cur.scale, t.order.cred.pmcur.cur.scale)
156
+ self.last_active = now()
143
157
  curs_map = {"RUB": "Ruble"}
144
-
145
- await self.go(self.pages.SEND)
158
+ await self.go(self.pages.SEND, False)
146
159
  await self.page.click("[class=combobox-account]")
147
- await self.page.click(f'[class=rf-ulst-itm] b:has-text("{curs_map[cur]}") ")')
148
- await self.page.wait_for_timeout(200)
160
+ await self.page.click(f'[class=rf-ulst-itm] b:has-text("{curs_map[cur]}")')
161
+ await self.page.wait_for_selector(f"#srcCurrency:has-text('{cur}')")
149
162
  await self.page.fill("#srcAmount", str(amount))
150
- await self.page.fill("#destWalletId", dest)
151
- await self.page.wait_for_timeout(300)
163
+ dw = self.page.locator("#destWalletId")
164
+ await dw.fill(dest)
165
+ await dw.blur()
166
+ await self.page.wait_for_selector(f"#destCurrency:has-text('{cur}')")
167
+ volet_bot_id, topic = 243630567, "otp_send"
168
+ hg = self.ubot.subscribe_for(volet_bot_id, topic)
152
169
  await self.page.locator("form#mainForm input[type=submit]", has_text="continue").click()
153
170
  # todo: check success confirming
154
171
  if otp := self.agent.auth.get("otp"):
155
172
  totp = TOTP(otp)
156
173
  code = totp.now()
157
174
  elif self.agent.user.username.session:
158
- if not (code := await self.wait_for_code("send")):
159
- if 1: # todo: need main confirm
160
- await self.gmail.mail_confirm()
161
- await self.bot.receive("no send trans code", photo=await self.page.screenshot())
175
+ if not (code := await self.wait_for_code(volet_bot_id, topic, hg)):
176
+ if 1: # todo: Is mail_confirm required?
177
+ if _mcr := await self.gmail.volet_confirm(amount, t.updated_at):
178
+ ...
179
+ # todo: click Continue
180
+ if not (code := await self.wait_for_code(volet_bot_id, topic, hg)):
181
+ code = await self.wait_for_code(volet_bot_id, topic, hg)
182
+ if not code:
183
+ await self.receive("no send trans code", photo=await self.page.screenshot())
162
184
  raise NoCodeException(self.agent.user_id)
163
185
  else:
164
186
  raise OtpNotSetException(self.agent.user_id)
165
187
  await self.page.fill("#securityValue", code)
166
188
  await self.page.locator("input[type=submit]", has_text="confirm").click()
167
189
  await self.page.wait_for_url(self.pages.SEND)
190
+ tid = await self.page.text_content("ul.p-confirmation-info dl.success>dd")
168
191
  await self.page.get_by_role("heading").click()
169
- slip = await self.page.screenshot(clip={"x": 440, "y": 205, "width": 420, "height": 360})
170
- await self.bot.receive(f"{amount} to {dest} sent", photo=slip)
192
+ slip = await self.page.screenshot(clip={"x": 440, "y": 205, "width": 440, "height": 415})
193
+ await self.receive(f"{amount} to {dest} sent", photo=slip)
194
+ return tid, slip
171
195
 
172
- async def go(self, url: Pages):
196
+ async def go(self, url: Pages, commit: bool = True):
173
197
  try:
174
- await self.page.goto(url)
198
+ await self.page.goto(url, wait_until="commit" if commit else "domcontentloaded")
175
199
  if len(await self.page.content()) < 1000: # todo: fix captcha symptom
176
200
  await self.captcha_click()
177
201
  except Exception as e:
178
- await self.bot.receive(repr(e), photo=await self.page.screenshot())
202
+ await self.receive(repr(e), photo=await self.page.screenshot())
179
203
  raise e
180
204
 
181
205
  async def send_cap_help(self, xcap: Locator):
182
206
  if await xcap.count():
183
207
  bb = await xcap.bounding_box(timeout=2000)
184
208
  byts = await self.page.screenshot(clip=bb)
185
- await self.bot.receive("put x, y", photo=byts)
186
- txt = await self.bot.bot.wait_from(self.bot.me.id, "xy", timeout=59)
209
+ await self.receive("put x, y", photo=byts)
210
+ txt = await self.ubot.wait_from(self.uid, "xy", timeout=59) # todo: fix
187
211
  for xy in txt.split(";"):
188
212
  px, py = xy
189
213
  x, y = bb["x"] + bb["width"] * int(px) / 100, bb["y"] + bb["height"] * int(py) / 100
@@ -202,7 +226,7 @@ class Client(PmAgentClient):
202
226
  if await xcap.count():
203
227
  await self.send_cap_help(xcap)
204
228
  try:
205
- await self.page.wait_for_url(lambda url: url != captcha_url)
229
+ await self.page.wait_for_url(lambda url: url != captcha_url, wait_until="commit")
206
230
  except TimeoutError: # if page no changed -> captcha is undone
207
231
  await self.page.screenshot()
208
232
  raise CaptchaException(self.page.url)
@@ -233,41 +257,36 @@ class Client(PmAgentClient):
233
257
  ]
234
258
  [await Fiat.update_or_create({"amount": amount}, cred=cred) for cred, amount in creds]
235
259
 
236
- async def stop(self):
237
- # save state
238
- self.agent.state = await self.page.context.storage_state()
239
- await self.agent.save()
240
- # closing
241
- await self.bot.stop()
242
- await self.gmail.stop()
243
- await self.page.context.close()
244
- await self.page.context.browser.close()
245
-
246
260
 
247
261
  async def _test():
248
262
  from x_model import init_db
249
- from xync_schema import TORM
263
+ from xync_client.loader import TORM
250
264
 
251
265
  _ = await init_db(TORM, True)
252
- logging.basicConfig(level=logging.DEBUG)
253
- uid = 193017646
266
+ logging.basicConfig(level=logging.INFO)
267
+ abot = Bot(PAY_TOKEN)
254
268
  playwright: Playwright = await async_playwright().start()
255
- agent = await PmAgent.get_or_none(pm__norm="volet", user__username_id=uid).prefetch_related(
256
- "user__username__session"
257
- )
258
- if not agent:
259
- raise Exception(f"No active user #{uid} with agent for volet!")
260
269
 
261
- va = agent.client()
262
270
  try:
263
- await va.start(playwright)
264
- await va.send("alena.artemeva25@gmail.com", 7.98)
265
- await va.wait_for_payments()
271
+ o = await models.Order.create(ad_id=7, exid=1, amount=900, cred_id=522, taker_id=419)
272
+ await o.fetch_related("cred__pmcur__cur", "ad")
273
+ pma = await models.PmAgent.get(
274
+ active=True,
275
+ auth__isnull=False,
276
+ pm_id=o.cred.pmcur.pmex_exid,
277
+ user__person__actors=o.ad.maker_id,
278
+ user__status=UserStatus.ACTIVE,
279
+ ).prefetch_related("pm", "user__gmail", "user__username__session")
280
+ t = models.Transfer(amount=9, created_at=now(), order=o)
281
+ pcl: Client = pma.client(abot)
282
+ pcl = await pcl.start(playwright, True, True)
283
+ await pcl.send(t)
284
+ await pcl.wait_for_payments()
266
285
  except TimeoutError as te:
267
- await va.bot.receive(repr(te), photo=await va.page.screenshot())
286
+ await pcl.receive(repr(te), photo=await pcl.page.screenshot())
268
287
  raise te
269
288
  finally:
270
- await va.stop()
289
+ await pcl.stop()
271
290
 
272
291
 
273
292
  if __name__ == "__main__":
@@ -88,16 +88,17 @@ class APIClient:
88
88
  async def check_by_amount(self, amount: decimal, cur: str = "RUB", timeout: int = 5 * 60, past: int = 0):
89
89
  hist: list = self.make_request("history", {"transactionDirection": "INCOMING", "count": 3, "from": 0})
90
90
  if int(hist[0].amount) == int(amount):
91
- return hist[0]
91
+ return hist[0]["amount"], hist[0]["id"]
92
92
  await sleep(period)
93
93
  past += period
94
94
  if past < timeout:
95
95
  return await self.check_by_amount(amount, cur, timeout, past)
96
- return False
96
+ return None, None
97
97
 
98
98
  def check_by_id(self, tid: str):
99
- t: dict = self.make_request("findTransaction", tid)
100
- return t
99
+ if t := self.make_request("findTransaction", tid):
100
+ return t["amount"], t["id"]
101
+ return None, None
101
102
 
102
103
 
103
104
  async def main():
xync_client/loader.py CHANGED
@@ -5,6 +5,7 @@ from xync_schema import models
5
5
  load_dotenv()
6
6
 
7
7
  NET_TOKEN = env("NET_TOKEN")
8
+ PAY_TOKEN = env("PAY_TOKEN")
8
9
  PG_DSN = f"postgres://{env('POSTGRES_USER')}:{env('POSTGRES_PASSWORD')}@{env('POSTGRES_HOST', 'xyncdbs')}:{env('POSTGRES_PORT', 5432)}/{env('POSTGRES_DB', env('POSTGRES_USER'))}"
9
10
  TORM = {
10
11
  "connections": {"default": PG_DSN},
xync_client/pm_unifier.py CHANGED
@@ -17,7 +17,7 @@ class PmUnifier:
17
17
  pms: dict[str, PmUni] = {} # {origin: normalized}
18
18
 
19
19
  re_bank = [
20
- r"^bank (?!of )|bank$",
20
+ r"^bank (?!(of |transfer))|(?<!(to|the)\s) bank$",
21
21
  r" banka$",
22
22
  r" bankas$",
23
23
  r" bankasi$",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xync-client
3
- Version: 0.0.141
3
+ Version: 0.0.155
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
@@ -8,6 +8,9 @@ Requires-Python: >=3.11
8
8
  Requires-Dist: asynchuobi
9
9
  Requires-Dist: bs4
10
10
  Requires-Dist: bybit-p2p
11
+ Requires-Dist: google-api-python-client
12
+ Requires-Dist: google-auth-httplib2
13
+ Requires-Dist: google-auth-oauthlib
11
14
  Requires-Dist: requests-toolbelt
12
15
  Requires-Dist: msgspec
13
16
  Requires-Dist: python-binance
@@ -1,17 +1,19 @@
1
1
  xync_client/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  xync_client/details.py,sha256=21itVPCgAtaYRR1H9J9oYudj95gafcFjExUN6QL17OI,1330
3
- xync_client/loader.py,sha256=zhslCMgtgp-xINPG4qQwhI1ee5Ap1vuoC8oK7GyhyMw,571
4
- xync_client/pm_unifier.py,sha256=T2Xh-tvcu114P2YBI6RK_XDiaIhyq6ABMrXDuXPlx7A,6541
5
- xync_client/Abc/Agent.py,sha256=OJaJ1RIMDYAS4xeefeXxVIVI0EKnMczQtrO35MLzqr4,5390
3
+ xync_client/loader.py,sha256=hxf8ob50DO7r_qjr2qBoO7IyjkXeHHzVQ63YjXerjoU,600
4
+ xync_client/pm_unifier.py,sha256=DYkFYXzmhVEh8WJvI---3Geas34mZ83cT1O-88D68YQ,6568
5
+ xync_client/Abc/AdLoader.py,sha256=EsrQY_yjhRE2V-4eK2nfq1aAmZPY-FX7x9yKXfp7ILk,14066
6
+ xync_client/Abc/Agent.py,sha256=FjpFWnVj6FB498KCDtGPzCMHdRuOo4ejPvRmOeug7qM,8764
6
7
  xync_client/Abc/Asset.py,sha256=hlgyFaU9byr2N2r8Heh-_ICx49SKuKxfRTUA4yQWmEw,454
7
8
  xync_client/Abc/Auth.py,sha256=OPQXN7_XYQZP9431ylFksd6JDusbKG8N_1g6CXTZ6yY,1495
8
9
  xync_client/Abc/BaseTest.py,sha256=vaAs5Z4HYV7k_C3zQz6JKO75s2hXtVbBI3-0Srkzv5Q,2388
9
- xync_client/Abc/Ex.py,sha256=n41-XCjoIV-KpC_lK3jO049tQKbFmE0eDU3SDlgZTws,12986
10
+ xync_client/Abc/Ex.py,sha256=s6v_jR_Wqj64RxU6lDd6-IYpmGBcWNASsBqkX3MCoPo,13554
10
11
  xync_client/Abc/Exception.py,sha256=Sts7RpP370NBdjaH_cyXDdHtjge8zXNUGWCrKw49Zyk,482
11
- xync_client/Abc/InAgent.py,sha256=svKGATUM0c9YIDDEVLc-NxpUNWqZoVr5PjxoxK64RKs,650
12
+ xync_client/Abc/HasAbotUid.py,sha256=LsTHHjMHBauCwJoqgDa9Lx4R6xsDOHfsN4jM539Bpqg,279
13
+ xync_client/Abc/InAgent.py,sha256=8BnZ7VzWLIJY93xnNTqlpY3JdarQkkpRRjDDEALaVAA,303
12
14
  xync_client/Abc/Order.py,sha256=7-FGIJu5z9aYi0A_eJV4F-cp_6Mz_izNpefexDQZvHw,2428
13
- xync_client/Abc/PmAgent.py,sha256=wS1ZQs-hcC8ICDLcc9EfyNBKrM_ZDpJolAg-l_5ro-8,4094
14
- xync_client/Abc/xtype.py,sha256=o1JEzWmEXCPddtlqWZ6HRTZTKX6SAnvsztbASj21zOQ,2584
15
+ xync_client/Abc/PmAgent.py,sha256=Xl-0-KMwcTp_7qIt7NV7-aD22j955tFYFqcHHbmGMTQ,4193
16
+ xync_client/Abc/xtype.py,sha256=H2S5UV67v5Uiy0KC3JI4N142MYQWS_8d9d3N8_WHnVs,3050
15
17
  xync_client/Binance/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
18
  xync_client/Binance/binance_async.py,sha256=LP2DZaHwkfsp_4Tjvetb-1ntjQtJfODF0OgZpoPx4KU,2688
17
19
  xync_client/Binance/earn_api.py,sha256=hvk0MaVTLszIglQXVhbUjGcaHfbF9Ul7FFXmy94U2so,4411
@@ -34,25 +36,25 @@ xync_client/BitGet/agent.py,sha256=YVs3bDY0OcEJGU7m2A8chzO6PFhWDnQQrA-E6MVkBBg,3
34
36
  xync_client/BitGet/ex.py,sha256=uEvvXuLaJv8o8BFi0bMA3XyBuTfVDWagAjLOHZl-xlE,3765
35
37
  xync_client/BitGet/etype/ad.py,sha256=fysSW47wGYjSOPUqY864z857AJz4gjN-nOkI1Jxd27U,1838
36
38
  xync_client/BitPapa/ex.py,sha256=U-RRB_RSOtErfRgxOZYWegZ_td_uZO37YKo3Jxchf_w,912
37
- xync_client/Bybit/InAgent.py,sha256=QQTRWcZXhNO-AZi9wfCAA-x24FIRL00_f4T5xCVgC10,25324
38
- xync_client/Bybit/agent.py,sha256=fz76f-6g81TnFoFqWX0AqMaKvnYzgYKfhpkckIOM0cM,61769
39
- xync_client/Bybit/ex.py,sha256=3oARvReBoDs90FzQY31-L-q_YU-TIRbvWB7z4lwESsA,4715
39
+ xync_client/Bybit/InAgent.py,sha256=sHpugXfgeAYG68z6cKiTc3QSeGGNGKUSCh5NzXIbAKw,26657
40
+ xync_client/Bybit/agent.py,sha256=ekzuPdZQpKMhONe_tZT54nri2D0aYRMao4UOjIE123A,59456
41
+ xync_client/Bybit/ex.py,sha256=ovbCZ1-36KIo-8FYb8yt_VNE3UZszBoik10Adzrpi2Y,5088
40
42
  xync_client/Bybit/order.py,sha256=H4UIb8hxFGnw1hZuSbr0yZ4qeaCOIZOMc6jEst0ycBs,1713
41
43
  xync_client/Bybit/web_earn.py,sha256=qjqS10xlFc8r40IhDdPZ0LxA2dFEGbvBGXdsrUUJCMo,3019
42
44
  xync_client/Bybit/web_p2p.py,sha256=sAXzK03t6jwDnz4rrvP2IzI0KxfKa7C_5GuzH1HwLuA,11768
43
45
  xync_client/Bybit/ws.py,sha256=OQjZHo_MiAH1dlOs3c-aUZBKyqToNTmH560udh6RYDE,1431
44
- xync_client/Bybit/etype/ad.py,sha256=HJOHi9KrbLQMpwEyd4oA8436QTNRqrd2HWFF-JNZGDo,8066
45
- xync_client/Bybit/etype/cred.py,sha256=dgFExLB4e5Wf6SqfU9SOdeooHQa84DRbTGm_OJhNw_o,1354
46
- xync_client/Bybit/etype/order.py,sha256=rPXw9eHJW3afVPQDRiooUkHfQhmqJ5fTdZ4vKdO6uHQ,8273
46
+ xync_client/Bybit/etype/ad.py,sha256=r356t4Kmho5Q6BAS0JWyRmsxui427W9O2Y1glUU6l3g,5091
47
+ xync_client/Bybit/etype/cred.py,sha256=CH6xqHh1214bLhHy_K9eVBb1SJVhWBfGb0l3LtBf3fU,1701
48
+ xync_client/Bybit/etype/order.py,sha256=A1LQSqSOIgDu-dfZDhAdSnED_Xty4vXdJEoikRbelH0,8350
47
49
  xync_client/Gate/ex.py,sha256=QbhB3u7TWnvVGD-AknB2nay6KZjEXQ-1JT9UacX4sWI,3735
48
50
  xync_client/Gate/premarket.py,sha256=IW-CgkmNJePJR2j_NRfULNKTePMX35XlhldqdiO76zY,2138
49
51
  xync_client/Gate/etype/ad.py,sha256=-EwtFcOWWvtE6UjaOdsuXWDTCVjAIRK0kSEsqPP4Yls,1296
50
- xync_client/Gmail/__init__.py,sha256=98pRNlyx7e49QJMxzYPcbCROv2m2LGyGkSCGyrh0dow,4646
51
- xync_client/Htx/agent.py,sha256=rOURgTeY9TsA-IzT78l5-Ze91i0x1PY683mrX38MSgs,7356
52
+ xync_client/Gmail/__init__.py,sha256=9JGT8PyzJaOTVvaFV0Gki3Fdo6Bp6m6DnWOPGZJ-eAA,5436
53
+ xync_client/Htx/agent.py,sha256=NqoiK95Zhxle5ZqB0aa1kfIbQo2qEGjkhlzwr4LA9Y0,12573
52
54
  xync_client/Htx/earn.py,sha256=jL6eRwytZEMRom_3bFm1DYthi_GFg-E1Mm3ZDXENHSg,2386
53
- xync_client/Htx/ex.py,sha256=GuWK5lA_MvtSd-0DhKf2MAstKvZMHhc3BIiZSgdwZv4,6074
55
+ xync_client/Htx/ex.py,sha256=66GTk7kitTXrNdwM0xRJTc2sIlLk0VUOAWunYG7iF-s,6051
54
56
  xync_client/Htx/etype/__init__.py,sha256=sZIhFOxj2dRQRmMe86-y9vlzOGAPo1qoOi6u1qVxWr0,123
55
- xync_client/Htx/etype/ad.py,sha256=bShCGHRAvFJxt2io5rjQrEFMB0zZzkTww7sBxIcmLVM,2000
57
+ xync_client/Htx/etype/ad.py,sha256=2nTTUgL1utDBVUYiVpDzCowlXFg-94leihFpAAguK8A,2311
56
58
  xync_client/Htx/etype/cred.py,sha256=sAOQTsk7BA8zBWUkkwM6vIQcq1LcSK5NLYGrkTdtkQ8,1129
57
59
  xync_client/Htx/etype/pm.py,sha256=ILCP9reFRkfuzmtsJDYomJ3WBTU4s_KE-69JksTxwMk,375
58
60
  xync_client/Htx/etype/test.py,sha256=uomFicPE1OoA3WXnXOxhsTtGJEpVCQ0CId9D0NI6vto,893
@@ -60,8 +62,11 @@ xync_client/KuCoin/ex.py,sha256=w-6-aedlC1mYf8LShMv6pOrQzqMR9E6yIyXGUHQP888,3237
60
62
  xync_client/KuCoin/web.py,sha256=--OHS0Z29xjfNUjdTL7K0EDmU4dwej95OJ8Sv4PsxLI,920
61
63
  xync_client/KuCoin/etype/ad.py,sha256=MTx90Qo2xFKvfgIr4_qMowjwO23HVpFCD6J7INNFDuQ,1223
62
64
  xync_client/KuCoin/etype/pm.py,sha256=S50S5fyY5YeWlcPwO66o-GsPcdqgoeXuxvmEIy6Zqvs,130
63
- xync_client/Mexc/ex.py,sha256=jpITGa2GTeYayMVStQOomBW-P0YQoXjKExKZi_kS-2A,4295
65
+ xync_client/Mexc/agent.py,sha256=7xhT-UH3aLFAVAfnGUhHqOauNeADNt84ifsT-x3ydq4,2843
66
+ xync_client/Mexc/api.py,sha256=RUbggGalZllKcxTRjXzhW05WTvhXCtdCLETRty-ZcAE,18998
67
+ xync_client/Mexc/ex.py,sha256=JAx07nIzMs8p2PfAmlTpvugis4dlgGjxhQiKlGRS0jY,4416
64
68
  xync_client/Mexc/etype/ad.py,sha256=GUgvylx_z64CXNcw0YejUQJHg9F59eRo5v0zU7DRrAM,1434
69
+ xync_client/Mexc/etype/order.py,sha256=LUA4jL5Y1Qmf1C6rU9_PFyg9aCqo60kZbZPAiSrx77U,19001
65
70
  xync_client/Mexc/etype/pm.py,sha256=m5kCoMx9IEKUPB-z7YwwymQhASkv2npC4-Z_ePYeeRY,453
66
71
  xync_client/Okx/ex.py,sha256=WG1NSh7wFMNePV0eXDePWELUBD1ksxE_-Q87QaDXLvE,4542
67
72
  xync_client/Okx/etype/ad.py,sha256=rTWMMmDwJK9chBByyihCZcgE5P6c5ti2yR1RbUtev3A,3773
@@ -72,14 +77,14 @@ xync_client/Pms/Alfa/state.json,sha256=MKE6vl-JsJO9PNCVqoQgBgYZTgYkHCas7USwl8QFt
72
77
  xync_client/Pms/MTS/__init__.py,sha256=P_E7W46IZEk8RsEgl7H1xV3JplMT5l9vYQYTYyNbyQ8,2101
73
78
  xync_client/Pms/Ozon/__init__.py,sha256=EvQZDSPv0fOT2hNCTP44nXHOIEQvP5bQf_7HVLiZc2I,4123
74
79
  xync_client/Pms/Payeer/.gitignore,sha256=sWORdRp8ROppV2CsMEDJ3M_SokrNWCf8b1hlaNs64hg,12
75
- xync_client/Pms/Payeer/__init__.py,sha256=xN3L-IURWJ6oYXq85qu34u0OZEQOXkshgeEuMG29qg8,9584
80
+ xync_client/Pms/Payeer/__init__.py,sha256=dSQw0JSQGW33sjScyhpOkFK4VsNU-ob1K-ldmZWLmQQ,10020
76
81
  xync_client/Pms/Payeer/api.py,sha256=bb8qrlPYyWafel1VR-2nate6xBeRZAVciFJblHygfAs,549
77
- xync_client/Pms/Payeer/login.py,sha256=W5FAA0reW5x2hSh8sBIWmR38VcYhwvrn1R64IAtWHVw,2921
82
+ xync_client/Pms/Payeer/login.py,sha256=GyNwB-GKE_1nlkbZJ0KNI-EnCT0j_S9ogFdn-ufb-zU,3053
78
83
  xync_client/Pms/Sber/__init__.py,sha256=dxQfd9ZPhFTc_C4xrwaxrV6p0SijDCLNzBeUv3oQG38,4926
79
84
  xync_client/Pms/Sber/utils.py,sha256=gIeJspwvoBbOBt-fjxwW4WDHPoL2Evs8LVufsjrFOfo,1870
80
85
  xync_client/Pms/Tinkoff/__init__.py,sha256=ZyLvBEUn-vh-85oPUUDS586AHgvx3c-mkQE3yBQtbw8,5580
81
- xync_client/Pms/Volet/__init__.py,sha256=h1bRO4x58-_-Yf9g3noYow0DDu8P4NFLwx83FnDZptM,10719
82
- xync_client/Pms/Volet/api.py,sha256=okqppqT7M5E6sswu-xz3L4Y9-ngefBPbFtywRi6A7Xo,3595
86
+ xync_client/Pms/Volet/__init__.py,sha256=mYJEmZwFoNU2B2erv7n8k6RA0PsXU12K7hpyrdEocrk,12088
87
+ xync_client/Pms/Volet/api.py,sha256=6_dH2rzmyyvha3PeoiZdSltiAzKDWn8roSUJOAErX4M,3673
83
88
  xync_client/Pms/Volet/pl.py,sha256=l7lvUrpjFoObXPHaseOIAcSbkNqJdpy6OLDutxYJH3U,2451
84
89
  xync_client/Pms/Volet/_todo_req/req.mjs,sha256=ut3Jw37rL5lY7SskjZ9f1l0VE33tuP-PZEYUTcJMc2I,817
85
90
  xync_client/Pms/Volet/_todo_req/req.py,sha256=mKvdPrb-lkQ98Ws92_oBKu5yqyU8Krxy9XwuIhdsBao,1570
@@ -95,7 +100,7 @@ xync_client/TgWallet/order.py,sha256=BOmBx5WWfJv0-_-A8DcR-Xd8utqO_VTmSqSegm0cteQ
95
100
  xync_client/TgWallet/pyd.py,sha256=Ys3E8b3RLuyQ26frWT0F0BorkNxVpxnd18tY4Gp9dik,5636
96
101
  xync_client/TgWallet/pyro.py,sha256=2K7QWdo48k4MbbgQt90gdz_HiPck69Njm4xaMjIVgoo,1440
97
102
  xync_client/TgWallet/web.py,sha256=kDcv9SKKQPe91mw1qJBpbuyKYCAmZdfdHJylHumLBVU,1608
98
- xync_client-0.0.141.dist-info/METADATA,sha256=Evn_XBCNvwhXH0mxMhCRRkwc7cMk8ux285aJ9NdRyyI,1037
99
- xync_client-0.0.141.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
100
- xync_client-0.0.141.dist-info/top_level.txt,sha256=bmYEVIIrD3v7yFwH-X15pEfRvzhuAdfsAZ2igvNI4O8,12
101
- xync_client-0.0.141.dist-info/RECORD,,
103
+ xync_client-0.0.155.dist-info/METADATA,sha256=PizI21QJhBoGXcmRFqqmjbcilHvhK9uwXdD5zmz1t6k,1149
104
+ xync_client-0.0.155.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
105
+ xync_client-0.0.155.dist-info/top_level.txt,sha256=bmYEVIIrD3v7yFwH-X15pEfRvzhuAdfsAZ2igvNI4O8,12
106
+ xync_client-0.0.155.dist-info/RECORD,,