xync-bot 0.3.7.dev4__py3-none-any.whl → 0.3.24.dev4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of xync-bot might be problematic. Click here for more details.

xync_bot/__init__.py CHANGED
@@ -5,10 +5,11 @@ from PGram import Bot
5
5
  from aiogram.client.default import DefaultBotProperties
6
6
  from x_model import init_db
7
7
 
8
- from xync_bot.routers.cond import cr
8
+ from xync_bot.routers import Store
9
+ from xync_bot.routers.cond import cr as cr
9
10
 
10
11
  # from xync_bot.routers.main import mr
11
- from xync_bot.routers.pay.main import pay as pay
12
+ from xync_bot.routers.pay.handler import pay as pay
12
13
 
13
14
  if __name__ == "__main__":
14
15
  from xync_bot.loader import TOKEN, TORM
@@ -17,7 +18,9 @@ if __name__ == "__main__":
17
18
 
18
19
  async def main() -> None:
19
20
  cn = await init_db(TORM)
20
- bot = Bot(TOKEN, [cr, pay], cn, default=DefaultBotProperties(parse_mode="HTML"))
21
+ store = Store()
22
+ store.glob = await Store.Global()
23
+ bot = Bot(TOKEN, [pay], cn, default=DefaultBotProperties(parse_mode="HTML"), store=store)
21
24
  await bot.start()
22
25
 
23
26
  run(main())
xync_bot/loader.py CHANGED
@@ -19,3 +19,5 @@ TORM = {
19
19
  "use_tz": False,
20
20
  "timezone": "UTC",
21
21
  }
22
+
23
+ glob = object
@@ -0,0 +1,77 @@
1
+ from tortoise.functions import Min
2
+ from x_model.func import ArrayAgg
3
+ from xync_schema import models
4
+
5
+ from xync_bot.routers.pay.dep import flags
6
+
7
+
8
+ class SingleStore(type):
9
+ _store = None
10
+
11
+ async def __call__(cls):
12
+ if not cls._store:
13
+ cls._store = super(SingleStore, cls).__call__()
14
+ cls._store.coins = {k: v for k, v in await models.Coin.all().order_by("ticker").values_list("id", "ticker")}
15
+ curs = {
16
+ k: v
17
+ for k, v in await models.Cur.filter(ticker__in=flags.keys())
18
+ .order_by("ticker")
19
+ .values_list("id", "ticker")
20
+ }
21
+ cls._store.curs = curs
22
+ cls._store.exs = {k: v for k, v in await models.Ex.all().values_list("id", "name")}
23
+ cls._store.pms = {
24
+ k: v
25
+ for k, v in await models.Pmex.filter(pm__pmcurs__cur_id__in=cls._store.curs.keys())
26
+ .annotate(sname=Min("name"))
27
+ .group_by("pm__pmcurs__id")
28
+ .values_list("pm__pmcurs__id", "sname")
29
+ }
30
+ cls._store.coinexs = {
31
+ c.id: [ex.ex_id for ex in c.coinexs] for c in await models.Coin.all().prefetch_related("coinexs")
32
+ }
33
+ cls._store.curpms = {
34
+ cur_id: ids
35
+ for cur_id, ids in await models.Pmcur.filter(cur_id__in=curs.keys())
36
+ .annotate(ids=ArrayAgg("id"))
37
+ .group_by("cur_id")
38
+ .values_list("cur_id", "ids")
39
+ }
40
+
41
+ return cls._store
42
+
43
+
44
+ class Store:
45
+ class Global(metaclass=SingleStore):
46
+ coins: dict[int, str] # id:ticker
47
+ curs: dict[int, str] # id:ticker
48
+ exs: dict[int, str] # id:name
49
+ coinexs: dict[int, list[int]] # id:[ex_ids]
50
+ pms: dict[int, str] # pmcur_id:name
51
+ curpms: dict[int, list[int]] # id:[pmcur_ids]
52
+
53
+ class Permanent:
54
+ msg_id: int = None
55
+ user: models.User = None
56
+ actors: dict[int, models.Actor] = None # key=ex_id
57
+
58
+ class Current:
59
+ is_target: bool = None
60
+ is_fiat: bool = None
61
+
62
+ class Payment:
63
+ t_cur_id: int = None
64
+ s_cur_id: int = None
65
+ t_coin_id: int = None
66
+ s_coin_id: int = None
67
+ t_pm_id: int = None
68
+ s_pm_id: int = None
69
+ t_ex_id: int = None
70
+ s_ex_id: int = None
71
+ addr: models.Addr = None
72
+ cred: models.Cred = None
73
+
74
+ glob: Global
75
+ perm: Permanent = Permanent()
76
+ pay: Payment = Payment()
77
+ curr: Current = Current()
@@ -0,0 +1,48 @@
1
+ from aiogram.filters.callback_data import CallbackData
2
+
3
+ from xync_bot.routers.pay.dep import PayStep, ActionType
4
+
5
+
6
+ class TargetType(CallbackData, prefix="target"):
7
+ is_fiat: int # bool
8
+ is_target: int # bool
9
+
10
+
11
+ class Cur(CallbackData, prefix="cur"):
12
+ id: int
13
+ is_target: int # bool
14
+
15
+
16
+ class Coin(CallbackData, prefix="coin"):
17
+ id: int
18
+ is_target: int # bool
19
+
20
+
21
+ class Cred(CallbackData, prefix="cred"):
22
+ id: int
23
+
24
+
25
+ class Ex(CallbackData, prefix="ex"):
26
+ id: int
27
+ is_target: int # bool
28
+
29
+
30
+ class Pm(CallbackData, prefix="pm"):
31
+ pmcur_id: int
32
+ is_target: bool
33
+
34
+
35
+ class Ppo(CallbackData, prefix="ppo"):
36
+ num: int
37
+
38
+
39
+ class PayNav(CallbackData, prefix="pay_nav"):
40
+ to: PayStep
41
+
42
+
43
+ class Time(CallbackData, prefix="time"):
44
+ minutes: int # время в минутах
45
+
46
+
47
+ class Action(CallbackData, prefix="action"):
48
+ act: ActionType # "received" или "not_received"
@@ -0,0 +1,70 @@
1
+ from enum import IntEnum
2
+
3
+ from aiogram.fsm.state import StatesGroup, State
4
+
5
+
6
+ class Report(StatesGroup):
7
+ text = State()
8
+
9
+
10
+ class CredState(StatesGroup):
11
+ detail = State()
12
+ name = State()
13
+
14
+
15
+ class PaymentState(StatesGroup):
16
+ amount = State()
17
+ timer = State()
18
+ timer_active = State()
19
+
20
+
21
+ class ActionType(IntEnum):
22
+ """Цель (назначение) платежа (target)"""
23
+
24
+ sent = 1 # Отправил
25
+ received = 2 # Получил
26
+ not_received = 3 # Не получил
27
+
28
+
29
+ class PayStep(IntEnum):
30
+ """Цель (назначение) платежа (target)"""
31
+
32
+ t_type = 1 # Выбор типа
33
+ t_cur = 2 # Выбор валюты
34
+ t_coin = 3 # Выбор монеты
35
+ t_pm = 4 # Выбор платежки
36
+ t_ex = 5 # Выбор биржи
37
+ t_cred_dtl = 6 # Ввод номера карты
38
+ t_cred_name = 7 # Ввод имени
39
+ # t_addr = 8 # todo: позже добавим: Выбор/ввод крипто кошелька
40
+ t_amount = 9 # Ввод суммы
41
+ """ Источник платежа (source) """
42
+ s_type = 10 # Выбор типа
43
+ s_cur = 11 # Выбор типа
44
+ s_pm = 12 # Выбор типа
45
+ s_coin = 13 # Выбор типа
46
+ s_ex = 14 # Выбор типа
47
+ ppo = 15 # Выбор возможности разбивки платежа
48
+ urgency = 16 # Выбор срочности получения платежа
49
+ pending_send = 17 # Ожидание отправки (если мы платим фиатом)
50
+ pending_confirm = 18 # Ожидание пока на той стороне подтвердят получение нашего фиата (если мы платим фиатом)
51
+ pending_receive = 19 # Ожидание поступления (если мы получаем фиат)
52
+
53
+
54
+ flags = {
55
+ "RUB": "🇷🇺",
56
+ "THB": "🇹🇭",
57
+ "IDR": "🇮🇩",
58
+ "TRY": "🇹🇷",
59
+ "GEL": "🇬🇪",
60
+ "VND": "🇻🇳",
61
+ "AED": "🇦🇪",
62
+ "AMD": "🇦🇲",
63
+ "AZN": "🇦🇿",
64
+ "CNY": "🇨🇳",
65
+ "EUR": "🇪🇺",
66
+ "HKD": "🇭🇰",
67
+ "INR": "🇮🇳",
68
+ "PHP": "🇵🇭",
69
+ "USD": "🇺🇸",
70
+ }
@@ -0,0 +1,297 @@
1
+ from asyncio import create_task
2
+ from datetime import timedelta, datetime
3
+
4
+ import PGram
5
+ from aiogram import Router, F
6
+ from aiogram.filters import Command
7
+ from aiogram.types import Message, CallbackQuery
8
+ from aiogram.fsm.context import FSMContext
9
+ from xync_schema import models
10
+ from aiogram.utils.keyboard import InlineKeyboardBuilder
11
+ from xync_bot.routers.pay import cd, dep, window
12
+
13
+ pay = Router()
14
+
15
+
16
+ @pay.message(Command("pay"))
17
+ async def h_start(msg: Message):
18
+ """Step 1: Select target type"""
19
+ msg.bot.store.curr.is_target = True
20
+ await msg.delete()
21
+ await window.type_select(msg)
22
+
23
+
24
+ @pay.callback_query(cd.TargetType.filter(F.is_fiat))
25
+ async def h_got_fiat_type(query: CallbackQuery, bot: PGram):
26
+ """Step 2f: Select cur"""
27
+ await query.answer("Понял, фиат")
28
+ bot.store.curr.is_fiat = True
29
+ await window.cur_select(query.message)
30
+
31
+
32
+ @pay.callback_query(cd.TargetType.filter(F.is_fiat.__eq__(0)))
33
+ async def h_got_crypto_type(query: CallbackQuery, bot: PGram):
34
+ """Step 2c: Select coin"""
35
+ bot.store.curr.is_fiat = False
36
+ await query.answer("Понял, крипта")
37
+ await window.coin_select(query.message)
38
+
39
+
40
+ @pay.callback_query(cd.Coin.filter())
41
+ async def h_got_coin(query: CallbackQuery, callback_data: cd.Coin, bot: PGram):
42
+ """Step 3c: Select target ex"""
43
+ setattr(bot.store.curr, ("t" if bot.store.curr.is_target else "s") + "_coin_id", callback_data.id)
44
+ await query.answer("Эта монета есть на следующих биржах")
45
+ await window.ex_select(query.message)
46
+
47
+
48
+ @pay.callback_query(cd.Cur.filter())
49
+ async def h_got_cur(query: CallbackQuery, callback_data: cd.Cur, bot: PGram):
50
+ """Step 3f: Select target pm"""
51
+ setattr(bot.store.curr, ("t" if bot.store.curr.is_target else "s") + "_cur_id", callback_data.id)
52
+ await query.answer("Вот платежные системы доступные для этой валюты")
53
+ await window.pm(query.message)
54
+
55
+
56
+ @pay.callback_query(cd.Pm.filter(F.is_target))
57
+ async def h_got_target_pm(query: CallbackQuery, callback_data: cd.Pm, state: FSMContext):
58
+ """Step 4f: Fill target cred.detail"""
59
+ await query.message.delete()
60
+ await state.update_data(t_pmcur_id=callback_data.pmcur_id, t_name=callback_data.name)
61
+ await query.answer("Теперь нужны реквизиты")
62
+ await window.fill_cred_dtl(query.message, state)
63
+
64
+
65
+ @pay.callback_query(cd.Cred.filter())
66
+ async def h_got_cred(query: CallbackQuery, callback_data: cd.Cred, state: FSMContext):
67
+ await query.message.delete()
68
+ await state.update_data(cred_id=callback_data.id)
69
+ await query.answer("Теперь нужна сумма")
70
+ await window.amount(query.message, state)
71
+
72
+
73
+ @pay.message(dep.CredState.detail)
74
+ async def h_got_cred_dtl(msg: Message, state: FSMContext):
75
+ """Step 4.1f: Fill target cred.name"""
76
+ while True:
77
+ if msg.text.isdigit():
78
+ await state.update_data(detail=int(msg.text))
79
+ break
80
+ else:
81
+ await msg.answer("Пожалуйста, введите корректное число")
82
+ return
83
+ await window.fill_cred_name(msg, state)
84
+
85
+
86
+ @pay.message(dep.CredState.name)
87
+ async def h_got_cred_name(msg: Message, state: FSMContext):
88
+ """Step 5f: Save target cred"""
89
+ data = await state.get_data()
90
+ await state.set_state(None)
91
+ cred, _ = await models.Cred.update_or_create(
92
+ {"name": msg.text}, detail=data["detail"], person_id=data["person_id"], pmcur_id=data["t_pmcur_id"]
93
+ )
94
+ await state.update_data(cred_id=cred.id)
95
+ await window.amount(msg, state)
96
+
97
+
98
+ @pay.callback_query(cd.Ex.filter())
99
+ async def h_got_ex(query: CallbackQuery, callback_data: cd.Ex, state: FSMContext):
100
+ """Step 4c: Save target"""
101
+ await query.message.delete()
102
+ if is_target := await state.get_value("is_target"):
103
+ await state.update_data(t_name=callback_data.name)
104
+ await state.update_data({("t" if is_target else "s") + "_ex_id": callback_data.id})
105
+ await query.answer(f"Биржа {callback_data.name} выбрана")
106
+ await (window.amount(query.message, state) if is_target else window.set_ppo(query.message))
107
+
108
+
109
+ @pay.message(dep.PaymentState.amount)
110
+ async def h_got_amount(msg: Message, state: FSMContext):
111
+ """Step 6: Save target amount"""
112
+ while True:
113
+ if msg.text.isdigit():
114
+ await state.update_data(amount=int(msg.text))
115
+ break
116
+ else:
117
+ await msg.answer("Пожалуйста, введите корректное число")
118
+ return
119
+ await state.set_state(None)
120
+ """Step 7: Select source type"""
121
+ await state.update_data(is_target=False)
122
+ if await state.get_value("is_fiat"):
123
+ await window.type_select(msg, False)
124
+ else:
125
+ await window.cur_select(msg, state) # сразу выбор валюты источника, тк если цель крипта
126
+
127
+
128
+ @pay.callback_query(cd.Pm.filter(F.is_target.__eq__(0)))
129
+ async def h_got_source_pm(query: CallbackQuery, callback_data: cd.Pm, state: FSMContext):
130
+ await query.message.delete()
131
+ await state.update_data(s_pmcur_id=callback_data.pmcur_id)
132
+ await query.answer(callback_data.name)
133
+ await window.set_ppo(query.message)
134
+
135
+
136
+ @pay.callback_query(cd.Ppo.filter())
137
+ async def h_got_ppo(query: CallbackQuery, state: FSMContext, callback_data: cd.Ppo):
138
+ await query.message.delete()
139
+ await state.update_data(ppo=callback_data.num)
140
+ await query.answer(str(callback_data.num))
141
+ await window.set_urgency(query.message)
142
+
143
+
144
+ @pay.callback_query(cd.Time.filter())
145
+ async def process_time_selection(callback: CallbackQuery, callback_data: cd.Time, state: FSMContext):
146
+ await callback.answer()
147
+ pay_until = datetime.now() + timedelta(minutes=callback_data.minutes)
148
+
149
+ data = await state.get_data()
150
+ if ex_id := data.get("t_ex_id", data.get("s_ex_id")):
151
+ if not (actor_id := data.get("actor_id")):
152
+ person_id = data.get("person_id")
153
+ actor_id = await models.Actor.get(ex_id=ex_id, person_id=person_id).values_list("id", flat=True)
154
+ await state.update_data(actor_id=actor_id)
155
+ if not (addr_id := data.get("addr_id")):
156
+ coin_id = data.get("t_coin_id", data.get("s_coin_id"))
157
+ addr_id = await models.Addr.get(coin_id=coin_id, actor_id=actor_id).values_list("id", flat=True)
158
+ await state.update_data(addr_id=addr_id)
159
+ else:
160
+ addr_id = None
161
+
162
+ pay_req = await models.PayReq.create(
163
+ pay_until=pay_until,
164
+ amount=data["amount"],
165
+ parts=data["ppo"],
166
+ payed_at=None,
167
+ addr_id=addr_id,
168
+ cred_id=data["cred_id"],
169
+ user_id=1,
170
+ )
171
+ await state.update_data(
172
+ timer=callback_data.minutes,
173
+ timer_active=True,
174
+ pay_until=pay_until,
175
+ pay_req_id=pay_req.id,
176
+ )
177
+
178
+ await state.set_state(dep.PaymentState.timer)
179
+ create_task(window.run_timer(callback.message, state))
180
+
181
+
182
+ # ACTIONS
183
+ @pay.callback_query(cd.Action.filter(F.act.__eq__(cd.ActionType.received)))
184
+ async def payment_confirmed(query: CallbackQuery, state: FSMContext):
185
+ await query.answer()
186
+ payed_at = datetime.now()
187
+ await state.update_data(timer_active=False, payed_at_formatted=payed_at)
188
+ data = await state.get_data()
189
+ if data.get("pay_req_id"):
190
+ pay_req = await models.PayReq.get(id=data["pay_req_id"])
191
+ pay_req.payed_at = payed_at
192
+ await pay_req.save()
193
+
194
+ builder = InlineKeyboardBuilder()
195
+ builder.button(text="Новый платеж💸", callback_data=cd.PayNav(to=cd.PayStep.t_type))
196
+ await query.message.answer("✅ Платеж успешно подтвержден", reply_markup=builder.as_markup())
197
+ await query.message.delete()
198
+ await state.clear()
199
+
200
+
201
+ @pay.callback_query(cd.Action.filter(F.act.__eq__(cd.ActionType.not_received)))
202
+ async def no_payment(query: CallbackQuery, state: FSMContext):
203
+ await query.answer()
204
+ await state.update_data(timer_active=False)
205
+ await query.message.edit_text("Платеж не получен!")
206
+ await query.message.answer("укажите детали платежа")
207
+ await state.clear()
208
+ await state.set_state(dep.Report.text)
209
+
210
+
211
+ @pay.message(dep.Report.text)
212
+ async def payment_not_specified(msg: Message, state: FSMContext):
213
+ await state.update_data(text=msg.text)
214
+ data = await state.get_data()
215
+ complaint_text = (
216
+ f"Жалоба на неполученный платеж:\n"
217
+ f"Пользователь: @{msg.from_user.username or msg.from_user.id}\n"
218
+ f"Детали платежа: {data["text"]}\n"
219
+ f"Время: {msg.date.strftime('%Y-%m-%d %H:%M:%S')}"
220
+ )
221
+ await msg.bot.send_message(chat_id="1779829771", text=complaint_text)
222
+
223
+
224
+ # NAVIGATION
225
+ @pay.callback_query(cd.PayNav.filter(F.to.in_([cd.PayStep.t_type, cd.PayStep.s_type])))
226
+ async def handle_home(query: CallbackQuery, state: FSMContext):
227
+ await query.message.delete()
228
+ await query.answer()
229
+ await window.type_select(query.message, await state.get_value("is_target"))
230
+
231
+
232
+ @pay.callback_query(cd.PayNav.filter(F.to.in_([cd.PayStep.t_coin, cd.PayStep.s_coin])))
233
+ async def to_coin_select(query: CallbackQuery, state: FSMContext):
234
+ await query.message.delete()
235
+ await query.answer()
236
+ is_target = await state.get_value("is_target")
237
+ pref = "t" if is_target else "s"
238
+ await state.update_data({pref + "_ex_id": None, pref + "_coin_id": None})
239
+ await window.coin_select(query.message, state)
240
+
241
+
242
+ @pay.callback_query(cd.PayNav.filter(F.to.in_([cd.PayStep.t_cur, cd.PayStep.s_cur])))
243
+ async def to_cur_select(query: CallbackQuery, state: FSMContext):
244
+ await query.message.delete()
245
+ await query.answer()
246
+ is_target = await state.get_value("is_target")
247
+ pref = "t" if is_target else "s"
248
+ await state.update_data({pref + "_pmcur_id": None, pref + "_cur_id": None})
249
+ await window.cur_select(query.message, state)
250
+
251
+
252
+ @pay.callback_query(cd.PayNav.filter(F.to.in_([cd.PayStep.t_pm, cd.PayStep.s_pm])))
253
+ async def to_pm_select(query: CallbackQuery, state: FSMContext):
254
+ await query.message.delete()
255
+ await query.answer()
256
+ await window.pm(query.message, state)
257
+
258
+
259
+ @pay.callback_query(cd.PayNav.filter(F.to.__eq__(cd.PayStep.t_cred_dtl)))
260
+ async def back_to_cred_detail(query: CallbackQuery, state: FSMContext):
261
+ await query.answer()
262
+ await state.update_data(detail=None)
263
+ await window.fill_cred_dtl(query.message, state)
264
+ await query.message.delete()
265
+
266
+
267
+ @pay.callback_query(cd.PayNav.filter(F.to.__eq__(cd.PayStep.t_cred_name)))
268
+ async def back_to_cred_name(query: CallbackQuery, state: FSMContext):
269
+ await query.message.delete()
270
+ await query.answer()
271
+ await state.update_data(name=None)
272
+ await window.fill_cred_name(query.message, state)
273
+ await query.message.delete()
274
+
275
+
276
+ @pay.callback_query(cd.PayNav.filter(F.to.in_([cd.PayStep.t_ex, cd.PayStep.s_ex])))
277
+ async def back_to_ex_select(query: CallbackQuery, state: FSMContext):
278
+ await query.message.delete()
279
+ await query.answer()
280
+ await state.update_data({("t" if await state.get_value("is_target") else "s") + "ex_id": None})
281
+ await window.ex_select(query.message, state)
282
+
283
+
284
+ @pay.callback_query(cd.PayNav.filter(F.to.__eq__(cd.PayStep.t_amount)))
285
+ async def back_to_amount(query: CallbackQuery, state: FSMContext):
286
+ await query.message.delete()
287
+ await query.answer()
288
+ await state.update_data(amount=None)
289
+ await window.amount(query.message, state)
290
+
291
+
292
+ @pay.callback_query(cd.PayNav.filter(F.to.in_([cd.PayStep.t_pm])))
293
+ async def back_to_payment(query: CallbackQuery, state: FSMContext):
294
+ await query.message.delete()
295
+ await query.answer()
296
+ await state.update_data(payment=None)
297
+ await window.pm(query.message, state)
@@ -0,0 +1,228 @@
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_schema import models
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
+ ist: bool = msg.bot.store.curr.is_target
15
+ rm = InlineKeyboardMarkup(
16
+ inline_keyboard=[
17
+ [
18
+ InlineKeyboardButton(
19
+ text="Банковская валюта", callback_data=cd.TargetType(is_fiat=1, is_target=ist).pack()
20
+ ),
21
+ InlineKeyboardButton(
22
+ text="Крипта", callback_data=cd.TargetType(is_fiat=0, is_target=msg.bot.store.curr.is_target).pack()
23
+ ),
24
+ ]
25
+ ]
26
+ )
27
+ txt = "Что нужно?" if msg.bot.store.curr.is_target else "Чем платишь?"
28
+ if msg.bot.store.perm.msg_id:
29
+ await msg.edit_text(txt)
30
+ await msg.edit_reply_markup(reply_markup=rm)
31
+ else:
32
+ msg = await msg.answer(txt, reply_markup=rm)
33
+ msg.bot.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)
46
+ await msg.edit_reply_markup(reply_markup=builder.as_markup())
47
+
48
+
49
+ async def coin_select(msg: Message):
50
+ """Common using coin func"""
51
+ builder = InlineKeyboardBuilder()
52
+ store: Store = msg.bot.store
53
+ for coin_id, ticker in store.glob.coins.items():
54
+ builder.button(text=ticker, callback_data=cd.Coin(id=coin_id, is_target=store.curr.is_target))
55
+ builder.button(
56
+ text="Назад к выбору типа",
57
+ callback_data=cd.PayNav(to=cd.PayStep.t_type if store.curr.is_target else cd.PayStep.s_type),
58
+ )
59
+ builder.adjust(1)
60
+ sfx = "ую нужно" if store.curr.is_target else "ой платишь"
61
+ await msg.edit_text("Выберите монету котор" + sfx)
62
+ await msg.edit_reply_markup(reply_markup=builder.as_markup())
63
+
64
+
65
+ async def ex_select(msg: Message):
66
+ store: Store = msg.bot.store
67
+ ist = store.curr.is_target
68
+ coin_id = getattr(store.curr, ("t" if ist else "s") + "_coin_id")
69
+ builder = InlineKeyboardBuilder()
70
+ for ex_id in store.glob.coinexs[coin_id]:
71
+ builder.button(text=store.glob.exs[ex_id], callback_data=cd.Ex(id=ex_id, is_target=ist))
72
+ builder.button(
73
+ text="Назад к выбору монеты", callback_data=cd.PayNav(to=cd.PayStep.t_coin if ist else cd.PayStep.s_coin)
74
+ )
75
+ builder.button(text="Домой", callback_data=cd.PayNav(to=cd.PayStep.t_type))
76
+ builder.adjust(1)
77
+ keyboard = builder.as_markup()
78
+ await msg.edit_text("На какую биржу?" if ist else "С какой биржи?")
79
+ await msg.edit_reply_markup(reply_markup=keyboard)
80
+
81
+
82
+ async def pm(msg: Message):
83
+ store: Store = msg.bot.store
84
+ ist = store.curr.is_target
85
+ cur_id = getattr(store.curr, ("t" if ist else "s") + "_cur_id")
86
+ builder = InlineKeyboardBuilder()
87
+ for pmcur_id in store.glob.curpms[cur_id]:
88
+ builder.button(text=store.glob.pms[pmcur_id], callback_data=cd.Pm(pmcur_id=pmcur_id, is_target=ist))
89
+ builder.button(
90
+ text="Назад к выбору валюты", callback_data=cd.PayNav(to=cd.PayStep.t_cur if ist else cd.PayStep.s_cur)
91
+ )
92
+ builder.button(text="Домой", callback_data=cd.PayNav(to=cd.PayStep.t_type))
93
+ builder.adjust(1)
94
+ keyboard = builder.as_markup()
95
+ await msg.edit_text("На какую платежную систему?" if ist else "C какой платежной системы?")
96
+ await msg.edit_reply_markup(reply_markup=keyboard)
97
+
98
+
99
+ async def fill_cred_dtl(msg: Message, state: FSMContext):
100
+ builder = InlineKeyboardBuilder()
101
+ data = await state.get_data()
102
+ if not (person_id := data.get("person_id")):
103
+ person_id = await models.User.get(username_id=193017646).values_list("person_id", flat=True)
104
+ await state.update_data(person_id=person_id)
105
+ pmcur_id = data["t_pmcur_id"]
106
+ if not (creds := data.get("creds", {}).get(pmcur_id)):
107
+ creds = await models.Cred.filter(person_id=person_id, pmcur_id=pmcur_id)
108
+ await state.update_data({"creds": {pmcur_id: creds}})
109
+ for cred in creds:
110
+ txt = f"{cred.detail}\n{cred.name}"
111
+ if cred.extra:
112
+ txt += f" ({cred.extra})"
113
+ builder.button(text=txt, callback_data=cd.Cred(id=cred.id))
114
+
115
+ builder.button(text="Назад к выбору платежной системы", callback_data=cd.PayNav(to=cd.PayStep.t_pm))
116
+ builder.button(text="Домой", callback_data=cd.PayNav(to=cd.PayStep.t_type))
117
+ builder.adjust(2)
118
+ txt = "Выберите реквизиты куда нужно получить деньги, если в списке нет нужных, то\n"
119
+ await msg.answer(f"{txt}Введите номер для {await state.get_value('t_name')}:", reply_markup=builder.as_markup())
120
+ await state.set_state(dep.CredState.detail)
121
+
122
+
123
+ async def fill_cred_name(msg: Message, state: FSMContext):
124
+ await msg.bot.delete_messages(chat_id=msg.chat.id, message_ids=[msg.message_id, msg.message_id - 1])
125
+ await state.update_data(detail=msg.text)
126
+ builder = InlineKeyboardBuilder()
127
+ builder.button(text="Назад к вводу реквизитов", callback_data=cd.PayNav(to=cd.PayStep.t_cred_dtl))
128
+ builder.button(text="Домой", callback_data=cd.PayNav(to=cd.PayStep.t_type))
129
+ builder.adjust(2)
130
+ data = await state.get_data()
131
+ cur = data["curs"].get(data["t_cur_id"])
132
+ payment = data["t_name"]
133
+ detail = data["detail"]
134
+ await msg.answer(f"{cur}:{payment}:{detail}: Введите имя получателя", reply_markup=builder.as_markup())
135
+ await state.set_state(dep.CredState.name)
136
+
137
+
138
+ async def amount(msg: Message, state: FSMContext):
139
+ await msg.bot.delete_messages(chat_id=msg.chat.id, message_ids=[msg.message_id, msg.message_id - 1])
140
+ """Step 5: Filling target amount"""
141
+ builder = InlineKeyboardBuilder()
142
+
143
+ if await state.get_value("is_fiat"):
144
+ cur_coin = (await state.get_value("curs"))[await state.get_value("t_cur_id")]
145
+ builder.button(text="Назад к вводу имени", callback_data=cd.PayNav(to=cd.PayStep.t_cred_name))
146
+ else:
147
+ cur_coin = (await state.get_value("coins"))[await state.get_value("t_coin_id")]
148
+ builder.button(text="Назад к выбору биржи", callback_data=cd.PayNav(to=cd.PayStep.t_ex))
149
+
150
+ builder.button(text="Домой", callback_data=cd.PayNav(to=cd.PayStep.t_type))
151
+ builder.adjust(2)
152
+
153
+ await msg.answer(
154
+ f"Введите нужную сумму {cur_coin} для {await state.get_value('t_name')}", reply_markup=builder.as_markup()
155
+ )
156
+ await state.set_state(dep.PaymentState.amount)
157
+
158
+
159
+ async def set_ppo(msg: Message):
160
+ rm = InlineKeyboardMarkup(
161
+ inline_keyboard=[
162
+ [
163
+ InlineKeyboardButton(text="Нет", callback_data="ppo:1"),
164
+ InlineKeyboardButton(text="Да", callback_data="ppo:2"),
165
+ ],
166
+ [InlineKeyboardButton(text="Да хоть на 3", callback_data="ppo:3")],
167
+ ]
168
+ )
169
+ await msg.answer("На 2 платежа сможем разбить?", reply_markup=rm)
170
+
171
+
172
+ async def set_urgency(msg: Message):
173
+ builder = InlineKeyboardBuilder()
174
+ builder.button(text="1 мин", callback_data=cd.Time(minutes=1))
175
+ builder.button(text="5 мин", callback_data=cd.Time(minutes=5))
176
+ builder.button(text="30 мин", callback_data=cd.Time(minutes=30))
177
+ builder.button(text="3 часа", callback_data=cd.Time(minutes=180))
178
+ builder.button(text="сутки", callback_data=cd.Time(minutes=60 * 24))
179
+ builder.button(text="Назад к вводу платежей", callback_data=cd.PayNav(to=cd.PayStep.t_pm))
180
+ builder.button(text="Домой", callback_data=cd.PayNav(to=cd.PayStep.t_type))
181
+ builder.adjust(2, 2, 1, 1, 1)
182
+ await msg.answer("Сколько можешь ждать?", reply_markup=builder.as_markup())
183
+
184
+
185
+ async def run_timer(message, state: FSMContext):
186
+ builder = InlineKeyboardBuilder()
187
+ builder.button(text="Платеж получен", callback_data=cd.Action(act=cd.ActionType.received))
188
+
189
+ data = await state.get_value("timer")
190
+ seconds = data * 60
191
+
192
+ def format(sec):
193
+ days = sec // (24 * 3600)
194
+ sec %= 24 * 3600
195
+ hours = sec // 3600
196
+ sec %= 3600
197
+ minutes = sec // 60
198
+ sec %= 60
199
+
200
+ if days > 0:
201
+ return f"{days}д {hours:02d}:{minutes:02d}:{sec:02d}"
202
+ elif hours > 0:
203
+ return f"{hours:02d}:{minutes:02d}:{sec:02d}"
204
+ else:
205
+ return f"{minutes:02d}:{sec:02d}"
206
+
207
+ try:
208
+ await message.edit_text(f"⏳ Осталось {format(seconds)}", reply_markup=builder.as_markup())
209
+ except Exception:
210
+ return
211
+
212
+ while seconds > 0:
213
+ await sleep(1)
214
+ seconds -= 1
215
+ try:
216
+ await message.edit_text(f"⏳ Осталось {format(seconds)}", reply_markup=builder.as_markup())
217
+ await state.update_data(timer=seconds)
218
+ except Exception:
219
+ break
220
+
221
+ if seconds <= 0:
222
+ builder = InlineKeyboardBuilder()
223
+ builder.button(text="Платеж получен", callback_data=cd.Action(act=cd.ActionType.received))
224
+ builder.button(text="Денег нет", callback_data=cd.Action(act=cd.ActionType.not_received))
225
+ try:
226
+ await message.edit_text("⏳ Время вышло!", reply_markup=builder.as_markup())
227
+ except Exception:
228
+ pass
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xync-bot
3
- Version: 0.3.7.dev4
3
+ Version: 0.3.24.dev4
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,20 @@
1
+ xync_bot/__init__.py,sha256=0m9zUYZUJHEJUMb24CU10wYfCIAg8eourNFlBLsHgWU,705
2
+ xync_bot/loader.py,sha256=4ZeR-yVMoOmswdLS0UEBG19K7JVcuvH6WpP-_0yAK3I,573
3
+ xync_bot/shared.py,sha256=MlKkTrsT29l7fF6-qAN9FO14cSuXuOuYxbNY5F4S2w4,137
4
+ xync_bot/typs.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ xync_bot/routers/__init__.py,sha256=NvHk-tI-27BBtI8HGB95s46xo5_z5jNEYqeEeUfVWw8,2544
6
+ xync_bot/routers/main.py,sha256=FumWa48ORhV77Df6NbEosHfgmFIe_Y2ci6IkJCvU4Zs,9535
7
+ xync_bot/routers/order.py,sha256=ZKWDLyiWrXzcR-aHKLBTBCACwp-P0Vvnr22T-EuLHaM,274
8
+ xync_bot/routers/photo.py,sha256=aq6ImIOoZQYTW-lEy26qjgj5TYAuk4bQjgiCv64mPJs,1203
9
+ xync_bot/routers/vpn.py,sha256=qKK55UrjEZeDvu7ljWXNUFBFgXTPTIEaCT2OAmKWky4,2219
10
+ xync_bot/routers/xicon.png,sha256=O57_kvzhVcCXSoGYZ61m0dW9pizY6gxR8Yj5aeCP0RQ,429283
11
+ xync_bot/routers/cond/__init__.py,sha256=It4djVO8AxXL1I76buRz8yYF12dsjXaa4WNtPdb7CFc,4333
12
+ xync_bot/routers/cond/func.py,sha256=m0NWDKunbqDJQmhv_5UnpjxjRzn78GFG94ThOFLVlQo,4720
13
+ xync_bot/routers/pay/cd.py,sha256=Ia0fN8B6ZPKi45z_k1f7O55C9n4PnX-EhebSHRiszSs,901
14
+ xync_bot/routers/pay/dep.py,sha256=QoOhmqKj8QesiIT6QqEomR2xu83cg9Z8mh6oquJKZnM,2208
15
+ xync_bot/routers/pay/handler.py,sha256=bTczwWws5lQj8sbnw0Vo-uZl5RApAVTSj_SEHsRGUwE,11691
16
+ xync_bot/routers/pay/window.py,sha256=h3jk42RJphD0TtX7IMCrXQERS2jGdRFuBf9oGJjRd0k,10184
17
+ xync_bot-0.3.24.dev4.dist-info/METADATA,sha256=Df0VsJlwjs2TZ9S5S1GJzzfhmOdouuhqmsnem0EqzLk,751
18
+ xync_bot-0.3.24.dev4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
19
+ xync_bot-0.3.24.dev4.dist-info/top_level.txt,sha256=O2IjMc1ryAf0rwIXWohSNT5Kzcs9johgKRDz8lCC0rs,9
20
+ xync_bot-0.3.24.dev4.dist-info/RECORD,,
@@ -1,133 +0,0 @@
1
- from aiogram import Router, F
2
- from aiogram.filters import Command
3
- from aiogram.types import Message
4
- from xync_schema import models
5
- from aiogram.types import ReplyKeyboardMarkup, KeyboardButton
6
- from aiogram.utils.keyboard import InlineKeyboardMarkup, InlineKeyboardButton
7
- from aiogram import types
8
-
9
- from aiogram.fsm.state import State, StatesGroup
10
- from aiogram.fsm.context import FSMContext
11
-
12
- pay = Router()
13
-
14
-
15
- class Cred(StatesGroup):
16
- detail = State()
17
- extra = State()
18
-
19
-
20
- class Addr(StatesGroup):
21
- name = State()
22
-
23
-
24
- @pay.message(Command("pay"))
25
- async def main(msg: Message):
26
- start = ReplyKeyboardMarkup(
27
- keyboard=[[KeyboardButton(text="крипта"), KeyboardButton(text="валюта (фиат)")]], resize_keyboard=True
28
- )
29
- await msg.answer("что нужно?", reply_markup=start)
30
-
31
-
32
- @pay.message(F.text == "валюта (фиат)")
33
- async def cur(msg: types.Message):
34
- currencies = await models.Cur.all()
35
- buttons = [[InlineKeyboardButton(text=cur.ticker, callback_data=f"cur_{cur.id}")] for cur in currencies]
36
- keyboard = InlineKeyboardMarkup(inline_keyboard=buttons)
37
- await msg.answer("Выберите валюту:", reply_markup=keyboard)
38
-
39
-
40
- @pay.message(F.text == "крипта")
41
- async def coin(msg: types.Message):
42
- crypt = await models.Coin.all()
43
- buttons = [[InlineKeyboardButton(text=coin.ticker, callback_data=f"coin_{coin.id}")] for coin in crypt]
44
- keyboard = InlineKeyboardMarkup(inline_keyboard=buttons)
45
- await msg.answer("Выберите крипту:", reply_markup=keyboard)
46
-
47
-
48
- @pay.callback_query(F.data.startswith("coin_"))
49
- async def coinex(query: types.CallbackQuery):
50
- ticker = query.data.replace("coin_", "")
51
- ex_id = await models.Coinex.filter(coin_id=ticker).values_list("ex_id", flat=True)
52
- ex = await models.Ex.filter(id__in=ex_id).values_list("name", flat=True)
53
- if not ex:
54
- await query.message.answer("Такой биржи нет")
55
- else:
56
- buttons = [[InlineKeyboardButton(text=i, callback_data=f"ad_{i}")] for i in ex]
57
- keyboard = InlineKeyboardMarkup(inline_keyboard=buttons)
58
- await query.message.answer("Выберите биржу", reply_markup=keyboard)
59
-
60
-
61
- @pay.callback_query(F.data.startswith("cur_"))
62
- async def pm(query: types.CallbackQuery, state: FSMContext):
63
- ticker = query.data.replace("cur_", "")
64
- pmcur = await models.Pmcur.filter(cur_id=ticker).values_list("pm_id", flat=True)
65
- pmex = await models.Pmex.filter(pm_id__in=pmcur).values_list("id", flat=True)
66
- pm = await models.PmexBank.filter(pmex_id__in=pmex).values_list("name", flat=True)
67
- if not pm:
68
- await query.message.answer("Такой платежки нет")
69
- else:
70
- buttons = [[InlineKeyboardButton(text=i, callback_data=f"pm_{i}")] for i in pm]
71
- keyboard = InlineKeyboardMarkup(inline_keyboard=buttons)
72
- await query.message.answer("Выберите платежку", reply_markup=keyboard)
73
-
74
-
75
- # 4) для cur
76
- @pay.callback_query(F.data.startswith("pm_"))
77
- async def cred(query: types.CallbackQuery, state: FSMContext):
78
- name = query.data.replace("pm_", "")
79
- await state.update_data(name=name)
80
- pmex_id = await models.PmexBank.filter(name=name).values_list("pmex_id", flat=True)
81
- pm_id = await models.Pmex.filter(id__in=pmex_id).values_list("pm_id", flat=True)
82
- pmcur = await models.Pmcur.get(id__in=pm_id)
83
- await state.update_data(pmcur_id=pmcur.id)
84
- await query.message.answer("Введите реквизиты")
85
- await state.set_state(Cred.detail)
86
-
87
-
88
- @pay.message(Cred.detail)
89
- async def cred_detail(msg: types.Message, state: FSMContext):
90
- user_id = msg.from_user.id
91
- # user_id = 193017646
92
- person_id = await models.User.get(username_id=user_id)
93
- await state.update_data(person_id=person_id.person_id)
94
- await state.update_data(detail=msg.text)
95
- await msg.answer("Введите доп информацию")
96
- await state.set_state(Cred.extra)
97
-
98
-
99
- @pay.message(Cred.extra)
100
- async def create_cred(msg: types.Message, state: FSMContext):
101
- await state.update_data(extra=msg.text)
102
- data = await state.get_data()
103
- await state.clear()
104
- # print(data)
105
- data_create = {
106
- "detail": data["detail"],
107
- "name": data["name"],
108
- "extra": data["extra"],
109
- "person_id": data["person_id"],
110
- "pmcur_id": data["pmcur_id"],
111
- }
112
- await models.Cred.create(**data_create)
113
-
114
-
115
- # 4) для coin
116
- @pay.callback_query(F.data.startswith("ad_"))
117
- async def addr(query: types.CallbackQuery, state: FSMContext):
118
- name = query.data.replace("ad_", "")
119
- ex = await models.Ex.filter(name=name).values_list("id", flat=True)
120
- await state.update_data(ex_id=ex)
121
- await query.message.answer("Введите имя")
122
- await state.set_state(Addr.name)
123
-
124
-
125
- @pay.message(Addr.name)
126
- async def addr_name(msg: types.Message, state: FSMContext):
127
- # user_id = msg.from_user.id
128
- user_id = 193017646
129
- person_id = await models.User.get(username_id=user_id)
130
- await state.update_data(person_id=person_id.person_id)
131
- await state.update_data(name=msg.text)
132
- await state.get_data()
133
- await state.clear()
@@ -1,17 +0,0 @@
1
- xync_bot/__init__.py,sha256=wiZpB8Bv4jjaHeGS_yt9HKtuLTHwx4nCsCgcrMesCFE,586
2
- xync_bot/loader.py,sha256=wnhRRMJ6KSFAFZnDBGg9mbbktq34VHtcNSt89WuPn04,558
3
- xync_bot/shared.py,sha256=MlKkTrsT29l7fF6-qAN9FO14cSuXuOuYxbNY5F4S2w4,137
4
- xync_bot/typs.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- xync_bot/routers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- xync_bot/routers/main.py,sha256=FumWa48ORhV77Df6NbEosHfgmFIe_Y2ci6IkJCvU4Zs,9535
7
- xync_bot/routers/order.py,sha256=ZKWDLyiWrXzcR-aHKLBTBCACwp-P0Vvnr22T-EuLHaM,274
8
- xync_bot/routers/photo.py,sha256=aq6ImIOoZQYTW-lEy26qjgj5TYAuk4bQjgiCv64mPJs,1203
9
- xync_bot/routers/vpn.py,sha256=qKK55UrjEZeDvu7ljWXNUFBFgXTPTIEaCT2OAmKWky4,2219
10
- xync_bot/routers/xicon.png,sha256=O57_kvzhVcCXSoGYZ61m0dW9pizY6gxR8Yj5aeCP0RQ,429283
11
- xync_bot/routers/cond/__init__.py,sha256=It4djVO8AxXL1I76buRz8yYF12dsjXaa4WNtPdb7CFc,4333
12
- xync_bot/routers/cond/func.py,sha256=m0NWDKunbqDJQmhv_5UnpjxjRzn78GFG94ThOFLVlQo,4720
13
- xync_bot/routers/pay/main.py,sha256=5swOvvKF2XA2UAwHewdidMoMONV4acTwR0mPyzA0ezA,5116
14
- xync_bot-0.3.7.dev4.dist-info/METADATA,sha256=4T0s0NFTh9QNuQ3JpSLKarYsXY-OZjN0vTjGrkNbeQI,750
15
- xync_bot-0.3.7.dev4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
16
- xync_bot-0.3.7.dev4.dist-info/top_level.txt,sha256=O2IjMc1ryAf0rwIXWohSNT5Kzcs9johgKRDz8lCC0rs,9
17
- xync_bot-0.3.7.dev4.dist-info/RECORD,,