diff options
| -rw-r--r-- | handlers/config.py | 23 | ||||
| -rw-r--r-- | handlers/gen.py | 59 | ||||
| -rw-r--r-- | handlers/member.py | 23 | ||||
| -rw-r--r-- | handlers/middleware.py | 5 | ||||
| -rw-r--r-- | handlers/pin.py | 6 | ||||
| -rw-r--r-- | poetry.lock | 41 | ||||
| -rw-r--r-- | pyproject.toml | 2 | ||||
| -rw-r--r-- | requirements.txt | 3 | ||||
| -rw-r--r-- | shared/__init__.py | 1 | ||||
| -rw-r--r-- | shared/commands.py | 3 | ||||
| -rw-r--r-- | shared/database.py | 1 | ||||
| -rw-r--r-- | shared/instances.py | 6 | ||||
| -rw-r--r-- | shared/samples.py | 31 | ||||
| -rw-r--r-- | shared/settings.py | 49 | ||||
| -rw-r--r-- | test.py | 15 | ||||
| -rw-r--r-- | utils/filters.py | 11 |
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 @@ | |||
| 1 | from copy import deepcopy | ||
| 1 | from json import JSONDecodeError, dumps, loads | 2 | from json import JSONDecodeError, dumps, loads |
| 2 | from logging import info | 3 | from logging import info |
| 3 | 4 | ||
| @@ -5,7 +6,8 @@ from aiogram import types as t | |||
| 5 | from pydantic import BaseModel, ValidationError | 6 | from pydantic import BaseModel, ValidationError |
| 6 | 7 | ||
| 7 | from shared.database import Message | 8 | from shared.database import Message |
| 8 | from shared.instances import config, dp, session | 9 | from shared.instances import chats, dp, session |
| 10 | from shared.samples import samples | ||
| 9 | from shared.settings import Config | 11 | from shared.settings import Config |
| 10 | from utils import filters as f | 12 | from 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"]) |
| 14 | async def void_command(msg: t.Message) -> None: | 16 | async 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 @@ | |||
| 1 | import random | ||
| 2 | |||
| 3 | import mc | ||
| 4 | from aiogram import types as t | 1 | from aiogram import types as t |
| 5 | 2 | ||
| 6 | from shared.database import Message | 3 | from shared.instances import chats, dp |
| 7 | from shared.instances import bot, config, dp, session | 4 | from shared.samples import samples |
| 8 | from utils import filters as f | 5 | from utils import filters as f |
| 9 | 6 | ||
| 10 | 7 | ||
| 11 | def 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"]) |
| 41 | async def gen_command(msg: t.Message) -> None: | 9 | async 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"]) | ||
| 48 | async 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 | ) |
| 65 | async def chance_message(msg: t.Message) -> None: | 20 | async 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 @@ | |||
| 1 | from aiogram import types as t | 1 | from aiogram import types as t |
| 2 | 2 | ||
| 3 | from shared.instances import bot, config, dp | 3 | from shared.instances import bot, chats, dp |
| 4 | from utils import filters as f | 4 | from utils import filters as f |
| 5 | 5 | ||
| 6 | polls: dict[int, int] = {} | ||
| 7 | |||
| 6 | 8 | ||
| 7 | @dp.chat_join_request_handler() | 9 | @dp.chat_join_request_handler() |
| 8 | async def new_member(cjr: t.ChatJoinRequest) -> None: | 10 | async 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) | ||
| 40 | async 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 @@ | |||
| 1 | from logging import info | ||
| 2 | |||
| 3 | from aiogram import types as t | 1 | from aiogram import types as t |
| 4 | from aiogram.dispatcher.middlewares import BaseMiddleware | 2 | from aiogram.dispatcher.middlewares import BaseMiddleware |
| 5 | 3 | ||
| 6 | from shared.database import Message | 4 | from shared.database import Message |
| 7 | from shared.instances import session | 5 | from shared.instances import session |
| 6 | from shared.samples import samples | ||
| 8 | 7 | ||
| 9 | 8 | ||
| 10 | class MessageMiddleware(BaseMiddleware): | 9 | class 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 @@ | |||
| 1 | from aiogram import types as t | 1 | from aiogram import types as t |
| 2 | 2 | ||
| 3 | from shared.instances import bot, config, dp | 3 | from shared.instances import bot, chats, dp |
| 4 | from utils import filters as f | 4 | from 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 | |||
| 190 | python-versions = ">=3.7,<4.0" | 190 | python-versions = ">=3.7,<4.0" |
| 191 | 191 | ||
| 192 | [[package]] | 192 | [[package]] |
| 193 | name = "mc.py" | ||
| 194 | version = "4.0.0" | ||
| 195 | description = "Python package which provides you a simple way to generate phrases using Markov chains" | ||
| 196 | category = "main" | ||
| 197 | optional = false | ||
| 198 | python-versions = ">=3.9,<4.0" | ||
| 199 | |||
| 200 | [[package]] | ||
| 201 | name = "multidict" | 193 | name = "multidict" |
| 202 | version = "6.0.2" | 194 | version = "6.0.2" |
| 203 | description = "multidict implementation" | 195 | description = "multidict implementation" |
| @@ -311,6 +303,17 @@ pymysql = ["pymysql"] | |||
| 311 | sqlcipher = ["sqlcipher3-binary"] | 303 | sqlcipher = ["sqlcipher3-binary"] |
| 312 | 304 | ||
| 313 | [[package]] | 305 | [[package]] |
| 306 | name = "tgen" | ||
| 307 | version = "0.3.0" | ||
| 308 | description = "A pretty simple text generation library" | ||
| 309 | category = "main" | ||
| 310 | optional = false | ||
| 311 | python-versions = ">=3.10,<4.0" | ||
| 312 | |||
| 313 | [package.dependencies] | ||
| 314 | u-msgpack-python = ">=2.7.2,<3.0.0" | ||
| 315 | |||
| 316 | [[package]] | ||
| 314 | name = "tomli" | 317 | name = "tomli" |
| 315 | version = "2.0.1" | 318 | version = "2.0.1" |
| 316 | description = "A lil' TOML parser" | 319 | description = "A lil' TOML parser" |
| @@ -327,6 +330,14 @@ optional = false | |||
| 327 | python-versions = ">=3.7" | 330 | python-versions = ">=3.7" |
| 328 | 331 | ||
| 329 | [[package]] | 332 | [[package]] |
| 333 | name = "u-msgpack-python" | ||
| 334 | version = "2.7.2" | ||
| 335 | description = "A portable, lightweight MessagePack serializer and deserializer written in pure Python." | ||
| 336 | category = "main" | ||
| 337 | optional = false | ||
| 338 | python-versions = "*" | ||
| 339 | |||
| 340 | [[package]] | ||
| 330 | name = "yarl" | 341 | name = "yarl" |
| 331 | version = "1.8.1" | 342 | version = "1.8.1" |
| 332 | description = "Yet another URL library" | 343 | description = "Yet another URL library" |
| @@ -341,7 +352,7 @@ multidict = ">=4.0" | |||
| 341 | [metadata] | 352 | [metadata] |
| 342 | lock-version = "1.1" | 353 | lock-version = "1.1" |
| 343 | python-versions = "^3.10" | 354 | python-versions = "^3.10" |
| 344 | content-hash = "4a5eec948c56acc838b2883ca7324b305189367039e1974947768f4ac252db6b" | 355 | content-hash = "a60189eae7993f31bd8274d5f3710cde0e406b80ac5fc7813e0fbf02ea94331e" |
| 345 | 356 | ||
| 346 | [metadata.files] | 357 | [metadata.files] |
| 347 | aiogram = [ | 358 | aiogram = [ |
| @@ -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 | ] | ||
| 649 | multidict = [ | 656 | multidict = [ |
| 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 | ] |
| 846 | tgen = [ | ||
| 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 | ] | ||
| 839 | tomli = [ | 850 | tomli = [ |
| 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 | ] |
| 858 | u-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 | ] | ||
| 847 | yarl = [ | 862 | yarl = [ |
| 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" | |||
| 9 | python = "^3.10" | 9 | python = "^3.10" |
| 10 | aiogram = "^2.20" | 10 | aiogram = "^2.20" |
| 11 | SQLAlchemy = "^2b3" | 11 | SQLAlchemy = "^2b3" |
| 12 | "mc.py" = "^4.0.0" | ||
| 13 | pydantic = "^1.10.2" | 12 | pydantic = "^1.10.2" |
| 13 | tgen = "^0.3.0" | ||
| 14 | 14 | ||
| 15 | [tool.poetry.group.dev.dependencies] | 15 | [tool.poetry.group.dev.dependencies] |
| 16 | mypy = "^0.991" | 16 | mypy = "^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" | |||
| 10 | greenlet==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" | 10 | greenlet==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" |
| 11 | idna==3.4 ; python_version >= "3.10" and python_version < "4.0" | 11 | idna==3.4 ; python_version >= "3.10" and python_version < "4.0" |
| 12 | magic-filter==1.0.9 ; python_version >= "3.10" and python_version < "4.0" | 12 | magic-filter==1.0.9 ; python_version >= "3.10" and python_version < "4.0" |
| 13 | mc-py==4.0.0 ; python_version >= "3.10" and python_version < "4.0" | ||
| 14 | multidict==6.0.2 ; python_version >= "3.10" and python_version < "4.0" | 13 | multidict==6.0.2 ; python_version >= "3.10" and python_version < "4.0" |
| 15 | pydantic==1.10.2 ; python_version >= "3.10" and python_version < "4.0" | 14 | pydantic==1.10.2 ; python_version >= "3.10" and python_version < "4.0" |
| 16 | pytz==2022.6 ; python_version >= "3.10" and python_version < "4.0" | 15 | pytz==2022.6 ; python_version >= "3.10" and python_version < "4.0" |
| 17 | sqlalchemy==2.0.0b3 ; python_version >= "3.10" and python_version < "4.0" | 16 | sqlalchemy==2.0.0b3 ; python_version >= "3.10" and python_version < "4.0" |
| 17 | tgen==0.3.0 ; python_version >= "3.10" and python_version < "4.0" | ||
| 18 | typing-extensions==4.4.0 ; python_version >= "3.10" and python_version < "4.0" | 18 | typing-extensions==4.4.0 ; python_version >= "3.10" and python_version < "4.0" |
| 19 | u-msgpack-python==2.7.2 ; python_version >= "3.10" and python_version < "4.0" | ||
| 19 | yarl==1.8.1 ; python_version >= "3.10" and python_version < "4.0" | 20 | yarl==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 @@ | |||
| 2 | from . import settings | 2 | from . import settings |
| 3 | from . import instances | 3 | from . import instances |
| 4 | from . import database | 4 | from . import database |
| 5 | from . import samples | ||
| 5 | from . import commands | 6 | from . 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 | |||
| 6 | commands = { | 6 | commands = { |
| 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 | |||
| 7 | from shared.settings import Chats, Settings | 7 | from shared.settings import Chats, Settings |
| 8 | 8 | ||
| 9 | settings = Settings() | 9 | settings = Settings() |
| 10 | config = Chats() | 10 | chats = Chats("data/config.json") |
| 11 | if not exists("data/config.json"): | 11 | if not exists("data/config.json"): |
| 12 | config.save("data/config.json") | 12 | chats.save() |
| 13 | config.load("data/config.json") | 13 | chats.load() |
| 14 | 14 | ||
| 15 | bot = Bot(token=settings.token) | 15 | bot = Bot(token=settings.token) |
| 16 | dp = Dispatcher(bot) | 16 | dp = 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 @@ | |||
| 1 | from tgen import TextGenerator | ||
| 2 | |||
| 3 | from shared.database import Message | ||
| 4 | from shared.instances import session | ||
| 5 | |||
| 6 | |||
| 7 | class 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 | |||
| 31 | samples = 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 | ||
| 37 | class PollConfig(BaseModel): | 27 | class PollConfig(BaseModel): |
| @@ -60,22 +50,29 @@ class Config(BaseModel): | |||
| 60 | ) | 50 | ) |
| 61 | 51 | ||
| 62 | 52 | ||
| 63 | class Chats(BaseModel): | 53 | class 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() | ||
| @@ -0,0 +1,15 @@ | |||
| 1 | class A: | ||
| 2 | def __init__(self, b: dict = {}) -> None: | ||
| 3 | self.b = b | ||
| 4 | |||
| 5 | |||
| 6 | a1 = A() | ||
| 7 | a2 = A() | ||
| 8 | |||
| 9 | print(a1.b) | ||
| 10 | print(a2.b) | ||
| 11 | |||
| 12 | a1.b["test"] = 123 | ||
| 13 | |||
| 14 | print(a1.b) | ||
| 15 | print(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 | |||
| 5 | from aiogram import filters as f | 5 | from aiogram import filters as f |
| 6 | from aiogram import types as t | 6 | from aiogram import types as t |
| 7 | 7 | ||
| 8 | from shared.instances import config | 8 | from shared.instances import chats |
| 9 | 9 | ||
| 10 | 10 | ||
| 11 | class message: | 11 | class 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 | ||
| 19 | class user: | 19 | class 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 | ) | ||
