xync-client 0.0.164__py3-none-any.whl → 0.0.172__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.
@@ -1,7 +1,6 @@
1
1
  import asyncio
2
2
  import json
3
3
  import logging
4
- import re
5
4
  from asyncio import sleep, gather
6
5
  from asyncio.tasks import create_task
7
6
  from datetime import datetime, timedelta, timezone
@@ -9,7 +8,6 @@ from difflib import SequenceMatcher
9
8
  from enum import IntEnum
10
9
  from hashlib import sha256
11
10
  from http.client import HTTPException
12
- from math import floor
13
11
  from typing import Literal
14
12
  from uuid import uuid4
15
13
 
@@ -21,27 +19,24 @@ from bybit_p2p._exceptions import FailedRequestError
21
19
  from payeer_api import PayeerAPI
22
20
  from pyro_client.client.file import FileClient
23
21
  from tortoise import BaseDBAsyncClient
24
- from tortoise.exceptions import IntegrityError
25
- from tortoise.expressions import Q
26
- from tortoise.functions import Count
27
22
  from tortoise.signals import post_save
28
23
  from tortoise.timezone import now
29
24
  from tortoise.transactions import in_transaction
25
+ from websockets import ConnectionClosedError
30
26
  from x_client import df_hdrs
31
27
  from x_model import init_db
32
- from x_model.func import ArrayAgg
33
28
  from xync_bot import XyncBot
34
29
 
35
30
  from xync_client.Bybit.ex import ExClient
36
31
  from xync_schema import models
37
32
  from xync_schema.enums import OrderStatus, AgentStatus
38
33
 
39
- from xync_schema.models import Actor, PmCur, Agent
34
+ from xync_schema.models import Agent
40
35
 
41
36
  from xync_client.Abc.Agent import BaseAgentClient
42
- from xync_client.Abc.xtype import FlatDict, BaseOrderReq, AdUpd, GetAds
43
- from xync_client.Bybit.etype.ad import AdPostRequest, AdUpdateRequest, Ad, AdStatus, MyAd
44
- from xync_client.Bybit.etype.cred import CredEpyd
37
+ from xync_client.Abc.xtype import FlatDict, BaseOrderReq, AdUpdReq, GetAdsReq
38
+ from xync_client.Bybit.etype.ad import AdPostRequest, AdRequest, Ad, AdStatusReq, MyAd
39
+ from xync_client.Bybit.etype.cred import CredEpyd, PaymentTerm, CredEx
45
40
  from xync_client.Bybit.etype.order import (
46
41
  OrderRequest,
47
42
  PreOrderResp,
@@ -77,6 +72,7 @@ class AgentClient(BaseAgentClient): # Bybit client
77
72
  # rewrite token for public methods
78
73
  api: P2P
79
74
  orders: dict[int, tuple[models.Order, OrderFull]] = {} # pending
75
+ cdx_cls: type[CredEx] = CredEx
80
76
 
81
77
  def __init__(
82
78
  self,
@@ -122,95 +118,11 @@ class AgentClient(BaseAgentClient): # Bybit client
122
118
  def get_payment_method(self, fiat_id: int) -> CredEpyd:
123
119
  return self.creds()[fiat_id]
124
120
 
125
- def creds(self) -> dict[int, CredEpyd]:
121
+ async def _get_creds(self) -> list[PaymentTerm]:
126
122
  data = self.api.get_user_payment_types()
127
123
  if data["ret_code"] > 0:
128
124
  return data
129
- return {credex["id"]: CredEpyd.model_validate(credex) for credex in data["result"]}
130
-
131
- async def cred_epyd2db(self, ecdx: CredEpyd, pers_id: int = None, cur_id: int = None) -> models.CredEx | None:
132
- if ecdx.paymentType in (416,): # what is 416??
133
- return None
134
- if not (
135
- pmex := await models.PmEx.get_or_none(exid=ecdx.paymentType, ex=self.ex_client.ex).prefetch_related(
136
- "pm__curs"
137
- )
138
- ):
139
- raise HTTPException(f"No PmEx {ecdx.paymentType} on ex#{self.ex_client.ex.name}", 404)
140
- if cred_old := await models.Cred.get_or_none(credexs__exid=ecdx.id, credexs__ex=self.actor.ex).prefetch_related(
141
- "pmcur"
142
- ):
143
- cur_id = cred_old.pmcur.cur_id
144
- elif not cur_id: # is new Cred
145
- cur_id = (
146
- pmex.pm.df_cur_id
147
- or await self.guess_cur(ecdx, len(pmex.pm.curs) > 1 and pmex.pm.curs)
148
- or (pmex.pm.country_id and (await pmex.pm.country).cur_id)
149
- # or (ecdx.currencyBalance and await models.Cur.get_or_none(ticker=ecdx.currencyBalance[0])) # это че еще за хуйня?
150
- )
151
- if not cur_id:
152
- raise Exception(f"Set default cur for {pmex.name}")
153
- if not (pmcur := await models.PmCur.get_or_none(cur_id=cur_id, pm_id=pmex.pm_id)):
154
- raise HTTPException(f"No PmCur with cur#{cur_id} and pm#{ecdx.paymentType}", 404)
155
- xtr = ecdx.branchName
156
- if ecdx.bankName:
157
- xtr += (" | " if xtr else "") + ecdx.bankName
158
- elif ecdx.payMessage:
159
- xtr += (" | " if xtr else "") + ecdx.payMessage
160
- elif ecdx.qrcode:
161
- xtr += (" | " if xtr else "") + ecdx.qrcode
162
- elif ecdx.paymentExt1:
163
- xtr += (" | " if xtr else "") + ecdx.paymentExt1
164
- try:
165
- cred_db, _ = await models.Cred.update_or_create(
166
- {
167
- "name": ecdx.realName,
168
- "extra": xtr,
169
- },
170
- pmcur=pmcur,
171
- person_id=pers_id or self.actor.person_id,
172
- detail=ecdx.accountNo or ecdx.payMessage,
173
- )
174
- if cred_db.ovr_pm_id is None and (cred_db.detail.startswith("XyncPay") or xtr.startswith("XyncPay")):
175
- cred_db.ovr_pm_id = 0
176
- await cred_db.save()
177
- credex_in = models.CredEx.validate({"exid": ecdx.id, "cred_id": cred_db.id, "ex_id": self.actor.ex.id})
178
- credex_db, _ = await models.CredEx.update_or_create(**credex_in.df_unq())
179
- except IntegrityError as e:
180
- raise e
181
- return credex_db
182
-
183
- async def guess_cur(self, ecdx: CredEpyd, curs: list[models.Cur]):
184
- mbs = ecdx.bankName.split(", ")
185
- mbs += ecdx.branchName.split(" / ")
186
- mbs = {mb.lower(): mb for mb in mbs}
187
- if (
188
- pms := await models.Pm.filter(Q(join_type="OR", pmexs__name__in=mbs.values(), norm__in=mbs.keys()))
189
- .group_by("pmcurs__cur_id", "pmcurs__cur__ticker")
190
- .annotate(ccnt=Count("id"), names=ArrayAgg("norm"))
191
- .order_by("-ccnt", "pmcurs__cur__ticker")
192
- .values("pmcurs__cur_id", "names", "ccnt")
193
- ):
194
- return pms[0]["pmcurs__cur_id"]
195
- curs = {c.ticker: c.id for c in curs or await models.Cur.all()}
196
- for cur, cid in curs.items():
197
- if re.search(re.compile(rf"\({cur}\)$"), ecdx.bankName):
198
- return cid
199
- if re.search(re.compile(rf"\({cur}\)$"), ecdx.branchName):
200
- return cid
201
- if re.search(re.compile(rf"\({cur}\)$"), ecdx.accountNo):
202
- return cid
203
- if re.search(re.compile(rf"\({cur}\)$"), ecdx.payMessage):
204
- return cid
205
- if re.search(re.compile(rf"\({cur}\)$"), ecdx.paymentExt1):
206
- return cid
207
- return None
208
-
209
- # 25: Список реквизитов моих платежных методов
210
- async def set_creds(self) -> list[models.CredEx]:
211
- credexs_epyd: dict[int, CredEpyd] = self.creds()
212
- credexs: list[models.CredEx] = [await self.cred_epyd2db(f) for f in credexs_epyd.values()]
213
- return credexs
125
+ return [PaymentTerm.model_validate(credex) for credex in data["result"] if credex["id"] != "-1"]
214
126
 
215
127
  async def ott(self):
216
128
  t = await self._post("/x-api/user/private/ott")
@@ -238,7 +150,7 @@ class AgentClient(BaseAgentClient): # Bybit client
238
150
  delete = await self._post("/x-api/fiat/otc/user/payment/new_delete", data)
239
151
  return delete
240
152
 
241
- async def switch_ads(self, new_status: AdStatus) -> dict:
153
+ async def switch_ads(self, new_status: AdStatusReq) -> dict:
242
154
  data = {"workStatus": new_status.name} # todo: переделать на апи, там status 0 -> 1
243
155
  res = await self._post("/x-api/fiat/otc/maker/work-config/switch", data)
244
156
  return res
@@ -248,26 +160,16 @@ class AgentClient(BaseAgentClient): # Bybit client
248
160
  ads = [ad for ad in list_ads if set(ad["payments"]) - {"5", "51"}]
249
161
  return float(ads[0]["price"])
250
162
 
251
- def my_ads(self, active: bool = True, page: int = 1) -> list[MyAd]:
252
- resp = self.api.get_ads_list(size="30", page=str(page), status=AdStatus.active if active else AdStatus.sold_out)
163
+ async def get_my_ads(self, active: bool = True, page: int = 1) -> list[MyAd]:
164
+ resp = self.api.get_ads_list(
165
+ size="30", page=str(page), status=AdStatusReq.active if active else AdStatusReq.sold_out
166
+ )
253
167
  ads = [MyAd.model_validate(ad) for ad in resp["result"]["items"]]
254
- if resp["result"]["count"] > 30 * page:
255
- ads.extend(self.my_ads(active, page + 1))
168
+ # todo: вернуть, что бы спарсил все объявы, а не только первые 30
169
+ # if resp["result"]["count"] > 30 * page:
170
+ # ads.extend(await self.get_my_ads(active, page + 1))
256
171
  return ads
257
172
 
258
- async def export_my_ads(self, active: bool = None) -> int: # upserted)
259
- ads = self.my_ads(True)
260
- if not active:
261
- ads += self.my_ads(False)
262
- for ad in ads:
263
- ad_db = await self.ex_client.ad_load(ad, maker=self.actor)
264
- mad_db, _ = await models.MyAd.update_or_create(ad=ad_db)
265
- exids = [pt.id for pt in ad.paymentTerms]
266
- credexs = await models.CredEx.filter(ex_id=self.actor.ex_id, exid__in=exids).prefetch_related("cred")
267
- await mad_db.credexs.clear()
268
- await mad_db.credexs.add(*credexs)
269
- return len(ads)
270
-
271
173
  async def ads_share(self, cur_id: int = None) -> int:
272
174
  mq = models.MyAd.hot_mads_query([4]).filter(ad__maker=self.actor)
273
175
  if cur_id:
@@ -373,8 +275,8 @@ class AgentClient(BaseAgentClient): # Bybit client
373
275
  data = self.api.post_new_ad(**ad.model_dump())
374
276
  return data["result"]["itemId"] if data["ret_code"] == 0 else data
375
277
 
376
- async def _ad_upd(self, req: AdUpd):
377
- upd = AdUpdateRequest({})
278
+ async def _ad_upd(self, req: AdUpdReq):
279
+ upd = AdRequest({})
378
280
  params = upd.model_dump()
379
281
  data = self.api.update_ad(**params)
380
282
  return data["result"] if data["ret_code"] == 0 else data
@@ -418,9 +320,9 @@ class AgentClient(BaseAgentClient): # Bybit client
418
320
  tokenId=bor.coin_exid,
419
321
  currencyId=bor.cur_exid,
420
322
  side="1" if bor.is_sell else "0",
421
- amount=f"{bor.fiat_amount:.2f}".rstrip("0").rstrip("."),
323
+ amount=f"{bor.amount:.2f}".rstrip("0").rstrip("."),
422
324
  curPrice=por.curPrice,
423
- quantity=str(round(bor.fiat_amount / float(por.price), bor.coin_scale)),
325
+ quantity=str(round(bor.amount / float(por.price), bor.coin_scale)),
424
326
  flag="amount",
425
327
  # online="0"
426
328
  )
@@ -531,155 +433,6 @@ class AgentClient(BaseAgentClient): # Bybit client
531
433
  },
532
434
  )
533
435
 
534
- async def create_order_db(self, order: OrderFull) -> models.Order:
535
- curex = await models.CurEx.get_or_none(ex=self.ex_client.ex, exid=order.currencyId).prefetch_related("cur")
536
- cur_scale = (curex.scale if curex.scale is not None else curex.cur.scale) if curex else 2
537
- coinex = await models.CoinEx.get(ex=self.ex_client.ex, exid=order.tokenId).prefetch_related("coin")
538
- coin_scale = coinex.scale if coinex.scale is not None else coinex.cur.scale
539
- sb_names = order.sellerRealName, order.buyerRealName
540
- im_maker = int(int(order.makerUserId) == self.actor.exid)
541
- taker_id = (order.userId, order.targetUserId)[im_maker]
542
- taker_name = sb_names[order.side] # todo: double check
543
- taker_person = await self.ex_client.person_name_update(taker_name, taker_id)
544
- seller_person = (
545
- self.actor.person
546
- if order.side
547
- else await self.ex_client.person_name_update(order.sellerRealName, int(order.targetUserId))
548
- )
549
- taker_nick = (self.actor.name, order.targetNickName)[im_maker] # todo: check
550
- ad_db = await models.Ad.get(exid=order.itemId)
551
- if not ad_db:
552
- ad = self.get_ad(order.itemId)
553
- # ad_db, cond_isnew = await self.ex_client.cond_load(ad, force=True, rname=maker_name[order.side])
554
- ad_db = await self.ex_client.ad_load(ad, maker=self.actor)
555
- ecredex: CredEpyd = order.confirmedPayTerm
556
-
557
- if ecredex.paymentType == 0 and im_maker and order.side:
558
- ecredex = order.paymentTermList[0]
559
- if ecredex.paymentType:
560
- if ecredex.paymentType == 51:
561
- ecredex.accountNo = ecredex.accountNo.replace("p", "P").replace("р", "P").replace("Р", "P")
562
- # if not re.match(r"^([Pp])\d{7,10}$", ecredex.accountNo):
563
- # msgs = self.api.get_chat_messages(orderId=order.id, size=100)["result"]["result"]
564
- # msgs = [m["message"] for m in msgs if m["roleType"] == "user" and m["userId"] == order.targetUserId]
565
- # msgs = [g.group() for m in msgs if (g := re.match(r"([PpРр])\d{7,10}\b", m))]
566
- # crd = await models.Cred.get_or_none(
567
- # detail=ecredex.accountNo, credexs__exid=ecredex.id, credexs__ex=self.ex_client.ex
568
- # )
569
- # if not msgs and re.match(r"^\d{7,10}$", ecredex.accountNo):
570
- # ecredex.accountNo = "P" + ecredex.accountNo
571
- # elif msgs:
572
- # ecredex.accountNo = msgs[-1]
573
- # else:
574
- # ...
575
- # if crd:
576
- # crd.detail = ecredex.accountNo
577
- # await crd.save(update_fields=["detail"])
578
- if not (credex := await models.CredEx.get_or_none(exid=ecredex.id, ex=self.ex_client.ex)):
579
- # cur_id = await Cur.get(ticker=ad.currencyId).values_list('id', flat=True)
580
- # await self.cred_epyd2db(ecredex, ad_db.maker.person_id, cur_id)
581
- if (
582
- await PmCur.filter(
583
- pm__pmexs__ex=self.ex_client.ex,
584
- pm__pmexs__exid=ecredex.paymentType,
585
- cur__ticker=order.currencyId,
586
- ).count()
587
- != 1
588
- ):
589
- ...
590
- if not (
591
- pmcur := await PmCur.get_or_none(
592
- pm__pmexs__ex=self.ex_client.ex,
593
- pm__pmexs__exid=ecredex.paymentType,
594
- cur__ticker=order.currencyId,
595
- )
596
- ):
597
- ...
598
- if not (
599
- crd := await models.Cred.get_or_none(pmcur=pmcur, person=seller_person, detail=ecredex.accountNo)
600
- ):
601
- extr = ", ".join(
602
- x
603
- for xtr in [
604
- ecredex.bankName,
605
- ecredex.branchName,
606
- ecredex.qrcode,
607
- ecredex.payMessage,
608
- ecredex.paymentExt1,
609
- ]
610
- if (x := xtr.strip())
611
- )
612
- crd = await models.Cred.create(
613
- detail=ecredex.accountNo,
614
- pmcur=pmcur,
615
- person=seller_person,
616
- name=ecredex.realName,
617
- extra=extr,
618
- )
619
- credex = await models.CredEx.create(exid=ecredex.id, ex=self.ex_client.ex, cred=crd)
620
- try:
621
- taker, _ = await Actor.get_or_create(
622
- {"name": taker_nick, "person": taker_person}, ex=self.ex_client.ex, exid=taker_id
623
- )
624
- except IntegrityError as e:
625
- logging.error(e)
626
- odb, _ = await models.Order.update_or_create(
627
- {
628
- "amount": float(order.amount) * 10**cur_scale,
629
- "quantity": float(order.quantity) * 10**coin_scale,
630
- "status": OrderStatus[Status(order.status).name],
631
- "created_at": ms2utc(order.createDate),
632
- "payed_at": order.transferDate != "0" and ms2utc(order.transferDate) or None,
633
- "confirmed_at": Status(order.status) == Status.completed and ms2utc(order.transferDate) or None,
634
- "appealed_at": order.status == 30 and ms2utc(order.transferDate) or None,
635
- "cred_id": ecredex.paymentType and credex.cred_id or None,
636
- "taker": taker,
637
- "ad": ad_db,
638
- },
639
- exid=order.id,
640
- )
641
- if order.status == Status.completed and ecredex.paymentType == 51:
642
- await odb.fetch_related("cred", "transfer")
643
- if odb.cred.detail != ecredex.accountNo:
644
- ...
645
- frm = (odb.created_at + timedelta(minutes=180 - 1)).isoformat(sep=" ").split("+")[0]
646
- to = ((odb.payed_at or odb.created_at) + timedelta(minutes=180 + 30)).isoformat(sep=" ").split("+")[0]
647
- tsa = [
648
- t
649
- for tid, t in (self.hist.items() if self.hist else [])
650
- if (ecredex.accountNo == t["to"] and t["from"] != "@merchant" and frm < t["date"] < to)
651
- ]
652
- buyer_person = (
653
- self.actor.person
654
- if not order.side
655
- else await self.ex_client.person_name_update(order.buyerRealName, int(order.targetUserId))
656
- )
657
- ts = [t for t in tsa if floor(fa := float(order.amount)) <= float(t["creditedAmount"]) <= round(fa)]
658
- if len(ts) != 1:
659
- if len(tsa) > 1:
660
- summ = sum(float(t["creditedAmount"]) for t in tsa)
661
- if floor(fa) <= summ <= round(fa):
662
- for tr in tsa:
663
- am = int(float(tr["creditedAmount"]) * 100)
664
- await models.Transfer.create(
665
- pmid=tr["id"], order=odb, amount=am, sender_acc=tr["from"], created_at=tr["date"]
666
- )
667
- else:
668
- bcred, _ = await models.Cred.get_or_create(
669
- {"detail": ts[0]["from"]}, person=buyer_person, pmcur_id=odb.cred.pmcur_id
670
- )
671
- am = int(float(ts[0]["creditedAmount"]) * 100)
672
- try:
673
- await models.Transfer.create(
674
- pmid=ts[0]["id"], order=odb, amount=am, sender_acc=ts[0]["from"], created_at=ts[0]["date"]
675
- )
676
- except IntegrityError as e:
677
- logging.error(e)
678
- ...
679
-
680
- await odb.fetch_related("ad")
681
- return odb
682
-
683
436
  async def get_api_orders(
684
437
  self,
685
438
  page: int = 1,
@@ -708,7 +461,7 @@ class AgentClient(BaseAgentClient): # Bybit client
708
461
  if o.status != Status.completed.value or oid in self.completed_orders:
709
462
  continue
710
463
  order = await self.get_order_full(o.id)
711
- order_db = await self.create_order_db(order)
464
+ order_db = await self.order_save(order)
712
465
  await sleep(1)
713
466
  dmsgs = self.api.get_chat_messages(orderId=oid, size=200)["result"]["result"][::-1]
714
467
  msgs = [Message.model_validate(m) for m in dmsgs if m["msgType"] in (1, 2, 7, 8)]
@@ -771,7 +524,7 @@ class AgentClient(BaseAgentClient): # Bybit client
771
524
 
772
525
  bor = BaseOrderReq(
773
526
  ad_id=str(req.ad_id),
774
- fiat_amount=req.amount,
527
+ amount=req.amount,
775
528
  is_sell=req.is_sell,
776
529
  cur_exid=curex.exid,
777
530
  coin_exid=coinex.exid,
@@ -788,7 +541,7 @@ class AgentClient(BaseAgentClient): # Bybit client
788
541
  i = 0
789
542
  while True:
790
543
  try:
791
- breq = GetAds(coin_id=1, cur_id=1, is_sell=False, limit=50)
544
+ breq = GetAdsReq(coin_id=1, cur_id=1, is_sell=False, limit=50)
792
545
  bs = await self.ex_client.ads(breq, post_pmexs=post_pmexs)
793
546
  bs = [b for b in bs if float(b.price) < 100 or int(b.userId) in mcs.keys()]
794
547
  if bs:
@@ -810,7 +563,7 @@ class AgentClient(BaseAgentClient): # Bybit client
810
563
  ord_resp: OrderResp = await self.take_ad(req)
811
564
  # order: OrderFull = OrderFull(**self.api.get_order_details(orderId=ord_resp.orderId)["result"])
812
565
  order: OrderFull = await self.get_order_info(ord_resp.orderId)
813
- odb = await self.create_order_db(order)
566
+ odb = await self.order_save(order)
814
567
  t = await models.Transfer(order=odb, amount=odb.amount, updated_at=now())
815
568
  await t.fetch_related("order__cred__pmcur__cur")
816
569
  # res = await self.pm_clients[366].send(t)
@@ -826,7 +579,7 @@ class AgentClient(BaseAgentClient): # Bybit client
826
579
 
827
580
  await sleep(5)
828
581
 
829
- sreq = GetAds(coin_id=1, cur_id=1, is_sell=True, limit=50, kwargs={"post_pmexs": post_pmexs})
582
+ sreq = GetAdsReq(coin_id=1, cur_id=1, is_sell=True, limit=50, kwargs={"post_pmexs": post_pmexs})
830
583
  ss = await self.ex_client.ads(sreq, post_pmexs=post_pmexs)
831
584
  ss = [s for s in ss if float(s.price) > 92 or int(s.userId) in mcs.keys()]
832
585
  if ss:
@@ -848,7 +601,7 @@ class AgentClient(BaseAgentClient): # Bybit client
848
601
  ord_resp: OrderResp = await self.take_ad(req)
849
602
  # order: OrderFull = OrderFull(**self.api.get_order_details(orderId=ord_resp.orderId)["result"])
850
603
  order: OrderFull = await self.get_order_info(ord_resp.orderId)
851
- odb = await self.create_order_db(order)
604
+ odb = await self.order_save(order)
852
605
  # t = await models.Transfer(order=odb, amount=odb.amount, updated_at=now())
853
606
  # await t.fetch_related("order__cred__pmcur__cur")
854
607
  # res = await self.pm_clients[366].check_in(t)
@@ -879,7 +632,7 @@ class AgentClient(BaseAgentClient): # Bybit client
879
632
  req = TakeAdReq(ad_id="1856989782009487360", amount=am, pm_id=366)
880
633
  ord_resp: OrderResp = await self.take_ad(req)
881
634
  order: OrderFull = await self.get_order_full(int(ord_resp.orderId))
882
- odb = await self.create_order_db(order)
635
+ odb = await self.order_save(order)
883
636
  t = await models.Transfer(order=odb, amount=odb.amount, updated_at=now())
884
637
  await t.fetch_related("order__cred__pmcur__cur")
885
638
  await self.pm_clients[366].send(t)
@@ -926,10 +679,14 @@ class AgentClient(BaseAgentClient): # Bybit client
926
679
 
927
680
  sub_msg = json.dumps({"op": "subscribe", "args": ["FIAT_OTC_TOPIC", "FIAT_OTC_ONLINE_TOPIC"]})
928
681
  await websocket.send(sub_msg)
929
- while resp := await websocket.recv():
930
- if data := json.loads(resp):
931
- logging.info(f" {now().strftime('%H:%M:%S')} upd: {data.get('topic')}:{data.get('type')}")
932
- await self.proc(data)
682
+ try:
683
+ while resp := await websocket.recv():
684
+ if data := json.loads(resp):
685
+ logging.info(f" {now().strftime('%H:%M:%S')} upd: {data.get('topic')}:{data.get('type')}")
686
+ await self.proc(data)
687
+ except ConnectionClosedError as e:
688
+ logging.warning(e)
689
+ await self._start_listen()
933
690
 
934
691
  async def proc(self, data: dict):
935
692
  match data.get("topic"):
@@ -937,10 +694,12 @@ class AgentClient(BaseAgentClient): # Bybit client
937
694
  match data["type"]:
938
695
  case "STATUS_CHANGE":
939
696
  upd = StatusChange.model_validate(data["data"])
940
- order_db, order = await self.load_order(upd.id)
697
+ if not upd.status:
698
+ logging.warning(data["data"])
699
+ order_db, order = await self.load_order(upd.exid)
941
700
  match upd.status:
942
- case Status.ws_new:
943
- logging.info(f"Order {upd.id} CREATED at {upd.createDate}")
701
+ case OrderStatus.created:
702
+ logging.info(f"Order {upd.exid} CREATED at {upd.created_at}")
944
703
  # await self.got_new_order(order_db, order)
945
704
 
946
705
  # # сразу уменьшаем доступный остаток монеты/валюты
@@ -951,8 +710,8 @@ class AgentClient(BaseAgentClient): # Bybit client
951
710
  # return
952
711
  # await order_db.fetch_related("ad__pair_side__pair", "cred__pmcur__cur")
953
712
  # await self.send_payment(order_db)
954
- case Status.created:
955
- if upd.side == 0: # я продавец, ждем когда покупатель оплатит
713
+ # case OrderStatus.created:
714
+ if upd.ad__pair_side__is_sell == 0: # я продавец, ждем когда покупатель оплатит
956
715
  # check_payment() # again
957
716
  ...
958
717
  # if not (pmacdx := await self.get_pma_by_cdex(order)):
@@ -990,7 +749,7 @@ class AgentClient(BaseAgentClient): # Bybit client
990
749
  # for o in pos.get("items", [])
991
750
  # if (
992
751
  # o["amount"] == order.amount
993
- # and o["id"] != upd.id
752
+ # and o["id"] != upd.exid
994
753
  # and int(order.createDate) < int(o["createDate"]) + 15 * 60 * 1000
995
754
  # # get full_order from o, and cred or pm from full_order:
996
755
  # and self.api.get_order_details(orderId=o["id"])["result"][
@@ -1017,53 +776,53 @@ class AgentClient(BaseAgentClient): # Bybit client
1017
776
  # return
1018
777
  #
1019
778
  # # !!! ОТПРАВЛЯЕМ ДЕНЬГИ !!!
1020
- # self.api.release_assets(orderId=upd.id)
779
+ # self.api.release_assets(orderId=upd.exid)
1021
780
  # logging.info(
1022
781
  # f"Order {order.id} created, paid before #{tid}:{am} at {order.createDate}, and RELEASED at {now()}"
1023
782
  # )
1024
- elif upd.side == 1: # я покупатель - ждем мою оплату
783
+ elif upd.ad__pair_side__is_sell == 1: # я покупатель - ждем мою оплату
1025
784
  # pay()
1026
- logging.warning(f"Order {upd.id} CREATED2 at {now()}")
785
+ logging.warning(f"Order {upd.exid} CREATED2 at {now()}")
1027
786
 
1028
- case Status.paid:
787
+ case OrderStatus.paid:
1029
788
  if order_db.status == OrderStatus.paid:
1030
789
  return
1031
790
  await order_db.update_from_dict(
1032
791
  {
1033
792
  "status": OrderStatus.paid,
1034
- "payed_at": datetime.fromtimestamp(float(order.transferDate) / 1000),
793
+ "payed_at": order.payed_at,
1035
794
  }
1036
795
  ).save()
1037
- logging.info(f"Order {order.id} payed at {order_db.payed_at}")
796
+ logging.info(f"Order {order.exid} payed at {order_db.payed_at}")
1038
797
 
1039
- case Status.appealed_by_seller: # just any appealed
798
+ case OrderStatus.appealed_by_seller: # just any appealed
1040
799
  # todo: appealed by WHO? щас наугад стоит by_seller
1041
800
  await order_db.update_from_dict(
1042
801
  {
1043
802
  "status": OrderStatus.appealed_by_seller,
1044
- "appealed_at": datetime.fromtimestamp(float(order.updateDate) / 1000),
803
+ "appealed_at": order.appealed_at,
1045
804
  }
1046
805
  ).save()
1047
- logging.info(f"Order {order.id} appealed at {order_db.appealed_at}")
806
+ logging.info(f"Order {order.exid} appealed at {order_db.appealed_at}")
1048
807
 
1049
- case Status.canceled:
808
+ case OrderStatus.canceled:
1050
809
  await order_db.update_from_dict({"status": OrderStatus.canceled}).save()
1051
- logging.info(f"Order {order.id} canceled at {datetime.now()}")
810
+ logging.info(f"Order {order.exid} canceled at {datetime.now()}")
1052
811
  # await self.money_upd(order_db)
1053
812
 
1054
- case Status.completed:
813
+ case OrderStatus.completed:
1055
814
  await order_db.refresh_from_db()
1056
815
  if order_db.status != OrderStatus.completed:
1057
816
  await order_db.update_from_dict(
1058
817
  {
1059
818
  "status": OrderStatus.completed,
1060
- "confirmed_at": datetime.fromtimestamp(float(order.updateDate) / 1000),
819
+ "confirmed_at": order.confirmed_at,
1061
820
  }
1062
821
  ).save(update_fields=["status", "confirmed_at"])
1063
822
  # await self.money_upd(order_db)
1064
823
 
1065
824
  case _:
1066
- logging.warning(f"Order {order.id} UNKNOWN STATUS {datetime.now()}")
825
+ logging.warning(f"Order {order.exid} UNKNOWN STATUS {datetime.now()}")
1067
826
  case "COUNT_DOWN":
1068
827
  upd = CountDown.model_validate(data["data"])
1069
828
 
@@ -1080,7 +839,7 @@ class AgentClient(BaseAgentClient): # Bybit client
1080
839
  # msg, _ = await models.Msg.update_or_create(
1081
840
  # {
1082
841
  # "to_maker": upd.userId == self.actor.exid and im_taker,
1083
- # "sent_at": datetime.fromtimestamp(float(upd.createDate) / 1000),
842
+ # "sent_at": upd.createDate,
1084
843
  # },
1085
844
  # txt=upd.message,
1086
845
  # order=order_db,
@@ -1112,29 +871,19 @@ class AgentClient(BaseAgentClient): # Bybit client
1112
871
  # self.listen(data)
1113
872
  case "SELLER_CANCEL_CHANGE":
1114
873
  upd = SellerCancelChange.model_validate(data["data"])
874
+ order_db, order = await self.load_order(upd.id)
875
+ await order_db.cancel_request(self.agent.actor_id)
1115
876
  case None:
1116
877
  if not data.get("success"):
1117
- logging.error(data, "NOT SUCCESS!")
878
+ raise HTTPException(401 if data["ret_msg"] == "Request not authorized" else data)
1118
879
  else:
1119
880
  return # success login, subscribes, input
1120
881
  case _:
1121
882
  logging.warning(data, "UNKNOWN TOPIC")
1122
883
 
1123
- async def get_order_full(self, oid: int) -> OrderFull:
1124
- order = self.api.get_order_details(orderId=oid)
1125
- return OrderFull.model_validate(order["result"])
1126
-
1127
- async def load_order(self, oid: int) -> tuple[models.Order, OrderFull]:
1128
- if not self.orders.get(oid):
1129
- order = await self.get_order_full(oid)
1130
- if not (
1131
- order_db := await models.Order.get_or_none(exid=oid, ad__maker__ex=self.actor.ex).prefetch_related(
1132
- "ad__pair_side__pair", "cred__pmcur__cur"
1133
- )
1134
- ):
1135
- order_db = await self.create_order_db(order)
1136
- self.orders[oid] = order_db, order
1137
- return self.orders[oid]
884
+ async def _get_order_full(self, order_exid: int) -> OrderFull:
885
+ order_dict: dict = self.api.get_order_details(orderId=order_exid)["result"]
886
+ return OrderFull.model_validate(order_dict)
1138
887
 
1139
888
  async def money_upd(self, odb: models.Order):
1140
889
  # обновляем остаток монеты
@@ -1301,7 +1050,7 @@ async def main():
1301
1050
  cn = await init_db(TORM)
1302
1051
 
1303
1052
  agent = (
1304
- await models.Agent.filter(actor__ex_id=4, auth__isnull=False, status__gt=AgentStatus.off, id=5)
1053
+ await models.Agent.filter(actor__ex_id=4, auth__isnull=False, status__gt=AgentStatus.off, id=2)
1305
1054
  .prefetch_related(
1306
1055
  "actor__ex",
1307
1056
  "actor__person__user__gmail",
@@ -1315,11 +1064,11 @@ async def main():
1315
1064
  # await filebot.start()
1316
1065
  # b.add_handler(MessageHandler(cond_start_handler, command("cond")))
1317
1066
  ex = await models.Ex.get(name="Bybit")
1318
- ecl: ExClient = ex.client(filebot)
1067
+ prx = PRX and "http://" + PRX
1068
+ ecl: ExClient = ex.client(filebot, proxy=prx)
1319
1069
  abot = XyncBot(PAY_TOKEN, cn)
1320
1070
  # pmas = await models.PmAgent.filter(active=True, user_id=1).prefetch_related("pm", "user__gmail")
1321
1071
  # pm_clients = {pma.pm_id: pma.client(abot) for pma in pmas}
1322
- prx = PRX and "http://" + PRX
1323
1072
  cl: AgentClient = agent.client(ecl, filebot, abot, proxy=prx)
1324
1073
 
1325
1074
  # req = TakeAdReq(ad_id=1955696985964089344, amount=504, pm_id=128)
@@ -1328,11 +1077,13 @@ async def main():
1328
1077
  # await cl.actual_cond()
1329
1078
  # cl.get_api_orders(), # 10, 1738357200000, 1742504399999
1330
1079
 
1080
+ # await cl.ex_client.set_coins()
1081
+ # await cl.ex_client.set_curs()
1331
1082
  # await cl.ex_client.set_pairs()
1332
1083
  # await cl.ex_client.set_pms()
1333
1084
 
1334
- await cl.set_creds()
1335
- await cl.export_my_ads()
1085
+ # await cl.load_creds()
1086
+ # await cl.load_my_ads()
1336
1087
 
1337
1088
  my_ad = await models.MyAd[5]
1338
1089
  await cl.ad_share(my_ad.id)
@@ -1381,7 +1132,7 @@ async def main():
1381
1132
 
1382
1133
  # await cl.cancel_order(res.orderId)
1383
1134
  await filebot.stop()
1384
- await cl.close()
1135
+ await cl.stop()
1385
1136
 
1386
1137
 
1387
1138
  if __name__ == "__main__":