xync-bot 0.3.4__tar.gz → 0.3.6__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.4/xync_bot.egg-info → xync_bot-0.3.6}/PKG-INFO +6 -4
- {xync_bot-0.3.4 → xync_bot-0.3.6}/pyproject.toml +7 -4
- xync_bot-0.3.6/xync_bot/__init__.py +20 -0
- xync_bot-0.3.6/xync_bot/loader.py +26 -0
- xync_bot-0.3.6/xync_bot/routers/cond/__init__.py +153 -0
- {xync_bot-0.3.4/xync_bot/handlers → xync_bot-0.3.6/xync_bot/routers}/main.py +21 -43
- {xync_bot-0.3.4 → xync_bot-0.3.6/xync_bot.egg-info}/PKG-INFO +6 -4
- {xync_bot-0.3.4 → xync_bot-0.3.6}/xync_bot.egg-info/SOURCES.txt +10 -7
- {xync_bot-0.3.4 → xync_bot-0.3.6}/xync_bot.egg-info/requires.txt +3 -0
- {xync_bot-0.3.4 → xync_bot-0.3.6}/.env.dist +0 -0
- {xync_bot-0.3.4 → xync_bot-0.3.6}/.gitignore +0 -0
- {xync_bot-0.3.4 → xync_bot-0.3.6}/.pre-commit-config.yaml +0 -0
- {xync_bot-0.3.4 → xync_bot-0.3.6}/makefile +0 -0
- {xync_bot-0.3.4 → xync_bot-0.3.6}/setup.cfg +0 -0
- {xync_bot-0.3.4 → xync_bot-0.3.6}/test_main.http +0 -0
- {xync_bot-0.3.4/xync_bot/handlers → xync_bot-0.3.6/xync_bot/routers}/__init__.py +0 -0
- /xync_bot-0.3.4/xync_bot/__init__.py → /xync_bot-0.3.6/xync_bot/routers/cond/cond.py +0 -0
- {xync_bot-0.3.4/xync_bot/handlers → xync_bot-0.3.6/xync_bot/routers}/order.py +0 -0
- {xync_bot-0.3.4/xync_bot/handlers → xync_bot-0.3.6/xync_bot/routers}/photo.py +0 -0
- {xync_bot-0.3.4/xync_bot/handlers → xync_bot-0.3.6/xync_bot/routers}/vpn.py +0 -0
- {xync_bot-0.3.4/xync_bot/handlers → xync_bot-0.3.6/xync_bot/routers}/xicon.png +0 -0
- {xync_bot-0.3.4 → xync_bot-0.3.6}/xync_bot/shared.py +0 -0
- /xync_bot-0.3.4/xync_bot/types.py → /xync_bot-0.3.6/xync_bot/typs.py +0 -0
- {xync_bot-0.3.4 → xync_bot-0.3.6}/xync_bot.egg-info/dependency_links.txt +0 -0
- {xync_bot-0.3.4 → xync_bot-0.3.6}/xync_bot.egg-info/top_level.txt +0 -0
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xync-bot
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.6
|
|
4
4
|
Summary: Telegram bot with web app for xync net
|
|
5
5
|
Author-email: Artemiev <mixartemev@gmail.com>
|
|
6
|
-
License:
|
|
6
|
+
License-Expression: GPL-3.0-or-later
|
|
7
7
|
Project-URL: Homepage, https://gitlab.com/xync/back/tg-bot
|
|
8
8
|
Project-URL: Repository, https://gitlab.com/xync/back/tg-bot
|
|
9
|
-
Keywords: aiogram,xync-net
|
|
9
|
+
Keywords: aiogram,cyrtranslit,xync-net
|
|
10
10
|
Requires-Python: >=3.12
|
|
11
|
-
Description-Content-Type: text/markdown
|
|
12
11
|
Requires-Dist: xync-schema
|
|
13
12
|
Provides-Extra: dev
|
|
13
|
+
Requires-Dist: PGram; extra == "dev"
|
|
14
|
+
Requires-Dist: pre-commit; extra == "dev"
|
|
14
15
|
Requires-Dist: pytest; extra == "dev"
|
|
15
16
|
Requires-Dist: python-dotenv; extra == "dev"
|
|
17
|
+
Requires-Dist: setuptools-scm; extra == "dev"
|
|
16
18
|
Requires-Dist: build; extra == "dev"
|
|
17
19
|
Requires-Dist: twine; extra == "dev"
|
|
@@ -4,18 +4,21 @@ requires-python = ">=3.12"
|
|
|
4
4
|
authors = [
|
|
5
5
|
{name = "Artemiev", email = "mixartemev@gmail.com"},
|
|
6
6
|
]
|
|
7
|
-
keywords = ["aiogram", "xync-net"]
|
|
7
|
+
keywords = ["aiogram", "cyrtranslit", "xync-net"]
|
|
8
8
|
description = "Telegram bot with web app for xync net"
|
|
9
|
-
readme = "README.md"
|
|
10
|
-
license =
|
|
9
|
+
#readme = "README.md"
|
|
10
|
+
license = "GPL-3.0-or-later"
|
|
11
11
|
dynamic = ["version"]
|
|
12
12
|
dependencies = [
|
|
13
13
|
"xync-schema",
|
|
14
14
|
]
|
|
15
15
|
[project.optional-dependencies]
|
|
16
16
|
dev = [
|
|
17
|
+
"PGram",
|
|
18
|
+
"pre-commit",
|
|
17
19
|
"pytest",
|
|
18
20
|
"python-dotenv",
|
|
21
|
+
"setuptools-scm",
|
|
19
22
|
"build",
|
|
20
23
|
"twine",
|
|
21
24
|
]
|
|
@@ -39,4 +42,4 @@ asyncio_default_fixture_loop_scope = "function"
|
|
|
39
42
|
line-length = 120
|
|
40
43
|
|
|
41
44
|
[tool.setuptools]
|
|
42
|
-
packages = ["xync_bot"
|
|
45
|
+
packages = ["xync_bot"]
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from asyncio import run
|
|
3
|
+
|
|
4
|
+
from PGram import Bot
|
|
5
|
+
from aiogram.client.default import DefaultBotProperties
|
|
6
|
+
from x_model import init_db
|
|
7
|
+
|
|
8
|
+
from xync_bot.routers.cond import r
|
|
9
|
+
|
|
10
|
+
if __name__ == '__main__':
|
|
11
|
+
from xync_bot.loader import dp, TOKEN, TORM
|
|
12
|
+
|
|
13
|
+
logging.basicConfig(level=logging.INFO)
|
|
14
|
+
|
|
15
|
+
async def main() -> None:
|
|
16
|
+
cn = await init_db(TORM)
|
|
17
|
+
bot = Bot(TOKEN, [r], cn, default=DefaultBotProperties(parse_mode='HTML'))
|
|
18
|
+
await bot.start()
|
|
19
|
+
|
|
20
|
+
run(main())
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from aiogram import Bot, Dispatcher
|
|
2
|
+
# from aiogram.client.default import DefaultBotProperties
|
|
3
|
+
from dotenv import load_dotenv
|
|
4
|
+
from os import getenv as env
|
|
5
|
+
|
|
6
|
+
from xync_schema import models
|
|
7
|
+
|
|
8
|
+
load_dotenv()
|
|
9
|
+
|
|
10
|
+
PG_DSN = (
|
|
11
|
+
f"postgres://{env('POSTGRES_USER')}:{env('POSTGRES_PASSWORD')}@{env('POSTGRES_HOST', 'dbs')}"
|
|
12
|
+
f":{env('POSTGRES_PORT', 5432)}/{env('POSTGRES_DB', env('POSTGRES_USER'))}"
|
|
13
|
+
)
|
|
14
|
+
TOKEN = env("TOKEN")
|
|
15
|
+
# API_URL = "https://" + env("API_DOMAIN")
|
|
16
|
+
# WH_URL = API_URL + "/wh/" + TOKEN
|
|
17
|
+
|
|
18
|
+
bot: Bot = Bot(token=TOKEN) # , default=DefaultBotProperties(parse_mode="HTML")
|
|
19
|
+
dp: Dispatcher = Dispatcher(bot=bot)
|
|
20
|
+
|
|
21
|
+
TORM = {
|
|
22
|
+
"connections": {"default": PG_DSN},
|
|
23
|
+
"apps": {"models": {"models": [models, "aerich.models"]}},
|
|
24
|
+
"use_tz": False,
|
|
25
|
+
"timezone": "UTC",
|
|
26
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
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()
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
from os import path
|
|
3
2
|
|
|
4
3
|
from aiogram import Router, F
|
|
5
4
|
from aiogram.enums import ContentType
|
|
@@ -13,9 +12,7 @@ from aiogram.types import (
|
|
|
13
12
|
InlineKeyboardMarkup,
|
|
14
13
|
InlineKeyboardButton,
|
|
15
14
|
CallbackQuery,
|
|
16
|
-
ChatJoinRequest,
|
|
17
15
|
WebAppInfo,
|
|
18
|
-
FSInputFile,
|
|
19
16
|
)
|
|
20
17
|
from aiogram.utils.deep_linking import create_start_link
|
|
21
18
|
from xync_bot.handlers import user_upsert
|
|
@@ -132,63 +129,44 @@ async def my_user_set_status(my_chat_member: ChatMemberUpdated):
|
|
|
132
129
|
|
|
133
130
|
@main.my_chat_member()
|
|
134
131
|
async def user_set_status(my_chat_member: ChatMemberUpdated):
|
|
132
|
+
if my_chat_member.new_chat_member.user.username == "XyncNetBot": # удалена группа где бот был добавлен админом
|
|
133
|
+
if forum := await Forum.get_or_none(id=my_chat_member.chat.id):
|
|
134
|
+
await forum.delete()
|
|
135
|
+
res = f"I {my_chat_member.new_chat_member.status} from {my_chat_member.chat.id}:{my_chat_member.chat.title}"
|
|
136
|
+
return logging.info(res)
|
|
135
137
|
logging.info({"my_chat_member": my_chat_member.model_dump(exclude_none=True)})
|
|
136
138
|
u: TgUser = my_chat_member.from_user
|
|
137
139
|
blocked = my_chat_member.new_chat_member.status in ("left", "kicked")
|
|
140
|
+
if blocked:
|
|
141
|
+
if forum := await Forum.get_or_none(id=my_chat_member.chat.id, user_id=u.id):
|
|
142
|
+
if forum.joined:
|
|
143
|
+
forum.joined = False
|
|
144
|
+
await forum.save()
|
|
138
145
|
await user_upsert(u, blocked)
|
|
139
146
|
|
|
140
147
|
|
|
141
|
-
@main.chat_member(ChatMemberUpdatedFilter(LEAVE_TRANSITION))
|
|
148
|
+
@main.chat_member(ChatMemberUpdatedFilter(LEAVE_TRANSITION)) # юзер покинул группу Ордеров
|
|
142
149
|
async def on_user_leave(member: ChatMemberUpdated):
|
|
143
150
|
logging.info({"user_leave": member.model_dump(exclude_none=True)})
|
|
144
151
|
if forum := await Forum[member.chat.id]:
|
|
145
|
-
if
|
|
146
|
-
resp = (
|
|
147
|
-
f"{member.from_user.username or member.from_user.full_name}#{member.from_user.id} "
|
|
148
|
-
f"already leaved from {member.chat.title}#{member.chat.id}"
|
|
149
|
-
)
|
|
150
|
-
logging.error(resp)
|
|
151
|
-
else:
|
|
152
|
+
if forum.joined:
|
|
152
153
|
forum.joined = False
|
|
153
154
|
await forum.save()
|
|
154
155
|
resp = "Bye!"
|
|
155
156
|
return await member.bot.send_message(member.new_chat_member.user.id, resp)
|
|
156
157
|
|
|
157
158
|
|
|
158
|
-
@main.
|
|
159
|
-
async def
|
|
160
|
-
logging.info({"join_request": req.model_dump(exclude_none=True)})
|
|
161
|
-
forum = await Forum[req.chat.id]
|
|
162
|
-
if forum.user_id != req.from_user.id:
|
|
163
|
-
resp = f"{req.chat.title} is chat for user#{forum.user_id}"
|
|
164
|
-
logging.error(resp)
|
|
165
|
-
forum.joined = not await req.decline()
|
|
166
|
-
else:
|
|
167
|
-
resp = "Your request approved"
|
|
168
|
-
forum.joined = await req.approve()
|
|
169
|
-
await forum.save()
|
|
170
|
-
return await req.bot.send_message(req.user_chat_id, resp)
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
@main.chat_member(ChatMemberUpdatedFilter(JOIN_TRANSITION))
|
|
174
|
-
async def on_user_join(member: ChatMemberUpdated):
|
|
159
|
+
@main.chat_member(ChatMemberUpdatedFilter(JOIN_TRANSITION)) # Юзер добавился в группу Ордеров
|
|
160
|
+
async def on_user_join(member: ChatMemberUpdated, app_url: str):
|
|
175
161
|
logging.info({"user_join": member.model_dump(exclude_none=True)})
|
|
176
|
-
forum
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
return
|
|
181
|
-
resp = f"{member.chat.title} is chat for user#{forum.user_id}"
|
|
182
|
-
logging.error(resp)
|
|
183
|
-
await member.bot.ban_chat_member(member.chat.id, member.new_chat_member.user.id)
|
|
162
|
+
if forum := await Forum.get_or_none(id=member.chat.id):
|
|
163
|
+
if not forum.joined:
|
|
164
|
+
forum.joined = True
|
|
165
|
+
await forum.save()
|
|
184
166
|
else:
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
resp = "Welcome to XyncNetwork"
|
|
189
|
-
rm = InlineKeyboardMarkup(
|
|
190
|
-
inline_keyboard=[[InlineKeyboardButton(text="Go!", web_app=WebAppInfo(url="https://test.xync.net/"))]]
|
|
191
|
-
)
|
|
167
|
+
return
|
|
168
|
+
resp = "Welcome to XyncNetwork"
|
|
169
|
+
rm = InlineKeyboardMarkup(inline_keyboard=[[InlineKeyboardButton(text="Go!", web_app=WebAppInfo(url=app_url))]])
|
|
192
170
|
return await member.bot.send_message(member.new_chat_member.user.id, resp, reply_markup=rm)
|
|
193
171
|
|
|
194
172
|
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xync-bot
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.6
|
|
4
4
|
Summary: Telegram bot with web app for xync net
|
|
5
5
|
Author-email: Artemiev <mixartemev@gmail.com>
|
|
6
|
-
License:
|
|
6
|
+
License-Expression: GPL-3.0-or-later
|
|
7
7
|
Project-URL: Homepage, https://gitlab.com/xync/back/tg-bot
|
|
8
8
|
Project-URL: Repository, https://gitlab.com/xync/back/tg-bot
|
|
9
|
-
Keywords: aiogram,xync-net
|
|
9
|
+
Keywords: aiogram,cyrtranslit,xync-net
|
|
10
10
|
Requires-Python: >=3.12
|
|
11
|
-
Description-Content-Type: text/markdown
|
|
12
11
|
Requires-Dist: xync-schema
|
|
13
12
|
Provides-Extra: dev
|
|
13
|
+
Requires-Dist: PGram; extra == "dev"
|
|
14
|
+
Requires-Dist: pre-commit; extra == "dev"
|
|
14
15
|
Requires-Dist: pytest; extra == "dev"
|
|
15
16
|
Requires-Dist: python-dotenv; extra == "dev"
|
|
17
|
+
Requires-Dist: setuptools-scm; extra == "dev"
|
|
16
18
|
Requires-Dist: build; extra == "dev"
|
|
17
19
|
Requires-Dist: twine; extra == "dev"
|
|
@@ -5,16 +5,19 @@ makefile
|
|
|
5
5
|
pyproject.toml
|
|
6
6
|
test_main.http
|
|
7
7
|
xync_bot/__init__.py
|
|
8
|
+
xync_bot/loader.py
|
|
8
9
|
xync_bot/shared.py
|
|
9
|
-
xync_bot/
|
|
10
|
+
xync_bot/typs.py
|
|
10
11
|
xync_bot.egg-info/PKG-INFO
|
|
11
12
|
xync_bot.egg-info/SOURCES.txt
|
|
12
13
|
xync_bot.egg-info/dependency_links.txt
|
|
13
14
|
xync_bot.egg-info/requires.txt
|
|
14
15
|
xync_bot.egg-info/top_level.txt
|
|
15
|
-
xync_bot/
|
|
16
|
-
xync_bot/
|
|
17
|
-
xync_bot/
|
|
18
|
-
xync_bot/
|
|
19
|
-
xync_bot/
|
|
20
|
-
xync_bot/
|
|
16
|
+
xync_bot/routers/__init__.py
|
|
17
|
+
xync_bot/routers/main.py
|
|
18
|
+
xync_bot/routers/order.py
|
|
19
|
+
xync_bot/routers/photo.py
|
|
20
|
+
xync_bot/routers/vpn.py
|
|
21
|
+
xync_bot/routers/xicon.png
|
|
22
|
+
xync_bot/routers/cond/__init__.py
|
|
23
|
+
xync_bot/routers/cond/cond.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|