在同一应用程序中运行 Flask 和 Discord 机器人
Posted
技术标签:
【中文标题】在同一应用程序中运行 Flask 和 Discord 机器人【英文标题】:Running Flask & a Discord bot in the same application 【发布时间】:2018-07-19 11:17:40 【问题描述】:我正在用 Python 构建一个 Discord 机器人,并希望从 Twitch.tv 的 API 接收 HTTP 请求(请参阅 Webhooks Guide 和 Webhooks Reference)(订阅事件,例如;X 流媒体已上线)并基于从 Twitch 收到的 HTTP(POST 或 GET)请求的内容,在 Discord bot 上执行某些操作,例如:在文本通道上输出消息。
我正在使用discord.py Python Discord API/库。
我调查了此事,发现Flask 似乎是网络服务器接收这些请求的一个很好的极简选择。
我应该先说我对 Python 很陌生,而且我以前从未使用过 Flask。
现在。问题是我似乎无法找到在我的不和谐机器人中运行 Flask 服务器的方法。
我尝试将这个简单的代码添加到我的 discord.py 脚本中:
from flask import Flask, request
app = Flask(__name__)
@app.route('/posts', methods=['POST'])
def result():
print(request.form['sched'])
# Send a message to a discord text channel etc...
return 'Received !'
当我运行如下所示的 discord.py 脚本时: (为了更短,去掉了一些命令和功能)
import discord
import asyncio
from flask import Flask, request
app = Flask(__name__)
@app.route('/posts', methods=['POST'])
def result():
print(request.form['sched'])
# Send a message to a discord text channel etc...
return 'Received !'
client = discord.Client()
@client.event
async def on_ready():
print('Logged in as')
print(client.user.name)
print(client.user.id)
print('------')
@client.event
async def on_message(message):
if message.author == client.user:
return
content = message.content
fullUser = message.author.name+'#'+message.author.discriminator
print(str(message.timestamp)+" #"+message.channel.name+" "+fullUser+": "+str(content.encode('ascii', 'ignore').decode('ascii')))
if content.startswith('!'):
content = content[1:]
if content.startswith('test'):
counter = 0
tmp = await client.send_message(message.channel, 'Calculating messages...')
async for log in client.logs_from(message.channel, limit=100):
if log.author == message.author:
counter += 1
await client.edit_message(tmp, 'You have messages.'.format(counter))
client.run('MyTokenHere')
似乎如果我将flask指向discord.py(上面)并运行它,它将启动代码,进入“client.run('MyTokenHere')”部分以获取不和谐,然后停在并运行不和谐机器人。直到我通过 Ctrl+C 退出机器人,实际的 Flask 服务器才启动,但现在不和谐机器人已断开连接,不再进行任何处理。
如果我要在代码中的某处添加“app.run()”(在调用启动 Discord 机器人部分的“client.run()”之前)以启动 Flask 服务器,同样的问题仍然存在;它只会运行烧瓶,一直卡在上面,直到我 Ctrl+C 退出 Flask 服务器,然后它将继续启动 Discord 机器人。 最终,我需要使用 Discord API,并且我需要连接到 Discord API 网关和所有优秀的爵士乐才能将消息实际发送到带有机器人的频道,所以我真的不知道在这里做什么。
所以。我想我已经尽力解释我最终想要在这里实现的目标,希望有人可以帮助我找到一种方法来使用 Flask 进行这项工作,或者如果有更好更简单的方法,提供不同的解决方案.
【问题讨论】:
你可能不得不在不同的线程中运行它们。 您需要为您的 discord 机器人创建一个子线程。尝试使用threading
模块。
【参考方案1】:
这是 discord.py 中的 cog 示例
我为 dbl(Discord Bot Lists)制作了这个东西,你可以实现,你需要的东西。
注意:使用 webprocess 运行您的 heroku 应用程序
示例: 网页:python main.py
那就继续https://uptimerobot.com/ 并设置为每 5 分钟 ping 您的网络应用程序
from aiohttp import web
from discord.ext import commands, tasks
import discord
import os
import aiohttp
app = web.Application()
routes = web.RouteTableDef()
def setup(bot):
bot.add_cog(Webserver(bot))
class Webserver(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.web_server.start()
@routes.get('/')
async def welcome(request):
return web.Response(text="Hello, world")
@routes.post('/dbl')
async def dblwebhook(request):
if request.headers.get('authorization') == '3mErTJMYFt':
data = await request.json()
user = self.bot.get_user(data['user']) or await self.bot.fetch_user(data['user'])
if user is None:
return
_type = f'Tested!' if data['type'] == 'test' else f'Voted!'
upvoted_bot = f'<@data["bot"]>'
embed = discord.Embed(title=_type, colour=discord.Color.blurple())
embed.description = f'**Upvoter :** user.mention Just _type' + f'\n**Upvoted Bot :** upvoted_bot'
embed.set_thumbnail(url=user.avatar_url)
channel = self.bot.get_channel(5645646545142312312)
await channel.send(embed=embed)
return 200
self.webserver_port = os.environ.get('PORT', 5000)
app.add_routes(routes)
@tasks.loop()
async def web_server(self):
runner = web.AppRunner(app)
await runner.setup()
site = web.TCPSite(runner, host='0.0.0.0', port=self.webserver_port)
await site.start()
@web_server.before_loop
async def web_server_before_loop(self):
await self.bot.wait_until_ready()
【讨论】:
【参考方案2】:正如好心的评论者告诉我的那样; threading 似乎是要走的路。 谢谢大家!
【讨论】:
你是在烧瓶还是机器人上穿线?【参考方案3】:如果您不打算使用烧瓶扩展,另一种很酷的方法是使用 quart 代替烧瓶,那么它对您来说非常容易。
注意:使用 webprocess 运行您的 heroku 应用程序
示例: 网页:python main.py
然后继续https://uptimerobot.com/ 并设置每 5 分钟 ping 您的网络应用程序
# Code Example
from discord.ext import commands
from quart import Quart
import os
app = Quart(__name__)
bot = commands.Bot('!')
@bot.command()
async def something(ctx):
...
"""
Note: On Heroku you cant bind your webserver with 5000 port as they aren't static.
To fix above problem you will have to get dynamic port from the environment variable and you are good to go.
"""
PORT = os.environ.get('PORT')
bot.loop.create_task(app.run_task('0.0.0.0', PORT))
bot.run('Token')
【讨论】:
【参考方案4】:或者您可以使用终端多路复用器tmux
独立运行它们!
如果您在 Linux 平台上运行,tmux python3 flaskapp.py
将运行 flask 应用程序,而您可以独立运行 discord bot。
【讨论】:
您的意思是在不同的文件中分别运行 discord.py 和 flask。我不认为那是他的意思。我认为他想在烧瓶中运行 discordpy,这样他就可以从 discordpy 中获取数据以上是关于在同一应用程序中运行 Flask 和 Discord 机器人的主要内容,如果未能解决你的问题,请参考以下文章
在同一个 apache 服务器上运行 django 和 flask