xync-bot 0.3.7.dev1__py3-none-any.whl → 0.3.24__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/__main__.py +36 -0
- xync_bot/loader.py +2 -0
- xync_bot/routers/__init__.py +39 -6
- xync_bot/routers/cond/__init__.py +67 -155
- xync_bot/routers/cond/func.py +118 -0
- xync_bot/routers/{main.py → main/handler.py} +53 -86
- xync_bot/routers/pay/cd.py +49 -0
- xync_bot/routers/pay/dep.py +270 -0
- xync_bot/routers/pay/handler.py +247 -0
- xync_bot/routers/pay/window.py +244 -0
- xync_bot/shared.py +19 -0
- xync_bot/store.py +150 -0
- {xync_bot-0.3.7.dev1.dist-info → xync_bot-0.3.24.dist-info}/METADATA +3 -1
- xync_bot-0.3.24.dist-info/RECORD +22 -0
- xync_bot/__init__.py +0 -20
- xync_bot-0.3.7.dev1.dist-info/RECORD +0 -16
- /xync_bot/routers/{cond/cond.py → main/__init__.py} +0 -0
- {xync_bot-0.3.7.dev1.dist-info → xync_bot-0.3.24.dist-info}/WHEEL +0 -0
- {xync_bot-0.3.7.dev1.dist-info → xync_bot-0.3.24.dist-info}/top_level.txt +0 -0
xync_bot/__main__.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from asyncio import run
|
|
3
|
+
|
|
4
|
+
from PGram import Bot
|
|
5
|
+
from aiogram.client.default import DefaultBotProperties
|
|
6
|
+
from aiogram.enums import UpdateType
|
|
7
|
+
from x_model import init_db
|
|
8
|
+
|
|
9
|
+
from xync_bot.routers.main.handler import mr
|
|
10
|
+
from xync_bot.routers.cond import cr
|
|
11
|
+
from xync_bot.routers.pay.handler import pr
|
|
12
|
+
from xync_bot.routers import last
|
|
13
|
+
from xync_bot.routers.pay.dep import Store
|
|
14
|
+
|
|
15
|
+
au = [
|
|
16
|
+
UpdateType.MESSAGE,
|
|
17
|
+
UpdateType.CALLBACK_QUERY,
|
|
18
|
+
UpdateType.CHAT_MEMBER,
|
|
19
|
+
UpdateType.MY_CHAT_MEMBER,
|
|
20
|
+
] # , UpdateType.CHAT_JOIN_REQUEST
|
|
21
|
+
bot = Bot([cr, pr, mr, last], Store(), au, default=DefaultBotProperties(parse_mode="HTML"))
|
|
22
|
+
|
|
23
|
+
if __name__ == "__main__":
|
|
24
|
+
from xync_bot.loader import TOKEN, TORM
|
|
25
|
+
|
|
26
|
+
logging.basicConfig(level=logging.INFO)
|
|
27
|
+
|
|
28
|
+
async def main() -> None:
|
|
29
|
+
cn = await init_db(TORM)
|
|
30
|
+
bot.dp.workflow_data["store"].glob = await Store.Global() # todo: refact store loading
|
|
31
|
+
await bot.start(
|
|
32
|
+
TOKEN,
|
|
33
|
+
cn,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
run(main())
|
xync_bot/loader.py
CHANGED
xync_bot/routers/__init__.py
CHANGED
|
@@ -1,8 +1,41 @@
|
|
|
1
|
-
|
|
2
|
-
from aiogram.utils.web_app import WebAppUser
|
|
3
|
-
from xync_schema import models
|
|
1
|
+
import logging
|
|
4
2
|
|
|
3
|
+
from aiogram import Router, F
|
|
4
|
+
from aiogram.enums import ContentType
|
|
5
|
+
from aiogram.exceptions import TelegramBadRequest
|
|
6
|
+
from aiogram.types import Message
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
last = Router(name="last")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@last.message(
|
|
12
|
+
F.content_type.not_in(
|
|
13
|
+
{
|
|
14
|
+
ContentType.NEW_CHAT_MEMBERS,
|
|
15
|
+
# ContentType.LEFT_CHAT_MEMBER,
|
|
16
|
+
# ContentType.SUPERGROUP_CHAT_CREATED,
|
|
17
|
+
# ContentType.NEW_CHAT_PHOTO,
|
|
18
|
+
# ContentType.FORUM_TOPIC_CREATED,
|
|
19
|
+
# ContentType.FORUM_TOPIC_EDITED,
|
|
20
|
+
ContentType.FORUM_TOPIC_CLOSED,
|
|
21
|
+
# ContentType.GENERAL_FORUM_TOPIC_HIDDEN, # deletable
|
|
22
|
+
}
|
|
23
|
+
)
|
|
24
|
+
)
|
|
25
|
+
async def del_cbq(msg: Message):
|
|
26
|
+
try:
|
|
27
|
+
await msg.delete()
|
|
28
|
+
logging.info({"DELETED": msg.model_dump(exclude_none=True)})
|
|
29
|
+
except TelegramBadRequest:
|
|
30
|
+
logging.error({"NOT_DELETED": msg.model_dump(exclude_none=True)})
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@last.message()
|
|
34
|
+
async def all_rest(msg: Message):
|
|
35
|
+
logging.warning(
|
|
36
|
+
{
|
|
37
|
+
"NO_HANDLED": msg.model_dump(
|
|
38
|
+
exclude_none=True,
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
)
|
|
@@ -1,114 +1,33 @@
|
|
|
1
|
-
import re
|
|
2
|
-
from enum import IntEnum
|
|
3
|
-
from inspect import isclass
|
|
4
|
-
from typing import Coroutine
|
|
5
|
-
|
|
6
1
|
from aiogram import Router, F
|
|
7
|
-
from aiogram.
|
|
2
|
+
from aiogram.exceptions import TelegramBadRequest
|
|
3
|
+
from aiogram.filters import Command
|
|
8
4
|
from aiogram.fsm.context import FSMContext
|
|
9
|
-
from aiogram.types import
|
|
10
|
-
Message,
|
|
11
|
-
ReplyKeyboardMarkup,
|
|
12
|
-
KeyboardButton,
|
|
13
|
-
InlineKeyboardMarkup,
|
|
14
|
-
InlineKeyboardButton,
|
|
15
|
-
CallbackQuery,
|
|
16
|
-
# ReplyKeyboardRemove,
|
|
17
|
-
)
|
|
18
|
-
from cyrtranslit import to_latin
|
|
5
|
+
from aiogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery
|
|
19
6
|
from xync_schema import models
|
|
20
|
-
from xync_schema.enums import SynonymType
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
for syn in await models.Synonym.all():
|
|
29
|
-
lb, rb = "\\b" if syn.boundary & Boundary.left else "", "\\b" if syn.boundary & Boundary.right else ""
|
|
30
|
-
if syn.typ == SynonymType.bank_side:
|
|
31
|
-
syn.txt.replace("#banks#", f"({bnks})")
|
|
32
|
-
if syn.is_re or syn.txt in txt:
|
|
33
|
-
pattern = re.compile(lb + syn.txt + rb)
|
|
34
|
-
if match := re.search(pattern, txt):
|
|
35
|
-
g = match.group()
|
|
36
|
-
val, hval = await get_val(syn.typ, syn.val)
|
|
37
|
-
val = syn.typ.name + (f'="{hval}"' if hval else "")
|
|
38
|
-
txt = re.sub(pattern, f"<code>{g}</code><tg-spoiler>[{val}]</tg-spoiler>", txt)
|
|
39
|
-
return txt
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
async def cbanks(bnid: str) -> list[tuple[int, str]]:
|
|
43
|
-
beginning = to_latin(bnid[:2], lang_code="ru")
|
|
44
|
-
return await models.Pm.filter(norm__startswith=beginning, bank=True).values_list("id", "norm")
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
async def cppo(txt: str) -> list[tuple[int, str]]:
|
|
48
|
-
opts = re.findall(r"\d+", txt) or [1, 2, 3, 5, 10]
|
|
49
|
-
return [(o, str(o)) for o in opts]
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
synopts: dict[SynonymType, list[str] | type(IntEnum) | None | Coroutine] = {
|
|
53
|
-
SynonymType.name: ["not_slavic", "slavic"],
|
|
54
|
-
SynonymType.ppo: cppo,
|
|
55
|
-
SynonymType.from_party: Party,
|
|
56
|
-
SynonymType.to_party: Party,
|
|
57
|
-
SynonymType.slip_req: Slip,
|
|
58
|
-
SynonymType.slip_send: Slip,
|
|
59
|
-
SynonymType.abuser: AbuserType,
|
|
60
|
-
SynonymType.scale: ["1", "10", "100", "1000"],
|
|
61
|
-
SynonymType.slavic: NameType,
|
|
62
|
-
SynonymType.mtl_like: None,
|
|
63
|
-
SynonymType.bank: cbanks,
|
|
64
|
-
SynonymType.bank_side: ["except", "only"],
|
|
65
|
-
}
|
|
66
|
-
rkm = ReplyKeyboardMarkup(
|
|
67
|
-
keyboard=[
|
|
68
|
-
[KeyboardButton(text="ppo"), KeyboardButton(text="abuser")],
|
|
69
|
-
[KeyboardButton(text="from_party"), KeyboardButton(text="to_party")],
|
|
70
|
-
[KeyboardButton(text="slip_send"), KeyboardButton(text="slip_req")],
|
|
71
|
-
[KeyboardButton(text="name"), KeyboardButton(text="slavic")],
|
|
72
|
-
[KeyboardButton(text="scale"), KeyboardButton(text="mtl_like")],
|
|
73
|
-
[KeyboardButton(text="bank"), KeyboardButton(text="bank_side")],
|
|
74
|
-
],
|
|
75
|
-
one_time_keyboard=True,
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
async def get_val(typ: SynonymType.__class__, val: str) -> tuple[SynonymType | int | bool, str]:
|
|
80
|
-
if isinstance(val, str) and val.isnumeric():
|
|
81
|
-
val = int(val)
|
|
82
|
-
if isclass(lst := synopts[typ]) and issubclass(lst, IntEnum):
|
|
83
|
-
return (v := lst(val)), v.name
|
|
84
|
-
elif isinstance(lst, list):
|
|
85
|
-
return val, lst[val]
|
|
86
|
-
elif typ == SynonymType.bank:
|
|
87
|
-
return val, (await models.Pm[val]).norm
|
|
88
|
-
return val, val
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
async def btns(typ: SynonymType.__class__, txt: str = None) -> InlineKeyboardMarkup | None:
|
|
92
|
-
if lst := synopts[typ]:
|
|
93
|
-
if isinstance(lst, list):
|
|
94
|
-
kb = [[InlineKeyboardButton(text=n, callback_data=f"st:{typ.name}:{i}")] for i, n in enumerate(lst)]
|
|
95
|
-
elif isclass(lst) and issubclass(lst, IntEnum):
|
|
96
|
-
kb = [[InlineKeyboardButton(text=i.name, callback_data=f"st:{typ.name}:{i.value}")] for i in lst]
|
|
97
|
-
else:
|
|
98
|
-
kb = [[InlineKeyboardButton(text=n, callback_data=f"st:{typ.name}:{i}")] for i, n in await lst(txt)]
|
|
99
|
-
return InlineKeyboardMarkup(inline_keyboard=kb)
|
|
100
|
-
else:
|
|
101
|
-
return lst
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
@r.message(CommandStart())
|
|
7
|
+
from xync_schema.enums import SynonymType
|
|
8
|
+
|
|
9
|
+
from xync_bot.routers.cond.func import wrap_cond, get_val, btns, rkm, ikm, SynTypeCd, CondCd
|
|
10
|
+
|
|
11
|
+
cr = Router(name="cond")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@cr.message(Command("cond"))
|
|
105
15
|
async def start(msg: Message, state: FSMContext):
|
|
16
|
+
await msg.reply('Заполняем синонимы признаков условий объявлений: "ссылка на инструкцию"', reply_markup=rkm)
|
|
17
|
+
await show_new_cond(msg, state)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
async def show_new_cond(msg: Message, state: FSMContext):
|
|
106
21
|
cond = await models.Cond.filter(parsed__isnull=True).order_by("-created_at").first().prefetch_related("parsed")
|
|
107
|
-
await state.set_data({"
|
|
108
|
-
await msg
|
|
22
|
+
await state.set_data({"cond": cond})
|
|
23
|
+
await show_cond(msg, cond)
|
|
24
|
+
|
|
109
25
|
|
|
26
|
+
async def show_cond(msg: Message, cond: models.Cond):
|
|
27
|
+
await msg.answer(await wrap_cond(cond), reply_markup=ikm)
|
|
110
28
|
|
|
111
|
-
|
|
29
|
+
|
|
30
|
+
@cr.message(F.quote)
|
|
112
31
|
async def got_synonym(msg: Message, state: FSMContext):
|
|
113
32
|
if not (msg.text in {st.name for st in SynonymType} and SynonymType[msg.text]):
|
|
114
33
|
return await msg.reply_text(
|
|
@@ -122,58 +41,51 @@ async def got_synonym(msg: Message, state: FSMContext):
|
|
|
122
41
|
await models.Synonym.update_or_create({"typ": typ}, txt=msg.quote.text)
|
|
123
42
|
if rm := await btns(typ, msg.quote.text):
|
|
124
43
|
return await msg.answer("Уточните", reply_markup=rm, reply_to_message_id=msg.message_id)
|
|
125
|
-
await syn_result(msg,
|
|
44
|
+
await syn_result(msg, SynTypeCd(typ=typ.name, val=1), state)
|
|
126
45
|
return None
|
|
127
46
|
|
|
128
47
|
|
|
129
|
-
@
|
|
130
|
-
async def got_synonym_val(cbq: CallbackQuery, state: FSMContext):
|
|
131
|
-
await syn_result(cbq.message,
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
async def syn_result(msg: Message,
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
InlineKeyboardButton(text="Готово! Давай новый", callback_data=f"cond:complete:{cid}"),
|
|
149
|
-
InlineKeyboardButton(text="Продолжить с этим текстом", callback_data=f"cond:process:{cid}"),
|
|
150
|
-
]
|
|
48
|
+
@cr.callback_query(SynTypeCd.filter())
|
|
49
|
+
async def got_synonym_val(cbq: CallbackQuery, callback_data: SynTypeCd, state: FSMContext):
|
|
50
|
+
await syn_result(cbq.message, callback_data, state)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
async def syn_result(msg: Message, cbd: SynTypeCd, state: FSMContext):
|
|
54
|
+
cond: models.Cond = await state.get_value("cond")
|
|
55
|
+
typ = SynonymType[cbd.typ]
|
|
56
|
+
val, hval = await get_val(typ, cbd.val)
|
|
57
|
+
syntext = await state.get_value("syntext")
|
|
58
|
+
syn, _ = await models.Synonym.update_or_create({"val": val}, typ=typ, txt=syntext)
|
|
59
|
+
await models.CondParsed.update_or_create({typ.name: val}, cond_id=cond.id)
|
|
60
|
+
await msg.answer(
|
|
61
|
+
f'Текст "{syntext}" определен как синоним для `{typ.name}` со значением {hval}',
|
|
62
|
+
reply_markup=InlineKeyboardMarkup(
|
|
63
|
+
inline_keyboard=[
|
|
64
|
+
[
|
|
65
|
+
InlineKeyboardButton(text="Готово! Давай новый", callback_data="cond:complete"),
|
|
66
|
+
InlineKeyboardButton(text="Продолжить с этим текстом", callback_data="cond:continue"),
|
|
151
67
|
]
|
|
152
|
-
|
|
153
|
-
)
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
@r.message()
|
|
177
|
-
async def unknown(msg: Message):
|
|
178
|
-
# user = await User.get(username_id=msg.from_user.id)
|
|
179
|
-
await msg.delete()
|
|
68
|
+
]
|
|
69
|
+
),
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@cr.callback_query(CondCd.filter())
|
|
74
|
+
async def got_action(cbq: CallbackQuery, callback_data: CondCd, state: FSMContext):
|
|
75
|
+
cond: models.Cond = await state.get_value("cond")
|
|
76
|
+
if callback_data.act == "complete":
|
|
77
|
+
await models.CondParsed.update_or_create({"parsed": True}, cond=cond)
|
|
78
|
+
await show_new_cond(cbq.message, state)
|
|
79
|
+
elif callback_data.act == "pass":
|
|
80
|
+
await show_new_cond(cbq.message, state)
|
|
81
|
+
elif callback_data.act == "refresh":
|
|
82
|
+
try:
|
|
83
|
+
await cbq.message.edit_text(await wrap_cond(cond), reply_markup=ikm)
|
|
84
|
+
except TelegramBadRequest as e:
|
|
85
|
+
if "message is not modified:" in e.message:
|
|
86
|
+
return await cbq.answer("Текст не изменился")
|
|
87
|
+
raise e
|
|
88
|
+
elif callback_data.act == "continue":
|
|
89
|
+
await (await state.get_value("cmsg")).delete()
|
|
90
|
+
await show_cond(cbq.message, cond)
|
|
91
|
+
return await cbq.answer(callback_data.act)
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from enum import IntEnum
|
|
3
|
+
from inspect import isclass
|
|
4
|
+
from typing import Coroutine
|
|
5
|
+
|
|
6
|
+
from aiogram.filters.callback_data import CallbackData
|
|
7
|
+
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton, ReplyKeyboardMarkup, KeyboardButton
|
|
8
|
+
from cyrtranslit import to_latin
|
|
9
|
+
from xync_schema import models
|
|
10
|
+
from xync_schema.enums import SynonymType, Boundary, Party, Slip, AbuserType, NameType
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class SynTypeCd(CallbackData, prefix="st"):
|
|
14
|
+
typ: str
|
|
15
|
+
val: int
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class CondCd(CallbackData, prefix="cond"):
|
|
19
|
+
act: str
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
async def wrap_cond(cond: models.Cond):
|
|
23
|
+
bnks = await models.Synonym.filter(typ=SynonymType.bank)
|
|
24
|
+
bnks = "|".join("\\b" + b.txt + ("\\b" if b.boundary & Boundary.right else "") for b in bnks)
|
|
25
|
+
ad = await models.Ad.filter(cond=cond).order_by("-updated_at").prefetch_related("ex", "pair_side").first()
|
|
26
|
+
hdr = ("SELL" if ad.pair_side.is_sell else "BUY") + f":{ad.price} [{ad.min_fiat}]"
|
|
27
|
+
if (mx := (ad.max_fiat or ad.amount)) > ad.min_fiat:
|
|
28
|
+
hdr += f"->[{mx}]"
|
|
29
|
+
txt = cond.raw_txt
|
|
30
|
+
for syn in await models.Synonym.all():
|
|
31
|
+
lb, rb = "\\b" if syn.boundary & Boundary.left else "", "\\b" if syn.boundary & Boundary.right else ""
|
|
32
|
+
if syn.typ == SynonymType.bank_side:
|
|
33
|
+
syn.txt.replace("#banks#", f"({bnks})")
|
|
34
|
+
if syn.is_re or syn.txt in txt:
|
|
35
|
+
pattern = re.compile(lb + syn.txt + rb)
|
|
36
|
+
if match := re.search(pattern, txt):
|
|
37
|
+
g = match.group()
|
|
38
|
+
val, hval = await get_val(syn.typ, syn.val)
|
|
39
|
+
val = syn.typ.name + (f'="{hval}"' if hval else "")
|
|
40
|
+
txt = re.sub(pattern, f"<code>{g}</code><tg-spoiler>[{val}]</tg-spoiler>", txt)
|
|
41
|
+
return f"<blockquote>{hdr} {ad.ex.name}</blockquote>{txt}"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
async def cbanks(bnid: str) -> list[tuple[int, str]]:
|
|
45
|
+
beginning = to_latin(bnid[:2], lang_code="ru")
|
|
46
|
+
return await models.Pm.filter(norm__startswith=beginning, bank=True).values_list("id", "norm")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
async def cppo(txt: str) -> list[tuple[int, str]]:
|
|
50
|
+
opts = re.findall(r"\d+", txt) or [1, 1000, 5000]
|
|
51
|
+
return [(o, str(o)) for o in opts]
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
async def contact(txt: str) -> list[tuple[int, str]]: ...
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
synopts: dict[SynonymType, list[str] | type(IntEnum) | None | Coroutine] = {
|
|
58
|
+
SynonymType.name: ["not_slavic", "slavic"],
|
|
59
|
+
SynonymType.ppo: cppo,
|
|
60
|
+
SynonymType.from_party: Party,
|
|
61
|
+
SynonymType.to_party: Party,
|
|
62
|
+
SynonymType.slip_req: Slip,
|
|
63
|
+
SynonymType.slip_send: Slip,
|
|
64
|
+
SynonymType.abuser: AbuserType,
|
|
65
|
+
SynonymType.scale: ["1", "100", "1000", "5000"],
|
|
66
|
+
SynonymType.slavic: NameType,
|
|
67
|
+
SynonymType.mtl_like: None,
|
|
68
|
+
SynonymType.bank: cbanks,
|
|
69
|
+
SynonymType.bank_side: ["except", "only"],
|
|
70
|
+
SynonymType.sbp_strict: ["no", "sbp", "card"],
|
|
71
|
+
SynonymType.contact: contact,
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
rkm = ReplyKeyboardMarkup(
|
|
75
|
+
keyboard=[
|
|
76
|
+
[KeyboardButton(text="ppo"), KeyboardButton(text="abuser")],
|
|
77
|
+
[KeyboardButton(text="from_party"), KeyboardButton(text="to_party")],
|
|
78
|
+
[KeyboardButton(text="slip_send"), KeyboardButton(text="slip_req")],
|
|
79
|
+
[KeyboardButton(text="name"), KeyboardButton(text="slavic")],
|
|
80
|
+
[KeyboardButton(text="scale"), KeyboardButton(text="mtl_like")],
|
|
81
|
+
[KeyboardButton(text="bank"), KeyboardButton(text="bank_side")],
|
|
82
|
+
[KeyboardButton(text="sbp_strict"), KeyboardButton(text="contact")],
|
|
83
|
+
],
|
|
84
|
+
# one_time_keyboard=True,
|
|
85
|
+
)
|
|
86
|
+
ikm = InlineKeyboardMarkup(
|
|
87
|
+
inline_keyboard=[
|
|
88
|
+
[
|
|
89
|
+
InlineKeyboardButton(text="Обновить", callback_data="cond:refresh"),
|
|
90
|
+
InlineKeyboardButton(text="Пропустить", callback_data="cond:pass"),
|
|
91
|
+
]
|
|
92
|
+
]
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
async def get_val(typ: SynonymType.__class__, val: str | int) -> tuple[SynonymType | int | bool, str]:
|
|
97
|
+
if isinstance(val, str) and val.isnumeric():
|
|
98
|
+
val = int(val)
|
|
99
|
+
if isclass(lst := synopts[typ]) and issubclass(lst, IntEnum):
|
|
100
|
+
return (v := lst(val)), v.name
|
|
101
|
+
elif isinstance(lst, list):
|
|
102
|
+
return val, lst[val]
|
|
103
|
+
elif typ == SynonymType.bank:
|
|
104
|
+
return val, (await models.Pm[val]).norm
|
|
105
|
+
return val, val
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
async def btns(typ: SynonymType.__class__, txt: str = None) -> InlineKeyboardMarkup | None:
|
|
109
|
+
if lst := synopts[typ]:
|
|
110
|
+
if isinstance(lst, list):
|
|
111
|
+
kb = [[InlineKeyboardButton(text=n, callback_data=f"st:{typ.name}:{i}")] for i, n in enumerate(lst)]
|
|
112
|
+
elif isclass(lst) and issubclass(lst, IntEnum):
|
|
113
|
+
kb = [[InlineKeyboardButton(text=i.name, callback_data=f"st:{typ.name}:{i.value}")] for i in lst]
|
|
114
|
+
else:
|
|
115
|
+
kb = [[InlineKeyboardButton(text=n, callback_data=f"st:{typ.name}:{i}")] for i, n in await lst(txt)]
|
|
116
|
+
return InlineKeyboardMarkup(inline_keyboard=kb)
|
|
117
|
+
else:
|
|
118
|
+
return lst
|