如何在不达到 Discord 的 1,000 个最大连接数的情况下运行从 API 更新的 Discord 机器人?

Posted

技术标签:

【中文标题】如何在不达到 Discord 的 1,000 个最大连接数的情况下运行从 API 更新的 Discord 机器人?【英文标题】:How can I run my Discord bot that updates from an API without hitting Discord's 1,000 connection maximum? 【发布时间】:2021-05-16 10:37:47 【问题描述】:

我构建了一个机器人,它将机器人的名称更新为 Python 中的价格。同样,机器人的状态也会更新为不同的价格。该机器人按预期工作了一段时间,但随后我收到了来自 Discord 的以下消息:

您的机器人“MY BOT NAME”似乎在短时间内连接到 Discord 超过 1000 次。由于这种行为通常是由错误引起的,因此我们已着手重置您的机器人令牌。

我的机器人每 15 秒从一个 shell 脚本在 linux 服务器上运行一次,这也会杀死它之前运行的最后一个进程。我杀死了前面的进程,这样它们就不会占用我的内存并导致我的服务器崩溃。

这是我的代码:

#!/usr/bin/python
import discord
from discord.ext import commands
import requests
import json
import emoji
import sys
import asyncio

client = commands.Bot(command_prefix = '.')

url = 'URL FOR THE API'
price = requests.get(url)

rapid_gprice = price.json()['data']['price1']
standardp = price.json()['data']['price2']

@client.event
async def on_ready():
    guild = client.get_guild(MY GUILD ID)
    me = guild.me
    await me.edit(nick=standardp)
    activity = discord.Game(name=rapid_gprice)
    await client.change_presence(status=discord.Status.online, activity=activity)

client.run('MY TOKEN')

我相当确定我需要在我的 Python 脚本中使用某种函数,该函数循环通过价格 api 并相应地更新 Discord 机器人,只需运行 Python 脚本一次。

我很乐意提供您可能需要的任何其他信息。提前致谢。

【问题讨论】:

【参考方案1】:

每 15 秒运行一次脚本是一个非常糟糕的主意,有一个名为 tasks 的内置 discord.py 扩展,它可以让你运行后台任务,因此得名。

from discord.ext import tasks

@tasks.loop(seconds=15)
async def change_nick(guild):
    nick = # Get the nick here
    await guild.me.edit(nick=nick)


@client.event
async def on_ready():
    await client.wait_until_ready()
    guild = client.get_guild(MY GUILD ID)
    change_nick.start(guild)

我还看到您正在使用requests,这是一个阻塞库,我建议您改用aiohttp

看看tasks introduction

【讨论】:

感谢您的回答@Łukasz。我对 Python 和 Discord 都很陌生。每 15 秒重新运行一次 shell 脚本的想法是经常更新价格 [,以及不完全了解机器人的功能]。我相信我使用的 api 每 6 秒更新一次价格,但我不需要到那个程度。 好吧,你可以将装饰器中的时间间隔更改为 6 秒,因为更改用户昵称的速率限制是每个公会每秒 1 个请求,因此速率限制不是问题。如果有帮助,请记住接受答案。 我已经接受了您的回答,但我仍然对此有疑问。即使我只运行您在上面提供的代码以及我在 url 上的原始“请求”,循环似乎也不会每 15 秒刷新一次机器人的名称。 这不是代码的问题,或者您的网站没有提供更新的数据,或者您没有获得更新的昵称。我的代码没有任何问题,尝试创建一个随机字符串作为昵称,它可以完美运行 虽然我很感谢您的提交,因为它对我有很大帮助,但它是一个不完整的答案,因此不能成为“答案”。【参考方案2】:

这就是我最终解决问题的方式。这可能是代码过度杀伤,但它有效。请随时帮助我对其进行修改以提高效率:

#!/usr/bin/python
from discord.ext import tasks, commands
import aiohttp
import json
import asyncio
import discord

client = commands.Bot(command_prefix = '.')

url = 'THE API LINK I''M USING'

async def getPrice1():
   async with aiohttp.ClientSession() as session:
    async with session.get(url) as resp:
      response = await resp.json()
      price1 = response['data']['priceZYX']
      return price1

async def getPrice2():
   async with aiohttp.ClientSession() as session:
    async with session.get(url) as resp:
      response = await resp.json()
      price2 = response['data']['priceXYZ']
      return price2

@tasks.loop(seconds=7)
async def change_nick(guild):
    nick = await getPrice1()
    await guild.me.edit(nick=nick)
    activity = discord.Game(name=await getPrice2())
    await client.change_presence(status=discord.Status.online, activity=activity)

@client.event
async def on_ready():
    await client.wait_until_ready()
    guild = client.get_guild(MY GUILD ID)
    change_nick.start(guild)

【讨论】:

【参考方案3】:

我在尝试将 pricedata(来自 url)实现到我的机器人的用户名时出错。 错误:discord.errors.HTTPException: 400 Bad Request (error code: 50035): Invalid Form Body 在 nick:无法将“(实时价格)”解释为字符串。

如果您有同样的问题(并且使用不和谐重写),请确保将 (nick=nick) 标记为字符串:

@tasks.loop(seconds=15)
async def change_nick(guild):
   nick = await getPrice1()
   await guild.me.edit(nick=str(nick))

PS:我对编码相当陌生,所以如果我错了,请纠正我,它对我有用。还要感谢这篇文章,它帮助我制作了我的机器人。

【讨论】:

以上是关于如何在不达到 Discord 的 1,000 个最大连接数的情况下运行从 API 更新的 Discord 机器人?的主要内容,如果未能解决你的问题,请参考以下文章

discord.js 如何在不提及已记录用户的情况下记录用户名以供将来使用?

如何在不下载任何 .mp3 文件和更多文件的情况下播放音乐 discord.py

如何在不使用 Discord Invite Api 的情况下让 DiscordJS Selfbot 加入服务器?

如何让 discord.js 机器人在不包含前缀和命令名称的情况下重复用户的消息?

如何在不耗尽内存的情况下部署包含 130,000 多个条目的脚本

Discord Bot Maker - MySQL 调平系统或 Discord.js - MySQL 调平系统