创建将消息作为嵌入消息移动的 Discord Bot 方法

时间:2020-12-31 05:06:50

标签: python discord.py

我最近一直在学习如何编写一个不和谐的机器人,但我遇到了困难。我想创建一种方法,允许我将消息从一个频道移动到另一个频道。我创建了一个有效的解决方案,但不是我想要的。理想情况下,我只想让机器人几乎做一个 reddit 转帖,它接收确切的消息并嵌入。目前我拥有的方法是

@client.event
async def on_message(message):
    author = message.author
    content = message.context
    channel = message.channel

    if message.content.startswith('!move'):
        #code to process the input, nothing special or important to this
        for i in fetchedMessages:
            embededMessage = discord.Embed()
            embededMessage.description = i.context
            embededMessage.set_author(name=i.author, icon_url=i.author.avatar_url)
            await channelToPostIn.send(embeded=embededMessage)
            # delete the old message
            i.delete()

现在这非常适用于文本消息,但不适用于图像,或者例如如果帖子首先被嵌入。如果有人有更优雅的解决方案,或者能够在文档中为我指出正确的方向,我将不胜感激。谢谢。

2 个答案:

答案 0 :(得分:1)

如果您使用 commands.Bot 扩展名,这会容易得多:discord.ext.commands.Bot()(查看 basic bot

bot = commands.Bot(...)

@bot.command()
async def move(ctx, channel: discord.TextChannel, *message_ids: int): # Typehint to a Messageable
    '''Moves the message content to another channel'''
    # Loop over each message id provided
    for message_id in message_ids:
        # Holds the Message instance that should be moved
        message = await ctx.channel.fetch_message(message_id)

        # It is possible the bot fails to fetch the message, if it has been deleted for example
        if not message:
            return

        # Check if message has an embed (only webhooks can send multiple in one message)
        if message.embeds:
            # Just copy the embed including all its properties
            embed = message.embeds[0]
            # Overwrite their title
            embed.title = f'Embed by: {message.author}'

        else:
            embed = discord.Embed(
                title=f'Message by: {message.author}',
                description=message.content
            )

        # send the message to specified channel
        await channel.send(embed=embed)
        # delete the original
        await message.delete()

可能的问题:

  • 该消息有嵌入和内容(简单修复,只需将 message.content 添加到 embed.description,并检查长度是否未超过限制)
  • 在消息所在的通道中没有使用该命令,所以找不到消息(可以通过指定一个通道来搜索消息,而不是使用Context来修复)
  • 视频被嵌入,我不确定例如嵌入的 youtube 链接会发生什么,因为机器人无法嵌入视频 afaik

答案 1 :(得分:0)

@Buster 的解决方案工作正常,除非用户将图片作为附加到消息的文件上传。为了解决这个问题,我最终使用附加图像的 proxy_url 设置了嵌入消息的图像。我的整个移动命令如下。

# Move: !move {channel to move to} {number of messages}
# Used to move messages from one channel to another.
@client.command(name='move')
async def move(context):

    if "mod" not in [y.name.lower() for y in context.message.author.roles]:
        await context.message.delete()
        await context.channel.send("{} you do not have the permissions to move messages.".format(context.message.author))
        return

    # get the content of the message
    content = context.message.content.split(' ')
    # if the length is not three the command was used incorrectly
    if len(content) != 3 or not content[2].isnumeric():
        await context.message.channel.send("Incorrect usage of !move. Example: !move {channel to move to} {number of messages}.")
        return
    # channel that it is going to be posted to
    channelTo = content[1]
    # get the number of messages to be moved (including the command message)
    numberOfMessages = int(content[2]) + 1
    # get a list of the messages
    fetchedMessages = await context.channel.history(limit=numberOfMessages).flatten()
    
    # delete all of those messages from the channel
    for i in fetchedMessages:
        await i.delete()

    # invert the list and remove the last message (gets rid of the command message)
    fetchedMessages = fetchedMessages[::-1]
    fetchedMessages = fetchedMessages[:-1]

    # Loop over the messages fetched
    for messages in fetchedMessages:
        # get the channel object for the server to send to
        channelTo = discord.utils.get(messages.guild.channels, name=channelTo)

        # if the message is embeded already
        if messages.embeds:
            # set the embed message to the old embed object
            embedMessage = messages.embeds[0]
        # else
        else:
            # Create embed message object and set content to original
            embedMessage = discord.Embed(
                        description = messages.content
                        )
            # set the embed message author to original author
            embedMessage.set_author(name=messages.author, icon_url=messages.author.avatar_url)
            # if message has attachments add them
            if messages.attachments:
                for i in messages.attachments:
                    embedMessage.set_image(url = i.proxy_url)

        # Send to the desired channel
        await channelTo.send(embed=embedMessage)

感谢所有帮助解决此问题的人。