Skip to content

Commit

Permalink
Merge pull request #96 from bomzheg/aiogram3
Browse files Browse the repository at this point in the history
migrate to Aiogram3
  • Loading branch information
bomzheg authored Feb 4, 2023
2 parents 65fa341 + 8e10a25 commit 57528d9
Show file tree
Hide file tree
Showing 50 changed files with 560 additions and 922 deletions.
22 changes: 0 additions & 22 deletions .github/workflows/semgrep.yml

This file was deleted.

4 changes: 3 additions & 1 deletion app/__main__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import asyncio

from app.config.main import load_config
from app.utils.cli import cli

if __name__ == "__main__":
cli(load_config())
asyncio.run(cli(load_config()))
3 changes: 2 additions & 1 deletion app/config/moderation.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
from functools import partial

from aiogram import Bot
from aiogram.types import ChatPermissions

from app.models.common import TypeRestriction


DEFAULT_RESTRICT_DURATION = timedelta(hours=1)
FOREVER_RESTRICT_DURATION = timedelta(days=666)
RO_ACTION = partial(Bot.restrict_chat_member, can_send_messages=False)
RO_ACTION = partial(Bot.restrict_chat_member, permissions=ChatPermissions(can_send_messages=False))
BAN_ACTION = Bot.kick_chat_member
action_for_restrict = {
TypeRestriction.ban: BAN_ACTION,
Expand Down
29 changes: 3 additions & 26 deletions app/filters/__init__.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,7 @@
from functools import partialmethod

from aiogram import Dispatcher

from app.models.config import Config
from app.utils.log import Logger

from .karma_change import KarmaFilter
from .tg_permissions import BotHasPermissions, HasPermissions
from .has_target import HasTargetFilter

logger = Logger(__name__)


def setup(dispatcher: Dispatcher, config: Config):
logger.info("Configure filters...")
from .superuser import IsSuperuserFilter
from .karma_change import KarmaFilter
from .tg_permissions import BotHasPermissions, HasPermissions
from .has_target import HasTargetFilter

text_messages = [
dispatcher.message_handlers,
dispatcher.edited_message_handlers,
dispatcher.callback_query_handlers,
]
IsSuperuserFilter.check = partialmethod(IsSuperuserFilter.check, config.superusers)

dispatcher.filters_factory.bind(KarmaFilter, event_handlers=text_messages)
dispatcher.filters_factory.bind(IsSuperuserFilter, event_handlers=text_messages)
dispatcher.filters_factory.bind(BotHasPermissions, event_handlers=text_messages)
dispatcher.filters_factory.bind(HasPermissions, event_handlers=text_messages)
dispatcher.filters_factory.bind(HasTargetFilter, event_handlers=text_messages)
24 changes: 9 additions & 15 deletions app/filters/has_target.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,20 @@
import typing
from dataclasses import dataclass

from aiogram import types
from aiogram.dispatcher.filters import BoundFilter
from aiogram.filters import BaseFilter
from aiogram.types import Message

from app.models import dto
from app.services.find_target_user import get_target_user


@dataclass
class HasTargetFilter(BoundFilter):
key = "has_target"
has_target: typing.Optional[typing.Dict[str, bool]]
class HasTargetFilter(BaseFilter):
can_be_same: bool = False
can_be_bot: bool = False

def __post_init__(self):
if self.has_target is True:
self.has_target = {}

async def check(self, message: types.Message) -> typing.Dict[str, types.User]:
can_be_same = self.has_target.get("can_be_same", False)
can_be_bot = self.has_target.get("can_be_bot", False)
target_user = get_target_user(message, can_be_same, can_be_bot)
async def __call__(self, message: Message) -> dict[str, dto.TargetUser]:
target_user = get_target_user(message, self.can_be_same, self.can_be_bot)
if target_user is None:
return {}
rez = {'target': target_user}
rez = {"target": target_user}
return rez
17 changes: 6 additions & 11 deletions app/filters/karma_change.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
from dataclasses import dataclass

from aiogram import types
from aiogram.dispatcher.filters import BoundFilter
from aiogram.dispatcher.handler import ctx_data
from aiogram.filters import BaseFilter

from app.config.karmic_triggers import (
PLUS,
Expand All @@ -20,19 +19,15 @@


@dataclass
class KarmaFilter(BoundFilter):
class KarmaFilter(BaseFilter):
"""
Filtered message should be change karma
"""

key = "karma_change"

karma_change: bool

async def check(self, message: types.Message) -> dict[str, dict[str, float]]:
data = ctx_data.get()
settings: ChatSettings = data.get("chat_settings", None)
if settings is None or not settings.karma_counting:
async def __call__(
self, message: types.Message, chat_settings: ChatSettings,
) -> dict[str, dict[str, float]]:
if chat_settings is None or not chat_settings.karma_counting:
return {}
return await check(message)

Expand Down
18 changes: 0 additions & 18 deletions app/filters/superuser.py

This file was deleted.

44 changes: 14 additions & 30 deletions app/filters/tg_permissions.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
# from https://github.com/aiogram/bot/blob/master/app/filters/has_permissions.py
import typing
from dataclasses import dataclass
from typing import Any, Union, Dict

from aiogram import types
from aiogram.dispatcher.filters import Filter
from aiogram import types, Bot
from aiogram.filters import Filter


@dataclass
class HasPermissions(Filter):
"""
Validate the user has specified permissions in chat
"""

can_post_messages: bool = False
can_edit_messages: bool = False
can_delete_messages: bool = False
Expand All @@ -38,52 +37,37 @@ def __post_init__(self):
arg: True for arg in self.ARGUMENTS.values() if getattr(self, arg)
}

@classmethod
def validate(
cls, full_config: typing.Dict[str, typing.Any]
) -> typing.Optional[typing.Dict[str, typing.Any]]:
config = {}
for alias, argument in cls.ARGUMENTS.items():
if alias in full_config:
config[argument] = full_config.pop(alias)
return config

def _get_cached_value(self, message: types.Message):
try:
return message.conf[self.PAYLOAD_ARGUMENT_NAME]
except KeyError:
return None
return None # TODO

def _set_cached_value(self, message: types.Message, member: types.ChatMember):
message.conf[self.PAYLOAD_ARGUMENT_NAME] = member
return None # TODO

async def _get_chat_member(self, message: types.Message):
async def _get_chat_member(self, message: types.Message, bot: Bot):
chat_member: types.ChatMember = self._get_cached_value(message)
if chat_member is None:
admins = await message.chat.get_administrators()
target_user_id = self.get_target_id(message)
admins = await bot.get_chat_administrators(message.chat.id)
target_user_id = self.get_target_id(message, bot)
try:
chat_member = next(filter(lambda member: member.user.id == target_user_id, admins))
except StopIteration:
return False
self._set_cached_value(message, chat_member)
return chat_member

async def check(
self, message: types.Message
) -> typing.Union[bool, typing.Dict[str, typing.Any]]:
chat_member = await self._get_chat_member(message)
async def __call__(self, message: types.Message, bot: Bot) -> Union[bool, Dict[str, Any]]:
chat_member = await self._get_chat_member(message, bot)
if not chat_member:
return False
if chat_member.status == types.ChatMemberStatus.CREATOR:
if chat_member.status == "creator":
return chat_member
for permission, value in self.required_permissions.items():
if not getattr(chat_member, permission):
return False

return {self.PAYLOAD_ARGUMENT_NAME: chat_member}

def get_target_id(self, message: types.Message) -> int:
def get_target_id(self, message: types.Message, bot: Bot) -> int:
return message.from_user.id


Expand All @@ -104,5 +88,5 @@ class BotHasPermissions(HasPermissions):
}
PAYLOAD_ARGUMENT_NAME = "bot_member"

def get_target_id(self, message: types.Message) -> int:
return message.bot.id
def get_target_id(self, message: types.Message, bot: Bot) -> int:
return bot.id
25 changes: 13 additions & 12 deletions app/handlers/__init__.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
from . import admin_bot
from aiogram import Dispatcher, Bot

from . import base
from . import change_karma
from . import errors
from . import import_karma
from . import karma
from . import moderator
from . import settings
from . import superuser
from ..models.config import Config


__all__ = [
errors,
admin_bot,
base,
karma,
change_karma,
import_karma,
moderator,
settings,
]
def setup(dp: Dispatcher, bot: Bot, config: Config):
errors.setup(dp, bot, config)
dp.include_router(base.router)
dp.include_router(change_karma.router)
dp.include_router(karma.router)
dp.include_router(moderator.router)
dp.include_router(settings.router)
dp.include_router(superuser.setup_superuser(config))
Loading

0 comments on commit 57528d9

Please sign in to comment.