xync-bot 0.3.24.dev8__tar.gz → 0.3.24.dev11__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of xync-bot might be problematic. Click here for more details.
- {xync_bot-0.3.24.dev8/xync_bot.egg-info → xync_bot-0.3.24.dev11}/PKG-INFO +1 -1
- {xync_bot-0.3.24.dev8 → xync_bot-0.3.24.dev11}/xync_bot/__init__.py +1 -1
- {xync_bot-0.3.24.dev8 → xync_bot-0.3.24.dev11}/xync_bot/routers/pay/cd.py +1 -0
- xync_bot-0.3.24.dev11/xync_bot/routers/pay/dep.py +244 -0
- {xync_bot-0.3.24.dev8 → xync_bot-0.3.24.dev11}/xync_bot/routers/pay/handler.py +21 -50
- {xync_bot-0.3.24.dev8 → xync_bot-0.3.24.dev11}/xync_bot/routers/pay/window.py +83 -33
- xync_bot-0.3.24.dev11/xync_bot/typs.py +0 -0
- {xync_bot-0.3.24.dev8 → xync_bot-0.3.24.dev11/xync_bot.egg-info}/PKG-INFO +1 -1
- xync_bot-0.3.24.dev8/xync_bot/routers/__init__.py +0 -92
- xync_bot-0.3.24.dev8/xync_bot/routers/pay/dep.py +0 -122
- {xync_bot-0.3.24.dev8 → xync_bot-0.3.24.dev11}/.env.dist +0 -0
- {xync_bot-0.3.24.dev8 → xync_bot-0.3.24.dev11}/.gitignore +0 -0
- {xync_bot-0.3.24.dev8 → xync_bot-0.3.24.dev11}/.pre-commit-config.yaml +0 -0
- {xync_bot-0.3.24.dev8 → xync_bot-0.3.24.dev11}/makefile +0 -0
- {xync_bot-0.3.24.dev8 → xync_bot-0.3.24.dev11}/pyproject.toml +0 -0
- {xync_bot-0.3.24.dev8 → xync_bot-0.3.24.dev11}/setup.cfg +0 -0
- {xync_bot-0.3.24.dev8 → xync_bot-0.3.24.dev11}/test_main.http +0 -0
- {xync_bot-0.3.24.dev8 → xync_bot-0.3.24.dev11}/xync_bot/loader.py +0 -0
- /xync_bot-0.3.24.dev8/xync_bot/typs.py → /xync_bot-0.3.24.dev11/xync_bot/routers/__init__.py +0 -0
- {xync_bot-0.3.24.dev8 → xync_bot-0.3.24.dev11}/xync_bot/routers/cond/__init__.py +0 -0
- {xync_bot-0.3.24.dev8 → xync_bot-0.3.24.dev11}/xync_bot/routers/cond/func.py +0 -0
- {xync_bot-0.3.24.dev8 → xync_bot-0.3.24.dev11}/xync_bot/routers/main.py +0 -0
- {xync_bot-0.3.24.dev8 → xync_bot-0.3.24.dev11}/xync_bot/routers/order.py +0 -0
- {xync_bot-0.3.24.dev8 → xync_bot-0.3.24.dev11}/xync_bot/routers/photo.py +0 -0
- {xync_bot-0.3.24.dev8 → xync_bot-0.3.24.dev11}/xync_bot/routers/vpn.py +0 -0
- {xync_bot-0.3.24.dev8 → xync_bot-0.3.24.dev11}/xync_bot/routers/xicon.png +0 -0
- {xync_bot-0.3.24.dev8 → xync_bot-0.3.24.dev11}/xync_bot/shared.py +0 -0
- {xync_bot-0.3.24.dev8 → xync_bot-0.3.24.dev11}/xync_bot.egg-info/SOURCES.txt +0 -0
- {xync_bot-0.3.24.dev8 → xync_bot-0.3.24.dev11}/xync_bot.egg-info/dependency_links.txt +0 -0
- {xync_bot-0.3.24.dev8 → xync_bot-0.3.24.dev11}/xync_bot.egg-info/requires.txt +0 -0
- {xync_bot-0.3.24.dev8 → xync_bot-0.3.24.dev11}/xync_bot.egg-info/top_level.txt +0 -0
|
@@ -5,8 +5,8 @@ from PGram import Bot
|
|
|
5
5
|
from aiogram.client.default import DefaultBotProperties
|
|
6
6
|
from x_model import init_db
|
|
7
7
|
|
|
8
|
-
from xync_bot.routers import Store
|
|
9
8
|
from xync_bot.routers.cond import cr as cr
|
|
9
|
+
from xync_bot.routers.pay.dep import Store
|
|
10
10
|
|
|
11
11
|
# from xync_bot.routers.main import mr
|
|
12
12
|
from xync_bot.routers.pay.handler import pay as pay
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
from asyncio import gather
|
|
2
|
+
from enum import IntEnum
|
|
3
|
+
|
|
4
|
+
from aiogram.exceptions import TelegramBadRequest
|
|
5
|
+
from aiogram.fsm.state import StatesGroup, State
|
|
6
|
+
from aiogram.types import Message, InlineKeyboardMarkup
|
|
7
|
+
from pyrogram.types import CallbackQuery
|
|
8
|
+
from tortoise.functions import Min
|
|
9
|
+
from x_auth.enums import Role
|
|
10
|
+
from x_model.func import ArrayAgg
|
|
11
|
+
from xync_schema import models
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Report(StatesGroup):
|
|
15
|
+
text = State()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class CredState(StatesGroup):
|
|
19
|
+
detail = State()
|
|
20
|
+
name = State()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class PaymentState(StatesGroup):
|
|
24
|
+
amount = State()
|
|
25
|
+
timer = State()
|
|
26
|
+
timer_active = State()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class ActionType(IntEnum):
|
|
30
|
+
"""Цель (назначение) платежа (target)"""
|
|
31
|
+
|
|
32
|
+
sent = 1 # Отправил
|
|
33
|
+
received = 2 # Получил
|
|
34
|
+
not_received = 3 # Не получил
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class PayStep(IntEnum):
|
|
38
|
+
"""Цель (назначение) платежа (target)"""
|
|
39
|
+
|
|
40
|
+
t_type = 1 # Выбор типа
|
|
41
|
+
t_cur = 2 # Выбор валюты
|
|
42
|
+
t_coin = 3 # Выбор монеты
|
|
43
|
+
t_pm = 4 # Выбор платежки
|
|
44
|
+
t_ex = 5 # Выбор биржи
|
|
45
|
+
t_cred_dtl = 6 # Ввод номера карты
|
|
46
|
+
t_cred_name = 7 # Ввод имени
|
|
47
|
+
# t_addr = 8 # todo: позже добавим: Выбор/ввод крипто кошелька
|
|
48
|
+
t_amount = 9 # Ввод суммы
|
|
49
|
+
""" Источник платежа (source) """
|
|
50
|
+
s_type = 10 # Выбор типа
|
|
51
|
+
s_cur = 11 # Выбор типа
|
|
52
|
+
s_pm = 12 # Выбор типа
|
|
53
|
+
s_coin = 13 # Выбор типа
|
|
54
|
+
s_ex = 14 # Выбор типа
|
|
55
|
+
ppo = 15 # Выбор возможности разбивки платежа
|
|
56
|
+
urgency = 16 # Выбор срочности получения платежа
|
|
57
|
+
pending_send = 17 # Ожидание отправки (если мы платим фиатом)
|
|
58
|
+
pending_confirm = 18 # Ожидание пока на той стороне подтвердят получение нашего фиата (если мы платим фиатом)
|
|
59
|
+
pending_receive = 19 # Ожидание поступления (если мы получаем фиат)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
flags = {
|
|
63
|
+
"RUB": "🇷🇺",
|
|
64
|
+
"THB": "🇹🇭",
|
|
65
|
+
"IDR": "🇮🇩",
|
|
66
|
+
"TRY": "🇹🇷",
|
|
67
|
+
"GEL": "🇬🇪",
|
|
68
|
+
"VND": "🇻🇳",
|
|
69
|
+
"AED": "🇦🇪",
|
|
70
|
+
"AMD": "🇦🇲",
|
|
71
|
+
"AZN": "🇦🇿",
|
|
72
|
+
"CNY": "🇨🇳",
|
|
73
|
+
"EUR": "🇪🇺",
|
|
74
|
+
"HKD": "🇭🇰",
|
|
75
|
+
"INR": "🇮🇳",
|
|
76
|
+
"PHP": "🇵🇭",
|
|
77
|
+
"USD": "🇺🇸",
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class SingleStore(type):
|
|
82
|
+
_store = None
|
|
83
|
+
|
|
84
|
+
async def __call__(cls):
|
|
85
|
+
if not cls._store:
|
|
86
|
+
cls._store = super(SingleStore, cls).__call__()
|
|
87
|
+
cls._store.coins = {k: v for k, v in await models.Coin.all().order_by("ticker").values_list("id", "ticker")}
|
|
88
|
+
curs = {c.id: c for c in await models.Cur.filter(ticker__in=flags.keys()).order_by("ticker")}
|
|
89
|
+
cls._store.curs = curs
|
|
90
|
+
cls._store.exs = {k: v for k, v in await models.Ex.all().values_list("id", "name")}
|
|
91
|
+
cls._store.pmcurs = {
|
|
92
|
+
k: v
|
|
93
|
+
for k, v in await models.Pmex.filter(pm__pmcurs__cur_id__in=cls._store.curs.keys())
|
|
94
|
+
.annotate(sname=Min("name"))
|
|
95
|
+
.group_by("pm__pmcurs__id")
|
|
96
|
+
.values_list("pm__pmcurs__id", "sname")
|
|
97
|
+
}
|
|
98
|
+
cls._store.coinexs = {
|
|
99
|
+
c.id: [ex.ex_id for ex in c.coinexs] for c in await models.Coin.all().prefetch_related("coinexs")
|
|
100
|
+
}
|
|
101
|
+
cls._store.curpms = {
|
|
102
|
+
cur_id: ids
|
|
103
|
+
for cur_id, ids in await models.Pmcur.filter(cur_id__in=curs.keys())
|
|
104
|
+
.annotate(ids=ArrayAgg("id"))
|
|
105
|
+
.group_by("cur_id")
|
|
106
|
+
.values_list("cur_id", "ids")
|
|
107
|
+
}
|
|
108
|
+
cls._store.curpms = {
|
|
109
|
+
cur_id: ids
|
|
110
|
+
for cur_id, ids in await models.Pmcur.filter(cur_id__in=curs.keys())
|
|
111
|
+
.annotate(ids=ArrayAgg("id"))
|
|
112
|
+
.group_by("cur_id")
|
|
113
|
+
.values_list("cur_id", "ids")
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return cls._store
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class Store:
|
|
120
|
+
class Global(metaclass=SingleStore):
|
|
121
|
+
coins: dict[int, str] # id:ticker
|
|
122
|
+
curs: dict[int, models.Cur] # id:Cur
|
|
123
|
+
exs: dict[int, str] # id:name
|
|
124
|
+
coinexs: dict[int, list[int]] # id:[ex_ids]
|
|
125
|
+
pmcurs: dict[int, str] # pmcur_id:name
|
|
126
|
+
curpms: dict[int, list[int]] # id:[pmcur_ids]
|
|
127
|
+
|
|
128
|
+
class Permanent:
|
|
129
|
+
msg_id: int = None
|
|
130
|
+
user: models.User = None
|
|
131
|
+
actors: dict[int, int] = None # key=ex_id
|
|
132
|
+
creds: dict[int, models.Cred] = None # key=cred_id
|
|
133
|
+
cur_creds: dict[int, list[int]] = None # pmcur_id:[cred_ids]
|
|
134
|
+
|
|
135
|
+
class Current:
|
|
136
|
+
is_target: bool = True
|
|
137
|
+
is_fiat: bool = None
|
|
138
|
+
msg_to_del: Message = None
|
|
139
|
+
|
|
140
|
+
class Payment:
|
|
141
|
+
t_cur_id: int = None
|
|
142
|
+
s_cur_id: int = None
|
|
143
|
+
t_coin_id: int = None
|
|
144
|
+
s_coin_id: int = None
|
|
145
|
+
t_pmcur_id: int = None
|
|
146
|
+
s_pmcur_id: int = None
|
|
147
|
+
t_ex_id: int = None
|
|
148
|
+
s_ex_id: int = None
|
|
149
|
+
amount: int | float = None
|
|
150
|
+
ppo: int = 1
|
|
151
|
+
addr_id: int = None
|
|
152
|
+
cred_dtl: str = None
|
|
153
|
+
cred_id: int = None
|
|
154
|
+
urg: int = 5
|
|
155
|
+
pr_id: int = None
|
|
156
|
+
|
|
157
|
+
glob: Global
|
|
158
|
+
perm: Permanent = Permanent()
|
|
159
|
+
pay: Payment = Payment()
|
|
160
|
+
curr: Current = Current()
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
async def fill_creds(person_id: int) -> tuple[dict[int, models.Cred], dict[int, list[int]]]:
|
|
164
|
+
cq = models.Cred.filter(person_id=person_id)
|
|
165
|
+
creds = {c.id: c for c in await cq}
|
|
166
|
+
cur_creds = {
|
|
167
|
+
pci: ids
|
|
168
|
+
for pci, ids in await cq.annotate(ids=ArrayAgg("id")).group_by("pmcur_id").values_list("pmcur_id", "ids")
|
|
169
|
+
}
|
|
170
|
+
return creds, cur_creds
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
async def fill_actors(person_id: int) -> dict[int, int]:
|
|
174
|
+
ex_actors = {
|
|
175
|
+
# todo: check len(ids) == 1
|
|
176
|
+
exi: ids[0]
|
|
177
|
+
for exi, ids in await models.Actor.filter(person_id=person_id)
|
|
178
|
+
.annotate(ids=ArrayAgg("id"))
|
|
179
|
+
.group_by("ex_id")
|
|
180
|
+
.values_list("ex_id", "ids")
|
|
181
|
+
}
|
|
182
|
+
return ex_actors
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
async def edit(msg: Message, txt: str, rm: InlineKeyboardMarkup):
|
|
186
|
+
await gather(msg.edit_text(txt), msg.edit_reply_markup(reply_markup=rm))
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
async def ans(cbq: CallbackQuery, txt: str = None):
|
|
190
|
+
await cbq.answer(txt, cache_time=0)
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
async def dlt(msg: Message):
|
|
194
|
+
await msg.delete()
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
async def edt(msg: Message, txt: str, rm: InlineKeyboardMarkup):
|
|
198
|
+
if msg.message_id == msg.bot.store.perm.msg_id:
|
|
199
|
+
await msg.edit_text(txt, reply_markup=rm)
|
|
200
|
+
else: # окно вызвано в ответ на текст, а не кнопку
|
|
201
|
+
try:
|
|
202
|
+
await msg.bot.edit_message_text(
|
|
203
|
+
txt, chat_id=msg.chat.id, message_id=msg.bot.store.perm.msg_id, reply_markup=rm
|
|
204
|
+
)
|
|
205
|
+
except TelegramBadRequest as e:
|
|
206
|
+
print(msg.bot.store.perm.msg_id, e)
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
async def have_coin_amount(store: Store) -> bool:
|
|
210
|
+
actor_id = store.perm.actors[store.pay.t_ex_id]
|
|
211
|
+
asset = await models.Asset.get_or_none(addr__coin_id=store.pay.t_coin_id, addr__actor_id=actor_id)
|
|
212
|
+
return store.pay.amount <= asset.free
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
async def need_ppo(store: Store):
|
|
216
|
+
cur_id = getattr(store.pay, ("t" if store.curr.is_target else "s") + "_cur_id")
|
|
217
|
+
usd_amount = store.pay.amount * store.glob.curs[cur_id].rate
|
|
218
|
+
if usd_amount < 50:
|
|
219
|
+
return 0
|
|
220
|
+
elif usd_amount > 100:
|
|
221
|
+
return 2
|
|
222
|
+
else:
|
|
223
|
+
return 1
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
async def get_in(store: Store) -> tuple[models.Addr | models.Cred, str]:
|
|
227
|
+
if store.pay.s_ex_id:
|
|
228
|
+
addr_in = await models.Addr.get(
|
|
229
|
+
actor__ex_id=store.pay.s_ex_id, coin_id=store.pay.s_coin_id, actor__user__role__gte=Role.ADMIN
|
|
230
|
+
).prefetch_related("actor")
|
|
231
|
+
return addr_in, (
|
|
232
|
+
f"{store.glob.coins[store.pay.s_coin_id]} на {store.glob.exs[store.pay.s_ex_id]}, "
|
|
233
|
+
f"по id: `{addr_in.actor.exid}`"
|
|
234
|
+
)
|
|
235
|
+
else:
|
|
236
|
+
s_pmcur = await models.Pmcur.get(id=store.pay.s_pmcur_id).prefetch_related("pm__grp")
|
|
237
|
+
cred_id = await models.Cred.get( # todo: extend cred search conditions
|
|
238
|
+
**({"pmcur__pm__grp": s_pmcur.pm.grp} if s_pmcur.pm.grp else {"pmcur_id": store.pay.s_pmcur_id}),
|
|
239
|
+
person__user__role__gte=Role.ADMIN,
|
|
240
|
+
)
|
|
241
|
+
return cred_id, (
|
|
242
|
+
f"{store.glob.curs[store.pay.s_cur_id]} на {store.glob.pmcurs[store.pay.s_pmcur_id]} "
|
|
243
|
+
f"по номеру: `{cred_id.detail}`, имя: {cred_id.name}{cred_id.extra and f' ({cred_id.extra})' or ''}"
|
|
244
|
+
)
|
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
from asyncio import
|
|
2
|
-
from datetime import
|
|
1
|
+
from asyncio import gather
|
|
2
|
+
from datetime import datetime
|
|
3
3
|
|
|
4
4
|
import PGram
|
|
5
5
|
from aiogram import Router, F
|
|
6
6
|
from aiogram.filters import Command
|
|
7
7
|
from aiogram.types import Message, CallbackQuery
|
|
8
8
|
from aiogram.fsm.context import FSMContext
|
|
9
|
-
from xync_bot.routers.pay.dep import fill_creds, fill_actors, dlt, ans
|
|
9
|
+
from xync_bot.routers.pay.dep import fill_creds, fill_actors, dlt, ans, Store
|
|
10
10
|
from xync_schema import models
|
|
11
|
-
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
|
12
11
|
|
|
13
|
-
from xync_bot import Store
|
|
14
12
|
from xync_bot.routers.pay import cd, dep, window
|
|
15
13
|
|
|
16
14
|
pay = Router()
|
|
@@ -37,7 +35,7 @@ async def h_got_fiat_type(query: CallbackQuery, bot: PGram):
|
|
|
37
35
|
async def h_got_crypto_type(query: CallbackQuery, bot: PGram):
|
|
38
36
|
"""Step 2c: Select coin"""
|
|
39
37
|
bot.store.curr.is_fiat = False
|
|
40
|
-
|
|
38
|
+
bot.store.perm.actors, *_ = await gather(
|
|
41
39
|
fill_actors(bot.store.perm.user.person_id), window.coin_select(query.message), ans(query, "Понял, крипта")
|
|
42
40
|
)
|
|
43
41
|
|
|
@@ -92,7 +90,8 @@ async def h_got_cred_name(msg: Message, state: FSMContext):
|
|
|
92
90
|
person_id=store.perm.user.person_id,
|
|
93
91
|
pmcur_id=store.pay.t_pmcur_id,
|
|
94
92
|
)
|
|
95
|
-
|
|
93
|
+
store.pay.cred_id = cred.id
|
|
94
|
+
store.perm.creds[cred.id] = cred
|
|
96
95
|
await gather(window.amount(msg), dlt(msg), state.set_state(dep.PaymentState.amount))
|
|
97
96
|
|
|
98
97
|
|
|
@@ -102,11 +101,15 @@ async def h_got_ex(query: CallbackQuery, callback_data: cd.Ex, state: FSMContext
|
|
|
102
101
|
store: Store = query.message.bot.store
|
|
103
102
|
ist = store.curr.is_target
|
|
104
103
|
setattr(store.pay, ("t" if ist else "s") + "_ex_id", callback_data.id)
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
104
|
+
if ist:
|
|
105
|
+
await window.amount(query.message)
|
|
106
|
+
actor_id = store.perm.actors[store.pay.t_ex_id]
|
|
107
|
+
addr = await models.Addr.get(coin_id=store.pay.t_coin_id, actor_id=actor_id)
|
|
108
|
+
store.pay.addr_id = addr.id
|
|
109
|
+
else:
|
|
110
|
+
await window.set_ppo(query.message)
|
|
111
|
+
await ans(query, f"Биржа {store.glob.exs[callback_data.id]} выбрана")
|
|
112
|
+
await state.set_state(dep.PaymentState.amount)
|
|
110
113
|
|
|
111
114
|
|
|
112
115
|
@pay.message(dep.PaymentState.amount)
|
|
@@ -130,7 +133,7 @@ async def h_got_source_pm(query: CallbackQuery, callback_data: cd.Pm):
|
|
|
130
133
|
store.pay.s_pmcur_id = callback_data.pmcur_id
|
|
131
134
|
await gather(
|
|
132
135
|
window.set_ppo(query.message),
|
|
133
|
-
ans(query, store.glob.
|
|
136
|
+
ans(query, store.glob.pmcurs[callback_data.pmcur_id]),
|
|
134
137
|
)
|
|
135
138
|
|
|
136
139
|
|
|
@@ -141,39 +144,10 @@ async def h_got_ppo(query: CallbackQuery, callback_data: cd.Ppo):
|
|
|
141
144
|
|
|
142
145
|
|
|
143
146
|
@pay.callback_query(cd.Time.filter())
|
|
144
|
-
async def
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
if ex_id := (store.pay.t_ex_id or store.pay.s_ex_id):
|
|
150
|
-
actor_id = store.perm.ex_actors[ex_id]
|
|
151
|
-
if not (addr_id := store.pay.addr_id):
|
|
152
|
-
coin_id = store.pay.t_coin_id or store.pay.s_coin_id
|
|
153
|
-
addr_id = await models.Addr.get(coin_id=coin_id, actor_id=actor_id).values_list("id", flat=True)
|
|
154
|
-
store.pay.addr_id = addr_id
|
|
155
|
-
else:
|
|
156
|
-
addr_id = None
|
|
157
|
-
pr_data = dict(
|
|
158
|
-
pay_until=pay_until,
|
|
159
|
-
amount=store.pay.amount,
|
|
160
|
-
parts=store.pay.ppo,
|
|
161
|
-
payed_at=None,
|
|
162
|
-
addr_id=addr_id,
|
|
163
|
-
cred_id=store.pay.cred_id,
|
|
164
|
-
user=store.perm.user,
|
|
165
|
-
)
|
|
166
|
-
(pay_req, _), *__ = await gather(
|
|
167
|
-
models.PayReq.update_or_create(**pr_data), ans(query, None), state.set_state(dep.PaymentState.timer)
|
|
168
|
-
)
|
|
169
|
-
|
|
170
|
-
await state.update_data(
|
|
171
|
-
timer=callback_data.minutes,
|
|
172
|
-
timer_active=True,
|
|
173
|
-
pay_until=pay_until,
|
|
174
|
-
pay_req_id=pay_req.id,
|
|
175
|
-
)
|
|
176
|
-
create_task(window.run_timer(query.message, state))
|
|
147
|
+
async def h_got_urgency(query: CallbackQuery, callback_data: cd.Time):
|
|
148
|
+
query.message.bot.store.pay.urg = callback_data.minutes
|
|
149
|
+
await window.create_payreq(query.message)
|
|
150
|
+
await ans(query, f"Ok {callback_data.minutes} min.")
|
|
177
151
|
|
|
178
152
|
|
|
179
153
|
# ACTIONS
|
|
@@ -187,11 +161,8 @@ async def payment_confirmed(query: CallbackQuery, state: FSMContext):
|
|
|
187
161
|
pay_req = await models.PayReq.get(id=data["pay_req_id"])
|
|
188
162
|
pay_req.payed_at = payed_at
|
|
189
163
|
await pay_req.save()
|
|
190
|
-
|
|
191
|
-
builder = InlineKeyboardBuilder()
|
|
192
|
-
builder.button(text="Новый платеж💸", callback_data=cd.PayNav(to=cd.PayStep.t_type))
|
|
193
|
-
await query.message.answer("✅ Платеж успешно подтвержден", reply_markup=builder.as_markup())
|
|
194
164
|
await state.clear()
|
|
165
|
+
await window.success(query.message)
|
|
195
166
|
|
|
196
167
|
|
|
197
168
|
@pay.callback_query(cd.Action.filter(F.act.__eq__(cd.ActionType.not_received)))
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
from asyncio import sleep
|
|
2
|
+
from datetime import datetime, timedelta
|
|
2
3
|
|
|
3
4
|
from aiogram.fsm.context import FSMContext
|
|
4
5
|
from aiogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton
|
|
5
6
|
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
|
6
|
-
from
|
|
7
|
+
from xync_schema import models
|
|
8
|
+
|
|
9
|
+
from xync_bot.routers.pay.dep import edt, need_ppo, have_coin_amount, get_in, Store
|
|
7
10
|
|
|
8
|
-
from xync_bot import Store
|
|
9
11
|
from xync_bot.routers.pay import cd, dep
|
|
10
12
|
|
|
11
13
|
|
|
@@ -25,7 +27,16 @@ async def type_select(msg: Message):
|
|
|
25
27
|
]
|
|
26
28
|
]
|
|
27
29
|
)
|
|
28
|
-
|
|
30
|
+
if store.curr.is_target:
|
|
31
|
+
txt = "Что нужно?"
|
|
32
|
+
else:
|
|
33
|
+
if store.pay.t_coin_id:
|
|
34
|
+
inf = f"{store.glob.coins[store.pay.t_coin_id]} на {store.glob.exs[store.pay.t_ex_id]}:{store.pay.addr_id}"
|
|
35
|
+
else:
|
|
36
|
+
cur = store.glob.curs[store.pay.t_cur_id].ticker
|
|
37
|
+
cred: models.Cred = store.perm.creds[store.pay.cred_id]
|
|
38
|
+
inf = f"{cur} на {store.glob.pmcurs[store.pay.t_pmcur_id]}: {cred.repr()}"
|
|
39
|
+
txt = f"Нужен платеж: {store.pay.amount} {inf}\nЧем будете платить?"
|
|
29
40
|
if store.perm.msg_id:
|
|
30
41
|
await edt(msg, txt, rm)
|
|
31
42
|
else:
|
|
@@ -37,8 +48,8 @@ async def cur_select(msg: Message):
|
|
|
37
48
|
"""Common using cur func"""
|
|
38
49
|
builder = InlineKeyboardBuilder()
|
|
39
50
|
ist: bool = msg.bot.store.curr.is_target
|
|
40
|
-
for cur_id,
|
|
41
|
-
builder.button(text=ticker + dep.flags[ticker], callback_data=cd.Cur(id=cur_id, is_target=ist))
|
|
51
|
+
for cur_id, cur in msg.bot.store.glob.curs.items():
|
|
52
|
+
builder.button(text=cur.ticker + dep.flags[cur.ticker], callback_data=cd.Cur(id=cur_id, is_target=ist))
|
|
42
53
|
builder.button(text="Назад к выбору типа", callback_data=cd.PayNav(to=cd.PayStep.t_type))
|
|
43
54
|
builder.adjust(3, 3, 3, 3, 3, 1)
|
|
44
55
|
sfx = "ую нужно" if ist else "ой платишь"
|
|
@@ -82,7 +93,7 @@ async def pm(msg: Message):
|
|
|
82
93
|
cur_id = getattr(store.pay, ("t" if ist else "s") + "_cur_id")
|
|
83
94
|
builder = InlineKeyboardBuilder()
|
|
84
95
|
for pmcur_id in store.glob.curpms[cur_id]:
|
|
85
|
-
builder.button(text=store.glob.
|
|
96
|
+
builder.button(text=store.glob.pmcurs[pmcur_id], callback_data=cd.Pm(pmcur_id=pmcur_id, is_target=ist))
|
|
86
97
|
builder.button(
|
|
87
98
|
text="Назад к выбору валюты", callback_data=cd.PayNav(to=cd.PayStep.t_cur if ist else cd.PayStep.s_cur)
|
|
88
99
|
)
|
|
@@ -99,10 +110,7 @@ async def fill_cred_dtl(msg: Message):
|
|
|
99
110
|
if cred_ids := store.perm.cur_creds.get(store.pay.t_pmcur_id):
|
|
100
111
|
for cred_id in cred_ids:
|
|
101
112
|
cred = store.perm.creds[cred_id]
|
|
102
|
-
|
|
103
|
-
if cred.extra:
|
|
104
|
-
txt += f" ({cred.extra})"
|
|
105
|
-
builder.button(text=txt, callback_data=cd.Cred(id=cred_id))
|
|
113
|
+
builder.button(text=cred.repr(), callback_data=cd.Cred(id=cred_id))
|
|
106
114
|
txt = "Выберите реквизиты куда нужно получить деньги, если в списке нет нужных, то\nв"
|
|
107
115
|
|
|
108
116
|
builder.button(text="Назад к выбору платежной системы", callback_data=cd.PayNav(to=cd.PayStep.t_pm))
|
|
@@ -110,7 +118,7 @@ async def fill_cred_dtl(msg: Message):
|
|
|
110
118
|
builder.adjust(2)
|
|
111
119
|
|
|
112
120
|
await msg.edit_text(
|
|
113
|
-
f"{txt}ведите номер для {store.glob.
|
|
121
|
+
f"{txt}ведите номер для {store.glob.pmcurs[store.pay.t_pmcur_id]}:", reply_markup=builder.as_markup()
|
|
114
122
|
)
|
|
115
123
|
|
|
116
124
|
|
|
@@ -121,9 +129,9 @@ async def fill_cred_name(msg: Message):
|
|
|
121
129
|
builder.adjust(2)
|
|
122
130
|
store: Store = msg.bot.store
|
|
123
131
|
cur = store.glob.curs[store.pay.t_cur_id]
|
|
124
|
-
payment = store.glob.
|
|
132
|
+
payment = store.glob.pmcurs[store.pay.t_pmcur_id]
|
|
125
133
|
detail = store.pay.cred_dtl
|
|
126
|
-
await edt(msg, f"{cur}:{payment}:{detail}: Введите имя получателя", builder.as_markup())
|
|
134
|
+
await edt(msg, f"{cur.ticker}:{payment}:{detail}: Введите имя получателя", builder.as_markup())
|
|
127
135
|
|
|
128
136
|
|
|
129
137
|
async def amount(msg: Message):
|
|
@@ -131,9 +139,9 @@ async def amount(msg: Message):
|
|
|
131
139
|
builder = InlineKeyboardBuilder()
|
|
132
140
|
store: Store = msg.bot.store
|
|
133
141
|
if store.curr.is_fiat:
|
|
134
|
-
cur_coin = store.glob.curs[store.pay.t_cur_id]
|
|
142
|
+
cur_coin = store.glob.curs[store.pay.t_cur_id].ticker
|
|
135
143
|
builder.button(text="Назад к вводу имени", callback_data=cd.PayNav(to=cd.PayStep.t_cred_name))
|
|
136
|
-
t_name = store.glob.
|
|
144
|
+
t_name = store.glob.pmcurs[store.pay.t_pmcur_id]
|
|
137
145
|
else:
|
|
138
146
|
cur_coin = store.glob.coins[store.pay.t_coin_id]
|
|
139
147
|
builder.button(text="Назад к выбору биржи", callback_data=cd.PayNav(to=cd.PayStep.t_ex))
|
|
@@ -146,29 +154,62 @@ async def amount(msg: Message):
|
|
|
146
154
|
|
|
147
155
|
|
|
148
156
|
async def set_ppo(msg: Message):
|
|
157
|
+
store: Store = msg.bot.store
|
|
158
|
+
ist = store.curr.is_target
|
|
159
|
+
if nppo := await need_ppo(store):
|
|
160
|
+
builder = InlineKeyboardBuilder()
|
|
161
|
+
builder.button(text="Нет", callback_data=cd.Ppo(num=1, is_target=ist)).button(
|
|
162
|
+
text="Да", callback_data=cd.Ppo(num=2, is_target=ist)
|
|
163
|
+
)
|
|
164
|
+
if nppo > 1:
|
|
165
|
+
builder.button(text="Да хоть 3мя", callback_data=cd.Ppo(num=3, is_target=ist))
|
|
166
|
+
builder.adjust(2)
|
|
167
|
+
await edt(msg, f"2мя платежами сможете {'принять' if ist else 'отравить'}?", builder.as_markup())
|
|
168
|
+
elif ist:
|
|
169
|
+
store.curr.is_target = False
|
|
170
|
+
await type_select(msg)
|
|
171
|
+
else:
|
|
172
|
+
await set_urgency(msg)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
async def set_urgency(msg: Message):
|
|
176
|
+
store: Store = msg.bot.store
|
|
177
|
+
if not store.curr.is_fiat or have_coin_amount(store):
|
|
178
|
+
return await create_payreq(msg) # next
|
|
179
|
+
builder = InlineKeyboardBuilder()
|
|
180
|
+
(
|
|
181
|
+
builder.button(text="1 мин", callback_data=cd.Time(minutes=1))
|
|
182
|
+
.button(text="5 мин", callback_data=cd.Time(minutes=5))
|
|
183
|
+
.button(text="30 мин", callback_data=cd.Time(minutes=30))
|
|
184
|
+
.button(text="3 часа", callback_data=cd.Time(minutes=180))
|
|
185
|
+
.button(text="сутки", callback_data=cd.Time(minutes=60 * 24))
|
|
186
|
+
.button(text="Назад к вводу платежей", callback_data=cd.PayNav(to=cd.PayStep.t_pm))
|
|
187
|
+
.button(text="Домой", callback_data=cd.PayNav(to=cd.PayStep.t_type))
|
|
188
|
+
.adjust(2, 2, 1, 1, 1)
|
|
189
|
+
)
|
|
190
|
+
return await edt(msg, "Сколько можешь ждать?", builder.as_markup())
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
async def create_payreq(msg: Message):
|
|
194
|
+
store: Store = msg.bot.store
|
|
195
|
+
pay_req, _ = await models.PayReq.update_or_create(
|
|
196
|
+
{"pay_until": datetime.now() + timedelta(minutes=store.pay.urg)},
|
|
197
|
+
amount=store.pay.amount,
|
|
198
|
+
parts=store.pay.ppo,
|
|
199
|
+
addr_id=store.pay.addr_id,
|
|
200
|
+
cred_id=store.pay.cred_id,
|
|
201
|
+
user=store.perm.user,
|
|
202
|
+
)
|
|
203
|
+
store.pay.pr_id = pay_req.id
|
|
204
|
+
inp, txt = await get_in(store)
|
|
149
205
|
rm = InlineKeyboardMarkup(
|
|
150
206
|
inline_keyboard=[
|
|
151
|
-
[
|
|
152
|
-
InlineKeyboardButton(text="Нет", callback_data="ppo:1"),
|
|
153
|
-
InlineKeyboardButton(text="Да", callback_data="ppo:2"),
|
|
154
|
-
],
|
|
155
|
-
[InlineKeyboardButton(text="Да хоть на 3", callback_data="ppo:3")],
|
|
207
|
+
[InlineKeyboardButton(text="Отправил", callback_data=cd.Action(act=cd.ActionType.sent).pack())],
|
|
156
208
|
]
|
|
157
209
|
)
|
|
158
|
-
await msg.
|
|
210
|
+
await edt(msg, f"Отправь {store.pay.amount}" + txt, rm.as_markup())
|
|
159
211
|
|
|
160
|
-
|
|
161
|
-
async def set_urgency(msg: Message):
|
|
162
|
-
builder = InlineKeyboardBuilder()
|
|
163
|
-
builder.button(text="1 мин", callback_data=cd.Time(minutes=1))
|
|
164
|
-
builder.button(text="5 мин", callback_data=cd.Time(minutes=5))
|
|
165
|
-
builder.button(text="30 мин", callback_data=cd.Time(minutes=30))
|
|
166
|
-
builder.button(text="3 часа", callback_data=cd.Time(minutes=180))
|
|
167
|
-
builder.button(text="сутки", callback_data=cd.Time(minutes=60 * 24))
|
|
168
|
-
builder.button(text="Назад к вводу платежей", callback_data=cd.PayNav(to=cd.PayStep.t_pm))
|
|
169
|
-
builder.button(text="Домой", callback_data=cd.PayNav(to=cd.PayStep.t_type))
|
|
170
|
-
builder.adjust(2, 2, 1, 1, 1)
|
|
171
|
-
await msg.edit_text("Сколько можешь ждать?", reply_markup=builder.as_markup())
|
|
212
|
+
# create_task(window.run_timer(msg))
|
|
172
213
|
|
|
173
214
|
|
|
174
215
|
async def run_timer(message, state: FSMContext):
|
|
@@ -215,3 +256,12 @@ async def run_timer(message, state: FSMContext):
|
|
|
215
256
|
await message.edit_text("⏳ Время вышло!", reply_markup=builder.as_markup())
|
|
216
257
|
except Exception:
|
|
217
258
|
pass
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
async def success(msg: Message):
|
|
262
|
+
rm = InlineKeyboardMarkup(
|
|
263
|
+
inline_keyboard=[
|
|
264
|
+
[InlineKeyboardButton(text="Новый платеж💸", callback_data=cd.PayNav(to=cd.PayStep.t_type).pack())]
|
|
265
|
+
]
|
|
266
|
+
)
|
|
267
|
+
await msg.edit_text("✅ Платеж успешно подтвержден", reply_markup=rm)
|
|
File without changes
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
from aiogram.types import Message
|
|
2
|
-
from tortoise.functions import Min
|
|
3
|
-
from x_model.func import ArrayAgg
|
|
4
|
-
from xync_schema import models
|
|
5
|
-
|
|
6
|
-
from xync_bot.routers.pay.dep import flags
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class SingleStore(type):
|
|
10
|
-
_store = None
|
|
11
|
-
|
|
12
|
-
async def __call__(cls):
|
|
13
|
-
if not cls._store:
|
|
14
|
-
cls._store = super(SingleStore, cls).__call__()
|
|
15
|
-
cls._store.coins = {k: v for k, v in await models.Coin.all().order_by("ticker").values_list("id", "ticker")}
|
|
16
|
-
curs = {
|
|
17
|
-
k: v
|
|
18
|
-
for k, v in await models.Cur.filter(ticker__in=flags.keys())
|
|
19
|
-
.order_by("ticker")
|
|
20
|
-
.values_list("id", "ticker")
|
|
21
|
-
}
|
|
22
|
-
cls._store.curs = curs
|
|
23
|
-
cls._store.exs = {k: v for k, v in await models.Ex.all().values_list("id", "name")}
|
|
24
|
-
cls._store.pms = {
|
|
25
|
-
k: v
|
|
26
|
-
for k, v in await models.Pmex.filter(pm__pmcurs__cur_id__in=cls._store.curs.keys())
|
|
27
|
-
.annotate(sname=Min("name"))
|
|
28
|
-
.group_by("pm__pmcurs__id")
|
|
29
|
-
.values_list("pm__pmcurs__id", "sname")
|
|
30
|
-
}
|
|
31
|
-
cls._store.coinexs = {
|
|
32
|
-
c.id: [ex.ex_id for ex in c.coinexs] for c in await models.Coin.all().prefetch_related("coinexs")
|
|
33
|
-
}
|
|
34
|
-
cls._store.curpms = {
|
|
35
|
-
cur_id: ids
|
|
36
|
-
for cur_id, ids in await models.Pmcur.filter(cur_id__in=curs.keys())
|
|
37
|
-
.annotate(ids=ArrayAgg("id"))
|
|
38
|
-
.group_by("cur_id")
|
|
39
|
-
.values_list("cur_id", "ids")
|
|
40
|
-
}
|
|
41
|
-
cls._store.curpms = {
|
|
42
|
-
cur_id: ids
|
|
43
|
-
for cur_id, ids in await models.Pmcur.filter(cur_id__in=curs.keys())
|
|
44
|
-
.annotate(ids=ArrayAgg("id"))
|
|
45
|
-
.group_by("cur_id")
|
|
46
|
-
.values_list("cur_id", "ids")
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return cls._store
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
class Store:
|
|
53
|
-
class Global(metaclass=SingleStore):
|
|
54
|
-
coins: dict[int, str] # id:ticker
|
|
55
|
-
curs: dict[int, str] # id:ticker
|
|
56
|
-
exs: dict[int, str] # id:name
|
|
57
|
-
coinexs: dict[int, list[int]] # id:[ex_ids]
|
|
58
|
-
pms: dict[int, str] # pmcur_id:name
|
|
59
|
-
curpms: dict[int, list[int]] # id:[pmcur_ids]
|
|
60
|
-
|
|
61
|
-
class Permanent:
|
|
62
|
-
msg_id: int = None
|
|
63
|
-
user: models.User = None
|
|
64
|
-
actors: dict[int, models.Actor] = None # key=actor_id
|
|
65
|
-
ex_actors: dict[int, list[int]] = None # key=ex_id
|
|
66
|
-
creds: dict[int, models.Cred] = None # key=cred_id
|
|
67
|
-
cur_creds: dict[int, list[int]] = None # pmcur_id:[cred_ids]
|
|
68
|
-
|
|
69
|
-
class Current:
|
|
70
|
-
is_target: bool = None
|
|
71
|
-
is_fiat: bool = None
|
|
72
|
-
msg_to_del: Message = None
|
|
73
|
-
|
|
74
|
-
class Payment:
|
|
75
|
-
t_cur_id: int = None
|
|
76
|
-
s_cur_id: int = None
|
|
77
|
-
t_coin_id: int = None
|
|
78
|
-
s_coin_id: int = None
|
|
79
|
-
t_pmcur_id: int = None
|
|
80
|
-
s_pmcur_id: int = None
|
|
81
|
-
t_ex_id: int = None
|
|
82
|
-
s_ex_id: int = None
|
|
83
|
-
amount: int | float = None
|
|
84
|
-
ppo: int = None
|
|
85
|
-
addr_id: int = None
|
|
86
|
-
cred_dtl: str = None
|
|
87
|
-
cred_id: int = None
|
|
88
|
-
|
|
89
|
-
glob: Global
|
|
90
|
-
perm: Permanent = Permanent()
|
|
91
|
-
pay: Payment = Payment()
|
|
92
|
-
curr: Current = Current()
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
from asyncio import gather
|
|
2
|
-
from enum import IntEnum
|
|
3
|
-
|
|
4
|
-
from aiogram.exceptions import TelegramBadRequest
|
|
5
|
-
from aiogram.fsm.state import StatesGroup, State
|
|
6
|
-
from aiogram.types import Message, InlineKeyboardMarkup
|
|
7
|
-
from pyrogram.types import CallbackQuery
|
|
8
|
-
from x_model.func import ArrayAgg
|
|
9
|
-
from xync_schema import models
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class Report(StatesGroup):
|
|
13
|
-
text = State()
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class CredState(StatesGroup):
|
|
17
|
-
detail = State()
|
|
18
|
-
name = State()
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class PaymentState(StatesGroup):
|
|
22
|
-
amount = State()
|
|
23
|
-
timer = State()
|
|
24
|
-
timer_active = State()
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
class ActionType(IntEnum):
|
|
28
|
-
"""Цель (назначение) платежа (target)"""
|
|
29
|
-
|
|
30
|
-
sent = 1 # Отправил
|
|
31
|
-
received = 2 # Получил
|
|
32
|
-
not_received = 3 # Не получил
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
class PayStep(IntEnum):
|
|
36
|
-
"""Цель (назначение) платежа (target)"""
|
|
37
|
-
|
|
38
|
-
t_type = 1 # Выбор типа
|
|
39
|
-
t_cur = 2 # Выбор валюты
|
|
40
|
-
t_coin = 3 # Выбор монеты
|
|
41
|
-
t_pm = 4 # Выбор платежки
|
|
42
|
-
t_ex = 5 # Выбор биржи
|
|
43
|
-
t_cred_dtl = 6 # Ввод номера карты
|
|
44
|
-
t_cred_name = 7 # Ввод имени
|
|
45
|
-
# t_addr = 8 # todo: позже добавим: Выбор/ввод крипто кошелька
|
|
46
|
-
t_amount = 9 # Ввод суммы
|
|
47
|
-
""" Источник платежа (source) """
|
|
48
|
-
s_type = 10 # Выбор типа
|
|
49
|
-
s_cur = 11 # Выбор типа
|
|
50
|
-
s_pm = 12 # Выбор типа
|
|
51
|
-
s_coin = 13 # Выбор типа
|
|
52
|
-
s_ex = 14 # Выбор типа
|
|
53
|
-
ppo = 15 # Выбор возможности разбивки платежа
|
|
54
|
-
urgency = 16 # Выбор срочности получения платежа
|
|
55
|
-
pending_send = 17 # Ожидание отправки (если мы платим фиатом)
|
|
56
|
-
pending_confirm = 18 # Ожидание пока на той стороне подтвердят получение нашего фиата (если мы платим фиатом)
|
|
57
|
-
pending_receive = 19 # Ожидание поступления (если мы получаем фиат)
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
flags = {
|
|
61
|
-
"RUB": "🇷🇺",
|
|
62
|
-
"THB": "🇹🇭",
|
|
63
|
-
"IDR": "🇮🇩",
|
|
64
|
-
"TRY": "🇹🇷",
|
|
65
|
-
"GEL": "🇬🇪",
|
|
66
|
-
"VND": "🇻🇳",
|
|
67
|
-
"AED": "🇦🇪",
|
|
68
|
-
"AMD": "🇦🇲",
|
|
69
|
-
"AZN": "🇦🇿",
|
|
70
|
-
"CNY": "🇨🇳",
|
|
71
|
-
"EUR": "🇪🇺",
|
|
72
|
-
"HKD": "🇭🇰",
|
|
73
|
-
"INR": "🇮🇳",
|
|
74
|
-
"PHP": "🇵🇭",
|
|
75
|
-
"USD": "🇺🇸",
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
async def fill_creds(person_id: int) -> tuple[dict[int, models.Cred], dict[int, list[int]]]:
|
|
80
|
-
cq = models.Cred.filter(person_id=person_id)
|
|
81
|
-
creds = {c.id: c for c in await cq}
|
|
82
|
-
cur_creds = {
|
|
83
|
-
pci: ids
|
|
84
|
-
for pci, ids in await cq.annotate(ids=ArrayAgg("id")).group_by("pmcur_id").values_list("pmcur_id", "ids")
|
|
85
|
-
}
|
|
86
|
-
return creds, cur_creds
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
async def fill_actors(person_id: int) -> tuple[dict[int, models.Actor], dict[int, list[int]]]:
|
|
90
|
-
aq = models.Actor.filter(person_id=person_id)
|
|
91
|
-
actors = {a.id: a for a in await aq}
|
|
92
|
-
ex_act_id = {
|
|
93
|
-
exi: ids[0]
|
|
94
|
-
for exi, ids in await aq.annotate(ids=ArrayAgg("id")) # todo: check len(ids) == 1
|
|
95
|
-
.group_by("ex_id")
|
|
96
|
-
.values_list("ex_id", "ids")
|
|
97
|
-
}
|
|
98
|
-
return actors, ex_act_id
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
async def edit(msg: Message, txt: str, rm: InlineKeyboardMarkup):
|
|
102
|
-
await gather(msg.edit_text(txt), msg.edit_reply_markup(reply_markup=rm))
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
async def ans(cbq: CallbackQuery, txt: str = None):
|
|
106
|
-
await cbq.answer(txt, cache_time=99)
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
async def dlt(msg: Message):
|
|
110
|
-
await msg.delete()
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
async def edt(msg: Message, txt: str, rm: InlineKeyboardMarkup):
|
|
114
|
-
if msg.message_id == msg.bot.store.perm.msg_id:
|
|
115
|
-
await msg.edit_text(txt, reply_markup=rm)
|
|
116
|
-
else: # окно вызвано в ответ на текст, а не кнопку
|
|
117
|
-
try:
|
|
118
|
-
await msg.bot.edit_message_text(
|
|
119
|
-
txt, chat_id=msg.chat.id, message_id=msg.bot.store.perm.msg_id, reply_markup=rm
|
|
120
|
-
)
|
|
121
|
-
except TelegramBadRequest as e:
|
|
122
|
-
print(msg.bot.store.perm.msg_id, e)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/xync_bot-0.3.24.dev8/xync_bot/typs.py → /xync_bot-0.3.24.dev11/xync_bot/routers/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|