繁体   English   中英

在同一个应用程序中运行 Flask 和 Discord 机器人

[英]Running Flask & a Discord bot in the same application

我正在用 Python 构建一个 Discord 机器人,并希望从 Twitch.tv 的 API 接收 HTTP 请求(请参阅Webhooks 指南Webhooks 参考)(订阅事件,例如 X 流媒体已上线)并基于 HTTP 的内容( POST 或 GET)从 Twitch 收到的请求,在 Discord 机器人上做一些事情,例如:在文本频道上输出一条消息。

我正在使用discord.py Python Discord API/Library。

我调查了这个问题,发现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(上面的)并运行它,它将启动代码,进入discord的“client.run('MyTokenHere')”部分,然后停止并运行不和谐机器人。 直到我通过执行 Ctrl+C 退出机器人,实际的 Flask 服务器才启动,但现在不和谐机器人已断开连接,不再进行任何处理。

例如,如果我要在代码中的某处添加“app.run()”(在调用启动 Discord bot 部分的“client.run()”之前)以启动 Flask 服务器,同样的问题仍然存在; 它只会运行 Flask,在我 Ctrl+C 退出 Flask 服务器之前一直卡在它上面,然后它会继续启动 Discord 机器人。 最终,我需要使用 Discord API,我需要连接到 Discord API 网关和所有优秀的爵士乐才能使用机器人将消息实际发送到通道,所以我真的不知道在这里做什么。

所以。 我想我已经尽力解释了我最终要在这里实现的目标,希望有人能帮助我找到一种方法来使用 Flask 进行这项工作,或者如果有更好更简单的方法,请提供不同的解决方案.

这是 discord.py 中的 cog 示例

我为 dbl(Discord Bot Lists)制作了这个东西,你可以实现,你需要的东西。

注意:使用 webprocess 运行你的 heroku 应用程序

例子:
网络:python main.py

然后访问https://uptimerobot.com/并设置为每 5 分钟 ping 您的 Web 应用程序

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()

正如好心的评论者告诉我的那样; 线程似乎是要走的路。 谢谢各位!

如果您不打算使用烧瓶扩展,另一种很酷的方法是使用夸脱而不是烧瓶,那么这对您来说将非常容易。

注意:使用 webprocess 运行您的 heroku 应用程序

示例:网络:python main.py

然后访问https://uptimerobot.com/并设置为每 5 分钟 ping 您的 Web 应用程序

# 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')

或者您可以使用终端多路复用器tmux来独立运行它们!。 如果你在 Linux 平台上运行, tmux python3 flaskapp.py将运行flask应用程序,而你可以独立运行discord bot。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM