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.

Files changed (31) hide show
  1. {xync_bot-0.3.24.dev3/xync_bot.egg-info → xync_bot-0.3.24.dev5}/PKG-INFO +1 -1
  2. xync_bot-0.3.24.dev5/xync_bot/routers/__init__.py +92 -0
  3. {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot/routers/pay/cd.py +1 -3
  4. {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot/routers/pay/dep.py +45 -0
  5. {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot/routers/pay/handler.py +111 -117
  6. xync_bot-0.3.24.dev5/xync_bot/routers/pay/window.py +217 -0
  7. {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5/xync_bot.egg-info}/PKG-INFO +1 -1
  8. xync_bot-0.3.24.dev3/xync_bot/routers/__init__.py +0 -64
  9. xync_bot-0.3.24.dev3/xync_bot/routers/pay/window.py +0 -232
  10. {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/.env.dist +0 -0
  11. {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/.gitignore +0 -0
  12. {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/.pre-commit-config.yaml +0 -0
  13. {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/makefile +0 -0
  14. {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/pyproject.toml +0 -0
  15. {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/setup.cfg +0 -0
  16. {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/test_main.http +0 -0
  17. {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot/__init__.py +0 -0
  18. {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot/loader.py +0 -0
  19. {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot/routers/cond/__init__.py +0 -0
  20. {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot/routers/cond/func.py +0 -0
  21. {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot/routers/main.py +0 -0
  22. {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot/routers/order.py +0 -0
  23. {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot/routers/photo.py +0 -0
  24. {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot/routers/vpn.py +0 -0
  25. {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot/routers/xicon.png +0 -0
  26. {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot/shared.py +0 -0
  27. {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot/typs.py +0 -0
  28. {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot.egg-info/SOURCES.txt +0 -0
  29. {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot.egg-info/dependency_links.txt +0 -0
  30. {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot.egg-info/requires.txt +0 -0
  31. {xync_bot-0.3.24.dev3 → xync_bot-0.3.24.dev5}/xync_bot.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xync-bot
3
- Version: 0.3.24.dev3
3
+ Version: 0.3.24.dev5
4
4
  Summary: Telegram bot with web app for xync net
5
5
  Author-email: Artemiev <mixartemev@gmail.com>
6
6
  License-Expression: GPL-3.0-or-later
@@ -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 TargetType(CallbackData, prefix="target"):
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, state: FSMContext, **kwargs):
20
+ async def h_start(msg: Message):
16
21
  """Step 1: Select target type"""
17
- # await window.amount(msg, state)
18
- await state.set_data({"is_target": True})
19
- await window.type_select(msg, True)
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.TargetType.filter(F.is_fiat))
23
- async def h_got_fiat_type(query: CallbackQuery, state: FSMContext):
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
- await query.message.delete()
26
- await state.update_data(is_fiat=True)
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.TargetType.filter(F.is_fiat.__eq__(0)))
32
- async def h_got_crypto_type(query: CallbackQuery, state: FSMContext):
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
- await query.message.delete()
35
- await state.update_data(is_fiat=False)
36
- await query.answer("Понял, крипта")
37
- await window.coin_select(query.message, state)
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, state: FSMContext):
46
+ async def h_got_coin(query: CallbackQuery, callback_data: cd.Coin, bot: PGram):
42
47
  """Step 3c: Select target ex"""
43
- await query.message.delete()
44
- await state.update_data({("t" if await state.get_value("is_target") else "s") + "_coin_id": callback_data.id})
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, state: FSMContext):
53
+ async def h_got_cur(query: CallbackQuery, callback_data: cd.Cur, bot: PGram):
51
54
  """Step 3f: Select target pm"""
52
- await query.message.delete()
53
- await state.update_data({("t" if await state.get_value("is_target") else "s") + "_cur_id": callback_data.id})
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
- await query.message.delete()
62
- await state.update_data(t_pmcur_id=callback_data.pmcur_id, t_name=callback_data.name)
63
- await query.answer("Теперь нужны реквизиты")
64
- await window.fill_cred_dtl(query.message, state)
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
- await query.message.delete()
70
- await state.update_data(cred_id=callback_data.id)
71
- await query.answer("Теперь нужна сумма")
72
- await window.amount(query.message, state)
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
- while True:
79
- if msg.text.isdigit():
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
- data = await state.get_data()
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}, detail=data["detail"], person_id=data["person_id"], pmcur_id=data["t_pmcur_id"]
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
- await state.update_data(cred_id=cred.id)
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, state: FSMContext):
100
+ async def h_got_ex(query: CallbackQuery, callback_data: cd.Ex):
102
101
  """Step 4c: Save target"""
103
- await query.message.delete()
104
- if is_target := await state.get_value("is_target"):
105
- await state.update_data(t_name=callback_data.name)
106
- await state.update_data({("t" if is_target else "s") + "_ex_id": callback_data.id})
107
- await query.answer(f"Биржа {callback_data.name} выбрана")
108
- await (window.amount(query.message, state) if is_target else window.set_ppo(query.message))
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
- while True:
115
- if msg.text.isdigit():
116
- await state.update_data(amount=int(msg.text))
117
- break
118
- else:
119
- await msg.answer("Пожалуйста, введите корректное число")
120
- return
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
- await state.update_data(is_target=False)
124
- if await state.get_value("is_fiat"):
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, state: FSMContext):
132
- await query.message.delete()
133
- await state.update_data(s_pmcur_id=callback_data.pmcur_id)
134
- await query.answer(callback_data.name)
135
- await window.set_ppo(query.message)
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, state: FSMContext, callback_data: cd.Ppo):
140
- await query.message.delete()
141
- await state.update_data(ppo=callback_data.num)
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(callback: CallbackQuery, callback_data: cd.Time, state: FSMContext):
148
- await callback.answer()
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
- data = await state.get_data()
152
- if ex_id := data.get("t_ex_id", data.get("s_ex_id")):
153
- if not (actor_id := data.get("actor_id")):
154
- person_id = data.get("person_id")
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
- await state.update_data(addr_id=addr_id)
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=data["amount"],
167
- parts=data["ppo"],
158
+ amount=store.pay.amount,
159
+ parts=store.pay.ppo,
168
160
  payed_at=None,
169
161
  addr_id=addr_id,
170
- cred_id=data["cred_id"],
171
- user_id=1,
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.answer()
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.answer()
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.answer()
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.answer()
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, state)
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.answer()
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, state)
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.answer()
258
- await window.pm(query.message, state)
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.answer()
257
+ await ans(query, None)
264
258
  await state.update_data(detail=None)
265
- await window.fill_cred_dtl(query.message, state)
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.answer()
266
+ await ans(query, None)
273
267
  await state.update_data(name=None)
274
- await window.fill_cred_name(query.message, state)
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.answer()
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, state)
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.answer()
283
+ await ans(query, None)
290
284
  await state.update_data(amount=None)
291
- await window.amount(query.message, state)
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.answer()
291
+ await ans(query, None)
298
292
  await state.update_data(payment=None)
299
- await window.pm(query.message, state)
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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xync-bot
3
- Version: 0.3.24.dev3
3
+ Version: 0.3.24.dev5
4
4
  Summary: Telegram bot with web app for xync net
5
5
  Author-email: Artemiev <mixartemev@gmail.com>
6
6
  License-Expression: GPL-3.0-or-later
@@ -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