pythonbotstwitchdiscord.py

Running Flask & a Discord bot in the same application


I am building a Discord bot in Python and would like to receive HTTP requests from Twitch.tv's API (See Webhooks Guide & Webhooks Reference) (To subscribe to events like; X streamer has gone live) and based on the content of the HTTP (POST or GET) request received from Twitch, do something on the Discord bot, e.g: Output a message on a text channel.

I am using the discord.py Python Discord API/Library.

I've looked into the matter and found that Flask seemed like a good minimalist choice for a webserver to receive these requests on.

I should preface this by saying I'm very new to Python and I've never used Flask before.

Now. The problem is I can't seem to figure out a way to run the Flask server inside of my discord bot.

I've tried adding this simple code into my discord.py script:

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 !'

When I run my discord.py script which looks something like this: (Stripped away some commands and features for the sake of keeping this shorter)

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

It seems like if I point flask to discord.py (the above) and run it, it'll start the code, get to the "client.run('MyTokenHere')" part for discord, and just stop at that and run the discord bot. It's not until I exit out of the bot by doing Ctrl+C that the actual Flask server starts, but now the discord bot is disconnected and no longer does any processing.

The same problem persists if I were to for example add "app.run()" somewhere in my code (before calling "client.run()" which starts the Discord bot part) to launch the Flask server; It'll just run the flask, get stuck on that until I Ctrl+C out of the Flask server, then it'll proceed to start the Discord bot. Ultimately, I need to use the Discord API and I need to be connected to the Discord API gateway and all that good jazz to actually send messages to a channel with the bot, so I don't really know what to do here.

So. I think I've tried my best to explain what I'm ultimately trying to achieve here, and hopefully someone can help me find a way to either make this work with Flask, or if there's a better and easier way, provide a different solution.


Solution

  • As the kind commenters informed me; threading seems like the way to go. Thanks guys!