diff --git a/flask/__init__.py b/flask/__init__.py new file mode 100644 index 0000000..19879cd --- /dev/null +++ b/flask/__init__.py @@ -0,0 +1,5 @@ +from .flask import Flask + + +def setup(bot): + bot.add_cog(Flask(bot)) diff --git a/flask/flask.py b/flask/flask.py new file mode 100644 index 0000000..8c6ce57 --- /dev/null +++ b/flask/flask.py @@ -0,0 +1,102 @@ +import asyncio +import threading + +from quart import Quart, websocket, Response +from redbot.core import Config, checks, commands +from redbot.core.bot import Red + + +class EndpointAction(object): + + def __init__(self, action): + self.action = action + + async def __call__(self, *args): + response = await self.action() + return Response(response, status=200, headers={}) + + +class Flask: + """ + Run an owner only quart (async flask) server for issuing commands. + """ + app = Quart(__name__) + test_name = "FlaskQuart" + + def __init__(self, bot: Red): + self.bot = bot + self.config = Config.get_conf(self, identifier=9811198108111121, force_registration=True) + default_global = {} + default_guild = {} + + self.config.register_global(**default_global) + self.config.register_guild(**default_guild) + + self.threads = [] + self.t = threading.Thread(target=self.worker) + self.t.daemon = True + self.threads.append(self.t) + + self.context = None + + def __unload(self): + try: + self.t._stop() + except: + self.t._stop() # No really, stop + + @checks.is_owner() + @commands.command() + async def flask(self, ctx: commands.Context): + """Starts a quart server""" + self.context = ctx + self.add_endpoint(endpoint="/name", endpoint_name="name", handler=self.bot_name) + self.add_endpoint(endpoint="/help", endpoint_name="help", handler=self.quart_help) + self.t.start() + await ctx.send("Done") + + def add_endpoint(self, endpoint=None, endpoint_name=None, handler=None): + self.app.add_url_rule(endpoint, endpoint_name, EndpointAction(handler)) + + @staticmethod + @app.route('/') + async def hello(): + return "hello" + + async def bot_name(self): + return self.test_name + + async def quart_help(self): + f = commands.HelpFormatter() + msgs = await f.format_help_for(self.context, self.bot) + out = "" + for msg in msgs: + for line in msg.split('\n'): + if line == '```': + continue + if line.endswith(":"): + out += "

" + line + "

\n" + else: + line = line.strip().split(" ") + out += "

" + line[0] + " " + " ".join(line[1:]) + "

\n" + + return ''' + + + Red Bot - Help + + + {} + + '''.format(out) + + @staticmethod + @app.websocket('/ws') + async def ws(): + while True: + await websocket.send('hello') + + def worker(self): + second_loop = asyncio.new_event_loop() + asyncio.ensure_future(self.app.run(loop=second_loop)) + return diff --git a/flask/info..json b/flask/info..json new file mode 100644 index 0000000..4925696 --- /dev/null +++ b/flask/info..json @@ -0,0 +1,18 @@ +{ + "author": [ + "Bobloy" + ], + "bot_version": [ + 3, + 0, + 0 + ], + "description": "Add expiring flags on members to track warnings or incidents", + "hidden": true, + "install_msg": "Thank you for installing flask! Get started with `[p]load flask`, then `[p]help Flag`", + "requirements": ["quart"], + "short": "Run a Flask site to issue commands.", + "tags": [ + "bobloy" + ] +} \ No newline at end of file