From 46c11a893a5eedd7e0730432bf1331344c87d415 Mon Sep 17 00:00:00 2001 From: hok7z Date: Sun, 22 Jan 2023 12:27:20 +0200 Subject: [PATCH] Code refactoring --- app.py | 23 ++-- config/config.py | 19 ++-- filters/avaible_roles.py | 5 +- filters/replay_message.py | 1 + handlers/channels/channels_handler.py | 4 +- handlers/errors/errors_handler.py | 9 +- handlers/groups/main.py | 51 ++++++--- handlers/groups/new_chat_member.py | 17 ++- handlers/groups/simple_admin.py | 153 ++++++++++++++++---------- handlers/users/user.py | 126 +++++++++++++-------- keyboards/default/__init__.py | 4 +- keyboards/default/menu.py | 19 ---- keyboards/default/menus.py | 18 +++ keyboards/inline/__init__.py | 2 +- keyboards/inline/callback_data.py | 4 - keyboards/inline/report.py | 12 ++ keyboards/inline/report_button.py | 8 -- utils/parse_timedelta.py | 31 +++--- 18 files changed, 299 insertions(+), 207 deletions(-) delete mode 100644 keyboards/default/menu.py create mode 100644 keyboards/default/menus.py delete mode 100644 keyboards/inline/callback_data.py create mode 100644 keyboards/inline/report.py delete mode 100644 keyboards/inline/report_button.py diff --git a/app.py b/app.py index b5bbaf2..bf29879 100755 --- a/app.py +++ b/app.py @@ -1,17 +1,18 @@ #!/usr/bin/env python3 import logging -from aiogram import executor -from database import db, Member, Restriction +from aiogram import executor from load import dp, bot, scheduler + import filters +import config + dp.filters_factory.bind(filters.AvaibleRolesFilter) dp.filters_factory.bind(filters.ReplayMessageFilter) import handlers -import config logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) @@ -21,15 +22,16 @@ WEBAPP_PORT = 3001 # Don`t touch anything! WEBHOOK_HOST = f'http://{WEBAPP_HOST}:{WEBAPP_PORT}' WEBHOOK_PATH = f'/bot{config.token}/' -WEBHOOK_URL = f"{WEBHOOK_HOST}{WEBHOOK_PATH}" +WEBHOOK_URL = f"{WEBHOOK_HOST}{WEBHOOK_PATH}" + async def on_startup(dp): from utils.notify_start import notify_started_bot, database_is_empty - DATABASE_EMPTY = database_is_empty() + DATABASE_EMPTY = database_is_empty() if DATABASE_EMPTY: - await bot.send_message(config.second_group_id, - "Member table is empty, run: `!reload`",parse_mode="Markdown") + await bot.send_message(config.second_group_id, + "Member table is empty, run: `!reload`", parse_mode="Markdown") await notify_started_bot(bot) @@ -38,7 +40,7 @@ async def on_startup(dp): # Reloading users data from utils import reload_users_data - scheduler.add_job(reload_users_data,"interval", seconds=config.update_interval) + scheduler.add_job(reload_users_data, "interval", seconds=config.update_interval) scheduler.start() from load import tgc @@ -46,6 +48,7 @@ async def on_startup(dp): await bot.set_webhook(WEBHOOK_URL) + async def on_shutdown(dp): await bot.delete_webhook() @@ -53,6 +56,7 @@ async def on_shutdown(dp): await dp.storage.close() await dp.storage.wait_closed() + def main() -> None: if config.USE_WEBHOOK: @@ -67,7 +71,8 @@ def main() -> None: ) else: - executor.start_polling(dp,skip_updates=True) + executor.start_polling(dp, skip_updates=True) + if __name__ == '__main__': main() diff --git a/config/config.py b/config/config.py index f6b492e..dd46b34 100644 --- a/config/config.py +++ b/config/config.py @@ -1,6 +1,7 @@ from aiogram import Dispatcher, Bot from environs import Env + env = Env() env.read_env() @@ -19,17 +20,17 @@ api_id = env.int("api_id") api_hash = env.str("api_hash") # Data update interval -update_interval = env.int("update_interval") +update_interval = env.int("update_interval") group_permissions = { - "can_send_messages":True, - "can_send_media_messages":False, - "can_send_other_messages":True, - "can_send_polls":False, - "can_invite_users":False, - "can_change_info":False, - "can_add_web_page_previews":False, - "can_pin_messages":False + "can_send_messages": True, + "can_send_media_messages": False, + "can_send_other_messages": True, + "can_send_polls": False, + "can_invite_users": False, + "can_change_info": False, + "can_add_web_page_previews": False, + "can_pin_messages": False } db_url = env.str("db_url") diff --git a/filters/avaible_roles.py b/filters/avaible_roles.py index a240d6d..5168bb8 100644 --- a/filters/avaible_roles.py +++ b/filters/avaible_roles.py @@ -3,15 +3,16 @@ from aiogram.dispatcher.filters import BoundFilter from database import Member, MemberRoles + class AvaibleRolesFilter(BoundFilter): """Filter accessed roles""" key = "available_roles" - def __init__(self,available_roles:list[MemberRoles]): + def __init__(self, available_roles: list[MemberRoles]): self.avaible_roles = available_roles - async def check(self,message:types.Message): + async def check(self, message: types.Message): member = Member.get(Member.user_id == message.from_user.id) if (member.role == "owner"): diff --git a/filters/replay_message.py b/filters/replay_message.py index ea68e35..1f7bce7 100644 --- a/filters/replay_message.py +++ b/filters/replay_message.py @@ -1,6 +1,7 @@ from aiogram import types from aiogram.dispatcher.filters import BoundFilter + class ReplayMessageFilter(BoundFilter): """Check if message replied""" key = 'replied' diff --git a/handlers/channels/channels_handler.py b/handlers/channels/channels_handler.py index c19f6f4..a8c434c 100644 --- a/handlers/channels/channels_handler.py +++ b/handlers/channels/channels_handler.py @@ -1,7 +1,7 @@ -from load import dp,types +from load import dp, types from config import group_id @dp.channel_post_handler() -async def channel_handler(message:types.Message): +async def channel_handler(message: types.Message): await message.forward(group_id) diff --git a/handlers/errors/errors_handler.py b/handlers/errors/errors_handler.py index d408693..7addae3 100644 --- a/handlers/errors/errors_handler.py +++ b/handlers/errors/errors_handler.py @@ -10,20 +10,19 @@ from aiogram.utils.exceptions import Unauthorized @dp.errors_handler() async def errors_handler(update: types.Update, exception): - if (isinstance(exception,Unauthorized)): + if (isinstance(exception, Unauthorized)): logging.info(f"Unathorized:{config.token}") return True - if (isinstance(exception,DoesNotExist)): + if (isinstance(exception, DoesNotExist)): await update.message.reply("Membser not found, you shoud update database data `!reload`", parse_mode="Markdown") return True await update.message.answer("Error happaned!\nBot terminated!") - await bot.send_message(config.second_group_id, - ( + await bot.send_message(config.second_group_id, ( "Bot terminated" f"{exception}" - ),parse_mode="Markdown" + ), parse_mode="Markdown" ) diff --git a/handlers/groups/main.py b/handlers/groups/main.py index 531fe3f..bb399fb 100644 --- a/handlers/groups/main.py +++ b/handlers/groups/main.py @@ -4,8 +4,11 @@ import config from database import Member -@dp.message_handler(commands=["start","help"],chat_type=[types.ChatType.SUPERGROUP]) -async def start_command_group(message:types.Message): +@dp.message_handler( + commands=["start", "help"], + chat_type=[types.ChatType.SUPERGROUP] +) +async def start_command_group(message: types.Message): await message.answer(( f"Hi,**{message.from_user.first_name}**!\n" "My commands:\n" @@ -14,26 +17,40 @@ async def start_command_group(message:types.Message): parse_mode="Markdown" ) -@dp.message_handler(commands=["leave"],chat_type=[types.ChatType.SUPERGROUP]) -async def leave_group(message:types.Message): + +@dp.message_handler( + commands=["leave"], + chat_type=[types.ChatType.SUPERGROUP] +) +async def leave_group(message: types.Message): user = message.from_user if (message.text.split()[0] != "I UNDERSTAND!"): await message.answer("use /leave I UNDERSTAND") return - Member.delete().get(Member.user_id == user.id) - # Ban user and save (bool) - status = await bot.kick_chat_member(chat_id=message.chat.id,user_id=user.id,until_date=None) + status = await bot.kick_chat_member( + chat_id=message.chat.id, + user_id=user.id, + until_date=None + ) if status: - await message.answer(f"User [{user.first_name}](tg://user?id={user.id}) has laved chat forever",parse_mode="Markdown") + await message.answer(( + f"User [{user.first_name}](tg://user?id={user.id})" + "has leaved chat for forever" + ), parse_mode="Markdown" + ) - Member.delete().where(Member.user_id == user.id).execute() + Member.delete().where(Member.user_id == user.id).execute() -@dp.message_handler(commands=["bio","me"],chat_type=[types.ChatType.SUPERGROUP]) + +@dp.message_handler( + commands=["bio", "me"], + chat_type=[types.ChatType.SUPERGROUP] +) async def get_information(message: types.Message): user = Member.get(Member.user_id == message.from_user.id) @@ -45,7 +62,7 @@ async def get_information(message: types.Message): @dp.message_handler( - commands=["report"], + commands=["report2"], replied=True, chat_type=[types.ChatType.SUPERGROUP] ) @@ -53,19 +70,19 @@ async def user_report(message: types.Message): args = message.text.split() if (len(args) != 2): - await message.answer("!report (reason)") + await message.answer("/report (reason)") return reported_user = message.reply_to_message.from_user reporter_user = message.from_user - reason = args[1] + reason = args[1] await bot.send_message( config.second_group_id, ( "Complaint about: [{}](tg://user?id={})\n" - "Complaint from: [{}](tg://user?id={})\n" - "Reason: {}\n" + "Complaint from: [{}](tg://user?id={})\n\n" + "Note: {}\n" "{}" ).format( reported_user.first_name, @@ -73,7 +90,7 @@ async def user_report(message: types.Message): reporter_user.first_name, reporter_user.id, reason, - message.reply_to_message.link("Link message", as_html=False) + message.reply_to_message.link("link message", as_html=False) ), - parse_mode="Markdown", + parse_mode="Markdown", ) diff --git a/handlers/groups/new_chat_member.py b/handlers/groups/new_chat_member.py index ac475ba..5bf5da2 100644 --- a/handlers/groups/new_chat_member.py +++ b/handlers/groups/new_chat_member.py @@ -1,27 +1,26 @@ from load import dp, types from database import Member + @dp.message_handler(content_types=["new_chat_members"]) -async def welcome_message(message:types.Message): +async def welcome_message(message: types.Message): user = Member.get_or_none(Member.user_id == message.from_user.id) - if (user): await message.answer(f"Hi, {user.first_name} again") if not (user): Member.create( - user_id = message.from_user.id, - first_name = message.from_user.first_name, - username = message.from_user.username, + user_id=message.from_user.id, + first_name=message.from_user.first_name, + username=message.from_user.username, ) await message.answer(( f"Hi, **{user.first_name}**!\n" "Please, read [chat rules]({})" - ).format( - "https://nometa.xyz" - ),parse_mode="Markdown") - + ).format("https://nometa.xyz"), + parse_mode="Markdown" + ) await message.delete() diff --git a/handlers/groups/simple_admin.py b/handlers/groups/simple_admin.py index 0bbec9d..04221fe 100644 --- a/handlers/groups/simple_admin.py +++ b/handlers/groups/simple_admin.py @@ -3,7 +3,7 @@ from aiogram.types.chat_permissions import ChatPermissions import config -from database import Member, Restriction +from database import Restriction from database import MemberRoles from utils import get_command_args, get_argument, parse_timedelta_from_message @@ -20,7 +20,6 @@ async def ban_user(message: types.Message): to_user = command.to_user from_user = command.from_user - # If can't descibe user data if (not to_user) or (not from_user): await message.answer(( "Usage: !ban (@username|id) reason=None\n" @@ -28,14 +27,18 @@ async def ban_user(message: types.Message): ) return - # Ban user and save (bool) - status = await bot.kick_chat_member(chat_id=message.chat.id, user_id=to_user.user_id, until_date=None) + status = await bot.kick_chat_member( + chat_id=message.chat.id, + user_id=to_user.user_id, + until_date=None + ) if status and (not command.is_silent): - await message.answer(f"[{from_user.first_name}](tg://user?id={from_user.user_id}) has banned [{to_user.first_name}](tg://user?id={to_user.user_id})",parse_mode="Markdown") + await message.answer(( + f"[{from_user.first_name}](tg://user?id={from_user.user_id}) has banned " + f"[{to_user.first_name}](tg://user?id={to_user.user_id})" + ), parse_mode="Markdown") - - # Open restrict Restriction.create( from_user=from_user, to_user=to_user, @@ -43,10 +46,11 @@ async def ban_user(message: types.Message): message_id=message.message_id ) + @dp.message_handler( commands=["unban", "sunban"], commands_prefix="!", - available_roles=[MemberRoles.HELPER,MemberRoles.ADMIN] + available_roles=[MemberRoles.HELPER, MemberRoles.ADMIN] ) async def unban_user(message: types.Message): command = await get_command_args(message) @@ -54,7 +58,6 @@ async def unban_user(message: types.Message): to_user = command.to_user from_user = command.from_user - # If can't descibe user data if (not to_user) or (not from_user): await message.answer(( "Usage: !unban (@username|id) reason=None\n" @@ -62,12 +65,13 @@ async def unban_user(message: types.Message): ) return - # Unban user and set status status = await bot.unban_chat_member(chat_id=message.chat.id, user_id=to_user.user_id) if status and (not command.is_silent): - await message.answer(f"[{from_user.first_name}](tg://user?id={from_user.user_id}) has unbanned [{to_user.first_name}](tg://user?id={to_user.user_id})",parse_mode="Markdown") - + await message.answer(( + f"[{from_user.first_name}](tg://user?id={from_user.user_id}) has unbanned " + f"[{to_user.first_name}](tg://user?id={to_user.user_id})" + ), parse_mode="Markdown") Restriction.create( from_user=from_user, @@ -76,6 +80,7 @@ async def unban_user(message: types.Message): message_id=message.message_id ) + @dp.message_handler( commands=["info"], commands_prefix="!", @@ -83,8 +88,7 @@ async def unban_user(message: types.Message): ) async def info_user(message: types.Message): command = await get_command_args(message) - - to_user = command.to_user + to_user = command.to_user if (not to_user): await message.answer(( @@ -99,6 +103,7 @@ async def info_user(message: types.Message): parse_mode="Markdown" ) + @dp.message_handler( commands=["kick", "skick"], commands_prefix="!", @@ -118,12 +123,23 @@ async def kick_user(message: types.Message): return - status1 = await bot.kick_chat_member(chat_id=message.chat.id, user_id=to_user.user_id, until_date=None) - status2 = await bot.unban_chat_member(chat_id=message.chat.id, user_id=to_user.user_id) + status1 = await bot.kick_chat_member( + chat_id=message.chat.id, + user_id=to_user.user_id, + until_date=None + ) + + status2 = await bot.unban_chat_member( + chat_id=message.chat.id, + user_id=to_user.user_id + ) if (not status1 and status2) and (not command.is_silent): - await message.answer(f"[{from_user.first_name}](tg://user?id={from_user.user_id}) has kicked [{to_user.first_name}](tg://user?id={to_user.user_id})",parse_mode="Markdown") - + await message.answer(( + f"[{from_user.first_name}](tg://user?id={from_user.user_id}) has kicked " + f"[{to_user.first_name}](tg://user?id={to_user.user_id})" + ), parse_mode="Markdown") + Restriction.create( from_user=from_user, to_user=to_user, @@ -132,19 +148,18 @@ async def kick_user(message: types.Message): ) - @dp.message_handler( commands=["mute", "smute"], commands_prefix="!", available_roles=[MemberRoles.ADMIN] ) -async def mute_user(message:types.Message): - command = await get_command_args(message) - +async def mute_user(message: types.Message): + command = await get_command_args(message) + to_user = command.to_user from_user = command.from_user - duration = await parse_timedelta_from_message(message) + duration = parse_timedelta_from_message(message) if (not to_user) or (not from_user): await message.answer(( @@ -163,7 +178,10 @@ async def mute_user(message:types.Message): ) if status and (not command.is_silent): - await message.answer(f"[{from_user.first_name}](tg://user?id={from_user.user_id}) has muted [{to_user.first_name}](tg://user?id={to_user.user_id})",parse_mode="Markdown") + await message.answer(( + f"[{from_user.first_name}](tg://user?id={from_user.user_id}) has muted " + f"[{to_user.first_name}](tg://user?id={to_user.user_id})" + ), parse_mode="Markdown") Restriction.create( from_user=from_user, @@ -174,7 +192,7 @@ async def mute_user(message:types.Message): @dp.message_handler( - commands=["unmute","sunmute"], + commands=["unmute", "sunmute"], commands_prefix="!", available_roles=[MemberRoles.ADMIN] ) @@ -185,27 +203,26 @@ async def umute_user(message: types.Message): to_user = command.to_user from_user = command.from_user - # If can't if (not to_user) or (not from_user): await message.answer(( "Usage:!unmute (@username|id) reason=None.\n" "Reply to a message or use with a username/id.") ) - return + return # Get chat permissions group_permissions = config.group_permissions # Set permissions permissions = ChatPermissions( - can_send_messages = group_permissions["can_send_messages"], - can_send_media_messages = group_permissions["can_send_media_messages"], - can_send_polls = group_permissions["can_send_polls"], - can_send_other_messages = group_permissions["can_send_other_messages"], - can_add_web_page_previews = group_permissions["can_add_web_page_previews"], - can_change_info = group_permissions["can_change_info"], - can_invite_users = group_permissions["can_invite_users"], - can_pin_messages = group_permissions["can_pin_messages"] + can_send_messages=group_permissions["can_send_messages"], + can_send_media_messages=group_permissions["can_send_media_messages"], + can_send_polls=group_permissions["can_send_polls"], + can_send_other_messages=group_permissions["can_send_other_messages"], + can_add_web_page_previews=group_permissions["can_add_web_page_previews"], + can_change_info=group_permissions["can_change_info"], + can_invite_users=group_permissions["can_invite_users"], + can_pin_messages=group_permissions["can_pin_messages"] ) # Restrict user and save @@ -216,7 +233,10 @@ async def umute_user(message: types.Message): ) if status and (not command.is_silent): - await message.answer(f"[{from_user.first_name}](tg://user?id={from_user.user_id}) has unmuted [{to_user.first_name}](tg://user?id={to_user.user_id})",parse_mode="Markdown") + await message.answer(( + f"[{from_user.first_name}](tg://user?id={from_user.user_id}) has unmuted " + f"[{to_user.first_name}](tg://user?id={to_user.user_id})" + ), parse_mode="Markdown") @dp.message_handler( @@ -229,7 +249,7 @@ async def pin_message(message: types.Message): @dp.message_handler( - commands=["readonly","ro"], + commands=["readonly", "ro"], commands_prefix="!", available_roles=[MemberRoles.ADMIN] ) @@ -238,28 +258,32 @@ async def readonly_mode(message: types.Message): status = config.group_permissions['can_send_messages'] if (status): - await message.answer("🔕 Readonly mode enabled!") - chat_permissions = ChatPermissions( - can_send_messages = not status + await message.answer("🔕 Readonly mode enabled!") + chat_permissions = ChatPermissions( + can_send_messages=not status ) else: await message.answer("🔔 Readonly mode disabled!") chat_permissions = ChatPermissions( - can_send_messages = group_permissions['can_send_messages'], - can_send_media_messages = group_permissions["can_send_media_messages"], - can_send_other_messages = group_permissions['can_send_other_messages'], - can_send_polls = group_permissions['can_send_polls'], - can_invite_users = group_permissions['can_invite_users'], - can_change_info = group_permissions['can_change_info'], - can_add_web_page_previews = group_permissions['can_add_web_page_previews'], - can_pin_messages = group_permissions['can_pin_messages'] + can_send_messages=group_permissions['can_send_messages'], + can_send_media_messages=group_permissions["can_send_media_messages"], + can_send_other_messages=group_permissions['can_send_other_messages'], + can_send_polls=group_permissions['can_send_polls'], + can_invite_users=group_permissions['can_invite_users'], + can_change_info=group_permissions['can_change_info'], + can_add_web_page_previews=group_permissions['can_add_web_page_previews'], + can_pin_messages=group_permissions['can_pin_messages'] ) config.group_permissions["can_send_messages"] = not status - await bot.set_chat_permissions(chat_id = message.chat.id, permissions = chat_permissions) + await bot.set_chat_permissions( + chat_id=message.chat.id, + permissions=chat_permissions + ) + @dp.message_handler( - commands=["warn","w"], + commands=["warn", "w"], commands_prefix="!", available_roles=[MemberRoles.HELPER, MemberRoles.ADMIN] ) @@ -279,14 +303,24 @@ async def warn_user(message: types.Message): to_user.warns += 1 to_user.save() - - await message.answer(f"[{from_user.first_name}](tg://user?id={from_user.user_id}) has warned [{to_user.first_name}](tg://user?id={to_user.user_id}) ({to_user.warns}/{config.limit_of_warns})",parse_mode="Markdown") + await message.answer(( + f"[{from_user.first_name}](tg://user?id={from_user.user_id}) has warned " + f"[{to_user.first_name}](tg://user?id={to_user.user_id})" + ), parse_mode="Markdown") if (to_user.warns == config.limit_of_warns): - await message.answer(f"[{to_user.first_name}](tg://user?id={to_user.user_id}) has been banned!",parse_mode="Markdown") - await bot.kick_chat_member(chat_id=message.chat.id, user_id=to_user.user_id, until_date=None) - + await message.answer(( + f"[{from_user.first_name}](tg://user?id={from_user.user_id}) " + f"has banned {config.limit_of_warns}/{config.limit_of_warns} ⚠️ " + ), parse_mode="Markdown") + + await bot.kick_chat_member( + chat_id=message.chat.id, + user_id=to_user.user_id, + until_date=None + ) + Restriction.create( from_user=from_user, to_user=to_user, @@ -305,12 +339,13 @@ async def reload(message: types.Message): await message.answer("Reloaded!") + @dp.message_handler( commands=["setrole"], commands_prefix="!", available_roles=[MemberRoles.ADMIN] ) -async def set_role(message:types.Message): +async def set_role(message: types.Message): command = await get_command_args(message) new_role = get_argument(command.arguments) @@ -335,5 +370,7 @@ async def set_role(message:types.Message): to_user.role = new_role to_user.save() - await message.answer(f"{new_role.capitalize()} role set for \ - [{to_user.first_name}](tg://user?id={to_user.user_id})",parse_mode="Markdown") + await message.answer(( + f"{new_role.capitalize()} role set for " + f"[{to_user.first_name}](tg://user?id={to_user.user_id})" + ), parse_mode="Markdown") diff --git a/handlers/users/user.py b/handlers/users/user.py index ab7393c..36536cc 100644 --- a/handlers/users/user.py +++ b/handlers/users/user.py @@ -1,33 +1,37 @@ from load import dp, types, bot from database import Member, Restriction -from aiogram.types import KeyboardButton,ReplyKeyboardMarkup +from aiogram.types import KeyboardButton, ReplyKeyboardMarkup +from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup from aiogram.types.reply_keyboard import ReplyKeyboardRemove import config -from keyboards.default import menu +from keyboards.default import menus -from aiogram.types import CallbackQuery +from aiogram.types import CallbackQuery from aiogram.dispatcher.filters import Text from aiogram.dispatcher.storage import FSMContext from states.report_message import States -from keyboards.inline.report_button import report_button -from keyboards.inline.callback_data import report_callback +from keyboards.inline.report import report_callback -@dp.message_handler(commands=["start","help"],chat_type=[types.ChatType.PRIVATE]) -async def start_command_private(message:types.Message): + +@dp.message_handler( + commands=["start", "help"], + chat_type=[types.ChatType.PRIVATE] +) +async def start_command_private(message: types.Message): await message.answer(( f"Hi, **{message.from_user.first_name}**!\n" "My commands:\n" - "\t\t/help /start - read this message.") - ,parse_mode="Markdown",reply_markup=menu + "\t\t/help /start - read this message." + ), parse_mode="Markdown", reply_markup=menus.bot_description_menu ) -# Keyboard + @dp.message_handler(Text(equals=["About Us"])) -async def about_us(message:types.Message): +async def about_us(message: types.Message): await message.answer(( "Moderator bot - an open source project for managing a Telegram group.\n\n" "Possibilities:\n" @@ -37,13 +41,15 @@ async def about_us(message:types.Message): "4. Users can report admins.\n" "5. Admins can give warnings to users.\n" "\nRelease version:2.5.2\n" - "[Github](https://github.com/hok7z/moderator-bot)"), - parse_mode="Markdown" + "[Github](https://github.com/hok7z/moderator-bot)"),parse_mode="Markdown" ) -@dp.message_handler(Text(equals=["Check restrictions"]),state=None) -async def check_for_restrict(message:types.Message): +@dp.message_handler( + Text(equals=["Check restrictions"]), + state=None +) +async def check_for_restrict(message: types.Message): user = Member.get(Member.user_id == message.from_user.id) restrictions = Restriction.select().where(Restriction.to_user == user) @@ -53,29 +59,48 @@ async def check_for_restrict(message:types.Message): for restriction in restrictions: callback = report_callback.new(restriction_id=restriction.id) - markup = report_button("✉️ Report restriction",callback) - from_user = restriction.from_user - to_user = restriction.to_user + markup = InlineKeyboardMarkup() + report_restriction = InlineKeyboardButton( + "✉️ Report restriction", + callback_data=callback + ) + markup.insert(report_restriction) + + from_user = restriction.from_user + to_user = restriction.to_user - await message.answer( - ( - f"Restriction #{restriction.id}\n" - f"from user: [{from_user.first_name}](tg://user?id={from_user.user_id})\n" - f"to user: [{from_user.first_name}](tg://user?id={to_user.user_id})\n" - f"{restriction.text}\n" - f"{restriction.timestamp}\n" - ),parse_mode="Markdown", - reply_markup=markup + await message.answer(( + "Restriction #{}\n" + "from user [{}](tg://user?id={})\n" + "to user [{}](tg://user?id={})\n" + "Note: {}\n" + "{}\n" + ).format( + restriction.id, + + from_user.first_name, + from_user.user_id, + + to_user.first_name, + to_user.user_id, + + restriction.text, + restriction.timestamp + ), parse_mode="Markdown", reply_markup=markup ) - await States.state1.set() + await States.state1.set() -@dp.callback_query_handler(text_contains="report_restriction",state=States.state1) -async def report_restriction(call:CallbackQuery, state:FSMContext): + +@dp.callback_query_handler( + text_contains="report_restriction", + state=States.state1 +) +async def report_restriction(call: CallbackQuery, state: FSMContext): await call.answer(cache_time=60) - callback_data = call.data + callback_data = call.data restriction_id = callback_data.split(":")[1] markup = ReplyKeyboardMarkup(resize_keyboard=True) @@ -84,30 +109,32 @@ async def report_restriction(call:CallbackQuery, state:FSMContext): await state.update_data(restriction_id=restriction_id) - await call.message.answer("Please,enter your report.",reply_markup=markup) + await call.message.answer("Please,enter your report.", reply_markup=markup) await States.next() + @dp.message_handler(state=States.state2) -async def get_message_report(message:types.Message, state:FSMContext): +async def get_message_report(message: types.Message, state: FSMContext): answer = message.text if not ("Cancel" in answer): data = await state.get_data() - restriction_id = data.get("restriction_id") + restriction_id = data.get("restriction_id") restriction = Restriction.get(id=restriction_id) - from_user = restriction.from_user - to_user = restriction.to_user + from_user = restriction.from_user + to_user = restriction.to_user - await bot.send_message(config.second_group_id, - ( + restriction_timestamp = restriction.timestamp.strftime("%d.%m.%y at %H:%M (server time)") + + await bot.send_message(config.second_group_id, ( "Report on restriction #{}\n" - "from user: [{}](tg://user?id={})\n" - "to user: [{}](tg://user?id={})\n" + "Complaint from: [{}](tg://user?id={})\n" + "Complaint about: [{}](tg://user?id={})\n" + "Sent {}\n" "{}\n" - "{}\n" - "Message:{}" + "Message: {}" ).format( restriction_id, from_user.first_name, @@ -115,14 +142,19 @@ async def get_message_report(message:types.Message, state:FSMContext): to_user.first_name, to_user.user_id, restriction.text, - restriction.timestamp, + restriction_timestamp, answer, - ) - ,parse_mode="Markdown" + ), parse_mode="Markdown" ) - await message.answer("Report restriction sended",reply_markup=ReplyKeyboardRemove()) + await message.answer( + "Report restriction sended", + reply_markup=ReplyKeyboardRemove() + ) else: - await message.answer("Operation cancaled",reply_markup=ReplyKeyboardRemove()) + await message.answer( + "Operation cancaled", + reply_markup=ReplyKeyboardRemove() + ) await state.finish() diff --git a/keyboards/default/__init__.py b/keyboards/default/__init__.py index cb8d856..e2c3371 100644 --- a/keyboards/default/__init__.py +++ b/keyboards/default/__init__.py @@ -1,2 +1,2 @@ -from .menu import menu -from .menu import cancel +from .menus import bot_description_menu +from .menus import cancel_menu diff --git a/keyboards/default/menu.py b/keyboards/default/menu.py deleted file mode 100644 index 138210d..0000000 --- a/keyboards/default/menu.py +++ /dev/null @@ -1,19 +0,0 @@ -from aiogram.types import ReplyKeyboardMarkup,KeyboardButton - -menu = ReplyKeyboardMarkup( - resize_keyboard=True, - keyboard=[ - [ - KeyboardButton("Check restrictions"), - KeyboardButton("About Us"), - ] -]) - -cancel = ReplyKeyboardMarkup( - resize_keyboard=True, - keyboard=[ - [ - KeyboardButton("❌Cancel") - ] - ] -) diff --git a/keyboards/default/menus.py b/keyboards/default/menus.py new file mode 100644 index 0000000..5b2581c --- /dev/null +++ b/keyboards/default/menus.py @@ -0,0 +1,18 @@ +from aiogram.types import ReplyKeyboardMarkup, KeyboardButton + + +bot_description_menu = ReplyKeyboardMarkup( + resize_keyboard=True, + keyboard=[[ + KeyboardButton("Check restrictions"), + KeyboardButton("About Us"), + ]] +) + + +cancel_menu = ReplyKeyboardMarkup( + resize_keyboard=True, + keyboard=[[ + KeyboardButton("❌Cancel") + ]] +) diff --git a/keyboards/inline/__init__.py b/keyboards/inline/__init__.py index 82b070f..4c4f242 100644 --- a/keyboards/inline/__init__.py +++ b/keyboards/inline/__init__.py @@ -1 +1 @@ -from . import report_button +from . import report diff --git a/keyboards/inline/callback_data.py b/keyboards/inline/callback_data.py deleted file mode 100644 index 06f8953..0000000 --- a/keyboards/inline/callback_data.py +++ /dev/null @@ -1,4 +0,0 @@ -from aiogram.utils.callback_data import CallbackData - - -report_callback = CallbackData("report_restriction","restriction_id") diff --git a/keyboards/inline/report.py b/keyboards/inline/report.py new file mode 100644 index 0000000..9474251 --- /dev/null +++ b/keyboards/inline/report.py @@ -0,0 +1,12 @@ +from aiogram.utils.callback_data import CallbackData +from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup + + +report_callback = CallbackData("report_restriction", "restriction_id") + + +def inline_button(text, callback_data): + markup = InlineKeyboardMarkup() + button = InlineKeyboardButton(text, callback_data=callback_data) + markup.insert(button) + return markup diff --git a/keyboards/inline/report_button.py b/keyboards/inline/report_button.py deleted file mode 100644 index ebb6365..0000000 --- a/keyboards/inline/report_button.py +++ /dev/null @@ -1,8 +0,0 @@ -from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup - - -def report_button(text,callback_data): - markup = InlineKeyboardMarkup() - button = InlineKeyboardButton(text,callback_data=callback_data) - markup.insert(button) - return markup diff --git a/utils/parse_timedelta.py b/utils/parse_timedelta.py index 4ec5f8d..59ccde1 100644 --- a/utils/parse_timedelta.py +++ b/utils/parse_timedelta.py @@ -2,30 +2,31 @@ import re import typing import datetime - from load import types def parse_timedelta(value: str) -> typing.Optional[datetime.timedelta]: + regex = r'(?:(\d+)(?:d|д))?(?:(\d+)(?:h|ч))?(?:(\d+)(?:m|м))?(?:(\d+)(?:s|с))?' specification = value.strip().replace(' ', '') - match = re.fullmatch(r'(?:(\d+)(?:d|д))?(?:(\d+)(?:h|ч))?(?:(\d+)(?:m|м))?(?:(\d+)(?:s|с))?', specification) + match = re.fullmatch(regex, specification) if match: units = [(0 if i is None else int(i)) for i in match.groups()] - return datetime.timedelta(days=units[0], hours=units[1], minutes=units[2], seconds=units[3]) - else: - return None + return datetime.timedelta( + days=units[0], + hours=units[1], + minutes=units[2], + seconds=units[3] + ) -async def parse_timedelta_from_message( - message: types.Message, - ) -> typing.Optional[datetime.timedelta]: - _, *args = message.text.split() +def parse_timedelta_from_message(message: types.Message) -> typing.Optional[datetime.timedelta]: + _, *args = message.text.split() - if args: - duration = re.findall(r"(\d+d|\d+h|\d+m|\d+s)",''.join(message.text)) + if args: + duration = re.findall(r"(\d+d|\d+h|\d+m|\d+s)", ''.join(message.text)) + if duration: duration = " ".join(duration) duration = parse_timedelta(duration) - - return duration - else: - return datetime.timedelta(0,0,0) # forever + if not duration: + duration = datetime.timedelta(0, 0, 0) + return duration