получить имя канала и отправить сообщение по этому каналу

#discord.py #discord.py-rewrite

#discord.py

Вопрос:

Итак, я работаю над небольшим проектом здесь, и в значительной степени я хочу иметь одну из этих функций «Пожалуйста, введите имя канала на этом сервере».

В общем, бот запрашивает название канала, и я ввожу, например, «#changelog», А затем он запрашивает, что он должен написать в этом канале и т. Д. И т. Д. Поэтому нужно получить идентификатор канала (я предполагаю), но я не хочу, чтобы пользователи вводили идентификатор, вместо этого только записывая #server-name . И затем всякий раз, когда я это делал, бот должен писать в этом канале.

Вот мой текущий код!

 class Changelog(commands.Cog):

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

    @commands.Cog.listener()
    async def on_ready(self):
        print('Changelog is loaded')

    @commands.command()
    async def clhook(self, ctx):
        await ctx.send('Write text-channel: ')
        text_channel = await self.client.wait_for("message", check=lambda message: message.author == ctx.author, timeout=300)
        clhook = self.client.get_channel(text_channel)


def setup(client):
    client.add_cog(Changelog(client))
  

Редактировать:
Идентификатор канала должен быть сохранен «навсегда», что означает, что мне не нужно переписывать название канала, куда должно идти сообщение!

Ответ №1:

Вы можете использовать discord.utils.get() в этом примере:

 text_channel = await self.client.wait_for("message", check=lambda message: message.author == ctx.author, timeout=300)
channel = discord.utils.get(ctx.guild.text_channels, name=text_channel)
await channel.send('Bla Bla')
  

Поэтому, когда вы вводите (prefix)clhook только имя канала, например general, он будет отправлен Bla Bla на канал с именем general .

Есть другой способ сделать это, и я думаю, что это проще, чем первый вариант, вот он:

 @commands.command()
async def clhook(self, ctx, channel: discord.TextChannel):
    await channel.send('Bla Bla')
  

Итак, в этой команде использование изменено. Вы можете использовать это с помощью этого: (prefix)clhook #general(mention the channel) . Я предлагаю это решение, и я думаю, что оно более полезно.

Комментарии:

1. Хорошо, давайте посмотрим, понял ли я это. Первое, что дало мне некоторые ошибки 'NoneType' object has no attribute send , это в шестеренке. Нужно ли self где-то включать? Или что означает эта ошибка?

2. Это означает, что канал не существует или, возможно, связан с self. Вы пробовали второе решение?

3. Ну, во втором решении есть. Я не тестировал — как мне получить канал, который вводит пользователь?

4. Во втором решении used просто введет (prefix)clhook #channel-name , а затем отправит сообщение на этот канал.

5. Или ооо, поэтому каждый раз, когда мне нужно написать сообщение для этого конкретного канала, мне нужно запускать !!clhook #text-channel ? Я хотел, чтобы это было больше похоже на то, что вы пишете это один раз, и оно всегда будет применяться к этому каналу. Так !!clhook #text-channel будет команда «hook», и после этого все, что мне нужно написать !!changelog <text-goes-here> , и оно всегда будет там записываться.

Ответ №2:

Вы можете использовать message.channel_mentions . Это вернет list список всех каналов, которые были упомянуты с использованием #channel-name обозначения. Таким образом, вы можете просто использовать channel.id для получения id канала, который они упомянули.

Однако не забудьте проверить, действительно ли пользователь пометил канал (который вы также можете добавить в свой check ). Я поместил его в отдельную функцию, чтобы сделать его немного более читаемым для этого ответа, но вы можете поместить это в свой лямбда-код, если действительно хотите.

Кроме того, обязательно проверьте, является ли это a Text Channel , а не a Voice Channel или Category Channel .

 @commands.command()
async def clhook(self, ctx):

    def check(self, message):
        author_ok = message.author == ctx.author  # Sent by the same author
        mentioned_channel = len(message.channel_mentions) == 1 and isinstance(message.channel_mentions[0], discord.TextChannel)
        return author_ok and mentioned_channel

    await ctx.send("Write text-channel: ")
    text_channel = await self.client.wait_for("message", check=check)
    chlhook = text_channel.channel_mentions[0]
  

Я поставил два условия в mentioned_channel строке, потому что, если первое не выполняется, второе может вызвать ошибку IndexError. В качестве альтернативы вы также можете использовать if-statement , чтобы вернуться раньше в этом месте, чтобы решить ту же проблему.

Комментарии:

1. Аааа, я понимаю, но chlhook будет ли это там, где имя канала «сохранено»? Или как мне отправить «тестовое» сообщение на этот канал?

2. Нет, он не сохраняет name , но вы извлекаете фактический channel экземпляр из списка, поэтому вы можете просто clhook.send() отправлять ему сообщения или использовать clhook.id для получения его идентификатора. Таким образом, вам не нужно использовать utils.get() для поиска объекта channel, поскольку он у вас уже есть. Возможно, вы захотите переименовать его, так как это может все испортить (у него то же имя, что и у вашей функции).