xync-bot 0.3.24.dev3__tar.gz → 0.3.24.dev5__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.dev3/xync_bot.egg-info → xync_bot-0.3.24.dev5}/PKG-INFO +1 -1
- xync_bot-0.3.24.dev5/xync_bot/routers/__init__.py +92 -0
- {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot/routers/pay/cd.py +1 -3
- {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot/routers/pay/dep.py +45 -0
- {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot/routers/pay/handler.py +111 -117
- xync_bot-0.3.24.dev5/xync_bot/routers/pay/window.py +217 -0
- {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5/xync_bot.egg-info}/PKG-INFO +1 -1
- xync_bot-0.3.24.dev3/xync_bot/routers/__init__.py +0 -64
- xync_bot-0.3.24.dev3/xync_bot/routers/pay/window.py +0 -232
- {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/.env.dist +0 -0
- {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/.gitignore +0 -0
- {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/.pre-commit-config.yaml +0 -0
- {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/makefile +0 -0
- {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/pyproject.toml +0 -0
- {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/setup.cfg +0 -0
- {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/test_main.http +0 -0
- {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot/__init__.py +0 -0
- {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot/loader.py +0 -0
- {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot/routers/cond/__init__.py +0 -0
- {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot/routers/cond/func.py +0 -0
- {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot/routers/main.py +0 -0
- {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot/routers/order.py +0 -0
- {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot/routers/photo.py +0 -0
- {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot/routers/vpn.py +0 -0
- {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot/routers/xicon.png +0 -0
- {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot/shared.py +0 -0
- {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot/typs.py +0 -0
- {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot.egg-info/SOURCES.txt +0 -0
- {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot.egg-info/dependency_links.txt +0 -0
- {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot.egg-info/requires.txt +0 -0
- {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,92 @@
|
|
|
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=ex_id
|
|
65
|
+
ex_actors: dict[int, list[int]] = None # key=ex_id
|
|
66
|
+
creds: dict[int, models.Cred] = None # key=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()
|
|
@@ -3,7 +3,7 @@ from aiogram.filters.callback_data import CallbackData
|
|
|
3
3
|
from xync_bot.routers.pay.dep import PayStep, ActionType
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
class
|
|
6
|
+
class MoneyType(CallbackData, prefix="target"):
|
|
7
7
|
is_fiat: int # bool
|
|
8
8
|
is_target: int # bool
|
|
9
9
|
|
|
@@ -24,13 +24,11 @@ class Cred(CallbackData, prefix="cred"):
|
|
|
24
24
|
|
|
25
25
|
class Ex(CallbackData, prefix="ex"):
|
|
26
26
|
id: int
|
|
27
|
-
name: str
|
|
28
27
|
is_target: int # bool
|
|
29
28
|
|
|
30
29
|
|
|
31
30
|
class Pm(CallbackData, prefix="pm"):
|
|
32
31
|
pmcur_id: int
|
|
33
|
-
name: str
|
|
34
32
|
is_target: bool
|
|
35
33
|
|
|
36
34
|
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
+
from asyncio import gather
|
|
1
2
|
from enum import IntEnum
|
|
2
3
|
|
|
3
4
|
from aiogram.fsm.state import StatesGroup, State
|
|
5
|
+
from aiogram.types import Message, InlineKeyboardMarkup
|
|
6
|
+
from pyrogram.types import CallbackQuery
|
|
7
|
+
from x_model.func import ArrayAgg
|
|
8
|
+
from xync_schema import models
|
|
4
9
|
|
|
5
10
|
|
|
6
11
|
class Report(StatesGroup):
|
|
@@ -68,3 +73,43 @@ flags = {
|
|
|
68
73
|
"PHP": "🇵🇭",
|
|
69
74
|
"USD": "🇺🇸",
|
|
70
75
|
}
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
async def fill_creds(person_id: int) -> tuple[dict[int, models.Cred], dict[int, list[int]]]:
|
|
79
|
+
cq = models.Cred.filter(person_id=person_id)
|
|
80
|
+
creds = {c.id: c for c in await cq}
|
|
81
|
+
cur_creds = {
|
|
82
|
+
pci: ids
|
|
83
|
+
for pci, ids in await cq.annotate(ids=ArrayAgg("id")).group_by("pmcur_id").values_list("pmcur_id", "ids")
|
|
84
|
+
}
|
|
85
|
+
return creds, cur_creds
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
async def fill_actors(person_id: int) -> tuple[dict[int, models.Actor], dict[int, list[int]]]:
|
|
89
|
+
aq = models.Actor.filter(person_id=person_id)
|
|
90
|
+
actors = {a.id: a for a in await aq}
|
|
91
|
+
ex_act_ids = {
|
|
92
|
+
exi: ids for exi, ids in await aq.annotate(ids=ArrayAgg("id")).group_by("ex_id").values_list("ex_id", "ids")
|
|
93
|
+
}
|
|
94
|
+
return actors, ex_act_ids
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
async def edit(msg: Message, txt: str, rm: InlineKeyboardMarkup):
|
|
98
|
+
await gather(msg.edit_text(txt), msg.edit_reply_markup(reply_markup=rm))
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
async def ans(cbq: CallbackQuery, txt: str = None):
|
|
102
|
+
await cbq.answer(txt, cache_time=99)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
async def dlt(msg: Message):
|
|
106
|
+
await msg.delete()
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
async def edt(msg: Message, txt: str, rm: InlineKeyboardMarkup):
|
|
110
|
+
if msg.message_id == msg.bot.store.perm.msg_id:
|
|
111
|
+
await msg.edit_text(txt, reply_markup=rm)
|
|
112
|
+
else: # окно вызвано в ответ на текст, а не кнопку
|
|
113
|
+
await msg.bot.edit_message_text(txt, chat_id=msg.chat.id, message_id=msg.bot.store.perm.msg_id, reply_markup=rm)
|
|
114
|
+
|
|
115
|
+
await msg.edit_text(txt, reply_markup=rm)
|
|
@@ -1,190 +1,184 @@
|
|
|
1
|
-
from asyncio import create_task
|
|
1
|
+
from asyncio import create_task, gather
|
|
2
2
|
from datetime import timedelta, datetime
|
|
3
|
+
|
|
4
|
+
import PGram
|
|
3
5
|
from aiogram import Router, F
|
|
4
6
|
from aiogram.filters import Command
|
|
5
7
|
from aiogram.types import Message, CallbackQuery
|
|
6
8
|
from aiogram.fsm.context import FSMContext
|
|
9
|
+
from xync_bot.routers.pay.dep import fill_creds, fill_actors, dlt, ans
|
|
7
10
|
from xync_schema import models
|
|
8
11
|
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
|
12
|
+
|
|
13
|
+
from xync_bot import Store
|
|
9
14
|
from xync_bot.routers.pay import cd, dep, window
|
|
10
15
|
|
|
11
16
|
pay = Router()
|
|
12
17
|
|
|
13
18
|
|
|
14
19
|
@pay.message(Command("pay"))
|
|
15
|
-
async def h_start(msg: Message
|
|
20
|
+
async def h_start(msg: Message):
|
|
16
21
|
"""Step 1: Select target type"""
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
await window.type_select(msg,
|
|
22
|
+
store: Store = msg.bot.store
|
|
23
|
+
store.curr.is_target = True
|
|
24
|
+
await gather(window.type_select(msg), dlt(msg))
|
|
25
|
+
store.perm.user = await models.User.get(username_id=msg.from_user.id)
|
|
26
|
+
store.perm.creds, store.perm.cur_creds = await fill_creds(store.perm.user.person_id)
|
|
20
27
|
|
|
21
28
|
|
|
22
|
-
@pay.callback_query(cd.
|
|
23
|
-
async def h_got_fiat_type(query: CallbackQuery,
|
|
29
|
+
@pay.callback_query(cd.MoneyType.filter(F.is_fiat))
|
|
30
|
+
async def h_got_fiat_type(query: CallbackQuery, bot: PGram):
|
|
24
31
|
"""Step 2f: Select cur"""
|
|
25
|
-
|
|
26
|
-
await
|
|
27
|
-
await query.answer("Понял, фиат")
|
|
28
|
-
await window.cur_select(query.message, state)
|
|
32
|
+
bot.store.curr.is_fiat = True
|
|
33
|
+
await gather(window.cur_select(query.message), ans(query, "Понял, фиат"))
|
|
29
34
|
|
|
30
35
|
|
|
31
|
-
@pay.callback_query(cd.
|
|
32
|
-
async def h_got_crypto_type(query: CallbackQuery,
|
|
36
|
+
@pay.callback_query(cd.MoneyType.filter(F.is_fiat.__eq__(0)))
|
|
37
|
+
async def h_got_crypto_type(query: CallbackQuery, bot: PGram):
|
|
33
38
|
"""Step 2c: Select coin"""
|
|
34
|
-
|
|
35
|
-
await
|
|
36
|
-
|
|
37
|
-
|
|
39
|
+
bot.store.curr.is_fiat = False
|
|
40
|
+
(bot.store.perm.actors, bot.store.perm.cur_creds), *_ = await gather(
|
|
41
|
+
fill_actors(bot.store.perm.user.person_id), window.coin_select(query.message), ans(query, "Понял, крипта")
|
|
42
|
+
)
|
|
38
43
|
|
|
39
44
|
|
|
40
45
|
@pay.callback_query(cd.Coin.filter())
|
|
41
|
-
async def h_got_coin(query: CallbackQuery, callback_data: cd.Coin,
|
|
46
|
+
async def h_got_coin(query: CallbackQuery, callback_data: cd.Coin, bot: PGram):
|
|
42
47
|
"""Step 3c: Select target ex"""
|
|
43
|
-
|
|
44
|
-
await
|
|
45
|
-
await query.answer("Эта монета есть на следующих биржах")
|
|
46
|
-
await window.ex_select(query.message, state)
|
|
48
|
+
setattr(bot.store.pay, ("t" if bot.store.curr.is_target else "s") + "_coin_id", callback_data.id)
|
|
49
|
+
await gather(window.ex_select(query.message), ans(query, "Эта монета есть на следующих биржах"))
|
|
47
50
|
|
|
48
51
|
|
|
49
52
|
@pay.callback_query(cd.Cur.filter())
|
|
50
|
-
async def h_got_cur(query: CallbackQuery, callback_data: cd.Cur,
|
|
53
|
+
async def h_got_cur(query: CallbackQuery, callback_data: cd.Cur, bot: PGram):
|
|
51
54
|
"""Step 3f: Select target pm"""
|
|
52
|
-
|
|
53
|
-
await
|
|
54
|
-
await query.answer("Вот платежные системы доступные для этой валюты")
|
|
55
|
-
await window.pm(query.message, state)
|
|
55
|
+
setattr(bot.store.pay, ("t" if bot.store.curr.is_target else "s") + "_cur_id", callback_data.id)
|
|
56
|
+
await gather(window.pm(query.message), ans(query, "Вот платежные системы доступные для этой валюты"))
|
|
56
57
|
|
|
57
58
|
|
|
58
59
|
@pay.callback_query(cd.Pm.filter(F.is_target))
|
|
59
60
|
async def h_got_target_pm(query: CallbackQuery, callback_data: cd.Pm, state: FSMContext):
|
|
60
61
|
"""Step 4f: Fill target cred.detail"""
|
|
61
|
-
|
|
62
|
-
await
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
query.message.bot.store.pay.t_pmcur_id = callback_data.pmcur_id
|
|
63
|
+
await gather(
|
|
64
|
+
window.fill_cred_dtl(query.message),
|
|
65
|
+
ans(query, "Теперь нужны реквизиты"),
|
|
66
|
+
state.set_state(dep.CredState.detail),
|
|
67
|
+
)
|
|
65
68
|
|
|
66
69
|
|
|
67
70
|
@pay.callback_query(cd.Cred.filter())
|
|
68
71
|
async def h_got_cred(query: CallbackQuery, callback_data: cd.Cred, state: FSMContext):
|
|
69
|
-
|
|
70
|
-
await
|
|
71
|
-
|
|
72
|
-
|
|
72
|
+
query.message.bot.store.pay.cred_id = callback_data.id
|
|
73
|
+
await gather(
|
|
74
|
+
window.amount(query.message), ans(query, "Теперь нужна сумма"), state.set_state(dep.PaymentState.amount)
|
|
75
|
+
)
|
|
73
76
|
|
|
74
77
|
|
|
75
78
|
@pay.message(dep.CredState.detail)
|
|
76
79
|
async def h_got_cred_dtl(msg: Message, state: FSMContext):
|
|
77
80
|
"""Step 4.1f: Fill target cred.name"""
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
await state.update_data(detail=int(msg.text))
|
|
81
|
-
break
|
|
82
|
-
else:
|
|
83
|
-
await msg.answer("Пожалуйста, введите корректное число")
|
|
84
|
-
return
|
|
85
|
-
await window.fill_cred_name(msg, state)
|
|
81
|
+
msg.bot.store.pay.cred_dtl = msg.text
|
|
82
|
+
await gather(window.fill_cred_name(msg), dlt(msg), state.set_state(dep.CredState.name))
|
|
86
83
|
|
|
87
84
|
|
|
88
85
|
@pay.message(dep.CredState.name)
|
|
89
86
|
async def h_got_cred_name(msg: Message, state: FSMContext):
|
|
90
87
|
"""Step 5f: Save target cred"""
|
|
91
|
-
|
|
92
|
-
await state.set_state(None)
|
|
88
|
+
store: Store = msg.bot.store
|
|
93
89
|
cred, _ = await models.Cred.update_or_create(
|
|
94
|
-
{"name": msg.text},
|
|
90
|
+
{"name": msg.text},
|
|
91
|
+
detail=store.pay.cred_dtl,
|
|
92
|
+
person_id=store.perm.user.person_id,
|
|
93
|
+
pmcur_id=store.pay.t_pmcur_id,
|
|
95
94
|
)
|
|
96
|
-
|
|
97
|
-
await window.amount(msg, state)
|
|
95
|
+
msg.bot.store.pay.cred_id = cred.id
|
|
96
|
+
await gather(window.amount(msg), dlt(msg), state.set_state(dep.PaymentState.amount))
|
|
98
97
|
|
|
99
98
|
|
|
100
99
|
@pay.callback_query(cd.Ex.filter())
|
|
101
|
-
async def h_got_ex(query: CallbackQuery, callback_data: cd.Ex
|
|
100
|
+
async def h_got_ex(query: CallbackQuery, callback_data: cd.Ex):
|
|
102
101
|
"""Step 4c: Save target"""
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
await
|
|
107
|
-
|
|
108
|
-
|
|
102
|
+
store: Store = query.message.bot.store
|
|
103
|
+
ist = store.curr.is_target
|
|
104
|
+
setattr(store, ("t" if ist else "s") + "_ex_id", callback_data.id)
|
|
105
|
+
await gather(
|
|
106
|
+
(window.amount if ist else window.set_ppo)(query.message),
|
|
107
|
+
ans(query, f"Биржа {store.glob.exs[callback_data.id]} выбрана"),
|
|
108
|
+
)
|
|
109
109
|
|
|
110
110
|
|
|
111
111
|
@pay.message(dep.PaymentState.amount)
|
|
112
112
|
async def h_got_amount(msg: Message, state: FSMContext):
|
|
113
113
|
"""Step 6: Save target amount"""
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
await state.set_state(None)
|
|
114
|
+
store: Store = msg.bot.store
|
|
115
|
+
if not msg.text.isnumeric():
|
|
116
|
+
store.curr.msg_to_del = await msg.answer("Пожалуйста, введите корректное число")
|
|
117
|
+
return
|
|
118
|
+
if store.curr.msg_to_del:
|
|
119
|
+
await store.curr.msg_to_del.delete()
|
|
120
|
+
store.pay.amount = float(msg.text)
|
|
122
121
|
"""Step 7: Select source type"""
|
|
123
|
-
|
|
124
|
-
if
|
|
125
|
-
await window.type_select(msg, False)
|
|
126
|
-
else:
|
|
127
|
-
await window.cur_select(msg, state) # сразу выбор валюты источника, тк если цель крипта
|
|
122
|
+
store.curr.is_target = False
|
|
123
|
+
await gather((window.type_select if store.curr.is_fiat else window.cur_select)(msg), dlt(msg), state.clear())
|
|
128
124
|
|
|
129
125
|
|
|
130
126
|
@pay.callback_query(cd.Pm.filter(F.is_target.__eq__(0)))
|
|
131
|
-
async def h_got_source_pm(query: CallbackQuery, callback_data: cd.Pm
|
|
132
|
-
|
|
133
|
-
await
|
|
134
|
-
|
|
135
|
-
|
|
127
|
+
async def h_got_source_pm(query: CallbackQuery, callback_data: cd.Pm):
|
|
128
|
+
query.message.bot.store.pay.s_pmcur_id = callback_data.pmcur_id
|
|
129
|
+
await gather(
|
|
130
|
+
window.set_ppo(query.message),
|
|
131
|
+
query.message.delete(),
|
|
132
|
+
ans(query, callback_data.name),
|
|
133
|
+
)
|
|
136
134
|
|
|
137
135
|
|
|
138
136
|
@pay.callback_query(cd.Ppo.filter())
|
|
139
|
-
async def h_got_ppo(query: CallbackQuery,
|
|
140
|
-
|
|
141
|
-
await
|
|
142
|
-
await query.answer(str(callback_data.num))
|
|
143
|
-
await window.set_urgency(query.message)
|
|
137
|
+
async def h_got_ppo(query: CallbackQuery, callback_data: cd.Ppo):
|
|
138
|
+
query.message.bot.store.pay.ppo = callback_data.num
|
|
139
|
+
await gather(window.set_urgency(query.message), query.message.delete(), ans(query, str(callback_data.num)))
|
|
144
140
|
|
|
145
141
|
|
|
146
142
|
@pay.callback_query(cd.Time.filter())
|
|
147
|
-
async def process_time_selection(
|
|
148
|
-
|
|
143
|
+
async def process_time_selection(query: CallbackQuery, callback_data: cd.Time, state: FSMContext):
|
|
144
|
+
store: Store = query.message.bot.store
|
|
145
|
+
|
|
149
146
|
pay_until = datetime.now() + timedelta(minutes=callback_data.minutes)
|
|
150
147
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
if not (
|
|
154
|
-
|
|
155
|
-
actor_id = await models.Actor.get(ex_id=ex_id, person_id=person_id).values_list("id", flat=True)
|
|
156
|
-
await state.update_data(actor_id=actor_id)
|
|
157
|
-
if not (addr_id := data.get("addr_id")):
|
|
158
|
-
coin_id = data.get("t_coin_id", data.get("s_coin_id"))
|
|
148
|
+
if ex_id := (store.pay.t_ex_id or store.pay.s_ex_id):
|
|
149
|
+
actor_id = store.perm.actors[ex_id]
|
|
150
|
+
if not (addr_id := store.pay.addr):
|
|
151
|
+
coin_id = store.pay.t_coin_id or store.pay.s_coin_id
|
|
159
152
|
addr_id = await models.Addr.get(coin_id=coin_id, actor_id=actor_id).values_list("id", flat=True)
|
|
160
|
-
|
|
153
|
+
store.pay.addr_id = addr_id
|
|
161
154
|
else:
|
|
162
155
|
addr_id = None
|
|
163
|
-
|
|
164
|
-
pay_req = await models.PayReq.create(
|
|
156
|
+
pr_data = dict(
|
|
165
157
|
pay_until=pay_until,
|
|
166
|
-
amount=
|
|
167
|
-
parts=
|
|
158
|
+
amount=store.pay.amount,
|
|
159
|
+
parts=store.pay.ppo,
|
|
168
160
|
payed_at=None,
|
|
169
161
|
addr_id=addr_id,
|
|
170
|
-
cred_id=
|
|
171
|
-
|
|
162
|
+
cred_id=store.pay.cred_id,
|
|
163
|
+
user=store.perm.user,
|
|
172
164
|
)
|
|
165
|
+
pay_req, *_ = await gather(
|
|
166
|
+
models.PayReq.create(**pr_data), ans(query, None), state.set_state(dep.PaymentState.timer)
|
|
167
|
+
)
|
|
168
|
+
|
|
173
169
|
await state.update_data(
|
|
174
170
|
timer=callback_data.minutes,
|
|
175
171
|
timer_active=True,
|
|
176
172
|
pay_until=pay_until,
|
|
177
173
|
pay_req_id=pay_req.id,
|
|
178
174
|
)
|
|
179
|
-
|
|
180
|
-
await state.set_state(dep.PaymentState.timer)
|
|
181
|
-
create_task(window.run_timer(callback.message, state))
|
|
175
|
+
create_task(window.run_timer(query.message, state))
|
|
182
176
|
|
|
183
177
|
|
|
184
178
|
# ACTIONS
|
|
185
179
|
@pay.callback_query(cd.Action.filter(F.act.__eq__(cd.ActionType.received)))
|
|
186
180
|
async def payment_confirmed(query: CallbackQuery, state: FSMContext):
|
|
187
|
-
await query
|
|
181
|
+
await ans(query, None)
|
|
188
182
|
payed_at = datetime.now()
|
|
189
183
|
await state.update_data(timer_active=False, payed_at_formatted=payed_at)
|
|
190
184
|
data = await state.get_data()
|
|
@@ -202,7 +196,7 @@ async def payment_confirmed(query: CallbackQuery, state: FSMContext):
|
|
|
202
196
|
|
|
203
197
|
@pay.callback_query(cd.Action.filter(F.act.__eq__(cd.ActionType.not_received)))
|
|
204
198
|
async def no_payment(query: CallbackQuery, state: FSMContext):
|
|
205
|
-
await query
|
|
199
|
+
await ans(query, None)
|
|
206
200
|
await state.update_data(timer_active=False)
|
|
207
201
|
await query.message.edit_text("Платеж не получен!")
|
|
208
202
|
await query.message.answer("укажите детали платежа")
|
|
@@ -227,73 +221,73 @@ async def payment_not_specified(msg: Message, state: FSMContext):
|
|
|
227
221
|
@pay.callback_query(cd.PayNav.filter(F.to.in_([cd.PayStep.t_type, cd.PayStep.s_type])))
|
|
228
222
|
async def handle_home(query: CallbackQuery, state: FSMContext):
|
|
229
223
|
await query.message.delete()
|
|
230
|
-
await query
|
|
224
|
+
await ans(query, None)
|
|
231
225
|
await window.type_select(query.message, await state.get_value("is_target"))
|
|
232
226
|
|
|
233
227
|
|
|
234
228
|
@pay.callback_query(cd.PayNav.filter(F.to.in_([cd.PayStep.t_coin, cd.PayStep.s_coin])))
|
|
235
229
|
async def to_coin_select(query: CallbackQuery, state: FSMContext):
|
|
236
230
|
await query.message.delete()
|
|
237
|
-
await query
|
|
231
|
+
await ans(query, None)
|
|
238
232
|
is_target = await state.get_value("is_target")
|
|
239
233
|
pref = "t" if is_target else "s"
|
|
240
234
|
await state.update_data({pref + "_ex_id": None, pref + "_coin_id": None})
|
|
241
|
-
await window.coin_select(query.message
|
|
235
|
+
await window.coin_select(query.message)
|
|
242
236
|
|
|
243
237
|
|
|
244
238
|
@pay.callback_query(cd.PayNav.filter(F.to.in_([cd.PayStep.t_cur, cd.PayStep.s_cur])))
|
|
245
239
|
async def to_cur_select(query: CallbackQuery, state: FSMContext):
|
|
246
240
|
await query.message.delete()
|
|
247
|
-
await query
|
|
241
|
+
await ans(query, None)
|
|
248
242
|
is_target = await state.get_value("is_target")
|
|
249
243
|
pref = "t" if is_target else "s"
|
|
250
244
|
await state.update_data({pref + "_pmcur_id": None, pref + "_cur_id": None})
|
|
251
|
-
await window.cur_select(query.message
|
|
245
|
+
await window.cur_select(query.message)
|
|
252
246
|
|
|
253
247
|
|
|
254
248
|
@pay.callback_query(cd.PayNav.filter(F.to.in_([cd.PayStep.t_pm, cd.PayStep.s_pm])))
|
|
255
249
|
async def to_pm_select(query: CallbackQuery, state: FSMContext):
|
|
256
250
|
await query.message.delete()
|
|
257
|
-
await query
|
|
258
|
-
await window.pm(query.message
|
|
251
|
+
await ans(query, None)
|
|
252
|
+
await window.pm(query.message)
|
|
259
253
|
|
|
260
254
|
|
|
261
255
|
@pay.callback_query(cd.PayNav.filter(F.to.__eq__(cd.PayStep.t_cred_dtl)))
|
|
262
256
|
async def back_to_cred_detail(query: CallbackQuery, state: FSMContext):
|
|
263
|
-
await query
|
|
257
|
+
await ans(query, None)
|
|
264
258
|
await state.update_data(detail=None)
|
|
265
|
-
await window.fill_cred_dtl(query.message
|
|
259
|
+
await window.fill_cred_dtl(query.message)
|
|
266
260
|
await query.message.delete()
|
|
267
261
|
|
|
268
262
|
|
|
269
263
|
@pay.callback_query(cd.PayNav.filter(F.to.__eq__(cd.PayStep.t_cred_name)))
|
|
270
264
|
async def back_to_cred_name(query: CallbackQuery, state: FSMContext):
|
|
271
265
|
await query.message.delete()
|
|
272
|
-
await query
|
|
266
|
+
await ans(query, None)
|
|
273
267
|
await state.update_data(name=None)
|
|
274
|
-
await window.fill_cred_name(query.message
|
|
268
|
+
await window.fill_cred_name(query.message)
|
|
275
269
|
await query.message.delete()
|
|
276
270
|
|
|
277
271
|
|
|
278
272
|
@pay.callback_query(cd.PayNav.filter(F.to.in_([cd.PayStep.t_ex, cd.PayStep.s_ex])))
|
|
279
273
|
async def back_to_ex_select(query: CallbackQuery, state: FSMContext):
|
|
280
274
|
await query.message.delete()
|
|
281
|
-
await query
|
|
275
|
+
await ans(query, None)
|
|
282
276
|
await state.update_data({("t" if await state.get_value("is_target") else "s") + "ex_id": None})
|
|
283
|
-
await window.ex_select(query.message
|
|
277
|
+
await window.ex_select(query.message)
|
|
284
278
|
|
|
285
279
|
|
|
286
280
|
@pay.callback_query(cd.PayNav.filter(F.to.__eq__(cd.PayStep.t_amount)))
|
|
287
281
|
async def back_to_amount(query: CallbackQuery, state: FSMContext):
|
|
288
282
|
await query.message.delete()
|
|
289
|
-
await query
|
|
283
|
+
await ans(query, None)
|
|
290
284
|
await state.update_data(amount=None)
|
|
291
|
-
await window.amount(query.message
|
|
285
|
+
await window.amount(query.message)
|
|
292
286
|
|
|
293
287
|
|
|
294
288
|
@pay.callback_query(cd.PayNav.filter(F.to.in_([cd.PayStep.t_pm])))
|
|
295
289
|
async def back_to_payment(query: CallbackQuery, state: FSMContext):
|
|
296
290
|
await query.message.delete()
|
|
297
|
-
await query
|
|
291
|
+
await ans(query, None)
|
|
298
292
|
await state.update_data(payment=None)
|
|
299
|
-
await window.pm(query.message
|
|
293
|
+
await window.pm(query.message)
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
from asyncio import sleep
|
|
2
|
+
|
|
3
|
+
from aiogram.fsm.context import FSMContext
|
|
4
|
+
from aiogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton
|
|
5
|
+
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
|
6
|
+
from xync_bot.routers.pay.dep import edt
|
|
7
|
+
|
|
8
|
+
from xync_bot import Store
|
|
9
|
+
from xync_bot.routers.pay import cd, dep
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
async def type_select(msg: Message):
|
|
13
|
+
"""Step 1: Select type"""
|
|
14
|
+
store: Store = msg.bot.store
|
|
15
|
+
ist: bool = store.curr.is_target
|
|
16
|
+
rm = InlineKeyboardMarkup(
|
|
17
|
+
inline_keyboard=[
|
|
18
|
+
[
|
|
19
|
+
InlineKeyboardButton(
|
|
20
|
+
text="Банковская валюта", callback_data=cd.MoneyType(is_fiat=1, is_target=ist).pack()
|
|
21
|
+
),
|
|
22
|
+
InlineKeyboardButton(
|
|
23
|
+
text="Крипта", callback_data=cd.MoneyType(is_fiat=0, is_target=store.curr.is_target).pack()
|
|
24
|
+
),
|
|
25
|
+
]
|
|
26
|
+
]
|
|
27
|
+
)
|
|
28
|
+
txt = "Что нужно?" if store.curr.is_target else "Чем платишь?"
|
|
29
|
+
if store.perm.msg_id:
|
|
30
|
+
await edt(msg, txt, rm)
|
|
31
|
+
else:
|
|
32
|
+
msg = await msg.answer(txt, reply_markup=rm)
|
|
33
|
+
store.perm.msg_id = msg.message_id
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
async def cur_select(msg: Message):
|
|
37
|
+
"""Common using cur func"""
|
|
38
|
+
builder = InlineKeyboardBuilder()
|
|
39
|
+
ist: bool = msg.bot.store.curr.is_target
|
|
40
|
+
for cur_id, ticker in msg.bot.store.glob.curs.items():
|
|
41
|
+
builder.button(text=ticker + dep.flags[ticker], callback_data=cd.Cur(id=cur_id, is_target=ist))
|
|
42
|
+
builder.button(text="Назад к выбору типа", callback_data=cd.PayNav(to=cd.PayStep.t_type))
|
|
43
|
+
builder.adjust(3, 3, 3, 3, 3, 1)
|
|
44
|
+
sfx = "ую нужно" if ist else "ой платишь"
|
|
45
|
+
await msg.edit_text("Выбери валюту котор" + sfx, reply_markup=builder.as_markup())
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
async def coin_select(msg: Message):
|
|
49
|
+
"""Common using coin func"""
|
|
50
|
+
builder = InlineKeyboardBuilder()
|
|
51
|
+
store: Store = msg.bot.store
|
|
52
|
+
for coin_id, ticker in store.glob.coins.items():
|
|
53
|
+
builder.button(text=ticker, callback_data=cd.Coin(id=coin_id, is_target=store.curr.is_target))
|
|
54
|
+
builder.button(
|
|
55
|
+
text="Назад к выбору типа",
|
|
56
|
+
callback_data=cd.PayNav(to=cd.PayStep.t_type if store.curr.is_target else cd.PayStep.s_type),
|
|
57
|
+
)
|
|
58
|
+
builder.adjust(1)
|
|
59
|
+
sfx = "ую нужно" if store.curr.is_target else "ой платишь"
|
|
60
|
+
await msg.edit_text("Выберите монету котор" + sfx, reply_markup=builder.as_markup())
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
async def ex_select(msg: Message):
|
|
64
|
+
store: Store = msg.bot.store
|
|
65
|
+
ist = store.curr.is_target
|
|
66
|
+
coin_id = getattr(store.pay, ("t" if ist else "s") + "_coin_id")
|
|
67
|
+
builder = InlineKeyboardBuilder()
|
|
68
|
+
for ex_id in store.glob.coinexs[coin_id]:
|
|
69
|
+
builder.button(text=store.glob.exs[ex_id], callback_data=cd.Ex(id=ex_id, is_target=ist))
|
|
70
|
+
builder.button(
|
|
71
|
+
text="Назад к выбору монеты", callback_data=cd.PayNav(to=cd.PayStep.t_coin if ist else cd.PayStep.s_coin)
|
|
72
|
+
)
|
|
73
|
+
builder.button(text="Домой", callback_data=cd.PayNav(to=cd.PayStep.t_type))
|
|
74
|
+
builder.adjust(1)
|
|
75
|
+
keyboard = builder.as_markup()
|
|
76
|
+
await msg.edit_text("На какую биржу?" if ist else "С какой биржи?", reply_markup=keyboard)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
async def pm(msg: Message):
|
|
80
|
+
store: Store = msg.bot.store
|
|
81
|
+
ist = store.curr.is_target
|
|
82
|
+
cur_id = getattr(store.pay, ("t" if ist else "s") + "_cur_id")
|
|
83
|
+
builder = InlineKeyboardBuilder()
|
|
84
|
+
for pmcur_id in store.glob.curpms[cur_id]:
|
|
85
|
+
builder.button(text=store.glob.pms[pmcur_id], callback_data=cd.Pm(pmcur_id=pmcur_id, is_target=ist))
|
|
86
|
+
builder.button(
|
|
87
|
+
text="Назад к выбору валюты", callback_data=cd.PayNav(to=cd.PayStep.t_cur if ist else cd.PayStep.s_cur)
|
|
88
|
+
)
|
|
89
|
+
builder.button(text="Домой", callback_data=cd.PayNav(to=cd.PayStep.t_type))
|
|
90
|
+
builder.adjust(1)
|
|
91
|
+
keyboard = builder.as_markup()
|
|
92
|
+
await msg.edit_text("На какую платежную систему?" if ist else "C какой платежной системы?", reply_markup=keyboard)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
async def fill_cred_dtl(msg: Message):
|
|
96
|
+
builder = InlineKeyboardBuilder()
|
|
97
|
+
store: Store = msg.bot.store
|
|
98
|
+
txt = "В"
|
|
99
|
+
if cred_ids := store.perm.cur_creds.get(store.pay.t_pmcur_id):
|
|
100
|
+
for cred_id in cred_ids:
|
|
101
|
+
cred = store.perm.creds[cred_id]
|
|
102
|
+
txt = f"{cred.detail}\n{cred.name}"
|
|
103
|
+
if cred.extra:
|
|
104
|
+
txt += f" ({cred.extra})"
|
|
105
|
+
builder.button(text=txt, callback_data=cd.Cred(id=cred_id))
|
|
106
|
+
txt = "Выберите реквизиты куда нужно получить деньги, если в списке нет нужных, то\nв"
|
|
107
|
+
|
|
108
|
+
builder.button(text="Назад к выбору платежной системы", callback_data=cd.PayNav(to=cd.PayStep.t_pm))
|
|
109
|
+
builder.button(text="Домой", callback_data=cd.PayNav(to=cd.PayStep.t_type))
|
|
110
|
+
builder.adjust(2)
|
|
111
|
+
|
|
112
|
+
await msg.edit_text(
|
|
113
|
+
f"{txt}ведите номер для {store.glob.pms[store.pay.t_pmcur_id]}:", reply_markup=builder.as_markup()
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
async def fill_cred_name(msg: Message):
|
|
118
|
+
builder = InlineKeyboardBuilder()
|
|
119
|
+
builder.button(text="Назад к вводу реквизитов", callback_data=cd.PayNav(to=cd.PayStep.t_cred_dtl))
|
|
120
|
+
builder.button(text="Домой", callback_data=cd.PayNav(to=cd.PayStep.t_type))
|
|
121
|
+
builder.adjust(2)
|
|
122
|
+
store: Store = msg.bot.store
|
|
123
|
+
cur = store.glob.curs[store.pay.t_cur_id]
|
|
124
|
+
payment = store.glob.pms[store.pay.t_pmcur_id]
|
|
125
|
+
detail = store.pay.cred_dtl
|
|
126
|
+
await edt(msg, f"{cur}:{payment}:{detail}: Введите имя получателя", builder.as_markup())
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
async def amount(msg: Message):
|
|
130
|
+
"""Step 5: Filling target amount"""
|
|
131
|
+
builder = InlineKeyboardBuilder()
|
|
132
|
+
store: Store = msg.bot.store
|
|
133
|
+
if store.curr.is_fiat:
|
|
134
|
+
cur_coin = store.glob.curs[store.pay.t_cur_id]
|
|
135
|
+
builder.button(text="Назад к вводу имени", callback_data=cd.PayNav(to=cd.PayStep.t_cred_name))
|
|
136
|
+
t_name = store.glob.pms[store.pay.t_pmcur_id]
|
|
137
|
+
else:
|
|
138
|
+
cur_coin = store.glob.curs[store.pay.t_coin_id]
|
|
139
|
+
builder.button(text="Назад к выбору биржи", callback_data=cd.PayNav(to=cd.PayStep.t_ex))
|
|
140
|
+
t_name = store.glob.exs[store.pay.t_ex_id]
|
|
141
|
+
|
|
142
|
+
builder.button(text="Домой", callback_data=cd.PayNav(to=cd.PayStep.t_type))
|
|
143
|
+
builder.adjust(2)
|
|
144
|
+
|
|
145
|
+
await msg.edit_text(f"Введите нужную сумму {cur_coin} для {t_name}", reply_markup=builder.as_markup())
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
async def set_ppo(msg: Message):
|
|
149
|
+
rm = InlineKeyboardMarkup(
|
|
150
|
+
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")],
|
|
156
|
+
]
|
|
157
|
+
)
|
|
158
|
+
await msg.edit_text("На 2 платежа сможем разбить?", reply_markup=rm)
|
|
159
|
+
|
|
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())
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
async def run_timer(message, state: FSMContext):
|
|
175
|
+
builder = InlineKeyboardBuilder()
|
|
176
|
+
builder.button(text="Платеж получен", callback_data=cd.Action(act=cd.ActionType.received))
|
|
177
|
+
|
|
178
|
+
data = await state.get_value("timer")
|
|
179
|
+
seconds = data * 60
|
|
180
|
+
|
|
181
|
+
def format(sec):
|
|
182
|
+
days = sec // (24 * 3600)
|
|
183
|
+
sec %= 24 * 3600
|
|
184
|
+
hours = sec // 3600
|
|
185
|
+
sec %= 3600
|
|
186
|
+
minutes = sec // 60
|
|
187
|
+
sec %= 60
|
|
188
|
+
|
|
189
|
+
if days > 0:
|
|
190
|
+
return f"{days}д {hours:02d}:{minutes:02d}:{sec:02d}"
|
|
191
|
+
elif hours > 0:
|
|
192
|
+
return f"{hours:02d}:{minutes:02d}:{sec:02d}"
|
|
193
|
+
else:
|
|
194
|
+
return f"{minutes:02d}:{sec:02d}"
|
|
195
|
+
|
|
196
|
+
try:
|
|
197
|
+
await message.edit_text(f"⏳ Осталось {format(seconds)}", reply_markup=builder.as_markup())
|
|
198
|
+
except Exception:
|
|
199
|
+
return
|
|
200
|
+
|
|
201
|
+
while seconds > 0:
|
|
202
|
+
await sleep(1)
|
|
203
|
+
seconds -= 1
|
|
204
|
+
try:
|
|
205
|
+
await message.edit_text(f"⏳ Осталось {format(seconds)}", reply_markup=builder.as_markup())
|
|
206
|
+
await state.update_data(timer=seconds)
|
|
207
|
+
except Exception:
|
|
208
|
+
break
|
|
209
|
+
|
|
210
|
+
if seconds <= 0:
|
|
211
|
+
builder = InlineKeyboardBuilder()
|
|
212
|
+
builder.button(text="Платеж получен", callback_data=cd.Action(act=cd.ActionType.received))
|
|
213
|
+
builder.button(text="Денег нет", callback_data=cd.Action(act=cd.ActionType.not_received))
|
|
214
|
+
try:
|
|
215
|
+
await message.edit_text("⏳ Время вышло!", reply_markup=builder.as_markup())
|
|
216
|
+
except Exception:
|
|
217
|
+
pass
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
from tortoise.functions import Min
|
|
2
|
-
from xync_schema import models
|
|
3
|
-
|
|
4
|
-
from xync_bot.routers.pay.dep import flags
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class SingleStore(type):
|
|
8
|
-
_store = None
|
|
9
|
-
|
|
10
|
-
async def __call__(cls):
|
|
11
|
-
if not cls._store:
|
|
12
|
-
cls._store = super(SingleStore, cls).__call__()
|
|
13
|
-
cls._store.coins = {k: v for k, v in await models.Coin.all().order_by("ticker").values_list("id", "ticker")}
|
|
14
|
-
cls._store.curs = {
|
|
15
|
-
k: v
|
|
16
|
-
for k, v in await models.Cur.filter(ticker__in=flags.keys())
|
|
17
|
-
.order_by("ticker")
|
|
18
|
-
.values_list("id", "ticker")
|
|
19
|
-
}
|
|
20
|
-
cls._store.exs = {k: v for k, v in await models.Ex.all().values_list("id", "name")}
|
|
21
|
-
cls._store.pms = {
|
|
22
|
-
k: v
|
|
23
|
-
for k, v in await models.Pmex.filter(pm__pmcurs__id__in=cls._store.curs.keys())
|
|
24
|
-
.annotate(sname=Min("name"))
|
|
25
|
-
.group_by("pm_id")
|
|
26
|
-
.values_list("pm_id", "sname")
|
|
27
|
-
}
|
|
28
|
-
cls._store.coinexs = {
|
|
29
|
-
c.id: [ex.ex_id for ex in c.coinexs] for c in await models.Coin.all().prefetch_related("coinexs")
|
|
30
|
-
}
|
|
31
|
-
cls._store.curpms = {
|
|
32
|
-
c.id: [pmc.pm_id for pmc in c.pmcurs]
|
|
33
|
-
for c in await models.Cur.filter(id__in=cls._store.curs.keys()).prefetch_related("pmcurs")
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return cls._store
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
class Store:
|
|
40
|
-
class Global(metaclass=SingleStore):
|
|
41
|
-
coins: dict[int, str] # id:ticker
|
|
42
|
-
curs: dict[int, str] # id:ticker
|
|
43
|
-
exs: dict[int, str] # id:name
|
|
44
|
-
pms: dict[int, models.Pm] # id:name
|
|
45
|
-
|
|
46
|
-
class Permanent:
|
|
47
|
-
user: models.User
|
|
48
|
-
actors: dict[int, models.Actor] # key=ex_id
|
|
49
|
-
|
|
50
|
-
class Current:
|
|
51
|
-
t_cur_id: int = None
|
|
52
|
-
s_cur_id: int = None
|
|
53
|
-
t_coin_id: int = None
|
|
54
|
-
s_coin_id: int = None
|
|
55
|
-
t_pm_id: int = None
|
|
56
|
-
s_pm_id: int = None
|
|
57
|
-
t_ex_id: int = None
|
|
58
|
-
s_ex_id: int = None
|
|
59
|
-
addr: models.Addr = None
|
|
60
|
-
cred: models.Cred = None
|
|
61
|
-
|
|
62
|
-
glob: Global
|
|
63
|
-
perm: Permanent = Permanent()
|
|
64
|
-
curr: Current = Current()
|
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
from asyncio import sleep
|
|
2
|
-
|
|
3
|
-
from aiogram.fsm.context import FSMContext
|
|
4
|
-
from aiogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton
|
|
5
|
-
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
|
6
|
-
from tortoise.functions import Max
|
|
7
|
-
from xync_schema import models
|
|
8
|
-
|
|
9
|
-
from xync_bot.routers.pay import cd, dep
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
async def type_select(msg: Message, is_target: bool):
|
|
13
|
-
"""Step 1: Select type"""
|
|
14
|
-
if is_target is False:
|
|
15
|
-
await msg.bot.delete_messages(chat_id=msg.chat.id, message_ids=[msg.message_id, msg.message_id - 1])
|
|
16
|
-
rm = InlineKeyboardMarkup(
|
|
17
|
-
inline_keyboard=[
|
|
18
|
-
[
|
|
19
|
-
InlineKeyboardButton(
|
|
20
|
-
text="Банковская валюта", callback_data=cd.TargetType(is_fiat=1, is_target=is_target).pack()
|
|
21
|
-
),
|
|
22
|
-
InlineKeyboardButton(text="Крипта", callback_data=cd.TargetType(is_fiat=0, is_target=is_target).pack()),
|
|
23
|
-
]
|
|
24
|
-
]
|
|
25
|
-
)
|
|
26
|
-
await msg.answer("Что нужно?" if is_target else "Чем платишь?", reply_markup=rm)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
async def amount(msg: Message, state: FSMContext):
|
|
30
|
-
await msg.bot.delete_messages(chat_id=msg.chat.id, message_ids=[msg.message_id, msg.message_id - 1])
|
|
31
|
-
"""Step 5: Filling target amount"""
|
|
32
|
-
builder = InlineKeyboardBuilder()
|
|
33
|
-
|
|
34
|
-
if await state.get_value("is_fiat"):
|
|
35
|
-
cur_coin = (await state.get_value("curs"))[await state.get_value("t_cur_id")]
|
|
36
|
-
builder.button(text="Назад к вводу имени", callback_data=cd.PayNav(to=cd.PayStep.t_cred_name))
|
|
37
|
-
else:
|
|
38
|
-
cur_coin = (await state.get_value("coins"))[await state.get_value("t_coin_id")]
|
|
39
|
-
builder.button(text="Назад к выбору биржи", callback_data=cd.PayNav(to=cd.PayStep.t_ex))
|
|
40
|
-
|
|
41
|
-
builder.button(text="Домой", callback_data=cd.PayNav(to=cd.PayStep.t_type))
|
|
42
|
-
builder.adjust(2)
|
|
43
|
-
|
|
44
|
-
await msg.answer(
|
|
45
|
-
f"Введите нужную сумму {cur_coin} для {await state.get_value('t_name')}", reply_markup=builder.as_markup()
|
|
46
|
-
)
|
|
47
|
-
await state.set_state(dep.PaymentState.amount)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
async def cur_select(msg: Message, state: FSMContext):
|
|
51
|
-
"""Common using cur func"""
|
|
52
|
-
if not (curs := await state.get_value("curs")):
|
|
53
|
-
await state.update_data(curs=curs)
|
|
54
|
-
builder = InlineKeyboardBuilder()
|
|
55
|
-
is_target = await state.get_value("is_target")
|
|
56
|
-
for cur_id, ticker in curs.items():
|
|
57
|
-
builder.button(text=ticker + dep.flags[ticker], callback_data=cd.Cur(id=cur_id, is_target=is_target))
|
|
58
|
-
builder.button(text="Назад к выбору типа", callback_data=cd.PayNav(to=cd.PayStep.t_type))
|
|
59
|
-
builder.adjust(3, 3, 3, 3, 3, 1)
|
|
60
|
-
sfx = "ую нужно" if is_target else "ой платишь"
|
|
61
|
-
await msg.answer("Выбери валюту котор" + sfx, reply_markup=builder.as_markup())
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
async def coin_select(msg: Message, state: FSMContext):
|
|
65
|
-
"""Common using coin func"""
|
|
66
|
-
builder = InlineKeyboardBuilder()
|
|
67
|
-
if not (coins := await state.get_value("coins")):
|
|
68
|
-
coins = {k: v for k, v in await models.Coin.all().values_list("id", "ticker")}
|
|
69
|
-
await state.update_data(coins=coins)
|
|
70
|
-
is_target = await state.get_value("is_target")
|
|
71
|
-
for coin_id, ticker in coins.items():
|
|
72
|
-
builder.button(text=ticker, callback_data=cd.Coin(id=coin_id, is_target=is_target))
|
|
73
|
-
builder.button(
|
|
74
|
-
text="Назад к выбору типа", callback_data=cd.PayNav(to=cd.PayStep.t_type if is_target else cd.PayStep.s_type)
|
|
75
|
-
)
|
|
76
|
-
builder.adjust(1)
|
|
77
|
-
sfx = "ую нужно" if is_target else "ой платишь"
|
|
78
|
-
await msg.answer("Выберите монету котор" + sfx, reply_markup=builder.as_markup())
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
async def ex_select(msg: Message, state: FSMContext):
|
|
82
|
-
data = await state.get_data()
|
|
83
|
-
is_target = data["is_target"]
|
|
84
|
-
coin_id = data[("t" if is_target else "s") + "_coin_id"]
|
|
85
|
-
if not (exs := data.get("exs", {}).get(coin_id)):
|
|
86
|
-
await state.update_data({"exs": {coin_id: exs}})
|
|
87
|
-
builder = InlineKeyboardBuilder()
|
|
88
|
-
for eid, name in exs:
|
|
89
|
-
builder.button(text=name, callback_data=cd.Ex(id=eid, name=name, is_target=is_target))
|
|
90
|
-
builder.button(
|
|
91
|
-
text="Назад к выбору монеты", callback_data=cd.PayNav(to=cd.PayStep.t_coin if is_target else cd.PayStep.s_coin)
|
|
92
|
-
)
|
|
93
|
-
builder.button(text="Домой", callback_data=cd.PayNav(to=cd.PayStep.t_type))
|
|
94
|
-
builder.adjust(1)
|
|
95
|
-
keyboard = builder.as_markup()
|
|
96
|
-
await msg.answer("На какую биржу?" if is_target else "С какой биржи?", reply_markup=keyboard)
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
async def pm(msg: Message, state: FSMContext):
|
|
100
|
-
data = await state.get_data()
|
|
101
|
-
is_target = data["is_target"]
|
|
102
|
-
cur_id = data[("t" if is_target else "s") + "_cur_id"]
|
|
103
|
-
if not (pms := data.get("pms", {}).get(cur_id)):
|
|
104
|
-
pms = await (
|
|
105
|
-
models.Pmex.filter(pm__pmcurs__cur_id=cur_id)
|
|
106
|
-
.annotate(lname=Max("name"))
|
|
107
|
-
.group_by("pm__pmcurs__id")
|
|
108
|
-
.values_list("pm__pmcurs__id", "lname")
|
|
109
|
-
)
|
|
110
|
-
await state.update_data({"pms": {cur_id: pms}})
|
|
111
|
-
builder = InlineKeyboardBuilder()
|
|
112
|
-
for pmcur_id, name in pms:
|
|
113
|
-
builder.button(text=name, callback_data=cd.Pm(pmcur_id=pmcur_id, name=name[:50], is_target=is_target))
|
|
114
|
-
builder.button(
|
|
115
|
-
text="Назад к выбору валюты", callback_data=cd.PayNav(to=cd.PayStep.t_cur if is_target else cd.PayStep.s_cur)
|
|
116
|
-
)
|
|
117
|
-
builder.button(text="Домой", callback_data=cd.PayNav(to=cd.PayStep.t_type))
|
|
118
|
-
builder.adjust(1)
|
|
119
|
-
keyboard = builder.as_markup()
|
|
120
|
-
txt = "На какую платежную систему?" if is_target else "C какой платежной системы?"
|
|
121
|
-
await msg.answer(txt, reply_markup=keyboard)
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
async def fill_cred_dtl(msg: Message, state: FSMContext):
|
|
125
|
-
builder = InlineKeyboardBuilder()
|
|
126
|
-
data = await state.get_data()
|
|
127
|
-
if not (person_id := data.get("person_id")):
|
|
128
|
-
person_id = await models.User.get(username_id=193017646).values_list("person_id", flat=True)
|
|
129
|
-
await state.update_data(person_id=person_id)
|
|
130
|
-
pmcur_id = data["t_pmcur_id"]
|
|
131
|
-
if not (creds := data.get("creds", {}).get(pmcur_id)):
|
|
132
|
-
creds = await models.Cred.filter(person_id=person_id, pmcur_id=pmcur_id)
|
|
133
|
-
await state.update_data({"creds": {pmcur_id: creds}})
|
|
134
|
-
for cred in creds:
|
|
135
|
-
txt = f"{cred.detail}\n{cred.name}"
|
|
136
|
-
if cred.extra:
|
|
137
|
-
txt += f" ({cred.extra})"
|
|
138
|
-
builder.button(text=txt, callback_data=cd.Cred(id=cred.id))
|
|
139
|
-
|
|
140
|
-
builder.button(text="Назад к выбору платежной системы", callback_data=cd.PayNav(to=cd.PayStep.t_pm))
|
|
141
|
-
builder.button(text="Домой", callback_data=cd.PayNav(to=cd.PayStep.t_type))
|
|
142
|
-
builder.adjust(2)
|
|
143
|
-
txt = "Выберите реквизиты куда нужно получить деньги, если в списке нет нужных, то\n"
|
|
144
|
-
await msg.answer(f"{txt}Введите номер для {await state.get_value('t_name')}:", reply_markup=builder.as_markup())
|
|
145
|
-
await state.set_state(dep.CredState.detail)
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
async def fill_cred_name(msg: Message, state: FSMContext):
|
|
149
|
-
await msg.bot.delete_messages(chat_id=msg.chat.id, message_ids=[msg.message_id, msg.message_id - 1])
|
|
150
|
-
await state.update_data(detail=msg.text)
|
|
151
|
-
builder = InlineKeyboardBuilder()
|
|
152
|
-
builder.button(text="Назад к вводу реквизитов", callback_data=cd.PayNav(to=cd.PayStep.t_cred_dtl))
|
|
153
|
-
builder.button(text="Домой", callback_data=cd.PayNav(to=cd.PayStep.t_type))
|
|
154
|
-
builder.adjust(2)
|
|
155
|
-
data = await state.get_data()
|
|
156
|
-
cur = data["curs"].get(data["t_cur_id"])
|
|
157
|
-
payment = data["t_name"]
|
|
158
|
-
detail = data["detail"]
|
|
159
|
-
await msg.answer(f"{cur}:{payment}:{detail}: Введите имя получателя", reply_markup=builder.as_markup())
|
|
160
|
-
await state.set_state(dep.CredState.name)
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
async def set_ppo(msg: Message):
|
|
164
|
-
rm = InlineKeyboardMarkup(
|
|
165
|
-
inline_keyboard=[
|
|
166
|
-
[
|
|
167
|
-
InlineKeyboardButton(text="Нет", callback_data="ppo:1"),
|
|
168
|
-
InlineKeyboardButton(text="Да", callback_data="ppo:2"),
|
|
169
|
-
],
|
|
170
|
-
[InlineKeyboardButton(text="Да хоть на 3", callback_data="ppo:3")],
|
|
171
|
-
]
|
|
172
|
-
)
|
|
173
|
-
await msg.answer("На 2 платежа сможем разбить?", reply_markup=rm)
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
async def set_urgency(msg: Message):
|
|
177
|
-
builder = InlineKeyboardBuilder()
|
|
178
|
-
builder.button(text="1 мин", callback_data=cd.Time(minutes=1))
|
|
179
|
-
builder.button(text="5 мин", callback_data=cd.Time(minutes=5))
|
|
180
|
-
builder.button(text="30 мин", callback_data=cd.Time(minutes=30))
|
|
181
|
-
builder.button(text="3 часа", callback_data=cd.Time(minutes=180))
|
|
182
|
-
builder.button(text="сутки", callback_data=cd.Time(minutes=60 * 24))
|
|
183
|
-
builder.button(text="Назад к вводу платежей", callback_data=cd.PayNav(to=cd.PayStep.t_pm))
|
|
184
|
-
builder.button(text="Домой", callback_data=cd.PayNav(to=cd.PayStep.t_type))
|
|
185
|
-
builder.adjust(2, 2, 1, 1, 1)
|
|
186
|
-
await msg.answer("Сколько можешь ждать?", reply_markup=builder.as_markup())
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
async def run_timer(message, state: FSMContext):
|
|
190
|
-
builder = InlineKeyboardBuilder()
|
|
191
|
-
builder.button(text="Платеж получен", callback_data=cd.Action(act=cd.ActionType.received))
|
|
192
|
-
|
|
193
|
-
data = await state.get_value("timer")
|
|
194
|
-
seconds = data * 60
|
|
195
|
-
|
|
196
|
-
def format(sec):
|
|
197
|
-
days = sec // (24 * 3600)
|
|
198
|
-
sec %= 24 * 3600
|
|
199
|
-
hours = sec // 3600
|
|
200
|
-
sec %= 3600
|
|
201
|
-
minutes = sec // 60
|
|
202
|
-
sec %= 60
|
|
203
|
-
|
|
204
|
-
if days > 0:
|
|
205
|
-
return f"{days}д {hours:02d}:{minutes:02d}:{sec:02d}"
|
|
206
|
-
elif hours > 0:
|
|
207
|
-
return f"{hours:02d}:{minutes:02d}:{sec:02d}"
|
|
208
|
-
else:
|
|
209
|
-
return f"{minutes:02d}:{sec:02d}"
|
|
210
|
-
|
|
211
|
-
try:
|
|
212
|
-
await message.edit_text(f"⏳ Осталось {format(seconds)}", reply_markup=builder.as_markup())
|
|
213
|
-
except Exception:
|
|
214
|
-
return
|
|
215
|
-
|
|
216
|
-
while seconds > 0:
|
|
217
|
-
await sleep(1)
|
|
218
|
-
seconds -= 1
|
|
219
|
-
try:
|
|
220
|
-
await message.edit_text(f"⏳ Осталось {format(seconds)}", reply_markup=builder.as_markup())
|
|
221
|
-
await state.update_data(timer=seconds)
|
|
222
|
-
except Exception:
|
|
223
|
-
break
|
|
224
|
-
|
|
225
|
-
if seconds <= 0:
|
|
226
|
-
builder = InlineKeyboardBuilder()
|
|
227
|
-
builder.button(text="Платеж получен", callback_data=cd.Action(act=cd.ActionType.received))
|
|
228
|
-
builder.button(text="Денег нет", callback_data=cd.Action(act=cd.ActionType.not_received))
|
|
229
|
-
try:
|
|
230
|
-
await message.edit_text("⏳ Время вышло!", reply_markup=builder.as_markup())
|
|
231
|
-
except Exception:
|
|
232
|
-
pass
|
|
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
|
|
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
|