Discord Discord Bot #3 Clear, чистка чата.

Префикс для тем посвященных тематики Discord

Chaka

Новичок
Регистрация
27 Дек 2020
Сообщения
5
Реакции
6
Приветсвую всех после долгого перерыва!

В этой части обуздаем простенькую функцию очистки чата.

Для более понятной навигации, отнесем данную функцию к "модерированию". Создадим файл moderation.py, тыкнув по папке cogs -> new -> Python File



Как и в test.py импортируем все библиотеки и создаем class, но обязательно с другим названием! Дополнительно импортируем такие библиотеки, как: discord и typing. Первая нужна нам для того, чтобы получать участников сервера и создавать красивую форму(embed), вторая поможет коду легче понять, что стоит на 2-ом месте в аргументах. Позже вы поймете о чем я.
Python:
from discord.ext import commands
import discord
import typing

class Moder(commands.Cog):

    def __init__(self, py):
        self.py = py


def setup(py):
    py.add_cog(Moder(py))

Самый просто вариант чистки чата, это:
Python:
@commands.command()
@commands.has_permissions(administrator=True)
async def clear(self, ctx, amount: int):
    await ctx.message.delete()
    messages = 0
    async for i in ctx.channel.history(limit=amount):
        await i.delete()
        messages += 1
    await ctx.send(embed=discord.Embed(description=f'Очищено: **{messages}** сообщений',
                                        color=discord.Color.green()), delete_after=3)

Давайте по порядку.
Вы уже знаете, что @commands.command() - создание функции
А теперь к новенькому
@commands.has_permissions(administrator=True) - данная строчка позволит пользоваться командой ТОЛЬКО пользователям с правами Администратора

async def clear(self, ctx, amount: int): - идентификация функции, как он будет вызываться и что принимать. ctx - обязательный аргумент, он прямом смысле вшит в библиотеку дискорда. Второй amount - это уже то, что нам и надо. В нем мы будет вписывать кол-во сообщений, которые хотим удалить, отсюда следует, что аргумент должен иметь число, т.е. int, что мы и показываем аргументу через ":"

await ctx.message.delete() - Удаляет сообщение, в котором была вызвана функция

messages = 0 - счетчик сообщений, которые были удалены. По идее бесполезная штука, но она работает очень к стати, если в чате меньше сообщений, чем вы запросили удалить.

async for i in ctx.channel.history(limit=amount): - цикл по сообщениям. ctx.channel.history - история сообщений в канале, в котором была вызвана функция. Рядом в скобках указывается число сколько нужно сообщений прочесть(limit)

await i.delete() - непосредственно само удаление сообщения

messages += 1 - все тот же счетчик сообщений

await ctx.send(embed=discord.Embed(description=f'Очищено: **{messages}** сообщений', color=discord.Color.green()), delete_after=3) - красивая формочка сообщений в конце работы функции. Подробнее о ней мы поговорим в последующих уроках.

Собственно что мы имеем:
Python:
import discord
import typing
from discord.ext import commands


class Moder(commands.Cog):

    def __init__(self, py):
        self.py = py

    @commands.command()
    @commands.has_permissions(administrator=True)
    async def clear(self, ctx, amount: int):
        await ctx.message.delete()
        messages = 0
        async for i in ctx.channel.history(limit=amount):
            await i.delete()
            messages += 1
        await ctx.send(
            embed=discord.Embed(description=f'Очищено: **{messages}** сообщений', color=discord.Color.green()),
            delete_after=3)


def setup(py):
    py.add_cog(Moder(py))

Что получилось:



Мы научились удалять сообщений, но вдруг мы захотим удалить сообщение определенного пользователя?
Делаем следующее:
Python:
@commands.command()
@commands.has_permissions(administrator=True)
async def clear_m(self, ctx, member: discord.Member, amount: int):
    await ctx.message.delete()
    number = 0
    async for elem in ctx.channel.history():
        if elem.author.id == member.id:
            await elem.delete()
            number += 1
            if number >= amount:
                await ctx.send(embed=discord.Embed(
                    description=f':white_check_mark: Очищено: {amount} сообщений от пользователя {member.mention}',
                    color=discord.Color.green()), delete_after=3)
                break

Для начала назовем функцию чутка по другому, чтобы она не конфликтовала с прошлой функцией.
Как и в прошлом случае разрешаем использование функции только пользователям с правами Администратора.
Также проходимся по удалению сообщения где была вызвана функция, делаем счетчик и идем на цикл удаления.
В цикле проводим проверку:
if elem.author.id == member.id: - Если ID автора сообщения соответствует ID мембера, которого мы указали, то идем дальше

await elem.delete() - удаляем

number += 1 - счетчик

А дальше еще одна проверка:
if number >= amount: - если удаленных сообщений больше либо равно указанному кол-ву удаленных сообщений, которые мы указали, то выводим сообщение и break - выходим из функции.

Что в итоге:



Чужие сообщения не затронуты, значит все работает замечательно!

Но давайте под конец упростим нашу функцию до 1 команды, вместо 2. Здесь то на помощь и идет typing.
Код получится следующим:
Python:
@commands.command()
    @commands.has_permissions(administrator=True)
    async def clear(self, ctx, member: typing.Optional[discord.Member], amount: int):
        if member is not None and member in ctx.guild.members:
            await ctx.message.delete()
            number = 0
            async for elem in ctx.channel.history():
                if elem.author.id == member.id:
                    await elem.delete()
                    number += 1
                    if number >= amount:
                        await ctx.send(embed=discord.Embed(
                            description=f':white_check_mark: Очищено: {amount} сообщений от пользователя {member.mention}',
                            color=discord.Color.green()), delete_after=3)
                        break
        else:
            await ctx.message.delete()
            messages = 0
            async for i in ctx.channel.history(limit=amount):
                await i.delete()
                messages += 1
            await ctx.send(embed=discord.Embed(description=f'Очищено: **{messages}** сообщений',
                                               color=discord.Color.green()), delete_after=3)

async def clear(self, ctx, member: typing.Optional[discord.Member], amount: int): - здесь то нам как раз и пригодился typing. В случае если вместо первого аргумента стоит не мембер, а число, то typing, можно сказать, просто исчезает, а вместо него вставляется amount.
if member is not None and member in ctx.guild.members: - легкая доп. проверка, даже обязательная. Ведь мемберы ищутся не только тогда, когда вы их упоминаете, но и по нику и по ID. Все остальное после проверки - то же самое, что и в прошлом коде.
Если проверка не верна, то в силу вступает else

В прочем, мы закончили. Весь код который у нас должен был получиться в файле:
Python:
import discord
import typing
from discord.ext import commands


class Moder(commands.Cog):

    def __init__(self, py):
        self.py = py

    @commands.command()
    @commands.has_permissions(administrator=True)
    async def clear(self, ctx, member: typing.Optional[discord.Member], amount: int):
        if member is not None and member in ctx.guild.members:
            await ctx.message.delete()
            number = 0
            async for elem in ctx.channel.history():
                if elem.author.id == member.id:
                    await elem.delete()
                    number += 1
                    if number >= amount:
                        await ctx.send(embed=discord.Embed(
                            description=f':white_check_mark: Очищено: {amount} сообщений от пользователя {member.mention}',
                            color=discord.Color.green()), delete_after=3)
                        break
        else:
            await ctx.message.delete()
            messages = 0
            async for i in ctx.channel.history(limit=amount):
                await i.delete()
                messages += 1
            await ctx.send(embed=discord.Embed(description=f'Очищено: **{messages}** сообщений',
                                               color=discord.Color.green()), delete_after=3)


def setup(py):
    py.add_cog(Moder(py))

Удачи в ботокрафтинге!
 
Последнее редактирование:
  • Мне нравится
Реакции: SaNeR
Сверху Снизу