xync-bot 0.3.6__tar.gz → 0.3.7.dev4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of xync-bot might be problematic. Click here for more details.
- {xync_bot-0.3.6/xync_bot.egg-info → xync_bot-0.3.7.dev4}/PKG-INFO +3 -1
- {xync_bot-0.3.6 → xync_bot-0.3.7.dev4}/pyproject.toml +2 -0
- {xync_bot-0.3.6 → xync_bot-0.3.7.dev4}/xync_bot/__init__.py +7 -4
- {xync_bot-0.3.6 → xync_bot-0.3.7.dev4}/xync_bot/loader.py +0 -5
- xync_bot-0.3.7.dev4/xync_bot/routers/cond/__init__.py +97 -0
- xync_bot-0.3.7.dev4/xync_bot/routers/cond/func.py +118 -0
- {xync_bot-0.3.6 → xync_bot-0.3.7.dev4}/xync_bot/routers/main.py +35 -36
- xync_bot-0.3.7.dev4/xync_bot/routers/pay/main.py +133 -0
- {xync_bot-0.3.6 → xync_bot-0.3.7.dev4/xync_bot.egg-info}/PKG-INFO +3 -1
- {xync_bot-0.3.6 → xync_bot-0.3.7.dev4}/xync_bot.egg-info/SOURCES.txt +2 -1
- {xync_bot-0.3.6 → xync_bot-0.3.7.dev4}/xync_bot.egg-info/requires.txt +2 -0
- xync_bot-0.3.6/xync_bot/routers/__init__.py +0 -8
- xync_bot-0.3.6/xync_bot/routers/cond/__init__.py +0 -153
- {xync_bot-0.3.6 → xync_bot-0.3.7.dev4}/.env.dist +0 -0
- {xync_bot-0.3.6 → xync_bot-0.3.7.dev4}/.gitignore +0 -0
- {xync_bot-0.3.6 → xync_bot-0.3.7.dev4}/.pre-commit-config.yaml +0 -0
- {xync_bot-0.3.6 → xync_bot-0.3.7.dev4}/makefile +0 -0
- {xync_bot-0.3.6 → xync_bot-0.3.7.dev4}/setup.cfg +0 -0
- {xync_bot-0.3.6 → xync_bot-0.3.7.dev4}/test_main.http +0 -0
- /xync_bot-0.3.6/xync_bot/routers/cond/cond.py → /xync_bot-0.3.7.dev4/xync_bot/routers/__init__.py +0 -0
- {xync_bot-0.3.6 → xync_bot-0.3.7.dev4}/xync_bot/routers/order.py +0 -0
- {xync_bot-0.3.6 → xync_bot-0.3.7.dev4}/xync_bot/routers/photo.py +0 -0
- {xync_bot-0.3.6 → xync_bot-0.3.7.dev4}/xync_bot/routers/vpn.py +0 -0
- {xync_bot-0.3.6 → xync_bot-0.3.7.dev4}/xync_bot/routers/xicon.png +0 -0
- {xync_bot-0.3.6 → xync_bot-0.3.7.dev4}/xync_bot/shared.py +0 -0
- {xync_bot-0.3.6 → xync_bot-0.3.7.dev4}/xync_bot/typs.py +0 -0
- {xync_bot-0.3.6 → xync_bot-0.3.7.dev4}/xync_bot.egg-info/dependency_links.txt +0 -0
- {xync_bot-0.3.6 → xync_bot-0.3.7.dev4}/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.
|
|
3
|
+
Version: 0.3.7.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
|
|
@@ -8,6 +8,8 @@ Project-URL: Homepage, https://gitlab.com/xync/back/tg-bot
|
|
|
8
8
|
Project-URL: Repository, https://gitlab.com/xync/back/tg-bot
|
|
9
9
|
Keywords: aiogram,cyrtranslit,xync-net
|
|
10
10
|
Requires-Python: >=3.12
|
|
11
|
+
Requires-Dist: cyrtranslit
|
|
12
|
+
Requires-Dist: xn-auth
|
|
11
13
|
Requires-Dist: xync-schema
|
|
12
14
|
Provides-Extra: dev
|
|
13
15
|
Requires-Dist: PGram; extra == "dev"
|
|
@@ -5,16 +5,19 @@ 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
|
|
8
|
+
from xync_bot.routers.cond import cr
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
# from xync_bot.routers.main import mr
|
|
11
|
+
from xync_bot.routers.pay.main import pay as pay
|
|
12
|
+
|
|
13
|
+
if __name__ == "__main__":
|
|
14
|
+
from xync_bot.loader import TOKEN, TORM
|
|
12
15
|
|
|
13
16
|
logging.basicConfig(level=logging.INFO)
|
|
14
17
|
|
|
15
18
|
async def main() -> None:
|
|
16
19
|
cn = await init_db(TORM)
|
|
17
|
-
bot = Bot(TOKEN, [
|
|
20
|
+
bot = Bot(TOKEN, [cr, pay], cn, default=DefaultBotProperties(parse_mode="HTML"))
|
|
18
21
|
await bot.start()
|
|
19
22
|
|
|
20
23
|
run(main())
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from aiogram import Bot, Dispatcher
|
|
2
|
-
# from aiogram.client.default import DefaultBotProperties
|
|
3
1
|
from dotenv import load_dotenv
|
|
4
2
|
from os import getenv as env
|
|
5
3
|
|
|
@@ -15,9 +13,6 @@ TOKEN = env("TOKEN")
|
|
|
15
13
|
# API_URL = "https://" + env("API_DOMAIN")
|
|
16
14
|
# WH_URL = API_URL + "/wh/" + TOKEN
|
|
17
15
|
|
|
18
|
-
bot: Bot = Bot(token=TOKEN) # , default=DefaultBotProperties(parse_mode="HTML")
|
|
19
|
-
dp: Dispatcher = Dispatcher(bot=bot)
|
|
20
|
-
|
|
21
16
|
TORM = {
|
|
22
17
|
"connections": {"default": PG_DSN},
|
|
23
18
|
"apps": {"models": {"models": [models, "aerich.models"]}},
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
from aiogram import Router, F
|
|
2
|
+
from aiogram.exceptions import TelegramBadRequest
|
|
3
|
+
from aiogram.filters import Command
|
|
4
|
+
from aiogram.fsm.context import FSMContext
|
|
5
|
+
from aiogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery
|
|
6
|
+
from xync_schema import models
|
|
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()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@cr.message(Command("cond"))
|
|
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):
|
|
21
|
+
cond = await models.Cond.filter(parsed__isnull=True).order_by("-created_at").first().prefetch_related("parsed")
|
|
22
|
+
await state.set_data({"cond": cond})
|
|
23
|
+
await show_cond(msg, cond)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
async def show_cond(msg: Message, cond: models.Cond):
|
|
27
|
+
await msg.answer(await wrap_cond(cond), reply_markup=ikm)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@cr.message(F.quote)
|
|
31
|
+
async def got_synonym(msg: Message, state: FSMContext):
|
|
32
|
+
if not (msg.text in {st.name for st in SynonymType} and SynonymType[msg.text]):
|
|
33
|
+
return await msg.reply_text(
|
|
34
|
+
f'Нет раздела "{msg.text}", не пиши текст сам, выдели кусок из моего сообщения,'
|
|
35
|
+
f"ответь на него, выбери кнопку раздела"
|
|
36
|
+
)
|
|
37
|
+
if not msg.quote:
|
|
38
|
+
return await msg.reply_text(f"Вы забыли выделить кусок текста для {msg.text}")
|
|
39
|
+
if typ := SynonymType[msg.text]:
|
|
40
|
+
await state.update_data({"syntext": msg.quote.text, "cmsg": msg.reply_to_message})
|
|
41
|
+
await models.Synonym.update_or_create({"typ": typ}, txt=msg.quote.text)
|
|
42
|
+
if rm := await btns(typ, msg.quote.text):
|
|
43
|
+
return await msg.answer("Уточните", reply_markup=rm, reply_to_message_id=msg.message_id)
|
|
44
|
+
await syn_result(msg, SynTypeCd(typ=typ.name, val=1), state)
|
|
45
|
+
return None
|
|
46
|
+
|
|
47
|
+
|
|
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"),
|
|
67
|
+
]
|
|
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)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@cr.message()
|
|
95
|
+
async def unknown(msg: Message):
|
|
96
|
+
# user = await User.get(username_id=msg.from_user.id)
|
|
97
|
+
await msg.delete()
|
|
@@ -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
|
|
@@ -6,7 +6,7 @@ from aiogram.exceptions import TelegramBadRequest
|
|
|
6
6
|
from aiogram.filters import CommandStart, CommandObject, ChatMemberUpdatedFilter, JOIN_TRANSITION, LEAVE_TRANSITION
|
|
7
7
|
from aiogram.filters.callback_data import CallbackData
|
|
8
8
|
from aiogram.types import (
|
|
9
|
-
User
|
|
9
|
+
User,
|
|
10
10
|
ChatMemberUpdated,
|
|
11
11
|
Message,
|
|
12
12
|
InlineKeyboardMarkup,
|
|
@@ -15,12 +15,11 @@ from aiogram.types import (
|
|
|
15
15
|
WebAppInfo,
|
|
16
16
|
)
|
|
17
17
|
from aiogram.utils.deep_linking import create_start_link
|
|
18
|
-
from
|
|
19
|
-
from xync_schema.models import User, Order, Msg, Forum
|
|
18
|
+
from xync_schema import models
|
|
20
19
|
|
|
21
20
|
from xync_bot.shared import NavCallbackData
|
|
22
21
|
|
|
23
|
-
|
|
22
|
+
mr = Router()
|
|
24
23
|
|
|
25
24
|
|
|
26
25
|
class RrCallbackData(CallbackData, prefix="reg_res"): # registration response
|
|
@@ -38,19 +37,19 @@ home_btns = InlineKeyboardMarkup(
|
|
|
38
37
|
)
|
|
39
38
|
|
|
40
39
|
|
|
41
|
-
@
|
|
40
|
+
@mr.message(CommandStart(deep_link=True, deep_link_encoded=True))
|
|
42
41
|
async def start_handler(msg: Message, command: CommandObject):
|
|
43
|
-
me:
|
|
42
|
+
me: User = msg.from_user
|
|
44
43
|
ref_id: int = command.args.isnumeric() and int(command.args)
|
|
45
|
-
user = await User.get_or_none(id=me.id, blocked=False)
|
|
44
|
+
user = await models.User.get_or_none(id=me.id, blocked=False)
|
|
46
45
|
rm = None
|
|
47
46
|
logging.info(msg, {"src": "start"})
|
|
48
47
|
if user:
|
|
49
48
|
rs, rm = f"{me.full_name}, you have registered already😉", home_btns
|
|
50
|
-
elif not (ref := await User.get_or_none(id=ref_id)):
|
|
49
|
+
elif not (ref := await models.User.get_or_none(id=ref_id)):
|
|
51
50
|
rs = f"No registered user #{ref_id}😬"
|
|
52
51
|
else: # new user created
|
|
53
|
-
user, cr = await
|
|
52
|
+
user, cr = await models.User.tg2in(me, False)
|
|
54
53
|
await user.update_from_dict({"ref": ref}).save()
|
|
55
54
|
approve_btns = InlineKeyboardMarkup(
|
|
56
55
|
inline_keyboard=[
|
|
@@ -67,9 +66,9 @@ async def start_handler(msg: Message, command: CommandObject):
|
|
|
67
66
|
return await msg.answer(rs, reply_markup=rm)
|
|
68
67
|
|
|
69
68
|
|
|
70
|
-
@
|
|
69
|
+
@mr.callback_query(RrCallbackData.filter())
|
|
71
70
|
async def phrases_input_request(cb: CallbackQuery, callback_data: RrCallbackData) -> None:
|
|
72
|
-
protege = await User[callback_data.to]
|
|
71
|
+
protege = await models.User[callback_data.to]
|
|
73
72
|
if callback_data.res:
|
|
74
73
|
# protege.status = UserStatus.RESTRICTED
|
|
75
74
|
await protege.save()
|
|
@@ -84,17 +83,17 @@ async def phrases_input_request(cb: CallbackQuery, callback_data: RrCallbackData
|
|
|
84
83
|
await cb.message.edit_text(rs)
|
|
85
84
|
|
|
86
85
|
|
|
87
|
-
@
|
|
86
|
+
@mr.message(CommandStart(deep_link=True)) # attempt to reg by fake link
|
|
88
87
|
async def fraud_handler(msg: Message):
|
|
89
88
|
logging.warning(f"Start: {msg.from_user.id}. Msg: {msg}")
|
|
90
89
|
# todo: alert to admins! Fraud attempt!
|
|
91
90
|
await msg.answer("🤔")
|
|
92
91
|
|
|
93
92
|
|
|
94
|
-
@
|
|
93
|
+
@mr.message(CommandStart())
|
|
95
94
|
async def start_no_ref_handler(msg: Message):
|
|
96
95
|
me = msg.from_user
|
|
97
|
-
user, cr = await
|
|
96
|
+
user, cr = await models.User.tg2in(me, False)
|
|
98
97
|
rr = "сначала вы должны найти поручителя, и перейти по его реферальной ссылке.\nhttps://telegra.ph/XyncNet-02-13"
|
|
99
98
|
if cr: # has ref and created now
|
|
100
99
|
await msg.answer(f"Здравствуйте {me.full_name}, что бы использовать возможности нашей сети, {rr}")
|
|
@@ -104,10 +103,10 @@ async def start_no_ref_handler(msg: Message):
|
|
|
104
103
|
await msg.answer(f"{me.full_name}, не балуйтесь, вы и так уже активный участник👌🏼", reply_markup=home_btns)
|
|
105
104
|
|
|
106
105
|
|
|
107
|
-
@
|
|
106
|
+
@mr.callback_query(NavCallbackData.filter(F.to == "ref_link"))
|
|
108
107
|
async def ref_link_handler(cbq: CallbackQuery):
|
|
109
108
|
me = cbq.from_user
|
|
110
|
-
if not (u := await User.get_or_none(id=me.id, blocked=False).prefetch_related("ref")):
|
|
109
|
+
if not (u := await models.User.get_or_none(id=me.id, blocked=False).prefetch_related("ref")):
|
|
111
110
|
return await cbq.answer(f"{me.full_name}, сначала сами получите одобрение поручителя😉")
|
|
112
111
|
link = await create_start_link(cbq.bot, str(u.id), encode=True)
|
|
113
112
|
logging.info(f"Start: {me.id}. Msg: {cbq}")
|
|
@@ -119,36 +118,36 @@ async def ref_link_handler(cbq: CallbackQuery):
|
|
|
119
118
|
await cbq.answer("Wait for your protege request..")
|
|
120
119
|
|
|
121
120
|
|
|
122
|
-
@
|
|
121
|
+
@mr.my_chat_member(F.chat.type == "private") # my_chat_member is fired on add bot to any chat. filter for preventing
|
|
123
122
|
async def my_user_set_status(my_chat_member: ChatMemberUpdated):
|
|
124
123
|
logging.info({"my_chat_member": my_chat_member.model_dump(exclude_none=True)})
|
|
125
|
-
u:
|
|
124
|
+
u: User = my_chat_member.from_user
|
|
126
125
|
blocked = my_chat_member.new_chat_member.status in ("left", "kicked")
|
|
127
|
-
await
|
|
126
|
+
await models.User.tg2in(u, blocked)
|
|
128
127
|
|
|
129
128
|
|
|
130
|
-
@
|
|
129
|
+
@mr.my_chat_member()
|
|
131
130
|
async def user_set_status(my_chat_member: ChatMemberUpdated):
|
|
132
131
|
if my_chat_member.new_chat_member.user.username == "XyncNetBot": # удалена группа где бот был добавлен админом
|
|
133
|
-
if forum := await Forum.get_or_none(id=my_chat_member.chat.id):
|
|
132
|
+
if forum := await models.Forum.get_or_none(id=my_chat_member.chat.id):
|
|
134
133
|
await forum.delete()
|
|
135
134
|
res = f"I {my_chat_member.new_chat_member.status} from {my_chat_member.chat.id}:{my_chat_member.chat.title}"
|
|
136
135
|
return logging.info(res)
|
|
137
136
|
logging.info({"my_chat_member": my_chat_member.model_dump(exclude_none=True)})
|
|
138
|
-
u:
|
|
137
|
+
u: User = my_chat_member.from_user
|
|
139
138
|
blocked = my_chat_member.new_chat_member.status in ("left", "kicked")
|
|
140
139
|
if blocked:
|
|
141
|
-
if forum := await Forum.get_or_none(id=my_chat_member.chat.id, user_id=u.id):
|
|
140
|
+
if forum := await models.Forum.get_or_none(id=my_chat_member.chat.id, user_id=u.id):
|
|
142
141
|
if forum.joined:
|
|
143
142
|
forum.joined = False
|
|
144
143
|
await forum.save()
|
|
145
|
-
await
|
|
144
|
+
return await models.User.tg2in(u, blocked)
|
|
146
145
|
|
|
147
146
|
|
|
148
|
-
@
|
|
147
|
+
@mr.chat_member(ChatMemberUpdatedFilter(LEAVE_TRANSITION)) # юзер покинул группу Ордеров
|
|
149
148
|
async def on_user_leave(member: ChatMemberUpdated):
|
|
150
149
|
logging.info({"user_leave": member.model_dump(exclude_none=True)})
|
|
151
|
-
if forum := await Forum[member.chat.id]:
|
|
150
|
+
if forum := await models.Forum[member.chat.id]:
|
|
152
151
|
if forum.joined:
|
|
153
152
|
forum.joined = False
|
|
154
153
|
await forum.save()
|
|
@@ -156,10 +155,10 @@ async def on_user_leave(member: ChatMemberUpdated):
|
|
|
156
155
|
return await member.bot.send_message(member.new_chat_member.user.id, resp)
|
|
157
156
|
|
|
158
157
|
|
|
159
|
-
@
|
|
158
|
+
@mr.chat_member(ChatMemberUpdatedFilter(JOIN_TRANSITION)) # Юзер добавился в группу Ордеров
|
|
160
159
|
async def on_user_join(member: ChatMemberUpdated, app_url: str):
|
|
161
160
|
logging.info({"user_join": member.model_dump(exclude_none=True)})
|
|
162
|
-
if forum := await Forum.get_or_none(id=member.chat.id):
|
|
161
|
+
if forum := await models.Forum.get_or_none(id=member.chat.id):
|
|
163
162
|
if not forum.joined:
|
|
164
163
|
forum.joined = True
|
|
165
164
|
await forum.save()
|
|
@@ -170,26 +169,26 @@ async def on_user_join(member: ChatMemberUpdated, app_url: str):
|
|
|
170
169
|
return await member.bot.send_message(member.new_chat_member.user.id, resp, reply_markup=rm)
|
|
171
170
|
|
|
172
171
|
|
|
173
|
-
@
|
|
172
|
+
@mr.message(F.is_topic_message)
|
|
174
173
|
async def order_msg(msg: Message):
|
|
175
|
-
sender = await User[msg.from_user.id]
|
|
174
|
+
sender = await models.User[msg.from_user.id]
|
|
176
175
|
cid = msg.chat.shifted_id
|
|
177
176
|
assert sender.forum == cid, "sender is not client"
|
|
178
|
-
if order := await Order.get_or_none(taker__user_id=sender.id, taker_topic=msg.message_thread_id):
|
|
177
|
+
if order := await models.Order.get_or_none(taker__user_id=sender.id, taker_topic=msg.message_thread_id):
|
|
179
178
|
is_taker = True
|
|
180
|
-
elif order := await Order.get_or_none(ad__agent__user_id=sender.id, maker_topic=msg.message_thread_id):
|
|
179
|
+
elif order := await models.Order.get_or_none(ad__agent__user_id=sender.id, maker_topic=msg.message_thread_id):
|
|
181
180
|
is_taker = False
|
|
182
181
|
else:
|
|
183
182
|
return await msg.answer("No such order")
|
|
184
183
|
# raise Exception("No such order")
|
|
185
|
-
receiver: User = await (order.ad.maker.user if is_taker else order.taker.user)
|
|
184
|
+
receiver: models.User = await (order.ad.maker.user if is_taker else order.taker.user)
|
|
186
185
|
rcv_topic = order.taker_topic if is_taker else order.maker_topic
|
|
187
|
-
await Msg.create(tgid=msg.message_id, txt=msg.text, order_id=order.id, receiver=receiver)
|
|
186
|
+
await models.Msg.create(tgid=msg.message_id, txt=msg.text, order_id=order.id, receiver=receiver)
|
|
188
187
|
logging.info(msg, {"src": "order_msg"})
|
|
189
188
|
return await msg.send_copy(receiver.forum, message_thread_id=rcv_topic)
|
|
190
189
|
|
|
191
190
|
|
|
192
|
-
@
|
|
191
|
+
@mr.message(
|
|
193
192
|
F.content_type.not_in(
|
|
194
193
|
{
|
|
195
194
|
ContentType.NEW_CHAT_MEMBERS,
|
|
@@ -211,7 +210,7 @@ async def del_cbq(msg: Message):
|
|
|
211
210
|
logging.error({"NOT_DELETED": msg.model_dump(exclude_none=True)})
|
|
212
211
|
|
|
213
212
|
|
|
214
|
-
@
|
|
213
|
+
@mr.message()
|
|
215
214
|
async def all_rest(msg: Message):
|
|
216
215
|
logging.warning(
|
|
217
216
|
{
|
|
@@ -0,0 +1,133 @@
|
|
|
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,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xync-bot
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.7.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
|
|
@@ -8,6 +8,8 @@ Project-URL: Homepage, https://gitlab.com/xync/back/tg-bot
|
|
|
8
8
|
Project-URL: Repository, https://gitlab.com/xync/back/tg-bot
|
|
9
9
|
Keywords: aiogram,cyrtranslit,xync-net
|
|
10
10
|
Requires-Python: >=3.12
|
|
11
|
+
Requires-Dist: cyrtranslit
|
|
12
|
+
Requires-Dist: xn-auth
|
|
11
13
|
Requires-Dist: xync-schema
|
|
12
14
|
Provides-Extra: dev
|
|
13
15
|
Requires-Dist: PGram; extra == "dev"
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
from aiogram.types import User
|
|
2
|
-
from aiogram.utils.web_app import WebAppUser
|
|
3
|
-
from xync_schema import models
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
async def user_upsert(u: User | WebAppUser, blocked: bool = None) -> tuple[User, bool]:
|
|
7
|
-
user_in: models.User.Upd = await models.User.tg2in(u, blocked)
|
|
8
|
-
return await models.User.update_or_create(user_in.model_dump(exclude_none=True, exclude={"id"}), id=u.id)
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
import re
|
|
2
|
-
from asyncio import iscoroutinefunction
|
|
3
|
-
from enum import IntEnum
|
|
4
|
-
from inspect import isclass
|
|
5
|
-
from typing import Coroutine
|
|
6
|
-
|
|
7
|
-
from aiogram import Router, F
|
|
8
|
-
from aiogram.filters import CommandStart
|
|
9
|
-
from aiogram.fsm.context import FSMContext
|
|
10
|
-
from aiogram.types import Message, ReplyKeyboardMarkup, KeyboardButton, InlineKeyboardMarkup, InlineKeyboardButton, \
|
|
11
|
-
CallbackQuery, ReplyKeyboardRemove
|
|
12
|
-
from cyrtranslit import to_latin
|
|
13
|
-
from xync_schema import models
|
|
14
|
-
from xync_schema.enums import SynonymType, Party, Slip, AbuserType, NameType, Boundary
|
|
15
|
-
|
|
16
|
-
r = Router()
|
|
17
|
-
|
|
18
|
-
async def wrap_cond(txt: str):
|
|
19
|
-
bnks = await models.Synonym.filter(typ=SynonymType.bank)
|
|
20
|
-
bnks = '|'.join('\\b'+b.txt+('\\b' if b.boundary&Boundary.right else '') for b in bnks)
|
|
21
|
-
for syn in await models.Synonym.all():
|
|
22
|
-
lb, rb = "\\b" if syn.boundary&Boundary.left else "", "\\b" if syn.boundary&Boundary.right else ""
|
|
23
|
-
if syn.typ == SynonymType.bank_side:
|
|
24
|
-
syn.txt.replace('#banks#', f'({bnks})')
|
|
25
|
-
if syn.is_re or syn.txt in txt:
|
|
26
|
-
pattern = re.compile(lb+syn.txt+rb)
|
|
27
|
-
if match := re.search(pattern, txt):
|
|
28
|
-
g = match.group()
|
|
29
|
-
val, hval = await get_val(syn.typ, syn.val)
|
|
30
|
-
val = syn.typ.name + (f'="{hval}"' if hval else '')
|
|
31
|
-
txt = re.sub(pattern, f"<code>{g}</code><tg-spoiler>[{val}]</tg-spoiler>", txt)
|
|
32
|
-
return txt
|
|
33
|
-
|
|
34
|
-
async def cbanks(bnid: str) -> list[tuple[int, str]]:
|
|
35
|
-
beginning = to_latin(bnid[:2], lang_code='ru')
|
|
36
|
-
return await models.Pm.filter(norm__startswith=beginning, bank=True).values_list('id', 'norm')
|
|
37
|
-
|
|
38
|
-
async def cppo(txt: str) -> list[tuple[int, str]]:
|
|
39
|
-
opts = re.findall(r'\d+', txt) or [1, 2, 3, 5, 10]
|
|
40
|
-
return [(o, str(o)) for o in opts]
|
|
41
|
-
|
|
42
|
-
synopts: dict[SynonymType, list[str] | type(IntEnum) | None | Coroutine] = {
|
|
43
|
-
SynonymType.name: ["not_slavic", "slavic"],
|
|
44
|
-
SynonymType.ppo: cppo,
|
|
45
|
-
SynonymType.from_party: Party,
|
|
46
|
-
SynonymType.to_party: Party,
|
|
47
|
-
SynonymType.slip_req: Slip,
|
|
48
|
-
SynonymType.slip_send: Slip,
|
|
49
|
-
SynonymType.abuser: AbuserType,
|
|
50
|
-
SynonymType.scale: ["1", "10", "100", "1000"],
|
|
51
|
-
SynonymType.slavic: NameType,
|
|
52
|
-
SynonymType.mtl_like: None,
|
|
53
|
-
SynonymType.bank: cbanks,
|
|
54
|
-
SynonymType.bank_side: ["except", "only"],
|
|
55
|
-
}
|
|
56
|
-
rkm = ReplyKeyboardMarkup(keyboard=[
|
|
57
|
-
[KeyboardButton(text="ppo"), KeyboardButton(text="abuser")],
|
|
58
|
-
[KeyboardButton(text="from_party"), KeyboardButton(text="to_party")],
|
|
59
|
-
[KeyboardButton(text="slip_send"), KeyboardButton(text="slip_req")],
|
|
60
|
-
[KeyboardButton(text="name"), KeyboardButton(text="slavic")],
|
|
61
|
-
[KeyboardButton(text="scale"), KeyboardButton(text="mtl_like")],
|
|
62
|
-
[KeyboardButton(text="bank"), KeyboardButton(text="bank_side")],
|
|
63
|
-
], one_time_keyboard=True)
|
|
64
|
-
|
|
65
|
-
async def get_val(typ: SynonymType.__class__, val: str) -> tuple[SynonymType | int | bool, str]:
|
|
66
|
-
if isinstance(val, str) and val.isnumeric():
|
|
67
|
-
val = int(val)
|
|
68
|
-
if isclass(lst := synopts[typ]) and issubclass(lst, IntEnum):
|
|
69
|
-
return (v:=lst(val)), v.name
|
|
70
|
-
elif isinstance(lst, list):
|
|
71
|
-
return val, lst[val]
|
|
72
|
-
elif typ == SynonymType.bank:
|
|
73
|
-
return val, (await models.Pm[val]).norm
|
|
74
|
-
return val, val
|
|
75
|
-
|
|
76
|
-
async def btns(typ: SynonymType.__class__, txt: str = None) -> InlineKeyboardMarkup | None:
|
|
77
|
-
if lst := synopts[typ]:
|
|
78
|
-
if isinstance(lst, list):
|
|
79
|
-
kb = [[InlineKeyboardButton(text=n, callback_data=f'st:{typ.name}:{i}')] for i, n in enumerate(lst)]
|
|
80
|
-
elif isclass(lst) and issubclass(lst, IntEnum):
|
|
81
|
-
kb = [[InlineKeyboardButton(text=i.name, callback_data=f'st:{typ.name}:{i.value}')] for i in lst]
|
|
82
|
-
else:
|
|
83
|
-
kb = [[InlineKeyboardButton(text=n, callback_data=f'st:{typ.name}:{i}')] for i, n in await lst(txt)]
|
|
84
|
-
return InlineKeyboardMarkup(inline_keyboard=kb)
|
|
85
|
-
else:
|
|
86
|
-
return lst
|
|
87
|
-
|
|
88
|
-
@r.message(CommandStart())
|
|
89
|
-
async def start(msg: Message, state: FSMContext):
|
|
90
|
-
cond = await models.Cond.filter(parsed__isnull=True).order_by("-created_at").first().prefetch_related('parsed')
|
|
91
|
-
await state.set_data({"cid": cond.id, "cond_txt": cond.raw_txt})
|
|
92
|
-
await msg.reply(await wrap_cond(cond.raw_txt), reply_markup=rkm)
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
@r.message(F.quote)
|
|
96
|
-
async def got_synonym(msg: Message, state: FSMContext):
|
|
97
|
-
if not (msg.text in {st.name for st in SynonymType} and SynonymType[msg.text]):
|
|
98
|
-
return await msg.reply_text(f'Нет раздела "{msg.text}", не пиши текст сам, выдели кусок из моего сообщения,'
|
|
99
|
-
f'ответь на него, выбери кнопку раздела')
|
|
100
|
-
if not msg.quote:
|
|
101
|
-
return await msg.reply_text(f'Вы забыли выделить кусок текста для {msg.text}')
|
|
102
|
-
if typ := SynonymType[msg.text]:
|
|
103
|
-
await state.update_data({"syntext": msg.quote.text, "cmsg": msg.reply_to_message})
|
|
104
|
-
await models.Synonym.update_or_create({"typ": typ}, txt=msg.quote.text)
|
|
105
|
-
if rm := await btns(typ, msg.quote.text):
|
|
106
|
-
return await msg.answer("Уточните", reply_markup=rm, reply_to_message_id=msg.message_id)
|
|
107
|
-
await syn_result(msg, f'st:{typ.name}:1', state)
|
|
108
|
-
return None
|
|
109
|
-
|
|
110
|
-
@r.callback_query()
|
|
111
|
-
async def got_synonym_val(cbq: CallbackQuery, state: FSMContext):
|
|
112
|
-
await syn_result(cbq.message, cbq.data, state)
|
|
113
|
-
|
|
114
|
-
async def syn_result(msg: Message, data: str, state: FSMContext):
|
|
115
|
-
t, st, sv = data.split(':')
|
|
116
|
-
if t == "st":
|
|
117
|
-
typ = SynonymType[st]
|
|
118
|
-
val, hval = await get_val(typ, sv)
|
|
119
|
-
syntext = await state.get_value('syntext')
|
|
120
|
-
cid = await state.get_value('cid')
|
|
121
|
-
syn, _ = await models.Synonym.update_or_create({"val": val}, typ=typ, txt=syntext)
|
|
122
|
-
await models.CondParsed.update_or_create({typ.name: val}, cond_id=cid)
|
|
123
|
-
await msg.reply(
|
|
124
|
-
f'Текст "{syntext}" определен как синоним для `{typ.name}` со значением {hval}',
|
|
125
|
-
reply_markup=InlineKeyboardMarkup(inline_keyboard=[[
|
|
126
|
-
InlineKeyboardButton(text='Готово! Давай новый', callback_data=f'cond:complete:{cid}'),
|
|
127
|
-
InlineKeyboardButton(text='Продолжить с этим текстом', callback_data=f'cond:process:{cid}')
|
|
128
|
-
]])
|
|
129
|
-
)
|
|
130
|
-
# await msg.reply_to_message.delete()
|
|
131
|
-
# await msg.delete()
|
|
132
|
-
# await cmsg.edit_text(wrapped_txt)
|
|
133
|
-
|
|
134
|
-
elif t == "cond":
|
|
135
|
-
if st == 'complete':
|
|
136
|
-
await models.CondParsed.update_or_create({"parsed": True}, cond_id=int(sv))
|
|
137
|
-
await start(msg, state)
|
|
138
|
-
else:
|
|
139
|
-
wrapped_txt = await wrap_cond(await state.get_value('cond_txt'))
|
|
140
|
-
# cmsg: Message = await state.get_value('cmsg')
|
|
141
|
-
await msg.reply(wrapped_txt, reply_markup=rkm)
|
|
142
|
-
else:
|
|
143
|
-
await msg.reply("Где я?")
|
|
144
|
-
|
|
145
|
-
@r.message(F.reply_to_message)
|
|
146
|
-
async def clear(msg: Message):
|
|
147
|
-
await msg.reply_to_message.delete_reply_markup()
|
|
148
|
-
await msg.delete()
|
|
149
|
-
|
|
150
|
-
@r.message()
|
|
151
|
-
async def unknown(msg: Message):
|
|
152
|
-
# user = await User.get(username_id=msg.from_user.id)
|
|
153
|
-
await msg.delete()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/xync_bot-0.3.6/xync_bot/routers/cond/cond.py → /xync_bot-0.3.7.dev4/xync_bot/routers/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|