【问题标题】:How to make reactions (when editing embed) in discord.py faster?如何更快地在 discord.py 中做出反应(编辑嵌入时)?
【发布时间】:2021-07-31 23:56:55
【问题描述】:

代码现在工作得很好,但是在使用了一段时间后,我发现了它周围的一些错误。我的问题是,在用户使用反应对嵌入做出反应(图片显示here)后,从单击反应到实际编辑嵌入需要太长时间(在 1-3 秒的范围内),这也不理想许多用户一次做出反应,或者一个用户对其中的更多答案做出反应。

有时当用户反应过快时,它会显示this。正如你所看到的,我对两个答案的反应太快了,对它“没有反应”。它显示了嵌入中的一些变化,但最后它什么也没显示。用户必须“取消反应”并再次对其做出反应以显示嵌入中的任何更改。

我的理论是我的代码很糟糕和/或 API 跟不上。您有什么建议如何在不进行任何权衡的情况下使其更快?

下面显示的代码与 cmets 一起显示我为什么这样做以及为什么这样做。


@commands.Cog.listener()
async def on_raw_reaction_add(self, payload: discord.RawReactionActionEvent):
   
   #open an json to retrieve the embed ID where I added it
    with open("cogs/message_id.json") as f:
        data = json.load(f)
    
    #fetch the channel and message from the payload id
    channel = self.bot.get_channel(payload.channel_id)
    message = await channel.fetch_message(payload.message_id)

    #don't react to anything other than in json file
    if payload.message_id in data["message_ids"]:

        embed = message.embeds[0]
        reaction = discord.utils.get(message.reactions, emoji=payload.emoji.name)
        
        #prepared the dictionary for reactions, as it helps with performance
        emoticon_dict = {
            "1️⃣": 0,
            "2️⃣": 1,
            "3️⃣": 2,
            "4️⃣": 3,
            "5️⃣": 4,
            "6️⃣": 5,
            "7️⃣": 6,
            "8️⃣": 7,
            "9️⃣": 8,
            "????": 9
        }
        dictionary = {}
        i = emoticon_dict[str(payload.emoji)]
        dictionary[i] = reaction.count - 1 #the bot vote counts, subtract it
        
        #set for when duplicates are in there
        members = set()
        async for user in reaction.users():
            if user.id == self.bot.user.id:  #don't add bot user to it
                continue
            else:
                members.add(user)
        
        #show the votes in members = set() and join them
        vypis_hlasu = f"{', '.join(user.display_name for user in members)}"
        #edit the message based on dictionary index
        edit = embed.set_field_at(i, name=embed.fields[i].name, value="{} | {}".format(dictionary[i], vypis_hlasu),
                                  inline=False)
        await reaction.message.edit(embed=edit)

如果你想知道 on_raw_reaction_remove 装饰器,代码是一样的。

感谢您的帮助。

【问题讨论】:

  • 获得更好的互联网连接?
  • 我没有从本地网络运行机器人,因为我的网速一般。我正在使用位于波兰的服务器,网络所在的位置(无法测量它,但使用了一个测量其延迟的命令),它的范围在 60 到 122 毫秒之间。是不是很担心?

标签: python python-3.x discord discord.py


【解决方案1】:

所以答案很简单。我能够将这些值插入 MySQL 数据库,因此我不使用 JSON 来添加消息 ID。我创建了一个简单的缓存,它使用 pythonic set() 从数据库中缓存 id,以便更快地搜索广泛的值,如下所示:

class Poll(commands.Cog):
   def __init__(self, bot):
      self.bot = bot
      self.caching = set()
      self.cache.start()

   @commands.command()
   async def your_command(self, ctx):
     #here you should insert ctx.message.id into the database and self.caching
     pass

   @tasks.loop(minutes=30)
   async def cache(self):
        try:
            self.cursor = self.connect(user="xxx", password="xxx", host="xxx", database="xxx")
            #so you don't overclog your databse.
            query2 = "DELETE FROM `Poll` WHERE `DateOfPoll` < CURRENT_DATE - 7;"
            self.cursor.execute(operation=query2)

            query = "SELECT `PollID` FROM `Poll`"
            tuples = self.query(query = query)
            
            #set comprehension for having clean numbers in cache, return of tuples are [("321654", " "...)]
            self.caching = {int(clean_variable) for variable in tuples for clean_variable in variable}

            return self.caching

        except mysql.connector.Error as e:
            print(e)
            self.database.rollback()

        finally:
            self.close(commit=True)
      
    @cache.before_loop
    async def before_cache(self):
        try:
            self.cursor = self.connect(user="xxx", password="xxx", host="xxx", database="xxx")
            query = "your query"
            self.cursor.execute(query)

        except mysql.connector.Error as e:
            print(e)
            self.database.rollback()
            return

        finally:
            self.close(commit=True)

这允许我将这些值插入数据库并每 30 分钟缓存一次。为了创建下一个嵌入,我只需将新值添加到 self.caching 并插入到数据库中。如果我只是插入到数据库中,反应将不起作用,因为嵌入的 ID 不在缓存中,您必须等待 30 分钟才能将其全部整理出来。使用self.caching.add(id_embed),您会立即做出反应,因为 Pythonic 集合的时间复杂度(平均)为 O(1),如 here 所示。

这里和那里都有一些错误,但总体而言,平均优化比打开 json 和阅读列表要快。解决此问题的另一种方法是使用字典而不是 set 进行缓存,但我无法进一步探索这个想法。

您还应该考虑 API 限制。你不能比这更快,但我能够以更好的结果重现相同的代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-15
    • 2020-10-29
    • 2020-03-17
    • 2021-05-08
    • 1970-01-01
    • 2019-06-03
    • 2021-05-05
    • 1970-01-01
    相关资源
    最近更新 更多