Migrate to aiogram dev-3.0b6

This commit is contained in:
hok7z 2023-02-18 15:16:54 +02:00
parent 65eada8924
commit f42f28a0ce
15 changed files with 225 additions and 238 deletions

9
app.py
View File

@ -11,14 +11,9 @@ from aiogram.webhook.aiohttp_server import (
)
# import filters
import config
# dp.filters_factory.bind(filters.AvaibleRolesFilter)
# dp.filters_factory.bind(filters.ReplayMessageFilter)
# import handlers
import handlers
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)
@ -38,7 +33,7 @@ async def on_startup():
if DATABASE_EMPTY:
await bot.send_message(
config.second_group_id,
"Member table is empty, run: `!reload`", parse_mode="Markdown"
"Member table is empty, run: `!reload`"
)
await notify_started_bot(bot)

View File

@ -1,2 +1,3 @@
from .avaible_roles import AvaibleRolesFilter
from .replay_message import ReplayMessageFilter
from .available_roles import AvailableRoles
from .reply_message import MessageReplied
from .chat_type_filter import ChatTypeFilter

View File

@ -1,18 +1,15 @@
from aiogram import types
from aiogram.dispatcher.filters import BoundFilter
from aiogram.filters import Filter
from database import Member, MemberRoles
class AvaibleRolesFilter(BoundFilter):
class AvailableRoles(Filter):
"""Filter accessed roles"""
key = "available_roles"
def __init__(self, *args):
self.avaible_roles: list[MemberRoles] = args
def __init__(self, available_roles: list[MemberRoles]):
self.avaible_roles = available_roles
async def check(self, message: types.Message):
async def __call__(self, message: types.Message) -> bool:
member = Member.get(Member.user_id == message.from_user.id)
if (member.role == "owner"):

View File

@ -0,0 +1,10 @@
from aiogram.filters import Filter
from aiogram import types
class ChatTypeFilter(Filter):
def __init__(self, *chat_types: list[str]):
self.chat_types = chat_types
async def __call__(self, message: types.Message):
return message.chat.type in self.chat_types

View File

@ -1,16 +0,0 @@
from aiogram import types
from aiogram.dispatcher.filters import BoundFilter
class ReplayMessageFilter(BoundFilter):
"""Check if message replied"""
key = 'replied'
def __init__(self, replied):
self.replied = replied
async def check(self, message: types.Message):
if message.reply_to_message is None:
await message.reply("Is command must be reply")
return False
return True

15
filters/reply_message.py Normal file
View File

@ -0,0 +1,15 @@
from aiogram import types
from aiogram.filters import Filter
class MessageReplied(Filter):
"""Check if message replied"""
def __init__(self, replied=True):
self.replied = replied
async def __call__(self, message: types.Message):
if not message.reply_to_message:
await message.reply("Is command must be reply")
return False
return True

View File

@ -2,6 +2,6 @@ from load import dp, types
from config import group_id
@dp.channel_post_handler()
async def channel_handler(message: types.Message):
@dp.channel_post()
async def channel_handler(message):
await message.forward(group_id)

View File

@ -1,28 +1,23 @@
import logging
from peewee import DoesNotExist
from load import dp, bot, types
import config
from aiogram.utils.exceptions import Unauthorized
from peewee import DoesNotExist
from aiogram.exceptions import TelegramUnauthorizedError
@dp.errors_handler()
async def errors_handler(update: types.Update, exception):
if (isinstance(exception, Unauthorized)):
logging.info(f"Unathorized:{config.token}")
@dp.errors()
async def errors_handler(event: types.error_event.ErrorEvent):
if (isinstance(event.exception, TelegramUnauthorizedError)):
logging.info(f"Unathorized: {config.token}")
return True
if (isinstance(exception, DoesNotExist)):
await update.message.reply("Membser not found, you shoud update database data `!reload`",
parse_mode="Markdown")
if (isinstance(event.exception, DoesNotExist)):
event.update.message.reply("Membser not found, you shoud update database data `!reload`")
return True
await update.message.answer("Error happaned!\nBot terminated!")
await bot.send_message(config.second_group_id, (
"Bot terminated"
f"{exception}"
), parse_mode="Markdown"
)
"Bot terminated\n"
f"Exception: {event.exception}"
))

View File

@ -1,50 +1,59 @@
from load import bot, dp, types
from aiogram import Bot
import config
from aiogram.filters import Command
from filters import MessageReplied
from filters import ChatTypeFilter
from database import Member
from aiogram.filters.chat_member_updated import \
ChatMemberUpdatedFilter, JOIN_TRANSITION, ChatMemberUpdated
@dp.message_handler(content_types=["new_chat_members"])
async def welcome_message(message: types.Message):
user = Member.get_or_none(Member.user_id == message.from_user.id)
@dp.chat_member(
ChatMemberUpdatedFilter(member_status_changed=JOIN_TRANSITION)
)
async def welcome_message(event: ChatMemberUpdated, _bot: Bot):
user = Member.get_or_none(Member.user_id == event.from_user.id)
if (user):
await message.answer(f"Hi, {user.first_name} again")
await _bot.send_message(
chat_id=event.chat.id,
text=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=event.from_user.id,
first_name=event.from_user.first_name,
username=event.from_user.username,
)
await message.answer((
f"Hi, **{user.first_name}**!\n"
"Please, read [chat rules]({})"
).format("https://nometa.xyz"),
parse_mode="Markdown"
await _bot.send_message(
chat_id=event.chat.id,
text=f"Hi, [{user.first_name}](tg://user?id={user.id})!\n"
"Please, read [chat rules](https://nometa.xyz)"
)
await message.delete()
@dp.message_handler(
commands=["start", "help"],
chat_type=[types.ChatType.SUPERGROUP]
@dp.message(
Command("start", "help"),
ChatTypeFilter("supergroup")
)
async def start_command_group(message: types.Message):
await message.answer((
f"Hi,**{message.from_user.first_name}**!\n"
f"Hi, [{message.from_user.first_name}](tg://user?id={message.from_user.id})!\n"
"My commands:\n"
" /help , /start - read the message\n"
" /me , /bio - member information (if member group)"),
parse_mode="Markdown"
" /me , /bio - member information (if member group)")
)
@dp.message_handler(
commands=["leave"],
chat_type=[types.ChatType.SUPERGROUP]
@dp.message(
Command("leave"),
ChatTypeFilter("supergroup")
)
async def leave_group(message: types.Message):
user = message.from_user
@ -65,30 +74,28 @@ async def leave_group(message: types.Message):
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()
@dp.message_handler(
commands=["bio", "me"],
chat_type=[types.ChatType.SUPERGROUP]
@dp.message(
Command("bio", "me"),
ChatTypeFilter("supergroup")
)
async def get_information(message: types.Message):
user = Member.get(Member.user_id == message.from_user.id)
await message.answer((
f"[{user.first_name}](tg://user?id={user.user_id}) ({user.role})\n"
f"Warns: {user.warns}/{config.limit_of_warns}"),
parse_mode="Markdown"
)
f"Warns: {user.warns}/{config.limit_of_warns}"
))
@dp.message_handler(
commands=["report"],
replied=True,
chat_type=[types.ChatType.SUPERGROUP]
@dp.message(
Command("report"),
MessageReplied(),
ChatTypeFilter("supergroup")
)
async def user_report(message: types.Message):
args = message.text.split()
@ -115,6 +122,5 @@ async def user_report(message: types.Message):
reporter_user.id,
reason,
message.reply_to_message.link("link message", as_html=False)
),
parse_mode="Markdown",
)
)

View File

@ -1,6 +1,7 @@
from load import bot, dp, types
from aiogram.types.chat_permissions import ChatPermissions
from aiogram.filters.command import Command
from filters import AvailableRoles
import config
from database import Restriction
@ -9,10 +10,9 @@ from database import MemberRoles
from utils import get_command_args, get_argument, parse_timedelta_from_message
@dp.message_handler(
commands=["ban", "sban"],
commands_prefix="!",
available_roles=[MemberRoles.HELPER, MemberRoles.ADMIN]
@dp.message(
Command("ban", "sban", prefix="!"),
AvailableRoles(MemberRoles.HELPER, MemberRoles.ADMIN)
)
async def ban_user(message: types.Message):
command = await get_command_args(message)
@ -37,7 +37,7 @@ async def ban_user(message: types.Message):
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")
))
Restriction.create(
from_user=from_user,
@ -47,10 +47,9 @@ async def ban_user(message: types.Message):
)
@dp.message_handler(
commands=["unban", "sunban"],
commands_prefix="!",
available_roles=[MemberRoles.HELPER, MemberRoles.ADMIN]
@dp.message(
Command("unban", "sunban", prefix="!"),
AvailableRoles(MemberRoles.HELPER, MemberRoles.ADMIN)
)
async def unban_user(message: types.Message):
command = await get_command_args(message)
@ -65,13 +64,16 @@ async def unban_user(message: types.Message):
)
return
status = await bot.unban_chat_member(chat_id=message.chat.id, user_id=to_user.user_id)
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 "
f"[{to_user.first_name}](tg://user?id={to_user.user_id})"
), parse_mode="Markdown")
))
Restriction.create(
from_user=from_user,
@ -81,10 +83,9 @@ async def unban_user(message: types.Message):
)
@dp.message_handler(
commands=["info"],
commands_prefix="!",
available_roles=[MemberRoles.HELPER, MemberRoles.ADMIN]
@dp.message(
Command("info", prefix="!"),
AvailableRoles(MemberRoles.HELPER, MemberRoles.ADMIN)
)
async def info_user(message: types.Message):
command = await get_command_args(message)
@ -99,15 +100,13 @@ async def info_user(message: types.Message):
await message.answer((
f"[{to_user.first_name}](tg://user?id={to_user.user_id}) ({to_user.role})\n"
f"Warns: {to_user.warns}/{config.limit_of_warns}"),
parse_mode="Markdown"
f"Warns: {to_user.warns}/{config.limit_of_warns}")
)
@dp.message_handler(
commands=["kick", "skick"],
commands_prefix="!",
available_roles=[MemberRoles.HELPER, MemberRoles.ADMIN]
@dp.message(
Command("kick", "skick", prefix="!"),
AvailableRoles(MemberRoles.HELPER, MemberRoles.ADMIN)
)
async def kick_user(message: types.Message):
command = await get_command_args(message)
@ -122,7 +121,6 @@ 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,
@ -138,7 +136,7 @@ async def kick_user(message: types.Message):
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,
@ -148,10 +146,9 @@ async def kick_user(message: types.Message):
)
@dp.message_handler(
commands=["mute", "smute"],
commands_prefix="!",
available_roles=[MemberRoles.ADMIN]
@dp.message(
Command("mute", "smute", prefix="!"),
AvailableRoles(MemberRoles.ADMIN)
)
async def mute_user(message: types.Message):
command = await get_command_args(message)
@ -163,7 +160,7 @@ async def mute_user(message: types.Message):
if (not to_user) or (not from_user):
await message.answer((
"Usage:!mute (@username|id) (duration)\n"
"Usage: !mute (@username|id) (duration)\n"
"Reply to a message or use with a username/id")
)
return
@ -181,7 +178,7 @@ async def mute_user(message: types.Message):
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,
@ -191,10 +188,9 @@ async def mute_user(message: types.Message):
)
@dp.message_handler(
commands=["unmute", "sunmute"],
commands_prefix="!",
available_roles=[MemberRoles.ADMIN]
@dp.message(
Command("unmute", "sunmute", prefix="!"),
AvailableRoles(MemberRoles.ADMIN)
)
async def umute_user(message: types.Message):
# Get information
@ -205,7 +201,7 @@ async def umute_user(message: types.Message):
if (not to_user) or (not from_user):
await message.answer((
"Usage:!unmute (@username|id) reason=None.\n"
"Usage: !unmute (@username|id) reason=None\n"
"Reply to a message or use with a username/id.")
)
return
@ -236,22 +232,20 @@ async def umute_user(message: types.Message):
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(
commands=["pin"],
commands_prefix="!",
available_roles=[MemberRoles.HELPER, MemberRoles.ADMIN]
@dp.message(
Command("pin", prefix="!"),
AvailableRoles(MemberRoles.HELPER, MemberRoles.ADMIN)
)
async def pin_message(message: types.Message):
await bot.pin_chat_message(message.chat.id, message.reply_to_message.message_id)
@dp.message_handler(
commands=["readonly", "ro"],
commands_prefix="!",
available_roles=[MemberRoles.ADMIN]
@dp.message(
Command("ro", "readonly", prefix="!"),
AvailableRoles(MemberRoles.ADMIN)
)
async def readonly_mode(message: types.Message):
group_permissions = config.group_permissions
@ -282,10 +276,9 @@ async def readonly_mode(message: types.Message):
)
@dp.message_handler(
commands=["warn", "w"],
commands_prefix="!",
available_roles=[MemberRoles.HELPER, MemberRoles.ADMIN]
@dp.message(
Command("warn", "w", prefix="!"),
AvailableRoles(MemberRoles.HELPER, MemberRoles.ADMIN)
)
async def warn_user(message: types.Message):
# Get information
@ -307,13 +300,13 @@ async def warn_user(message: types.Message):
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"[{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,
@ -329,9 +322,8 @@ async def warn_user(message: types.Message):
)
@dp.message_handler(
commands=["reload"],
commands_prefix="!"
@dp.message(
Command("reload", prefix="!")
)
async def reload(message: types.Message):
from utils import reload_users_data
@ -340,10 +332,9 @@ async def reload(message: types.Message):
await message.answer("Reloaded!")
@dp.message_handler(
commands=["setrole"],
commands_prefix="!",
available_roles=[MemberRoles.ADMIN]
@dp.message(
Command("setrole", prefix="!"),
AvailableRoles(MemberRoles.ADMIN)
)
async def set_role(message: types.Message):
command = await get_command_args(message)
@ -373,4 +364,4 @@ async def set_role(message: types.Message):
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")
))

View File

@ -1,36 +1,42 @@
from load import dp, types, bot
from load import dp, bot, types
from database import Member, Restriction
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 menus
from aiogram.types import CallbackQuery
from aiogram.dispatcher.filters import Text
from aiogram.utils.keyboard import InlineKeyboardBuilder, ReplyKeyboardBuilder
from aiogram.fsm.context import FSMContext
from aiogram.types import ReplyKeyboardRemove
from aiogram.dispatcher.storage import FSMContext
from states.report_message import States
from aiogram.fsm.state import State, StatesGroup
from keyboards.inline.report import report_callback
from aiogram import F
from aiogram.filters import Command
from filters import ChatTypeFilter
@dp.message_handler(
commands=["start", "help"],
chat_type=[types.ChatType.PRIVATE]
class ReportRestriction(StatesGroup):
state1 = State()
state2 = State()
@dp.message(
Command("start", "help"),
ChatTypeFilter("private")
)
async def start_command_private(message: types.Message):
bot_description_menu = ReplyKeyboardBuilder()
bot_description_menu.button(text="Check restrictions")
bot_description_menu.button(text="About Us")
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=menus.bot_description_menu
)
), reply_markup=bot_description_menu.as_markup(resize_keyboard=True))
@dp.message_handler(Text(equals=["About Us"]))
@dp.message(F.text == "About Us")
async def about_us(message: types.Message):
await message.answer((
"Moderator bot - an open source project for managing a Telegram group.\n\n"
@ -40,16 +46,14 @@ async def about_us(message: types.Message):
"3. Convenient sticker/photo disabling with !stickers, !media\n"
"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"
"\nRelease version: 2.5.2\n"
"[Github](https://github.com/hok7z/moderator-bot)")
)
@dp.message_handler(
Text(equals=["Check restrictions"]),
state=None
)
async def check_for_restrict(message: types.Message):
@dp.message(F.text == "Check restrictions")
async def check_for_restrict(message: types.Message, state: FSMContext):
await state.set_state(ReportRestriction.state1)
user = Member.get(Member.user_id == message.from_user.id)
restrictions = Restriction.select().where(Restriction.to_user == user)
@ -58,14 +62,12 @@ async def check_for_restrict(message: types.Message):
return
for restriction in restrictions:
callback = report_callback.new(restriction_id=restriction.id)
markup = InlineKeyboardBuilder()
markup = InlineKeyboardMarkup()
report_restriction = InlineKeyboardButton(
"✉️ Report restriction",
callback_data=callback
markup.button(
text="✉️ Report restriction",
callback_data=restriction.id
)
markup.insert(report_restriction)
from_user = restriction.from_user
to_user = restriction.to_user
@ -76,45 +78,43 @@ async def check_for_restrict(message: types.Message):
"to user [{}](tg://user?id={})\n"
"Note: {}\n"
"{}\n"
).format(
restriction.id,
).format(
restriction.id,
from_user.first_name,
from_user.user_id,
from_user.first_name,
from_user.user_id,
to_user.first_name,
to_user.user_id,
to_user.first_name,
to_user.user_id,
restriction.text,
restriction.timestamp
), parse_mode="Markdown", reply_markup=markup
)
restriction.text,
restriction.timestamp
), reply_markup=markup.as_markup())
await States.state1.set()
await state.set_state(ReportRestriction.state1)
@dp.callback_query_handler(
text_contains="report_restriction",
state=States.state1
)
async def report_restriction(call: CallbackQuery, state: FSMContext):
@dp.callback_query(ReportRestriction.state1)
async def report_restriction(call: types.CallbackQuery, state: FSMContext):
await call.answer(cache_time=60)
callback_data = call.data
restriction_id = callback_data.split(":")[1]
restriction_id = int(callback_data)
markup = ReplyKeyboardMarkup(resize_keyboard=True)
cancel = KeyboardButton("❌ Cancel")
markup.add(cancel)
cancel_markup = ReplyKeyboardBuilder()
cancel_markup.button(text="❌ Cancel")
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=cancel_markup.as_markup(resize_keyboard=True)
)
await States.next()
await state.set_state(ReportRestriction.state2)
@dp.message_handler(state=States.state2)
@dp.message(ReportRestriction.state2)
async def get_message_report(message: types.Message, state: FSMContext):
answer = message.text
@ -126,26 +126,25 @@ async def get_message_report(message: types.Message, state: FSMContext):
from_user = restriction.from_user
to_user = restriction.to_user
restriction_timestamp = restriction.timestamp.strftime("%d.%m.%y at %H:%M (server time)")
restriction_timestamp = restriction.timestamp.strftime("%d.%m.%y at %H:%M")
await bot.send_message(config.second_group_id, (
"Report on restriction #{}\n"
"Complaint from: [{}](tg://user?id={})\n"
"Complaint about: [{}](tg://user?id={})\n"
"Sent {}\n"
"{}\n"
"Message: {}"
).format(
restriction_id,
from_user.first_name,
from_user.user_id,
to_user.first_name,
to_user.user_id,
restriction.text,
restriction_timestamp,
answer,
), parse_mode="Markdown"
)
"Report on restriction #{}\n"
"Complaint from: [{}](tg://user?id={})\n"
"Complaint about: [{}](tg://user?id={})\n"
"Sent {}\n"
"{}\n"
"Message: {}"
).format(
restriction_id,
from_user.first_name,
from_user.user_id,
to_user.first_name,
to_user.user_id,
restriction.text,
restriction_timestamp,
answer,
))
await message.answer(
"Report restriction sended",
@ -157,4 +156,4 @@ async def get_message_report(message: types.Message, state: FSMContext):
reply_markup=ReplyKeyboardRemove()
)
await state.finish()
await state.clear()

View File

@ -24,6 +24,7 @@ session = AiohttpSession(
bot = Bot(
token=config.token,
session=session,
parse_mode="Markdown"
)
dp = Dispatcher(storage=storage)

View File

View File

@ -1,6 +0,0 @@
from aiogram.dispatcher.filters.state import StatesGroup,State
class States(StatesGroup):
state1 = State()
state2 = State()

View File

@ -14,18 +14,17 @@ async def reload_users_data():
if (not user):
Member.create(
user_id = member["id"],
first_name = first_name,
username = member["username"],
user_id=member["id"],
first_name=first_name,
username=member["username"],
)
else:
user.first_name = first_name
user.username = member["username"]
user.save()
group = await bot.get_chat(config.group_id)
group_permissions = dict(group["permissions"])
group_permissions = group.permissions.__dict__
for permission in group_permissions.keys():
config.group_permissions[permission] = group_permissions[permission]