如何在不达到 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 机器人在不包含前缀和命令名称的情况下重复用户的消息?