run discord bot inside flask - flask

I would like to have a strife bot that accesses the Flask Database (Flask SQLAlchemy). I would like to know if there is a way to make the Discord bot run and managed via the Flask Web Application, how to connect the two so that they can interact with each other
Thanks, Regard
here is my flask configuration
# bot Client Config
client = commands.Bot(command_prefix='!', case_insensitive=True)
# Load Token Config
load_dotenv('.env')
# Token Config
TOKEN = os.getenv('TOKEN')
# Picture Extension
pict_ext = ('.jpg','.png','.jpeg')
#
# Flask Configuration
def create_app(script_info=None):
# environtment configurations
# module import
from projects.dashboard.views import dashboard_blueprint
# initialize app
app = Flask(__name__, static_url_path='')
# register blueprint
app.register_blueprint(dashboard_blueprint)
return app

running discord bot in the separate thread using thread module like this
# thread function
def flask_thread(func):
thread = Thread(target=func)
print('Start Separate Thread From Bot')
thread.start()
then add it to the main file
# main file
# function run flask with separate Thread
def run():
app.run(host='0.0.0.0', port=10000, use_reloader=False)
if __name__ == '__main__':
flask_thread(func=run)
client.run(os.getenv('TOKEN'))
running with command
python main.py
and see http://localhost:10000 in your browser

Related

Can a streamlit app be run within a flask app?

No code here, just a question. I have tried various means to get a streamlit app to run within a flask app. Main reason? Using Flask for user authentication into the streamlit app. Cannot get it to work out. Is it not possible perhaps?
Streamlit uses Tornado to serve HTTP and WebSocket data to its frontend. That is, it’s already its own web server, and is written in an existing web framework; it wouldn’t be trivial to wrap it inside another web framework.
Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed. By using non-blocking network I/O, Tornado can scale to tens of thousands of open connections, making it ideal for long polling, WebSockets, and other applications that require a long-lived connection to each user.
Flask is a synchronous web framework and not ideal for WebSockets etc.
Serving an interactive Streamlit app via flask.render_template isn’t feasible, because Streamlit apps are not static; when you interact with your Streamlit app, it is re-running your Python code to generate new results dynamically
Follow these discussions for more info
Integration with flask app
Serve streamlit within flask
import asyncio
import subprocess
from mlflow.server import app as mlflow_app
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.middleware.wsgi import WSGIMiddleware
import uvicorn
from fastapi.logger import logger
import uuid
from config import *
streamlit_app_process = None
streamlit_app_stdout = None
streamlit_app_stderr = None
async def registry_subprocess() -> None:
logger.debug("registry distance_matrix")
global streamlit_app_process
global streamlit_app_stdout
global streamlit_app_stderr
id = str(uuid.uuid1())
streamlit_app_stdout = open(f"/tmp/subprocess_stdout_{''.join(id.split('-'))}", 'w+b')
streamlit_app_stderr = open(f"/tmp/subprocess_stderr_{''.join(id.split('-'))}", 'w+b')
cmd = ['streamlit', 'run', f'{app_dir}/Home.py', f'--server.port={streamlit_app_port}', f'--server.address={streamlit_app_host}']
logger.info(f"subprocess start cmd {cmd}")
streamlit_app_process = subprocess.Popen(cmd, stdout=streamlit_app_stdout.fileno(), stderr=streamlit_app_stderr.fileno())
logger.info(f"subprocess start success {streamlit_app_process.pid} uid:{id}")
await asyncio.sleep(1)
streamlit_app_stdout.flush()
streamlit_app_stderr.flush()
[logger.info(i) for i in streamlit_app_stdout.readlines()]
[logger.info(i) for i in streamlit_app_stderr.readlines()]
async def close_subprocess() -> None:
logger.debug("close subprocess")
try:
streamlit_app_process.kill()
streamlit_app_stdout.flush()
streamlit_app_stderr.flush()
streamlit_app_stdout.close()
streamlit_app_stderr.close()
except Exception as error:
logger.error(error)
application = FastAPI()
application.add_event_handler("startup", registry_subprocess)
application.add_event_handler("shutdown", close_subprocess)
application.add_middleware(
CORSMiddleware,
allow_origins='*',
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
application.mount(f"/{mlflow_app_prefix.strip('/')}", WSGIMiddleware(mlflow_app))
if __name__ == "__main__":
uvicorn.run(application, host=mlflow_app_host, port=int(mlflow_app_port))

how to run mqtt in flask application simultaneously over wsgi

I created a flask application that consists of MQTT client which simultaneously subscribe data from esp32 and store it in database.
from flask import Flask, redirect, render_template, request, session, abort,make_response,jsonify, flash, url_for
import paho.mqtt.client as mqtt
import json
import config
import db_access
#mqtt code
def on_message(client, userdata, message):
topic = message.topic
print("line 12 - topic checkpoint - ",topic)
msgDecode=str(message.payload.decode("utf-8","ignore"))
msgJson=json.loads(msgDecode) #decode json data
print("line 15 - json checkpoint - ",type(msgJson))
# deviceID = msgJson["DeviceID"]
# currentCounter = msgJson["Counter"]
# status = msgJson["Status"]
db_access.updateStatus(msgJson["DeviceID"],msgJson["Status"])
app = Flask(__name__,template_folder='templates')
'''Web portal routes'''
#app.route('/device/switch', methods=['POST'])
def switch():
#parameter parsing
deviceID = request.args.get('deviceID')
status = request.args.get('status')
statusMap = {"on":1,"off":0}
#MQTT publish
mqtt_msg = json.dumps({"deviceID":int(deviceID),"status":statusMap[status]})
client.publish(config.MQTT_STATUS_CHANGE_TOPIC,mqtt_msg)
time_over_flag = 0
loop_Counter = 0
while status != db_access.getDeviceStatus(deviceID):
time.sleep(2)
loop_Counter+=1
if loop_Counter ==2:
time_over_flag = 1
break
if time_over_flag:
return make_response(jsonify({"statusChange":False}))
else:
return make_response(jsonify({"statusChange":True}))
if __name__ == "__main__":
db_access.createUserTable()
db_access.insertUserData()
db_access.createDeviceTable()
db_access.insertDeviceData()
print("creating new instance")
client = mqtt.Client("server") #create new instance
client.on_message=on_message #attach function to callback
print("connecting to broker")
client.connect(config.MQTT_BROKER_ADDRESS)
client.loop_start()
print("Subscribing to topic","esp/#")
client.subscribe("esp/#")
app.run(debug=True, use_reloader=False)
This is code in ____init____.py
db_access.py is consist of database operations and config.py consist of configurations.
Will this work in apache?
also, I have no previous experience with WSGI
The problem with launching your code (as included) with a WSGI server, is the part in that last if block, only gets run when you execute that file directly with the python command.
To make this work, I'd try moving that block of code to the top of your file, around here:
app = Flask(__name__,template_folder='templates')
db_access.createUserTable()
db_access.insertUserData()
db_access.createDeviceTable()
db_access.insertDeviceData()
print("creating new instance")
client = mqtt.Client("server") #create new instance
client.on_message=on_message #attach function to callback
print("connecting to broker")
client.connect(config.MQTT_BROKER_ADDRESS)
client.loop_start()
print("Subscribing to topic","esp/#")
client.subscribe("esp/#")
I'd also rename that __init__.py file, to something like server.py as the init file isn't meant to be heavy.
Once you've done that, run it with the development server again and test that it works as expected.
Then install a WSGI server like gunicorn into your virtual enviornment:
pip install gunicorn
And launch the app with gunicorn (this command should work, assuming you renamed your file to server.py):
gunicorn --bind '0.0.0.0:5000' server:app
Then test again.

Making use of CherryPy as webserver for flask application

I have a simple flask application that works really well. I've been developing it separately from the main desktop application, I want to "plugin" the flask application into the main application. I also want to use cherrypy as the webserver as the default webserver that comes with flask is not production ready. I am not sure how to get both these to work together. My flask application code looks like this
from flask import Flask, render_template,send_from_directory
from scripts_data import test_data
from schedule_data import scheduledata
import os
app=Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/scripts')
def scripts():
test_data=t_data()
return render_template('scripts.html',data_scripts=test_data)
#app.route('/sch')
def schedules():
data_schedule=s_data()
return render_template('schedules.html',table_data=data_schedule)
if __name__=='__main__':
app.run(debug=True)
so obviously as I want to integrate into the main application I can't use app.run. Its not clear how to swap out the flask webserver for the Cherrypy Webserver
I have seen the following
from flask import Flask
import cherrypy
app = Flask(__name__)
app.debug = True
Class setup_webserver(object):
#app.route("/")
def hello():
return "Hello World!"
def run_server():
# Mount the WSGI callable object (app) on the root directory
cherrypy.tree.graft(app, '/')
# Set the configuration of the web server
cherrypy.config.update({
'engine.autoreload_on': True,
'log.screen': True,
'server.socket_port': 5000,
'server.socket_host': '0.0.0.0'
})
# Start the CherryPy WSGI web server
cherrypy.engine.start()
cherrypy.engine.block()
Class start_it_all(object)
import setup_webserver
setup_webserver.run_server()
But when I start the webserver and go to the site (0.0.0.0:5000) I get a 404?
I don't get the 404 when its just flask on its own. All I want to do is swap out the flask built-in webserver for the cherrpy webserver. I don't want to use cherrypy for anything else, as Flask will be the framework
Any suggestions? I'm on Windows and using python 2.7

celery with flask: application not registered on db instance and no application bound to current context

I'm trying to add some background tasks to my flask app using celery. I'm using blueprint with my flask app like this:
db = SQLAlchemy()
def create_app():
app = Flask(__name__)
app.config.from_object('config')
db.init_app(app)
from .main import main as main_blueprint
app.register_blueprint(main_blueprint)
from .api_1_0 import api as api_1_0_blueprint
app.register_blueprint(api_1_0_blueprint, url_prefix='/api/v1.0')
return app
And I have run.py like this:
app = create_app()
app.run(port=7000, debug=True, threaded=True)
Then I have a separate file with some tasks:
celery = Celery(__name__, broker=CELERY_BROKER_URL)
#celery.task
def send_async_sms(to, msg):
app = current_app._get_current_object()
with app.app_context():
time.sleep(12)
print "Sending to {0}: {1}".format(to, msg)
Without the two lines with app context, things work fine. But adding them cause the following problem:
ERROR/MainProcess] Task app.notify.send_async_sms[0d535fc4-7465-470e-9204-548ecca2c6e0] raised unexpected: RuntimeError('working outside of application context',)
What am I doing wrong here?

Importing Flask app when using app factory and flask script

This is Flask app context
app = Flask(__name__)
with app.app_context():
# insert code here
Most of the use cases of app context involves having 'app' initialized on the same script or importing app from the base.
My application is structured as the following:
# application/__init__.py
def create_app(config):
app = Flask(__name__)
return app
# manage.py
from application import create_app
from flask_script import Manager
manager = Manager(create_app)
manager.add_command("debug", Server(host='0.0.0.0', port=7777))
This might be really trivial issue, but how I should call 'with app.app_context()' if my application is structured like this?
Flask-Script calls everything inside the test context, so you can use current_app and other idioms:
The Manager runs the command inside a Flask test context. This means that you can access request-local proxies where appropriate, such as current_app, which may be used by extensions.
http://flask-script.readthedocs.org/en/latest/#accessing-local-proxies
So you don't need to use with app.app_context() with Manager scripts. If you're trying to do something else, then you'd have to create the app first:
from application import create_app
app = create_app()
with app.app_context():
# stuff here