aboutsummaryrefslogtreecommitdiff
path: root/handlers
diff options
context:
space:
mode:
Diffstat (limited to 'handlers')
-rw-r--r--handlers/__init__.py7
-rw-r--r--handlers/config.py77
-rw-r--r--handlers/gen.py102
-rw-r--r--handlers/member.py25
-rw-r--r--handlers/middleware.py21
-rw-r--r--handlers/msg.py18
-rw-r--r--handlers/pin.py32
-rw-r--r--handlers/system.py17
8 files changed, 188 insertions, 111 deletions
diff --git a/handlers/__init__.py b/handlers/__init__.py
index d689d15..d451cea 100644
--- a/handlers/__init__.py
+++ b/handlers/__init__.py
@@ -1,8 +1,7 @@
1# isort: skip_file 1# isort: skip_file
2from . import msg 2from . import middleware
3
4from . import pin
5from . import member 3from . import member
4from . import pin
5from . import config
6from . import gen 6from . import gen
7
8from . import system 7from . import system
diff --git a/handlers/config.py b/handlers/config.py
new file mode 100644
index 0000000..7eaf9eb
--- /dev/null
+++ b/handlers/config.py
@@ -0,0 +1,77 @@
1from ast import literal_eval
2from copy import deepcopy
3from logging import info
4from typing import Any, get_args
5
6from aiogram import types as t
7from pydantic import BaseModel, ValidationError
8
9from shared.database import Message
10from shared.instances import config, dp, session
11from shared.settings import Config
12from utils import filters as f
13
14
15@dp.message_handler(f.user.is_admin, commands=["void"])
16async def void_command(msg: t.Message) -> None:
17 if msg.get_args() == "Я знаю что делаю":
18 with session.begin() as s:
19 s.query(Message).filter(Message.chat_id == msg.chat.id).delete()
20 await msg.answer("Лоботомия проведена успешно")
21 else:
22 await msg.answer(
23 "Напишите <code>/void Я знаю что делаю</code>",
24 parse_mode=t.ParseMode.HTML,
25 )
26
27
28@dp.message_handler(f.message.is_chat, f.user.is_admin, commands=["config"])
29async def settings_command(msg: t.Message) -> None:
30 def get_fields(config: BaseModel, level: int = 1) -> str:
31 text = ""
32 for name in config.__fields__:
33 value = getattr(config, name)
34 if isinstance(value, BaseModel):
35 text += f"\n{' '*level*4}<code>{name}.</code>"
36 text += get_fields(value, level + 1)
37 else:
38 text += f"\n{' '*level*4}<code>{name}</code> = {value!r}"
39 return text
40
41 args = msg.get_args().split()
42 chat_config = deepcopy(config.get_config(msg.chat.id))
43 try:
44 if len(args) == 0:
45 text = f"<code>/config</code>{get_fields(chat_config)}\n\n"
46 await msg.reply(text, parse_mode=t.ParseMode.HTML)
47 else:
48 conf = chat_config
49 *path, field = args[0].split(".")
50 for f in path:
51 conf = getattr(conf, f)
52 if not isinstance(conf, BaseModel):
53 raise KeyError()
54
55 if len(args) == 2:
56 if isinstance(getattr(conf, field), BaseModel):
57 raise KeyError()
58 value = args[1]
59 setattr(conf, field, literal_eval(value))
60
61 config.set_config(msg.chat.id, Config.parse_obj(chat_config.dict()))
62 config.save("data/config.json")
63
64 await msg.reply(
65 f"<code>/config {args[0]}</code> = {getattr(conf, field)!r}",
66 parse_mode=t.ParseMode.HTML,
67 )
68 else:
69 field_info = conf.__fields__[field].field_info
70 await msg.reply(
71 f"<code>/config {args[0]}</code> = {getattr(conf, field)!r}\n{field_info.description}",
72 parse_mode=t.ParseMode.HTML,
73 )
74 except (ValidationError, ValueError, SyntaxError):
75 await msg.reply("Неверное значение")
76 except (KeyError, AttributeError):
77 await msg.reply("Параметр не найден")
diff --git a/handlers/gen.py b/handlers/gen.py
index b618fec..8f19e96 100644
--- a/handlers/gen.py
+++ b/handlers/gen.py
@@ -1,67 +1,69 @@
1import os 1import random
2 2
3import mc 3import mc
4from aiogram import types as t 4from aiogram import types as t
5 5
6from shared import config 6from shared.database import Message
7from shared.instances import bot, dp 7from shared.instances import bot, config, dp, session
8from utils import filters as f 8from utils import filters as f
9 9
10 10
11@dp.message_handler(commands=["gen"]) 11def get_text(chat_id: int) -> str:
12async def сгенерировать_хуету(msg: t.Message): 12 with session() as s:
13 await msg.answer(получить_говно(msg.chat.id)) 13 samples = [
14 m.tuple()[0]
15 for m in s.query(Message.message).filter(Message.chat_id == chat_id).all()
16 ]
14 17
18 assert (
19 len(samples) != 0
20 ), "Нету сообщений на основе которых можно сгенерировать сообщение"
15 21
16@dp.message_handler(commands=["del"]) 22 generator = mc.PhraseGenerator(samples)
17async def удалить_хуету(msg: t.Message): 23 gen_config = config.get_config(chat_id).gen
18 await msg.delete() 24 validators = []
19 25
20 if msg.reply_to_message: 26 if gen_config.max_word_count is not None or gen_config.min_word_count is not None:
21 if msg.reply_to_message.from_user.id in [bot.id, msg.from_user.id]: 27 validators.append(
22 await msg.reply_to_message.delete() 28 mc.builtin.validators.words_count(
23 else: 29 minimal=gen_config.min_word_count,
24 await msg.answer("Ты умник, можно только свои или мои удалять") 30 maximal=gen_config.max_word_count,
25 else: 31 )
26 await msg.answer("Ты умник, ответь на сообщение")
27
28
29@dp.message_handler(commands=["void"])
30async def лоботомия(msg: t.Message):
31 if msg.get_args() == "Я знаю что делаю":
32 os.remove(f"data/{msg.chat.id}")
33 await msg.answer("Лоботомия проведена успешно")
34 else:
35 await msg.answer(
36 "Напишите <code>/void Я знаю что делаю</code>", parse_mode=t.ParseMode.HTML
37 ) 32 )
38 33
34 while True:
35 message = generator.generate_phrase_or_none(1, validators=validators)
36 if message is not None:
37 return message
39 38
40@dp.message_handler(commands=["chance"])
41async def изменить_шанс_срания(msg: t.Message):
42 if msg.get_args():
43 try:
44 chance = int(msg.get_args().split()[0])
45 if 0 <= chance <= 100:
46 config.chances[str(msg.chat.id)] = chance
47 config.save()
48 else:
49 raise RuntimeError()
50
51 await msg.answer(f"Теперь я сру с шансом в: {chance}%")
52 except Exception:
53 await msg.answer(
54 "Я хз что не так, но я знаю что ты дебил \n /chance <ЧИСЛО ОТ 0 ДО 100>"
55 )
56 else:
57 await msg.answer(f"Я сру с шансом в: {config.chances.get(str(msg.chat.id), 10)}%")
58 39
40@dp.message_handler(commands=["gen"])
41async def gen_command(msg: t.Message) -> None:
42 await msg.delete()
43 message = get_text(msg.chat.id)
44 if message is not None:
45 await msg.answer(message)
59 46
60@dp.message_handler(f.message.chance, content_types=[t.ContentType.ANY])
61async def срать_сообщение_с_шансом(msg: t.Message):
62 await msg.answer(получить_говно(msg.chat.id))
63 47
48@dp.message_handler(commands=["del"])
49async def del_command(msg: t.Message) -> None:
50 await msg.delete()
64 51
65def получить_говно(id: int) -> str: 52 if msg.reply_to_message:
66 samples = mc.util.load_txt_samples(f"data/{id}", separator="§") 53 if msg.reply_to_message.from_user.id == bot.id:
67 return mc.StringGenerator(samples=samples).generate_string() 54 await msg.reply_to_message.delete()
55 else:
56 await msg.reply("Можно удалять только сообщения бота")
57 else:
58 await msg.reply("Вы не ответили на сообщение")
59
60
61@dp.message_handler(
62 f.message.is_chat,
63 f.message.chance,
64 content_types=[t.ContentType.ANY],
65)
66async def chance_message(msg: t.Message) -> None:
67 message = get_text(msg.chat.id)
68 if message is not None:
69 await msg.reply(message)
diff --git a/handlers/member.py b/handlers/member.py
index c4b1495..a4fc4cc 100644
--- a/handlers/member.py
+++ b/handlers/member.py
@@ -1,17 +1,17 @@
1from aiogram import types as t 1from aiogram import types as t
2 2
3from shared.instances import bot, dp 3from shared.instances import bot, config, dp
4from utils import filters as f 4from utils import filters as f
5 5
6 6
7@dp.chat_join_request_handler() 7@dp.chat_join_request_handler()
8async def приём_запроса(cjr: t.ChatJoinRequest): 8async def new_member(cjr: t.ChatJoinRequest) -> None:
9 r = await bot.send_message( 9 reply = await bot.send_message(
10 cjr.chat.id, 10 cjr.chat.id,
11 f'<a href="tg://user?id={cjr.from_user.id}">{cjr.from_user.mention}</a> хочет в чат', 11 f'<a href="tg://user?id={cjr.from_user.id}">{cjr.from_user.mention}</a> хочет в чат',
12 parse_mode=t.ParseMode.HTML, 12 parse_mode=t.ParseMode.HTML,
13 ) 13 )
14 await r.reply_poll( 14 await reply.reply_poll(
15 "Пускаем ?", 15 "Пускаем ?",
16 [ 16 [
17 "Да", 17 "Да",
@@ -33,28 +33,27 @@ async def приём_запроса(cjr: t.ChatJoinRequest):
33@dp.callback_query_handler( 33@dp.callback_query_handler(
34 f.message.is_chat, lambda clb: clb.data.split(":")[0] == "check_request_poll" 34 f.message.is_chat, lambda clb: clb.data.split(":")[0] == "check_request_poll"
35) 35)
36async def проверить_запрос(clb: t.CallbackQuery): 36async def check_poll(clb: t.CallbackQuery) -> None:
37 poll = clb.message.poll 37 poll = clb.message.poll
38 msg = clb.message 38 msg = clb.message
39 data = clb.data.split(":") 39 data = clb.data.split(":")
40 user_id = int(data[1]) 40 user_id = int(data[1])
41 min_answers = config.get_config(msg.chat.id).commands.accept_member_answers_count
41 42
42 if poll.total_voter_count < 4: 43 if poll.total_voter_count < min_answers:
43 await clb.answer(f"Нужно хотябы 4 голоса, сейчас {poll.total_voter_count}") 44 await clb.answer(
45 f"Нужно хотябы {min_answers} голоса, сейчас {poll.total_voter_count}"
46 )
44 else: 47 else:
45 if not poll.is_closed: 48 if not poll.is_closed:
46 await bot.stop_poll(msg.chat.id, msg.message_id) 49 await bot.stop_poll(msg.chat.id, msg.message_id)
47 50
48 yes = poll.options[0].voter_count 51 if poll.options[0].voter_count > poll.options[1].voter_count:
49 no = poll.options[1].voter_count
50 win = max(yes, no)
51
52 if win == yes:
53 await bot.approve_chat_join_request(msg.chat.id, user_id) 52 await bot.approve_chat_join_request(msg.chat.id, user_id)
54 await bot.send_message( 53 await bot.send_message(
55 user_id, "Ваша заявка на вступление принята, добро пожаловать в группу" 54 user_id, "Ваша заявка на вступление принята, добро пожаловать в группу"
56 ) 55 )
57 elif win == no: 56 else:
58 await bot.decline_chat_join_request(msg.chat.id, user_id) 57 await bot.decline_chat_join_request(msg.chat.id, user_id)
59 await bot.send_message(user_id, "Ваша заявка на вступление НЕ принята") 58 await bot.send_message(user_id, "Ваша заявка на вступление НЕ принята")
60 if not msg.chat.has_protected_content: 59 if not msg.chat.has_protected_content:
diff --git a/handlers/middleware.py b/handlers/middleware.py
new file mode 100644
index 0000000..6cf39b6
--- /dev/null
+++ b/handlers/middleware.py
@@ -0,0 +1,21 @@
1from logging import info
2
3from aiogram import types as t
4from aiogram.dispatcher.middlewares import BaseMiddleware
5
6from shared.database import Message
7from shared.instances import session
8
9
10class MessageMiddleware(BaseMiddleware):
11 async def on_pre_process_message(self, msg: t.Message, data: dict) -> None:
12 text = msg.text or msg.caption
13 if text is not None and not text.startswith("/"):
14 with session.begin() as s:
15 s.add(
16 Message(
17 chat_id=msg.chat.id,
18 message_id=msg.message_id,
19 message=text,
20 )
21 )
diff --git a/handlers/msg.py b/handlers/msg.py
deleted file mode 100644
index dca295f..0000000
--- a/handlers/msg.py
+++ /dev/null
@@ -1,18 +0,0 @@
1from aiogram import types as t
2
3from shared.instances import dp
4from utils import filters as f
5
6
7async def сосалка(msg: t.Message):
8 text = msg.text or msg.caption
9 if text.startswith("/"):
10 return False
11 with open(f"data/{msg.chat.id}", "a+") as file:
12 file.write(text.lower().replace("§", "") + "§")
13 return False
14
15
16@dp.message_handler(f.message.has_text, сосалка, content_types=[t.ContentType.ANY])
17async def ХУЙ():
18 pass
diff --git a/handlers/pin.py b/handlers/pin.py
index fc81ed1..9eb91a4 100644
--- a/handlers/pin.py
+++ b/handlers/pin.py
@@ -1,22 +1,21 @@
1from aiogram import types as t 1from aiogram import types as t
2 2
3from shared.instances import bot, dp 3from shared.instances import bot, config, dp
4from utils import filters as f 4from utils import filters as f
5 5
6 6
7@dp.message_handler(f.message.is_chat, commands=["pin"]) 7@dp.message_handler(f.message.is_chat, commands=["pin"])
8async def закрепить_хуету(msg: t.Message): 8async def pin_command(msg: t.Message) -> None:
9 await msg.delete() 9 await msg.delete()
10 if msg.reply_to_message: 10 if msg.reply_to_message:
11 r = await msg.reply_to_message.reply( 11 reply = await msg.reply_to_message.reply(
12 f'<a href="tg://user?id={msg.from_user.id}">{msg.from_user.mention}</a> хочет закрепить сообщение', 12 f'<a href="tg://user?id={msg.from_user.id}">{msg.from_user.mention}</a> хочет закрепить сообщение',
13 parse_mode=t.ParseMode.HTML, 13 parse_mode=t.ParseMode.HTML,
14 ) 14 )
15 await r.reply_poll( 15 await reply.reply_poll(
16 "Закрепить ?", 16 "Закрепить сообщение ?",
17 [ 17 [
18 "Да", 18 "Да",
19 "УДАЛИ НАХУЙ",
20 "Нет", 19 "Нет",
21 ], 20 ],
22 reply_markup=t.InlineKeyboardMarkup().add( 21 reply_markup=t.InlineKeyboardMarkup().add(
@@ -33,23 +32,18 @@ async def закрепить_хуету(msg: t.Message):
33@dp.callback_query_handler( 32@dp.callback_query_handler(
34 f.message.is_chat, lambda clb: clb.data.split(":")[0] == "check_pin_poll" 33 f.message.is_chat, lambda clb: clb.data.split(":")[0] == "check_pin_poll"
35) 34)
36async def проверить_закреп(clb: t.CallbackQuery): 35async def check_poll(clb: t.CallbackQuery) -> None:
37 poll = clb.message.poll 36 poll = clb.message.poll
38 msg = clb.message 37 msg = clb.message
39 pin = int(clb.data.split(":")[1]) 38 pin = int(clb.data.split(":")[1])
39 min_answers = config.get_config(msg.chat.id).commands.pin_answers_count
40 40
41 if poll.total_voter_count < 2: 41 if poll.total_voter_count < min_answers:
42 await clb.answer(f"Нужно хотябы 2 голоса, сейчас {poll.total_voter_count}") 42 await clb.answer(
43 f"Нужно хотябы {min_answers} голоса, сейчас {poll.total_voter_count}"
44 )
43 else: 45 else:
46 if poll.options[0].voter_count > poll.options[1].voter_count:
47 await msg.chat.pin_message(pin)
44 if not poll.is_closed: 48 if not poll.is_closed:
45 await bot.stop_poll(msg.chat.id, msg.message_id) 49 await bot.stop_poll(msg.chat.id, msg.message_id)
46
47 yes = poll.options[0].voter_count
48 delete = poll.options[1].voter_count
49 win = max(yes, delete)
50
51 if win == yes:
52 await msg.chat.pin_message(pin)
53 elif win == delete:
54 await msg.chat.delete_message(pin)
55 await msg.delete()
diff --git a/handlers/system.py b/handlers/system.py
index 5346c54..f97ff86 100644
--- a/handlers/system.py
+++ b/handlers/system.py
@@ -7,17 +7,20 @@ from shared.instances import dp
7 7
8 8
9@dp.errors_handler() 9@dp.errors_handler()
10async def уборщик_какашек(upd: t.Update, err: Exception): 10async def error_handler(upd: t.Update, err: Exception) -> bool:
11 txt = "Я хз что произошло, но да \n" 11 if isinstance(err, AssertionError):
12 txt += f" {err.__class__.__name__}: {' '.join(map(str, err.args))}" 12 text = " ".join(map(str, err.args))
13 else:
14 text = f"{err.__class__.__name__}: {' '.join(map(str, err.args))}"
13 15
14 if upd.message: 16 if upd.message:
15 await upd.message.answer(txt) 17 await upd.message.answer(text)
16 elif upd.callback_query: 18 elif upd.callback_query:
17 await upd.callback_query.answer(txt) 19 await upd.callback_query.answer(text)
18 else: 20 else:
19 return 21 return False
20 22
21 logging.error(traceback.format_exc()) 23 if not isinstance(err, AssertionError):
24 logging.error(traceback.format_exc())
22 25
23 return True 26 return True