aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Tolmachov <me@igorek.dev>2022-12-05 22:29:41 +0900
committerIgor Tolmachov <me@igorek.dev>2022-12-05 22:29:41 +0900
commit0de7969d30e3e57d681afdfcadd245f6988a0342 (patch)
treebc0957e9208f51354aa2330dc20a090b7f680823
parent0d5cab62b0d077ad7946b64a534e3914f1cc79dd (diff)
downloadkarpov_ai_bot-0de7969d30e3e57d681afdfcadd245f6988a0342.tar.gz
karpov_ai_bot-0de7969d30e3e57d681afdfcadd245f6988a0342.zip
2.1
-rw-r--r--handlers/config.py23
-rw-r--r--handlers/gen.py59
-rw-r--r--handlers/member.py23
-rw-r--r--handlers/middleware.py5
-rw-r--r--handlers/pin.py6
-rw-r--r--poetry.lock41
-rw-r--r--pyproject.toml2
-rw-r--r--requirements.txt3
-rw-r--r--shared/__init__.py1
-rw-r--r--shared/commands.py3
-rw-r--r--shared/database.py1
-rw-r--r--shared/instances.py6
-rw-r--r--shared/samples.py31
-rw-r--r--shared/settings.py49
-rw-r--r--test.py15
-rw-r--r--utils/filters.py11
16 files changed, 164 insertions, 115 deletions
diff --git a/handlers/config.py b/handlers/config.py
index 7628805..2865694 100644
--- a/handlers/config.py
+++ b/handlers/config.py
@@ -1,3 +1,4 @@
1from copy import deepcopy
1from json import JSONDecodeError, dumps, loads 2from json import JSONDecodeError, dumps, loads
2from logging import info 3from logging import info
3 4
@@ -5,7 +6,8 @@ from aiogram import types as t
5from pydantic import BaseModel, ValidationError 6from pydantic import BaseModel, ValidationError
6 7
7from shared.database import Message 8from shared.database import Message
8from shared.instances import config, dp, session 9from shared.instances import chats, dp, session
10from shared.samples import samples
9from shared.settings import Config 11from shared.settings import Config
10from utils import filters as f 12from utils import filters as f
11 13
@@ -13,9 +15,19 @@ from utils import filters as f
13@dp.message_handler(f.user.is_admin, commands=["void"]) 15@dp.message_handler(f.user.is_admin, commands=["void"])
14async def void_command(msg: t.Message) -> None: 16async def void_command(msg: t.Message) -> None:
15 if msg.get_args() == "Я знаю что делаю": 17 if msg.get_args() == "Я знаю что делаю":
18 samples.delete(msg.chat.id)
16 with session.begin() as s: 19 with session.begin() as s:
17 s.query(Message).filter(Message.chat_id == msg.chat.id).delete() 20 query = s.query(Message).filter(Message.chat_id == msg.chat.id)
18 await msg.answer("Лоботомия проведена успешно") 21 if msg.reply_to_message is not None:
22 query = query.filter(Message.user_id == msg.reply_to_message.from_user.id)
23 query.delete()
24 if msg.reply_to_message is not None:
25 await msg.answer(
26 f'Связи пользователя <a href="tg://user?id={msg.reply_to_message.from_user.id}">{msg.reply_to_message.from_user.mention}</a> были очищены',
27 parse_mode=t.ParseMode.HTML,
28 )
29 else:
30 await msg.answer("Связи были очищены")
19 else: 31 else:
20 await msg.answer( 32 await msg.answer(
21 "Напишите <code>/void Я знаю что делаю</code>", 33 "Напишите <code>/void Я знаю что делаю</code>",
@@ -79,7 +91,7 @@ async def settings_command(msg: t.Message) -> None:
79 91
80 return text 92 return text
81 93
82 chat_config = config.get_config(msg.chat.id) 94 chat_config = deepcopy(chats.get(msg.chat.id))
83 args = msg.get_args().split() 95 args = msg.get_args().split()
84 if len(args) == 0: 96 if len(args) == 0:
85 text = f"<code>/config</code>{get_fields(chat_config)}" 97 text = f"<code>/config</code>{get_fields(chat_config)}"
@@ -88,8 +100,7 @@ async def settings_command(msg: t.Message) -> None:
88 elif len(args) == 2: 100 elif len(args) == 2:
89 try: 101 try:
90 text = set_filed(chat_config, args[0].split("."), args[1]) 102 text = set_filed(chat_config, args[0].split("."), args[1])
91 config.set_config(msg.chat.id, Config.parse_obj(chat_config.dict())) 103 chats.set(msg.chat.id, Config.parse_obj(chat_config.dict()))
92 config.save("data/config.json")
93 except (JSONDecodeError, ValidationError): 104 except (JSONDecodeError, ValidationError):
94 text = "Неверное значение" 105 text = "Неверное значение"
95 else: 106 else:
diff --git a/handlers/gen.py b/handlers/gen.py
index 72afb79..ef397db 100644
--- a/handlers/gen.py
+++ b/handlers/gen.py
@@ -1,60 +1,15 @@
1import random
2
3import mc
4from aiogram import types as t 1from aiogram import types as t
5 2
6from shared.database import Message 3from shared.instances import chats, dp
7from shared.instances import bot, config, dp, session 4from shared.samples import samples
8from utils import filters as f 5from utils import filters as f
9 6
10 7
11def get_text(chat_id: int) -> str:
12 with session() as s:
13 samples = [
14 m.tuple()[0]
15 for m in s.query(Message.message).filter(Message.chat_id == chat_id).all()
16 ]
17
18 assert (
19 len(samples) != 0
20 ), "Нету данных на основе которых можно сгенерировать сообщение"
21
22 generator = mc.PhraseGenerator(samples)
23 gen_config = config.get_config(chat_id).gen
24 validators = []
25
26 if gen_config.max_word_count is not None or gen_config.min_word_count is not None:
27 validators.append(
28 mc.builtin.validators.words_count(
29 minimal=gen_config.min_word_count,
30 maximal=gen_config.max_word_count,
31 )
32 )
33
34 while True:
35 message = generator.generate_phrase_or_none(1, validators=validators)
36 if message is not None:
37 return message
38
39
40@dp.message_handler(commands=["gen"]) 8@dp.message_handler(commands=["gen"])
41async def gen_command(msg: t.Message) -> None: 9async def gen_command(msg: t.Message) -> None:
42 if config.get_config(msg.chat.id).gen.delete_command: 10 if chats.get(msg.chat.id).gen.delete_command:
43 await msg.delete() 11 await msg.delete()
44 await msg.answer(get_text(msg.chat.id)) 12 await msg.answer(samples.get(msg.chat.id).generate())
45
46
47@dp.message_handler(commands=["del"])
48async def del_command(msg: t.Message) -> None:
49 await msg.delete()
50
51 if msg.reply_to_message:
52 if msg.reply_to_message.from_user.id == bot.id:
53 await msg.reply_to_message.delete()
54 else:
55 await msg.reply("Можно удалять только сообщения бота")
56 else:
57 await msg.reply("Вы не ответили на сообщение")
58 13
59 14
60@dp.message_handler( 15@dp.message_handler(
@@ -63,7 +18,7 @@ async def del_command(msg: t.Message) -> None:
63 content_types=[t.ContentType.ANY], 18 content_types=[t.ContentType.ANY],
64) 19)
65async def chance_message(msg: t.Message) -> None: 20async def chance_message(msg: t.Message) -> None:
66 if config.get_config(msg.chat.id).gen.reply: 21 if chats.get(msg.chat.id).gen.reply:
67 await msg.reply(get_text(msg.chat.id)) 22 await msg.reply(samples.get(msg.chat.id).generate())
68 else: 23 else:
69 await msg.answer(get_text(msg.chat.id)) 24 await msg.answer(samples.get(msg.chat.id).generate())
diff --git a/handlers/member.py b/handlers/member.py
index 830351d..b228f6c 100644
--- a/handlers/member.py
+++ b/handlers/member.py
@@ -1,17 +1,22 @@
1from aiogram import types as t 1from aiogram import types as t
2 2
3from shared.instances import bot, config, dp 3from shared.instances import bot, chats, dp
4from utils import filters as f 4from utils import filters as f
5 5
6polls: dict[int, int] = {}
7
6 8
7@dp.chat_join_request_handler() 9@dp.chat_join_request_handler()
8async def new_member(cjr: t.ChatJoinRequest) -> None: 10async def new_member(cjr: t.ChatJoinRequest) -> None:
11 if cjr.from_user.id in polls:
12 return
13
9 reply = await bot.send_message( 14 reply = await bot.send_message(
10 cjr.chat.id, 15 cjr.chat.id,
11 f'<a href="tg://user?id={cjr.from_user.id}">{cjr.from_user.mention}</a> хочет в чат', 16 f'<a href="tg://user?id={cjr.from_user.id}">{cjr.from_user.mention}</a> хочет в чат',
12 parse_mode=t.ParseMode.HTML, 17 parse_mode=t.ParseMode.HTML,
13 ) 18 )
14 await reply.reply_poll( 19 poll = await reply.reply_poll(
15 "Пускаем ?", 20 "Пускаем ?",
16 [ 21 [
17 "Да", 22 "Да",
@@ -28,6 +33,18 @@ async def new_member(cjr: t.ChatJoinRequest) -> None:
28 await bot.send_message( 33 await bot.send_message(
29 cjr.from_user.id, "Заявка на вступление в группу будет вскоре рассмотрена" 34 cjr.from_user.id, "Заявка на вступление в группу будет вскоре рассмотрена"
30 ) 35 )
36 polls[cjr.from_user.id] = poll.message_id
37
38
39@dp.chat_member_handler(f.user.new_user)
40async def admin_accept_member(cmu: t.ChatMemberUpdated) -> None:
41 user_id = cmu.new_chat_member.user.id
42 if user_id in polls:
43 polls.pop(user_id)
44 await bot.send_message(
45 user_id,
46 "Ваша заявка на вступление принята, добро пожаловать в группу",
47 )
31 48
32 49
33@dp.callback_query_handler( 50@dp.callback_query_handler(
@@ -38,7 +55,7 @@ async def check_poll(clb: t.CallbackQuery) -> None:
38 msg = clb.message 55 msg = clb.message
39 data = clb.data.split(":") 56 data = clb.data.split(":")
40 user_id = int(data[1]) 57 user_id = int(data[1])
41 min_answers = config.get_config(msg.chat.id).members.answer_count 58 min_answers = chats.get(msg.chat.id).members.answer_count
42 59
43 if poll.total_voter_count < min_answers: 60 if poll.total_voter_count < min_answers:
44 await clb.answer( 61 await clb.answer(
diff --git a/handlers/middleware.py b/handlers/middleware.py
index 6cf39b6..046037d 100644
--- a/handlers/middleware.py
+++ b/handlers/middleware.py
@@ -1,10 +1,9 @@
1from logging import info
2
3from aiogram import types as t 1from aiogram import types as t
4from aiogram.dispatcher.middlewares import BaseMiddleware 2from aiogram.dispatcher.middlewares import BaseMiddleware
5 3
6from shared.database import Message 4from shared.database import Message
7from shared.instances import session 5from shared.instances import session
6from shared.samples import samples
8 7
9 8
10class MessageMiddleware(BaseMiddleware): 9class MessageMiddleware(BaseMiddleware):
@@ -16,6 +15,8 @@ class MessageMiddleware(BaseMiddleware):
16 Message( 15 Message(
17 chat_id=msg.chat.id, 16 chat_id=msg.chat.id,
18 message_id=msg.message_id, 17 message_id=msg.message_id,
18 user_id=msg.from_user.id,
19 message=text, 19 message=text,
20 ) 20 )
21 ) 21 )
22 samples.get(msg.chat.id).feed(text)
diff --git a/handlers/pin.py b/handlers/pin.py
index 17995ee..e4d21db 100644
--- a/handlers/pin.py
+++ b/handlers/pin.py
@@ -1,6 +1,6 @@
1from aiogram import types as t 1from aiogram import types as t
2 2
3from shared.instances import bot, config, dp 3from shared.instances import bot, chats, dp
4from utils import filters as f 4from utils import filters as f
5 5
6 6
@@ -18,7 +18,7 @@ async def pin_command(msg: t.Message) -> None:
18 "Да", 18 "Да",
19 "Нет", 19 "Нет",
20 ], 20 ],
21 config.get_config(msg.chat.id).pin.anonym, 21 chats.get(msg.chat.id).pin.anonym,
22 reply_markup=t.InlineKeyboardMarkup().add( 22 reply_markup=t.InlineKeyboardMarkup().add(
23 t.InlineKeyboardButton( 23 t.InlineKeyboardButton(
24 "Проверить опрос", 24 "Проверить опрос",
@@ -37,7 +37,7 @@ async 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 pin = int(clb.data.split(":")[1]) 39 pin = int(clb.data.split(":")[1])
40 min_answers = config.get_config(msg.chat.id).pin.answer_count 40 min_answers = chats.get(msg.chat.id).pin.answer_count
41 41
42 if poll.total_voter_count < min_answers: 42 if poll.total_voter_count < min_answers:
43 await clb.answer( 43 await clb.answer(
diff --git a/poetry.lock b/poetry.lock
index 2ef1bd2..01570d0 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -190,14 +190,6 @@ optional = false
190python-versions = ">=3.7,<4.0" 190python-versions = ">=3.7,<4.0"
191 191
192[[package]] 192[[package]]
193name = "mc.py"
194version = "4.0.0"
195description = "Python package which provides you a simple way to generate phrases using Markov chains"
196category = "main"
197optional = false
198python-versions = ">=3.9,<4.0"
199
200[[package]]
201name = "multidict" 193name = "multidict"
202version = "6.0.2" 194version = "6.0.2"
203description = "multidict implementation" 195description = "multidict implementation"
@@ -311,6 +303,17 @@ pymysql = ["pymysql"]
311sqlcipher = ["sqlcipher3-binary"] 303sqlcipher = ["sqlcipher3-binary"]
312 304
313[[package]] 305[[package]]
306name = "tgen"
307version = "0.3.0"
308description = "A pretty simple text generation library"
309category = "main"
310optional = false
311python-versions = ">=3.10,<4.0"
312
313[package.dependencies]
314u-msgpack-python = ">=2.7.2,<3.0.0"
315
316[[package]]
314name = "tomli" 317name = "tomli"
315version = "2.0.1" 318version = "2.0.1"
316description = "A lil' TOML parser" 319description = "A lil' TOML parser"
@@ -327,6 +330,14 @@ optional = false
327python-versions = ">=3.7" 330python-versions = ">=3.7"
328 331
329[[package]] 332[[package]]
333name = "u-msgpack-python"
334version = "2.7.2"
335description = "A portable, lightweight MessagePack serializer and deserializer written in pure Python."
336category = "main"
337optional = false
338python-versions = "*"
339
340[[package]]
330name = "yarl" 341name = "yarl"
331version = "1.8.1" 342version = "1.8.1"
332description = "Yet another URL library" 343description = "Yet another URL library"
@@ -341,7 +352,7 @@ multidict = ">=4.0"
341[metadata] 352[metadata]
342lock-version = "1.1" 353lock-version = "1.1"
343python-versions = "^3.10" 354python-versions = "^3.10"
344content-hash = "4a5eec948c56acc838b2883ca7324b305189367039e1974947768f4ac252db6b" 355content-hash = "a60189eae7993f31bd8274d5f3710cde0e406b80ac5fc7813e0fbf02ea94331e"
345 356
346[metadata.files] 357[metadata.files]
347aiogram = [ 358aiogram = [
@@ -642,10 +653,6 @@ magic-filter = [
642 {file = "magic-filter-1.0.9.tar.gz", hash = "sha256:d0f1ffa5ff1fbe5105fd5f293c79b5d3795f336ea0f6129c636959a687bf422a"}, 653 {file = "magic-filter-1.0.9.tar.gz", hash = "sha256:d0f1ffa5ff1fbe5105fd5f293c79b5d3795f336ea0f6129c636959a687bf422a"},
643 {file = "magic_filter-1.0.9-py3-none-any.whl", hash = "sha256:51002312a8972fa514b998b7ff89340c98be3fc499967c1f5f2af98d13baf8d5"}, 654 {file = "magic_filter-1.0.9-py3-none-any.whl", hash = "sha256:51002312a8972fa514b998b7ff89340c98be3fc499967c1f5f2af98d13baf8d5"},
644] 655]
645"mc.py" = [
646 {file = "mc.py-4.0.0-py3-none-any.whl", hash = "sha256:aa9a13bf95fc818cc56d1363f3522b050f5ad92715218701992b23217b151417"},
647 {file = "mc.py-4.0.0.tar.gz", hash = "sha256:310f2e9a48ca69b23d4e538a316575380654ff94a14f6e0e38b85928d5d5ea19"},
648]
649multidict = [ 656multidict = [
650 {file = "multidict-6.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b9e95a740109c6047602f4db4da9949e6c5945cefbad34a1299775ddc9a62e2"}, 657 {file = "multidict-6.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b9e95a740109c6047602f4db4da9949e6c5945cefbad34a1299775ddc9a62e2"},
651 {file = "multidict-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ac0e27844758d7177989ce406acc6a83c16ed4524ebc363c1f748cba184d89d3"}, 658 {file = "multidict-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ac0e27844758d7177989ce406acc6a83c16ed4524ebc363c1f748cba184d89d3"},
@@ -836,6 +843,10 @@ SQLAlchemy = [
836 {file = "SQLAlchemy-2.0.0b3-py3-none-any.whl", hash = "sha256:5a4dcd4e740cf0e1c38f4053b365a0270690dee60e6061f0eebb1b8d4afcc455"}, 843 {file = "SQLAlchemy-2.0.0b3-py3-none-any.whl", hash = "sha256:5a4dcd4e740cf0e1c38f4053b365a0270690dee60e6061f0eebb1b8d4afcc455"},
837 {file = "SQLAlchemy-2.0.0b3.tar.gz", hash = "sha256:8325a4648e639cb2010199f64fad679d2f4ec8ce7e6f424ee1a41b07940cadb6"}, 844 {file = "SQLAlchemy-2.0.0b3.tar.gz", hash = "sha256:8325a4648e639cb2010199f64fad679d2f4ec8ce7e6f424ee1a41b07940cadb6"},
838] 845]
846tgen = [
847 {file = "tgen-0.3.0-py3-none-any.whl", hash = "sha256:6c145c1f99613cfa345251a5fee9333b648ae2b42af39a7f2d5ddd5449d88e29"},
848 {file = "tgen-0.3.0.tar.gz", hash = "sha256:459d6ef8490d158fdfef90ea429fe44a0baf8b0d61fbd98c2694ddb183a526a8"},
849]
839tomli = [ 850tomli = [
840 {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, 851 {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
841 {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, 852 {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
@@ -844,6 +855,10 @@ typing-extensions = [
844 {file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"}, 855 {file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"},
845 {file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"}, 856 {file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"},
846] 857]
858u-msgpack-python = [
859 {file = "u-msgpack-python-2.7.2.tar.gz", hash = "sha256:e86f7ac6aa0ef4c6c49f004b4fd435bce99c23e2dd5d73003f3f9816024c2bd8"},
860 {file = "u_msgpack_python-2.7.2-py2.py3-none-any.whl", hash = "sha256:00c77bbb65f8f68c8bd2570e0a14dee84aba429629ea78adc713f94da52ee386"},
861]
847yarl = [ 862yarl = [
848 {file = "yarl-1.8.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:abc06b97407868ef38f3d172762f4069323de52f2b70d133d096a48d72215d28"}, 863 {file = "yarl-1.8.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:abc06b97407868ef38f3d172762f4069323de52f2b70d133d096a48d72215d28"},
849 {file = "yarl-1.8.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:07b21e274de4c637f3e3b7104694e53260b5fc10d51fb3ec5fed1da8e0f754e3"}, 864 {file = "yarl-1.8.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:07b21e274de4c637f3e3b7104694e53260b5fc10d51fb3ec5fed1da8e0f754e3"},
diff --git a/pyproject.toml b/pyproject.toml
index fe03f00..3faa60d 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -9,8 +9,8 @@ license = "GPL-3.0-only"
9python = "^3.10" 9python = "^3.10"
10aiogram = "^2.20" 10aiogram = "^2.20"
11SQLAlchemy = "^2b3" 11SQLAlchemy = "^2b3"
12"mc.py" = "^4.0.0"
13pydantic = "^1.10.2" 12pydantic = "^1.10.2"
13tgen = "^0.3.0"
14 14
15[tool.poetry.group.dev.dependencies] 15[tool.poetry.group.dev.dependencies]
16mypy = "^0.991" 16mypy = "^0.991"
diff --git a/requirements.txt b/requirements.txt
index 90d4534..cf90e66 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -10,10 +10,11 @@ frozenlist==1.3.3 ; python_version >= "3.10" and python_version < "4.0"
10greenlet==2.0.1 ; python_version >= "3.10" and python_version < "4.0" and platform_machine == "aarch64" or python_version >= "3.10" and python_version < "4.0" and platform_machine == "ppc64le" or python_version >= "3.10" and python_version < "4.0" and platform_machine == "x86_64" or python_version >= "3.10" and python_version < "4.0" and platform_machine == "amd64" or python_version >= "3.10" and python_version < "4.0" and platform_machine == "AMD64" or python_version >= "3.10" and python_version < "4.0" and platform_machine == "win32" or python_version >= "3.10" and python_version < "4.0" and platform_machine == "WIN32" 10greenlet==2.0.1 ; python_version >= "3.10" and python_version < "4.0" and platform_machine == "aarch64" or python_version >= "3.10" and python_version < "4.0" and platform_machine == "ppc64le" or python_version >= "3.10" and python_version < "4.0" and platform_machine == "x86_64" or python_version >= "3.10" and python_version < "4.0" and platform_machine == "amd64" or python_version >= "3.10" and python_version < "4.0" and platform_machine == "AMD64" or python_version >= "3.10" and python_version < "4.0" and platform_machine == "win32" or python_version >= "3.10" and python_version < "4.0" and platform_machine == "WIN32"
11idna==3.4 ; python_version >= "3.10" and python_version < "4.0" 11idna==3.4 ; python_version >= "3.10" and python_version < "4.0"
12magic-filter==1.0.9 ; python_version >= "3.10" and python_version < "4.0" 12magic-filter==1.0.9 ; python_version >= "3.10" and python_version < "4.0"
13mc-py==4.0.0 ; python_version >= "3.10" and python_version < "4.0"
14multidict==6.0.2 ; python_version >= "3.10" and python_version < "4.0" 13multidict==6.0.2 ; python_version >= "3.10" and python_version < "4.0"
15pydantic==1.10.2 ; python_version >= "3.10" and python_version < "4.0" 14pydantic==1.10.2 ; python_version >= "3.10" and python_version < "4.0"
16pytz==2022.6 ; python_version >= "3.10" and python_version < "4.0" 15pytz==2022.6 ; python_version >= "3.10" and python_version < "4.0"
17sqlalchemy==2.0.0b3 ; python_version >= "3.10" and python_version < "4.0" 16sqlalchemy==2.0.0b3 ; python_version >= "3.10" and python_version < "4.0"
17tgen==0.3.0 ; python_version >= "3.10" and python_version < "4.0"
18typing-extensions==4.4.0 ; python_version >= "3.10" and python_version < "4.0" 18typing-extensions==4.4.0 ; python_version >= "3.10" and python_version < "4.0"
19u-msgpack-python==2.7.2 ; python_version >= "3.10" and python_version < "4.0"
19yarl==1.8.1 ; python_version >= "3.10" and python_version < "4.0" 20yarl==1.8.1 ; python_version >= "3.10" and python_version < "4.0"
diff --git a/shared/__init__.py b/shared/__init__.py
index f708bfe..edfd5c2 100644
--- a/shared/__init__.py
+++ b/shared/__init__.py
@@ -2,4 +2,5 @@
2from . import settings 2from . import settings
3from . import instances 3from . import instances
4from . import database 4from . import database
5from . import samples
5from . import commands 6from . import commands
diff --git a/shared/commands.py b/shared/commands.py
index 684997c..a7ff002 100644
--- a/shared/commands.py
+++ b/shared/commands.py
@@ -6,19 +6,16 @@ from aiogram.types import BotCommandScopeAllPrivateChats as private
6commands = { 6commands = {
7 group(): [ 7 group(): [
8 cmd("gen", "Сгенерировать сообщение"), 8 cmd("gen", "Сгенерировать сообщение"),
9 cmd("del", "Удалить сообщение бота"),
10 cmd("pin", "Создать опрос для закрепления сообщения"), 9 cmd("pin", "Создать опрос для закрепления сообщения"),
11 ], 10 ],
12 admin(): [ 11 admin(): [
13 cmd("gen", "Сгенерировать сообщение"), 12 cmd("gen", "Сгенерировать сообщение"),
14 cmd("del", "Удалить сообщение бота"),
15 cmd("pin", "Создать опрос для закрепления сообщения"), 13 cmd("pin", "Создать опрос для закрепления сообщения"),
16 cmd("void", "Отчистить связи для генерации сообщений"), 14 cmd("void", "Отчистить связи для генерации сообщений"),
17 cmd("config", "Открыть настройки чата"), 15 cmd("config", "Открыть настройки чата"),
18 ], 16 ],
19 private(): [ 17 private(): [
20 cmd("gen", "Сгенерировать сообщение"), 18 cmd("gen", "Сгенерировать сообщение"),
21 cmd("del", "Удалить сообщение бота"),
22 cmd("void", "Отчистить связи для генерации сообщений"), 19 cmd("void", "Отчистить связи для генерации сообщений"),
23 ], 20 ],
24} 21}
diff --git a/shared/database.py b/shared/database.py
index 9dfe868..6ce5fa2 100644
--- a/shared/database.py
+++ b/shared/database.py
@@ -11,6 +11,7 @@ class Message(Base):
11 __tablename__ = "messages" 11 __tablename__ = "messages"
12 chat_id: Mapped[int] = mapped_column(primary_key=True) 12 chat_id: Mapped[int] = mapped_column(primary_key=True)
13 message_id: Mapped[int] = mapped_column(primary_key=True) 13 message_id: Mapped[int] = mapped_column(primary_key=True)
14 user_id: Mapped[int]
14 message: Mapped[str] 15 message: Mapped[str]
15 16
16 17
diff --git a/shared/instances.py b/shared/instances.py
index fb511b3..5528206 100644
--- a/shared/instances.py
+++ b/shared/instances.py
@@ -7,10 +7,10 @@ from sqlalchemy.orm import Session, sessionmaker
7from shared.settings import Chats, Settings 7from shared.settings import Chats, Settings
8 8
9settings = Settings() 9settings = Settings()
10config = Chats() 10chats = Chats("data/config.json")
11if not exists("data/config.json"): 11if not exists("data/config.json"):
12 config.save("data/config.json") 12 chats.save()
13config.load("data/config.json") 13chats.load()
14 14
15bot = Bot(token=settings.token) 15bot = Bot(token=settings.token)
16dp = Dispatcher(bot) 16dp = Dispatcher(bot)
diff --git a/shared/samples.py b/shared/samples.py
new file mode 100644
index 0000000..740cff5
--- /dev/null
+++ b/shared/samples.py
@@ -0,0 +1,31 @@
1from tgen import TextGenerator
2
3from shared.database import Message
4from shared.instances import session
5
6
7class Samples:
8 samples: dict[int, TextGenerator]
9
10 def __init__(self) -> None:
11 self.samples = {}
12
13 def get(self, chat_id: int) -> TextGenerator:
14 if chat_id not in self.samples:
15 with session() as s:
16 samples = [
17 m.tuple()[0]
18 for m in s.query(Message.message)
19 .filter(Message.chat_id == chat_id)
20 .all()
21 ]
22
23 self.samples[chat_id] = TextGenerator.from_samples(samples)
24 return self.samples[chat_id]
25
26 def delete(self, chat_id: int) -> None:
27 if chat_id in self.samples:
28 self.samples.pop(chat_id)
29
30
31samples = Samples()
diff --git a/shared/settings.py b/shared/settings.py
index 560f8f8..bff7ff9 100644
--- a/shared/settings.py
+++ b/shared/settings.py
@@ -11,7 +11,7 @@ class GenConfig(BaseModel):
11 chance: int = Field( 11 chance: int = Field(
12 10, 12 10,
13 description="Шанс с которым бот сгенерирует сообщение", 13 description="Шанс с которым бот сгенерирует сообщение",
14 ge=1, 14 ge=0,
15 le=100, 15 le=100,
16 ) 16 )
17 reply: bool = Field( 17 reply: bool = Field(
@@ -22,16 +22,6 @@ class GenConfig(BaseModel):
22 True, 22 True,
23 description="Включить/Выключить удаление /gen команды", 23 description="Включить/Выключить удаление /gen команды",
24 ) 24 )
25 min_word_count: int | str | None = Field(
26 None,
27 description="Минимальное количество слов в сгенерированном предложении",
28 ge=1,
29 )
30 max_word_count: int | None = Field(
31 None,
32 description="Максимальное количество слов в сгенерированном предложении",
33 ge=1,
34 )
35 25
36 26
37class PollConfig(BaseModel): 27class PollConfig(BaseModel):
@@ -60,22 +50,29 @@ class Config(BaseModel):
60 ) 50 )
61 51
62 52
63class Chats(BaseModel): 53class Chats:
64 chats: dict[int, Config] = {} 54 file_name: str
55 configs: dict[int, Config]
56
57 def __init__(self, file_name: str) -> None:
58 self.file_name = file_name
59 self.configs = {}
65 60
66 @classmethod 61 def load(self) -> None:
67 def load(cls, file_name: str) -> "Chats": 62 with open(self.file_name, "r") as file:
68 with open(file_name, "r") as file: 63 self.configs = {
69 return cls.parse_obj(load(file)) 64 id_: Config.parse_obj(config) for id_, config in load(file).items()
65 }
70 66
71 def save(self, file_name: str) -> None: 67 def save(self) -> None:
72 with open(file_name, "w") as file: 68 with open(self.file_name, "w") as file:
73 dump(self.schema(), file) 69 dump({id_: config.dict() for id_, config in self.configs.items()}, file)
74 70
75 def get_config(self, chat_id: int) -> Config: 71 def get(self, chat_id: int) -> Config:
76 if chat_id not in self.chats: 72 if chat_id not in self.configs:
77 self.chats[chat_id] = Config() 73 self.configs[chat_id] = Config()
78 return self.chats[chat_id] 74 return self.configs[chat_id]
79 75
80 def set_config(self, chat_id: int, config: Config) -> None: 76 def set(self, chat_id: int, config: Config) -> None:
81 self.chats[chat_id] = config 77 self.configs[chat_id] = config
78 self.save()
diff --git a/test.py b/test.py
new file mode 100644
index 0000000..f6fe3a0
--- /dev/null
+++ b/test.py
@@ -0,0 +1,15 @@
1class A:
2 def __init__(self, b: dict = {}) -> None:
3 self.b = b
4
5
6a1 = A()
7a2 = A()
8
9print(a1.b)
10print(a2.b)
11
12a1.b["test"] = 123
13
14print(a1.b)
15print(a2.b)
diff --git a/utils/filters.py b/utils/filters.py
index 59302fb..4f0fee2 100644
--- a/utils/filters.py
+++ b/utils/filters.py
@@ -5,7 +5,7 @@ from random import randint
5from aiogram import filters as f 5from aiogram import filters as f
6from aiogram import types as t 6from aiogram import types as t
7 7
8from shared.instances import config 8from shared.instances import chats
9 9
10 10
11class message: 11class message:
@@ -13,7 +13,7 @@ class message:
13 13
14 @staticmethod 14 @staticmethod
15 def chance(msg: t.Message) -> bool: 15 def chance(msg: t.Message) -> bool:
16 return config.get_config(msg.chat.id).gen.chance >= randint(1, 100) 16 return chats.get(msg.chat.id).gen.chance >= randint(1, 100)
17 17
18 18
19class user: 19class user:
@@ -28,3 +28,10 @@ class user:
28 ) 28 )
29 return False 29 return False
30 return True 30 return True
31
32 @staticmethod
33 async def new_user(cmu: t.ChatMemberUpdated) -> bool:
34 return (
35 not cmu.old_chat_member.is_chat_member()
36 and cmu.new_chat_member.is_chat_member()
37 )