예제 #1
0
async def handler_call(message: types.Message):
    await check_access(message, grant=Grant.READ_ACCESS)
    match = constraints.REGEX_CMD_GROUP_MESSAGE.search(message.text)
    if not match:
        return await message.reply(md.text(md_style.bold("Пример вызова:"),
                                           md_style.code("/call group"),
                                           " ",
                                           md_style.bold("Ограничения:"),
                                           md.text(
                                               "group:",
                                               constraints.MESSAGE_FOR_GROUP),
                                           sep='\n'),
                                   parse_mode=ParseMode.MARKDOWN)
    group_name = match.group("group")

    with db.get_connection() as conn:
        group = db.select_group_by_alias_name(conn,
                                              chat_id=message.chat.id,
                                              alias_name=group_name)
        if not group:
            return await message.reply(md.text('Группа',
                                               md_style.code(group_name),
                                               'не найдена!'),
                                       parse_mode=ParseMode.MARKDOWN)
        logging.info(f"group: {group}")
        members = db.select_members(conn, group_id=group.group_id)

    if len(members) == 0:
        return await message.reply('Группа пользователей пуста!')

    mentions = convert_members_to_mentions(members)

    await message.reply(" ".join(mentions), parse_mode=ParseMode.MARKDOWN)
예제 #2
0
async def handler_help(message: types.Message):
    await check_access(message, grant=Grant.READ_ACCESS)

    def prepare_commands(commands: Dict[str, str]) -> List[str]:
        return [
            md.text(md.escape_md(f"/{x[0]}"), "—", x[1])
            for x in commands.items()
        ]

    await message.reply(text=md.text(
        f"Привет, {message.from_user.get_mention()}! 👋",
        "",
        md_style.bold("Пример работы с ботом:"),
        md_style.code("/add_group group1"),
        md_style.code("/add_members group1 @user1 @user2 @user3"),
        md_style.code("/call group1"),
        "",
        md.text("Команда", md_style.italic("call"),
                "вызовет ранее добавленных пользователей из группы",
                md_style.italic("group1"), "вот в таком виде:"),
        md_style.code("@user1 @user2 @user3"),
        "",
        md_style.bold("Общие команды:"),
        *prepare_commands(COMMON_COMMANDS),
        "",
        md_style.bold("Административные команды:"),
        *prepare_commands(ADMIN_COMMANDS),
        sep='\n'),
                        parse_mode=ParseMode.MARKDOWN)
예제 #3
0
async def handler_remove_group_alias(message: types.Message):
    await check_access(message, Grant.WRITE_ACCESS)
    match = constraints.REGEX_CMD_GROUP_ALIAS.search(message.text)
    if not match:
        return await message.reply(md.text(
            md_style.bold("Пример вызова:"),
            md_style.code("/remove_alias group alias"),
            " ",
            md_style.bold("Ограничения:"),
            md.text("group:", constraints.MESSAGE_FOR_GROUP),
            md.text("alias:", constraints.MESSAGE_FOR_GROUP),
            sep='\n'),
                                   parse_mode=ParseMode.MARKDOWN)
    group_name = match.group('group')
    alias_name = match.group('alias')

    with db.get_connection() as conn:
        db.select_chat_for_update(conn, chat_id=message.chat.id)
        group = db.select_group_by_alias_name(conn,
                                              chat_id=message.chat.id,
                                              alias_name=group_name)
        if not group:
            return await message.reply(md.text('Группа',
                                               md_style.code(group_name),
                                               'не найдена!'),
                                       parse_mode=ParseMode.MARKDOWN)
        logging.info(f"group: {group}")

        group_aliases: Dict[str, GroupAlias] = {
            x.alias_name: x
            for x in db.select_group_aliases_by_group_id(
                conn, group_id=group.group_id)
        }

        if alias_name not in group_aliases:
            return await message.reply(md.text('Алиас',
                                               md_style.code(alias_name),
                                               'не найден для группы',
                                               md_style.code(group_name)),
                                       parse_mode=ParseMode.MARKDOWN)
        group_alias = group_aliases[alias_name]

        if len(group_aliases) == 1:
            return await message.reply(
                md.text("Нельзя удалить единственное название группы!"),
                parse_mode=ParseMode.MARKDOWN)

        db.delete_group_alias(conn, alias_id=group_alias.alias_id)

    await message.reply(md.text("Алиас", md_style.code(alias_name),
                                "удалён из группы", md_style.code(group_name)),
                        parse_mode=ParseMode.MARKDOWN)
예제 #4
0
async def handler_remove_members(message: types.Message):
    await check_access(message, Grant.WRITE_ACCESS)
    match = constraints.REGEX_CMD_GROUP_MEMBERS.search(message.text)
    if not match:
        return await message.reply(md.text(
            md_style.bold("Пример вызова:"),
            md_style.code("/remove_members group username1 username2"),
            " ",
            md_style.bold("Ограничения:"),
            md.text("group:", constraints.MESSAGE_FOR_GROUP),
            md.text("username:"******"group: {group}")

        mentions = [
            x.get_text(message.text) for x in message.entities
            if x.type == MessageEntityType.MENTION
        ]
        text_mentions = [
            f"[{x.user.full_name}]({x.user.url})" for x in message.entities
            if x.type == MessageEntityType.TEXT_MENTION
        ]
        all_members = mentions + text_mentions
        logging.info(f"members: {all_members}")

        if len(all_members) < 1:
            return await message.reply(
                'Нужно указать хотя бы одного пользователя!')

        for member in all_members:
            db.delete_member(conn, group_id=group.group_id, member_name=member)

    await message.reply(md.text(md.text("Пользователи удалённые из группы",
                                        md_style.code(group_name)),
                                md_style.code("\n".join(
                                    [f"- {x}" for x in all_members])),
                                sep='\n'),
                        parse_mode=ParseMode.MARKDOWN)
예제 #5
0
async def handler_add_group_alias(message: types.Message):
    await check_access(message, Grant.WRITE_ACCESS)
    match = constraints.REGEX_CMD_GROUP_ALIAS.search(message.text)
    if not match:
        return await message.reply(md.text(
            md_style.bold("Пример вызова:"),
            md_style.code("/add_alias group alias"),
            " ",
            md_style.bold("Ограничения:"),
            md.text("group:", constraints.MESSAGE_FOR_GROUP),
            md.text("alias:", constraints.MESSAGE_FOR_GROUP),
            sep='\n'),
                                   parse_mode=ParseMode.MARKDOWN)
    group_name = match.group('group')
    group_alias = match.group('alias')

    if len(group_alias) > constraints.MAX_GROUP_NAME_LENGTH:
        return await message.reply('Слишком длинное название группы!')

    with db.get_connection() as conn:
        db.select_chat_for_update(conn, chat_id=message.chat.id)
        group = db.select_group_by_alias_name(conn,
                                              chat_id=message.chat.id,
                                              alias_name=group_name)
        if not group:
            return await message.reply(md.text('Группа',
                                               md_style.code(group_name),
                                               'не найдена!'),
                                       parse_mode=ParseMode.MARKDOWN)
        logging.info(f"group: {group}")

        aliases: List[GroupAlias] = db.select_group_aliases_by_chat_id(
            conn, chat_id=message.chat.id)

        if group_alias in set(x.alias_name for x in aliases):
            return await message.reply("Такой алиас уже используется!")

        if len([x for x in aliases if x.group_id == group.group_id
                ]) >= constraints.MAX_ALIASES_PER_GROUP:
            return await message.reply(
                f"Нельзя добавить так много алиасов!"
                f" Текущее ограничение для одной группы: {constraints.MAX_ALIASES_PER_GROUP}"
            )

        db.insert_group_alias(conn,
                              chat_id=message.chat.id,
                              group_id=group.group_id,
                              alias_name=group_alias)

    await message.reply(md.text("Для группы", md_style.code(group_name),
                                "добавлен алиас", md_style.code(group_alias)),
                        parse_mode=ParseMode.MARKDOWN)
예제 #6
0
async def handler_list_groups(message: types.Message):
    await check_access(message, grant=Grant.READ_ACCESS)

    with db.get_connection() as conn:
        aliases: List[GroupAlias] = db.select_group_aliases_by_chat_id(
            conn, chat_id=message.chat.id)
        if len(aliases) == 0:
            return await message.reply("Нет ни одной группы.",
                                       parse_mode=ParseMode.MARKDOWN)

        aliases_lookup: Dict[int, List[GroupAlias]] = {}
        for a in aliases:
            aliases_lookup.setdefault(a.group_id, []).append(a)

    groups_for_print = []
    for group_id in sorted({x.group_id for x in aliases}):
        group_aliases = sorted(aliases_lookup.get(group_id, []),
                               key=lambda x: x.alias_id)
        group_aliases = [x.alias_name for x in group_aliases]
        head, *tail = group_aliases
        tail = f" (синонимы: {', '.join(tail)})" if len(tail) > 0 else ""
        groups_for_print.append(f"- {head}{tail}")

    await message.reply(md.text(md_style.bold("Вот такие группы существуют:"),
                                md_style.code("\n".join(groups_for_print)),
                                sep='\n'),
                        parse_mode=ParseMode.MARKDOWN)
예제 #7
0
async def handler_add_group(message: types.Message):
    await check_access(message, Grant.WRITE_ACCESS)
    match = constraints.REGEX_CMD_GROUP.search(message.text)
    if not match:
        return await message.reply(md.text(md_style.bold("Пример вызова:"),
                                           md_style.code("/add_group group"),
                                           " ",
                                           md_style.bold("Ограничения:"),
                                           md.text(
                                               "group:",
                                               constraints.MESSAGE_FOR_GROUP),
                                           sep='\n'),
                                   parse_mode=ParseMode.MARKDOWN)
    group_name = match.group("group")

    if len(group_name) > constraints.MAX_GROUP_NAME_LENGTH:
        return await message.reply('Слишком длинное название группы!')

    with db.get_connection() as conn:
        db.insert_chat(conn,
                       chat_id=message.chat.id,
                       chat_title=message.chat.title,
                       chat_username=message.chat.username)
        db.select_chat_for_update(conn, chat_id=message.chat.id)

        existing_groups: List[GroupAlias] = db.select_group_aliases_by_chat_id(
            conn, chat_id=message.chat.id)

        if group_name in {x.alias_name for x in existing_groups}:
            return await message.reply('Такая группа уже существует!')

        if len({x.group_id
                for x in existing_groups}) >= constraints.MAX_GROUPS_PER_CHAT:
            return await message.reply(
                f'Слишком много групп уже создано!'
                f' Текущее ограничение для чата: {constraints.MAX_GROUPS_PER_CHAT}'
            )

        group_id = db.insert_group(conn, chat_id=message.chat.id)
        db.insert_group_alias(conn,
                              chat_id=message.chat.id,
                              group_id=group_id,
                              alias_name=group_name)

    await message.reply(md.text("Группа", md_style.code(group_name),
                                "добавлена!"),
                        parse_mode=ParseMode.MARKDOWN)
예제 #8
0
async def handler_list_members(message: types.Message):
    await check_access(message, grant=Grant.READ_ACCESS)
    match = constraints.REGEX_CMD_GROUP.search(message.text)
    if not match:
        return await message.reply(md.text(md_style.bold("Пример вызова:"),
                                           md_style.code("/members group"),
                                           " ",
                                           md_style.bold("Ограничения:"),
                                           md.text(
                                               "group:",
                                               constraints.MESSAGE_FOR_GROUP),
                                           sep='\n'),
                                   parse_mode=ParseMode.MARKDOWN)
    group_name = match.group("group")

    with db.get_connection() as conn:
        group = db.select_group_by_alias_name(conn,
                                              chat_id=message.chat.id,
                                              alias_name=group_name)
        if not group:
            return await message.reply(md.text('Группа',
                                               md_style.code(group_name),
                                               'не найдена!'),
                                       parse_mode=ParseMode.MARKDOWN)
        members = db.select_members(conn, group_id=group.group_id)

    members = sorted(convert_members_to_names(members))
    logging.info(f"members: {members}")

    if len(members) == 0:
        text = md.text(
            "В группе",
            md_style.code(group_name),
            "нет ни одного пользователя!",
        )
    else:
        text = md.text(md.text(md_style.bold("Участники группы"),
                               md_style.code(group_name)),
                       md_style.code("\n".join([f"- {x}" for x in members])),
                       sep='\n')

    await message.reply(text, parse_mode=ParseMode.MARKDOWN)
예제 #9
0
async def handler_remove_group(message: types.Message):
    await check_access(message, Grant.WRITE_ACCESS)
    match = constraints.REGEX_CMD_GROUP.search(message.text)
    if not match:
        return await message.reply(md.text(
            md_style.bold("Пример вызова:"),
            md_style.code("/remove_group group"),
            " ",
            md_style.bold("Ограничения:"),
            md.text("group:", constraints.MESSAGE_FOR_GROUP),
            sep='\n'),
                                   parse_mode=ParseMode.MARKDOWN)
    group_name = match.group("group")

    with db.get_connection() as conn:
        db.select_chat_for_update(conn, chat_id=message.chat.id)
        group = db.select_group_by_alias_name(conn,
                                              chat_id=message.chat.id,
                                              alias_name=group_name)
        if not group:
            return await message.reply(md.text('Группа',
                                               md_style.code(group_name),
                                               'не найдена!'),
                                       parse_mode=ParseMode.MARKDOWN)
        logging.info(f"group: {group}")
        members = db.select_members(conn, group.group_id)
        if len(members) != 0:
            logging.info(f"members: {members}")
            return await message.reply(
                'Группу нельзя удалить, в ней есть пользователи!')

        group_aliases = db.select_group_aliases_by_group_id(
            conn, group_id=group.group_id)

        for a in group_aliases:
            db.delete_group_alias(conn, alias_id=a.alias_id)

        db.delete_group(conn, group_id=group.group_id)

    await message.reply(md.text("Группа", md_style.bold(group_name),
                                "удалена!"),
                        parse_mode=ParseMode.MARKDOWN)
예제 #10
0
async def handler_xcall(message: types.Message):
    await check_access(message, grant=Grant.READ_ACCESS)

    with db.get_connection() as conn:
        aliases: List[GroupAlias] = db.select_group_aliases_by_chat_id(
            conn, chat_id=message.chat.id)
        if len(aliases) == 0:
            return await message.reply("Нет ни одной группы.",
                                       parse_mode=ParseMode.MARKDOWN)

        aliases_lookup: Dict[int, List[GroupAlias]] = {}
        for a in aliases:
            aliases_lookup.setdefault(a.group_id, []).append(a)

    inline_keyboard = InlineKeyboardMarkup()

    inline_keyboard.add(
        InlineKeyboardButton(text="✖ Отмена ✖",
                             callback_data=CallbackData(
                                 type=CallbackType.CANCEL,
                                 user_id=message.from_user.id).serialize()))

    groups_for_print = []
    for group_id in sorted({x.group_id for x in aliases}):
        group_aliases = sorted(aliases_lookup.get(group_id, []),
                               key=lambda x: x.alias_id)
        group_aliases = [x.alias_name for x in group_aliases]
        head, *tail = group_aliases
        tail = f" (синонимы: {', '.join(tail)})" if len(tail) > 0 else ""
        groups_for_print.append(f"{head}{tail}")

        inline_keyboard.add(
            InlineKeyboardButton(text=f"{head}{tail}",
                                 callback_data=CallbackData(
                                     type=CallbackType.SELECT_GROUP,
                                     user_id=message.from_user.id,
                                     group_id=group_id).serialize()))

    await message.reply(md_style.bold("Выберите группу"),
                        parse_mode=ParseMode.MARKDOWN,
                        reply_markup=inline_keyboard)
예제 #11
0
async def handler_add_members(message: types.Message):
    await check_access(message, Grant.WRITE_ACCESS)
    match = constraints.REGEX_CMD_GROUP_MEMBERS.search(message.text)
    if not match:
        return await message.reply(md.text(
            md_style.bold("Пример вызова:"),
            md_style.code("/add_members group username1 username2"),
            " ",
            md_style.bold("Ограничения:"),
            md.text("group:", constraints.MESSAGE_FOR_GROUP),
            md.text("username:"******"members: {all_members}")

    if len(all_members) < 1:
        return await message.reply('Нужно указать хотя бы одного пользователя!'
                                   )

    with db.get_connection() as conn:
        db.select_chat_for_update(conn, chat_id=message.chat.id)

        group = db.select_group_by_alias_name(conn,
                                              chat_id=message.chat.id,
                                              alias_name=group_name)
        if not group:
            return await message.reply(md.text('Группа',
                                               md_style.code(group_name),
                                               'не найдена!'),
                                       parse_mode=ParseMode.MARKDOWN)
        logging.info(f"group: {group}")

        existing_members: List[Member] = db.select_members(
            conn, group_id=group.group_id)

        if len(existing_members) + len(
                all_members) > constraints.MAX_MEMBERS_PER_GROUP:
            return await message.reply(
                f'Слишком много пользователей уже добавлено в группу!'
                f' Текущее ограничение для одной группы: {constraints.MAX_MEMBERS_PER_GROUP}'
            )

        for member in all_members:
            db.insert_member(conn, group_id=group.group_id, member=member)

    await message.reply(md.text(
        md.text(
            "Пользователи добавленные в группу",
            md_style.code(group_name),
        ),
        md_style.code("\n".join(
            [f"- {x}" for x in convert_members_to_names(all_members)])),
        sep='\n'),
                        parse_mode=ParseMode.MARKDOWN)