簡體   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