xync-client 0.0.162__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:
@@ -276,9 +178,7 @@ class AgentClient(BaseAgentClient): # Bybit client
276
178
  return len([await self.ad_share(mad.id) for mad in mads])
277
179
 
278
180
  async def ad_share(self, maid: int):
279
- myad = await models.MyAd.get(id=maid).prefetch_related(
280
- "ad__pair_side__pair__coin", "ad__pair_side__pair__cur", "ad__maker"
281
- )
181
+ myad = await models.MyAd.get(id=maid).prefetch_related("ad__pair_side__pair__coin", "ad__pair_side__pair__cur")
282
182
  if myad.hex and myad.shared_at + timedelta(minutes=55) > now(): # check expired
283
183
  # check validity
284
184
  data = await self._post("/x-api/fiat/otc/item/shareItem/info", {"shareCode": myad.hex.hex()})
@@ -286,14 +186,14 @@ class AgentClient(BaseAgentClient): # Bybit client
286
186
  return myad.get_url()
287
187
  data = await self._post("/x-api/fiat/otc/item/share", {"itemId": str(myad.ad.exid)})
288
188
  if data["ret_code"] == 912300058:
289
- raise ShareException(
290
- f"Объява {myad.id}:{myad.ad.id}:{myad.ad.exid} агента {myad.ad.maker.agent_id} выключена"
291
- )
292
- if data["ret_code"] == 912300059:
293
- raise ShareException(f"Торговля агента {myad.ad.maker.agent_id} выключена")
294
- if data["ret_code"] == 10007:
189
+ raise ShareException(f"Ad {myad.id}:{myad.ad.id}:{myad.ad.exid} agent:{myad.ad.maker.agent_id} offline")
190
+ elif data["ret_code"] == 912300059:
191
+ raise ShareException(f"Торговля мейкера {myad.ad.maker_id} выключена")
192
+ elif data["ret_code"] == 10007:
295
193
  raise ShareException(f"Авторизация агента {myad.ad.maker.agent_id} слетела")
296
- if data["ret_code"] != 0: # Новая ошибка
194
+ elif data["ret_code"] == 912300064:
195
+ raise ShareException(f"Ad {myad.ad.exid} maker:{myad.ad.maker_id} shared too much")
196
+ elif data["ret_code"] != 0: # Новая ошибка
297
197
  raise ShareException(data)
298
198
  url = data["result"]["shareLink"]
299
199
  resp = await self.session.get(url)
@@ -375,8 +275,8 @@ class AgentClient(BaseAgentClient): # Bybit client
375
275
  data = self.api.post_new_ad(**ad.model_dump())
376
276
  return data["result"]["itemId"] if data["ret_code"] == 0 else data
377
277
 
378
- async def _ad_upd(self, req: AdUpd):
379
- upd = AdUpdateRequest({})
278
+ async def _ad_upd(self, req: AdUpdReq):
279
+ upd = AdRequest({})
380
280
  params = upd.model_dump()
381
281
  data = self.api.update_ad(**params)
382
282
  return data["result"] if data["ret_code"] == 0 else data
@@ -420,9 +320,9 @@ class AgentClient(BaseAgentClient): # Bybit client
420
320
  tokenId=bor.coin_exid,
421
321
  currencyId=bor.cur_exid,
422
322
  side="1" if bor.is_sell else "0",
423
- amount=f"{bor.fiat_amount:.2f}".rstrip("0").rstrip("."),
323
+ amount=f"{bor.amount:.2f}".rstrip("0").rstrip("."),
424
324
  curPrice=por.curPrice,
425
- quantity=str(round(bor.fiat_amount / float(por.price), bor.coin_scale)),
325
+ quantity=str(round(bor.amount / float(por.price), bor.coin_scale)),
426
326
  flag="amount",
427
327
  # online="0"
428
328
  )
@@ -533,155 +433,6 @@ class AgentClient(BaseAgentClient): # Bybit client
533
433
  },
534
434
  )
535
435
 
536
- async def create_order_db(self, order: OrderFull) -> models.Order:
537
- curex = await models.CurEx.get_or_none(ex=self.ex_client.ex, exid=order.currencyId).prefetch_related("cur")
538
- cur_scale = (curex.scale if curex.scale is not None else curex.cur.scale) if curex else 2
539
- coinex = await models.CoinEx.get(ex=self.ex_client.ex, exid=order.tokenId).prefetch_related("coin")
540
- coin_scale = coinex.scale if coinex.scale is not None else coinex.cur.scale
541
- sb_names = order.sellerRealName, order.buyerRealName
542
- im_maker = int(int(order.makerUserId) == self.actor.exid)
543
- taker_id = (order.userId, order.targetUserId)[im_maker]
544
- taker_name = sb_names[order.side] # todo: double check
545
- taker_person = await self.ex_client.person_name_update(taker_name, taker_id)
546
- seller_person = (
547
- self.actor.person
548
- if order.side
549
- else await self.ex_client.person_name_update(order.sellerRealName, int(order.targetUserId))
550
- )
551
- taker_nick = (self.actor.name, order.targetNickName)[im_maker] # todo: check
552
- ad_db = await models.Ad.get(exid=order.itemId)
553
- if not ad_db:
554
- ad = self.get_ad(order.itemId)
555
- # ad_db, cond_isnew = await self.ex_client.cond_load(ad, force=True, rname=maker_name[order.side])
556
- ad_db = await self.ex_client.ad_load(ad, maker=self.actor)
557
- ecredex: CredEpyd = order.confirmedPayTerm
558
-
559
- if ecredex.paymentType == 0 and im_maker and order.side:
560
- ecredex = order.paymentTermList[0]
561
- if ecredex.paymentType:
562
- if ecredex.paymentType == 51:
563
- ecredex.accountNo = ecredex.accountNo.replace("p", "P").replace("р", "P").replace("Р", "P")
564
- # if not re.match(r"^([Pp])\d{7,10}$", ecredex.accountNo):
565
- # msgs = self.api.get_chat_messages(orderId=order.id, size=100)["result"]["result"]
566
- # msgs = [m["message"] for m in msgs if m["roleType"] == "user" and m["userId"] == order.targetUserId]
567
- # msgs = [g.group() for m in msgs if (g := re.match(r"([PpРр])\d{7,10}\b", m))]
568
- # crd = await models.Cred.get_or_none(
569
- # detail=ecredex.accountNo, credexs__exid=ecredex.id, credexs__ex=self.ex_client.ex
570
- # )
571
- # if not msgs and re.match(r"^\d{7,10}$", ecredex.accountNo):
572
- # ecredex.accountNo = "P" + ecredex.accountNo
573
- # elif msgs:
574
- # ecredex.accountNo = msgs[-1]
575
- # else:
576
- # ...
577
- # if crd:
578
- # crd.detail = ecredex.accountNo
579
- # await crd.save(update_fields=["detail"])
580
- if not (credex := await models.CredEx.get_or_none(exid=ecredex.id, ex=self.ex_client.ex)):
581
- # cur_id = await Cur.get(ticker=ad.currencyId).values_list('id', flat=True)
582
- # await self.cred_epyd2db(ecredex, ad_db.maker.person_id, cur_id)
583
- if (
584
- await PmCur.filter(
585
- pm__pmexs__ex=self.ex_client.ex,
586
- pm__pmexs__exid=ecredex.paymentType,
587
- cur__ticker=order.currencyId,
588
- ).count()
589
- != 1
590
- ):
591
- ...
592
- if not (
593
- pmcur := await PmCur.get_or_none(
594
- pm__pmexs__ex=self.ex_client.ex,
595
- pm__pmexs__exid=ecredex.paymentType,
596
- cur__ticker=order.currencyId,
597
- )
598
- ):
599
- ...
600
- if not (
601
- crd := await models.Cred.get_or_none(pmcur=pmcur, person=seller_person, detail=ecredex.accountNo)
602
- ):
603
- extr = ", ".join(
604
- x
605
- for xtr in [
606
- ecredex.bankName,
607
- ecredex.branchName,
608
- ecredex.qrcode,
609
- ecredex.payMessage,
610
- ecredex.paymentExt1,
611
- ]
612
- if (x := xtr.strip())
613
- )
614
- crd = await models.Cred.create(
615
- detail=ecredex.accountNo,
616
- pmcur=pmcur,
617
- person=seller_person,
618
- name=ecredex.realName,
619
- extra=extr,
620
- )
621
- credex = await models.CredEx.create(exid=ecredex.id, ex=self.ex_client.ex, cred=crd)
622
- try:
623
- taker, _ = await Actor.get_or_create(
624
- {"name": taker_nick, "person": taker_person}, ex=self.ex_client.ex, exid=taker_id
625
- )
626
- except IntegrityError as e:
627
- logging.error(e)
628
- odb, _ = await models.Order.update_or_create(
629
- {
630
- "amount": float(order.amount) * 10**cur_scale,
631
- "quantity": float(order.quantity) * 10**coin_scale,
632
- "status": OrderStatus[Status(order.status).name],
633
- "created_at": ms2utc(order.createDate),
634
- "payed_at": order.transferDate != "0" and ms2utc(order.transferDate) or None,
635
- "confirmed_at": Status(order.status) == Status.completed and ms2utc(order.transferDate) or None,
636
- "appealed_at": order.status == 30 and ms2utc(order.transferDate) or None,
637
- "cred_id": ecredex.paymentType and credex.cred_id or None,
638
- "taker": taker,
639
- "ad": ad_db,
640
- },
641
- exid=order.id,
642
- )
643
- if order.status == Status.completed and ecredex.paymentType == 51:
644
- await odb.fetch_related("cred", "transfer")
645
- if odb.cred.detail != ecredex.accountNo:
646
- ...
647
- frm = (odb.created_at + timedelta(minutes=180 - 1)).isoformat(sep=" ").split("+")[0]
648
- to = ((odb.payed_at or odb.created_at) + timedelta(minutes=180 + 30)).isoformat(sep=" ").split("+")[0]
649
- tsa = [
650
- t
651
- for tid, t in (self.hist.items() if self.hist else [])
652
- if (ecredex.accountNo == t["to"] and t["from"] != "@merchant" and frm < t["date"] < to)
653
- ]
654
- buyer_person = (
655
- self.actor.person
656
- if not order.side
657
- else await self.ex_client.person_name_update(order.buyerRealName, int(order.targetUserId))
658
- )
659
- ts = [t for t in tsa if floor(fa := float(order.amount)) <= float(t["creditedAmount"]) <= round(fa)]
660
- if len(ts) != 1:
661
- if len(tsa) > 1:
662
- summ = sum(float(t["creditedAmount"]) for t in tsa)
663
- if floor(fa) <= summ <= round(fa):
664
- for tr in tsa:
665
- am = int(float(tr["creditedAmount"]) * 100)
666
- await models.Transfer.create(
667
- pmid=tr["id"], order=odb, amount=am, sender_acc=tr["from"], created_at=tr["date"]
668
- )
669
- else:
670
- bcred, _ = await models.Cred.get_or_create(
671
- {"detail": ts[0]["from"]}, person=buyer_person, pmcur_id=odb.cred.pmcur_id
672
- )
673
- am = int(float(ts[0]["creditedAmount"]) * 100)
674
- try:
675
- await models.Transfer.create(
676
- pmid=ts[0]["id"], order=odb, amount=am, sender_acc=ts[0]["from"], created_at=ts[0]["date"]
677
- )
678
- except IntegrityError as e:
679
- logging.error(e)
680
- ...
681
-
682
- await odb.fetch_related("ad")
683
- return odb
684
-
685
436
  async def get_api_orders(
686
437
  self,
687
438
  page: int = 1,
@@ -710,7 +461,7 @@ class AgentClient(BaseAgentClient): # Bybit client
710
461
  if o.status != Status.completed.value or oid in self.completed_orders:
711
462
  continue
712
463
  order = await self.get_order_full(o.id)
713
- order_db = await self.create_order_db(order)
464
+ order_db = await self.order_save(order)
714
465
  await sleep(1)
715
466
  dmsgs = self.api.get_chat_messages(orderId=oid, size=200)["result"]["result"][::-1]
716
467
  msgs = [Message.model_validate(m) for m in dmsgs if m["msgType"] in (1, 2, 7, 8)]
@@ -773,7 +524,7 @@ class AgentClient(BaseAgentClient): # Bybit client
773
524
 
774
525
  bor = BaseOrderReq(
775
526
  ad_id=str(req.ad_id),
776
- fiat_amount=req.amount,
527
+ amount=req.amount,
777
528
  is_sell=req.is_sell,
778
529
  cur_exid=curex.exid,
779
530
  coin_exid=coinex.exid,
@@ -790,7 +541,7 @@ class AgentClient(BaseAgentClient): # Bybit client
790
541
  i = 0
791
542
  while True:
792
543
  try:
793
- 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)
794
545
  bs = await self.ex_client.ads(breq, post_pmexs=post_pmexs)
795
546
  bs = [b for b in bs if float(b.price) < 100 or int(b.userId) in mcs.keys()]
796
547
  if bs:
@@ -812,7 +563,7 @@ class AgentClient(BaseAgentClient): # Bybit client
812
563
  ord_resp: OrderResp = await self.take_ad(req)
813
564
  # order: OrderFull = OrderFull(**self.api.get_order_details(orderId=ord_resp.orderId)["result"])
814
565
  order: OrderFull = await self.get_order_info(ord_resp.orderId)
815
- odb = await self.create_order_db(order)
566
+ odb = await self.order_save(order)
816
567
  t = await models.Transfer(order=odb, amount=odb.amount, updated_at=now())
817
568
  await t.fetch_related("order__cred__pmcur__cur")
818
569
  # res = await self.pm_clients[366].send(t)
@@ -828,7 +579,7 @@ class AgentClient(BaseAgentClient): # Bybit client
828
579
 
829
580
  await sleep(5)
830
581
 
831
- 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})
832
583
  ss = await self.ex_client.ads(sreq, post_pmexs=post_pmexs)
833
584
  ss = [s for s in ss if float(s.price) > 92 or int(s.userId) in mcs.keys()]
834
585
  if ss:
@@ -850,7 +601,7 @@ class AgentClient(BaseAgentClient): # Bybit client
850
601
  ord_resp: OrderResp = await self.take_ad(req)
851
602
  # order: OrderFull = OrderFull(**self.api.get_order_details(orderId=ord_resp.orderId)["result"])
852
603
  order: OrderFull = await self.get_order_info(ord_resp.orderId)
853
- odb = await self.create_order_db(order)
604
+ odb = await self.order_save(order)
854
605
  # t = await models.Transfer(order=odb, amount=odb.amount, updated_at=now())
855
606
  # await t.fetch_related("order__cred__pmcur__cur")
856
607
  # res = await self.pm_clients[366].check_in(t)
@@ -881,7 +632,7 @@ class AgentClient(BaseAgentClient): # Bybit client
881
632
  req = TakeAdReq(ad_id="1856989782009487360", amount=am, pm_id=366)
882
633
  ord_resp: OrderResp = await self.take_ad(req)
883
634
  order: OrderFull = await self.get_order_full(int(ord_resp.orderId))
884
- odb = await self.create_order_db(order)
635
+ odb = await self.order_save(order)
885
636
  t = await models.Transfer(order=odb, amount=odb.amount, updated_at=now())
886
637
  await t.fetch_related("order__cred__pmcur__cur")
887
638
  await self.pm_clients[366].send(t)
@@ -928,10 +679,14 @@ class AgentClient(BaseAgentClient): # Bybit client
928
679
 
929
680
  sub_msg = json.dumps({"op": "subscribe", "args": ["FIAT_OTC_TOPIC", "FIAT_OTC_ONLINE_TOPIC"]})
930
681
  await websocket.send(sub_msg)
931
- while resp := await websocket.recv():
932
- if data := json.loads(resp):
933
- logging.info(f" {now().strftime('%H:%M:%S')} upd: {data.get('topic')}:{data.get('type')}")
934
- 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()
935
690
 
936
691
  async def proc(self, data: dict):
937
692
  match data.get("topic"):
@@ -939,10 +694,12 @@ class AgentClient(BaseAgentClient): # Bybit client
939
694
  match data["type"]:
940
695
  case "STATUS_CHANGE":
941
696
  upd = StatusChange.model_validate(data["data"])
942
- 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)
943
700
  match upd.status:
944
- case Status.ws_new:
945
- 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}")
946
703
  # await self.got_new_order(order_db, order)
947
704
 
948
705
  # # сразу уменьшаем доступный остаток монеты/валюты
@@ -953,8 +710,8 @@ class AgentClient(BaseAgentClient): # Bybit client
953
710
  # return
954
711
  # await order_db.fetch_related("ad__pair_side__pair", "cred__pmcur__cur")
955
712
  # await self.send_payment(order_db)
956
- case Status.created:
957
- if upd.side == 0: # я продавец, ждем когда покупатель оплатит
713
+ # case OrderStatus.created:
714
+ if upd.ad__pair_side__is_sell == 0: # я продавец, ждем когда покупатель оплатит
958
715
  # check_payment() # again
959
716
  ...
960
717
  # if not (pmacdx := await self.get_pma_by_cdex(order)):
@@ -992,7 +749,7 @@ class AgentClient(BaseAgentClient): # Bybit client
992
749
  # for o in pos.get("items", [])
993
750
  # if (
994
751
  # o["amount"] == order.amount
995
- # and o["id"] != upd.id
752
+ # and o["id"] != upd.exid
996
753
  # and int(order.createDate) < int(o["createDate"]) + 15 * 60 * 1000
997
754
  # # get full_order from o, and cred or pm from full_order:
998
755
  # and self.api.get_order_details(orderId=o["id"])["result"][
@@ -1019,53 +776,53 @@ class AgentClient(BaseAgentClient): # Bybit client
1019
776
  # return
1020
777
  #
1021
778
  # # !!! ОТПРАВЛЯЕМ ДЕНЬГИ !!!
1022
- # self.api.release_assets(orderId=upd.id)
779
+ # self.api.release_assets(orderId=upd.exid)
1023
780
  # logging.info(
1024
781
  # f"Order {order.id} created, paid before #{tid}:{am} at {order.createDate}, and RELEASED at {now()}"
1025
782
  # )
1026
- elif upd.side == 1: # я покупатель - ждем мою оплату
783
+ elif upd.ad__pair_side__is_sell == 1: # я покупатель - ждем мою оплату
1027
784
  # pay()
1028
- logging.warning(f"Order {upd.id} CREATED2 at {now()}")
785
+ logging.warning(f"Order {upd.exid} CREATED2 at {now()}")
1029
786
 
1030
- case Status.paid:
787
+ case OrderStatus.paid:
1031
788
  if order_db.status == OrderStatus.paid:
1032
789
  return
1033
790
  await order_db.update_from_dict(
1034
791
  {
1035
792
  "status": OrderStatus.paid,
1036
- "payed_at": datetime.fromtimestamp(float(order.transferDate) / 1000),
793
+ "payed_at": order.payed_at,
1037
794
  }
1038
795
  ).save()
1039
- 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}")
1040
797
 
1041
- case Status.appealed_by_seller: # just any appealed
798
+ case OrderStatus.appealed_by_seller: # just any appealed
1042
799
  # todo: appealed by WHO? щас наугад стоит by_seller
1043
800
  await order_db.update_from_dict(
1044
801
  {
1045
802
  "status": OrderStatus.appealed_by_seller,
1046
- "appealed_at": datetime.fromtimestamp(float(order.updateDate) / 1000),
803
+ "appealed_at": order.appealed_at,
1047
804
  }
1048
805
  ).save()
1049
- 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}")
1050
807
 
1051
- case Status.canceled:
808
+ case OrderStatus.canceled:
1052
809
  await order_db.update_from_dict({"status": OrderStatus.canceled}).save()
1053
- logging.info(f"Order {order.id} canceled at {datetime.now()}")
810
+ logging.info(f"Order {order.exid} canceled at {datetime.now()}")
1054
811
  # await self.money_upd(order_db)
1055
812
 
1056
- case Status.completed:
813
+ case OrderStatus.completed:
1057
814
  await order_db.refresh_from_db()
1058
815
  if order_db.status != OrderStatus.completed:
1059
816
  await order_db.update_from_dict(
1060
817
  {
1061
818
  "status": OrderStatus.completed,
1062
- "confirmed_at": datetime.fromtimestamp(float(order.updateDate) / 1000),
819
+ "confirmed_at": order.confirmed_at,
1063
820
  }
1064
821
  ).save(update_fields=["status", "confirmed_at"])
1065
822
  # await self.money_upd(order_db)
1066
823
 
1067
824
  case _:
1068
- logging.warning(f"Order {order.id} UNKNOWN STATUS {datetime.now()}")
825
+ logging.warning(f"Order {order.exid} UNKNOWN STATUS {datetime.now()}")
1069
826
  case "COUNT_DOWN":
1070
827
  upd = CountDown.model_validate(data["data"])
1071
828
 
@@ -1082,7 +839,7 @@ class AgentClient(BaseAgentClient): # Bybit client
1082
839
  # msg, _ = await models.Msg.update_or_create(
1083
840
  # {
1084
841
  # "to_maker": upd.userId == self.actor.exid and im_taker,
1085
- # "sent_at": datetime.fromtimestamp(float(upd.createDate) / 1000),
842
+ # "sent_at": upd.createDate,
1086
843
  # },
1087
844
  # txt=upd.message,
1088
845
  # order=order_db,
@@ -1114,29 +871,19 @@ class AgentClient(BaseAgentClient): # Bybit client
1114
871
  # self.listen(data)
1115
872
  case "SELLER_CANCEL_CHANGE":
1116
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)
1117
876
  case None:
1118
877
  if not data.get("success"):
1119
- logging.error(data, "NOT SUCCESS!")
878
+ raise HTTPException(401 if data["ret_msg"] == "Request not authorized" else data)
1120
879
  else:
1121
880
  return # success login, subscribes, input
1122
881
  case _:
1123
882
  logging.warning(data, "UNKNOWN TOPIC")
1124
883
 
1125
- async def get_order_full(self, oid: int) -> OrderFull:
1126
- order = self.api.get_order_details(orderId=oid)
1127
- return OrderFull.model_validate(order["result"])
1128
-
1129
- async def load_order(self, oid: int) -> tuple[models.Order, OrderFull]:
1130
- if not self.orders.get(oid):
1131
- order = await self.get_order_full(oid)
1132
- if not (
1133
- order_db := await models.Order.get_or_none(exid=oid, ad__maker__ex=self.actor.ex).prefetch_related(
1134
- "ad__pair_side__pair", "cred__pmcur__cur"
1135
- )
1136
- ):
1137
- order_db = await self.create_order_db(order)
1138
- self.orders[oid] = order_db, order
1139
- 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)
1140
887
 
1141
888
  async def money_upd(self, odb: models.Order):
1142
889
  # обновляем остаток монеты
@@ -1303,7 +1050,7 @@ async def main():
1303
1050
  cn = await init_db(TORM)
1304
1051
 
1305
1052
  agent = (
1306
- 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)
1307
1054
  .prefetch_related(
1308
1055
  "actor__ex",
1309
1056
  "actor__person__user__gmail",
@@ -1317,11 +1064,11 @@ async def main():
1317
1064
  # await filebot.start()
1318
1065
  # b.add_handler(MessageHandler(cond_start_handler, command("cond")))
1319
1066
  ex = await models.Ex.get(name="Bybit")
1320
- ecl: ExClient = ex.client(filebot)
1067
+ prx = PRX and "http://" + PRX
1068
+ ecl: ExClient = ex.client(filebot, proxy=prx)
1321
1069
  abot = XyncBot(PAY_TOKEN, cn)
1322
1070
  # pmas = await models.PmAgent.filter(active=True, user_id=1).prefetch_related("pm", "user__gmail")
1323
1071
  # pm_clients = {pma.pm_id: pma.client(abot) for pma in pmas}
1324
- prx = PRX and "http://" + PRX
1325
1072
  cl: AgentClient = agent.client(ecl, filebot, abot, proxy=prx)
1326
1073
 
1327
1074
  # req = TakeAdReq(ad_id=1955696985964089344, amount=504, pm_id=128)
@@ -1330,11 +1077,13 @@ async def main():
1330
1077
  # await cl.actual_cond()
1331
1078
  # cl.get_api_orders(), # 10, 1738357200000, 1742504399999
1332
1079
 
1080
+ # await cl.ex_client.set_coins()
1081
+ # await cl.ex_client.set_curs()
1333
1082
  # await cl.ex_client.set_pairs()
1334
1083
  # await cl.ex_client.set_pms()
1335
1084
 
1336
- await cl.set_creds()
1337
- await cl.export_my_ads()
1085
+ # await cl.load_creds()
1086
+ # await cl.load_my_ads()
1338
1087
 
1339
1088
  my_ad = await models.MyAd[5]
1340
1089
  await cl.ad_share(my_ad.id)
@@ -1383,7 +1132,7 @@ async def main():
1383
1132
 
1384
1133
  # await cl.cancel_order(res.orderId)
1385
1134
  await filebot.stop()
1386
- await cl.close()
1135
+ await cl.stop()
1387
1136
 
1388
1137
 
1389
1138
  if __name__ == "__main__":