Search code examples
pythonpython-3.xsocketsdiscord.pyaiohttp

Discord-py Rewrite - Basic aiohttp webserver in a Cog


I am trying to integrate a basic aiohttp webserver in a Cog (using discord-py rewrite). I am using the following code for the cog:

from aiohttp import web
import discord
from discord.ext import commands

class Youtube():

    def __init__(self, bot):
        self.bot = bot

    async def webserver(self):
        async def handler(request):
            return web.Response(text="Hello, world")

        app = web.Application()
        app.router.add_get('/', handler)
        runner = web.AppRunner(app)
        await runner.setup()
        site = web.TCPSite(runner, '192.168.1.111', 8999)
        await self.bot.wait_until_ready()
        await site.start()

def setup(bot):
    yt = Youtube(bot)
    bot.add_cog(yt)
    bot.loop.create_task(yt.webserver())

It works fine upon starting the bot. But if I reload the cog while the bot is running, I encounter an issue:

OSError: [Errno 10048] error while attempting to bind on address ('192.168.1.111', 8999): only one usage of each socket address (protocol/network address/port) is normally permitted

I cannot think of an simple/elegant way to release and re bind every time the cog is reloaded.
I would love some suggestions on this. The end goal is to have a cog that supports youtube pubsubhubbub subscriptions.

It might just be that there is a better way to integrate a basic webserver to my bot. I could use a deamon (fork) upon starting the bot for example (I already have a webserver written using HTTPServer with a BaseHTTPRequestHandler that can handle pubsubhubbub youtube subscriptions) but somehow I have my mind set on integrating it in a cog using aiohttp :)


Solution

  •     from aiohttp import web
        import asyncio
        import discord 
        from discord.ext import commands
            
            class Youtube():
            
                def __init__(self, bot):
                    self.bot = bot
            
                async def webserver(self):
                    async def handler(request):
                        return web.Response(text="Hello, world")
            
                    app = web.Application()
                    app.router.add_get('/', handler)
                    runner = web.AppRunner(app)
                    await runner.setup()
                    self.site = web.TCPSite(runner, '192.168.1.111', 8999)
                    await self.bot.wait_until_ready()
                    await self.site.start()
        
                def __unload(self):
                    asyncio.ensure_future(self.site.stop())
            
            def setup(bot):
                yt = Youtube(bot)
                bot.add_cog(yt)
                bot.loop.create_task(yt.webserver())
    

    Thanks Patrick Haugh !!