I am creating a web dashboard for my discord bot using quart. I have 2 files, bot.py
and webserver.py
. The bot.py
file has the code for my bot and the webserver.py
has the code for the web dashboard.
Here is the code of bot.py
.
import os
import discord
from discord.ext import commands, ipc
from dotenv import load_dotenv
load_dotenv()
class BotClass(commands.Bot):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.ipc = ipc.Server(self, secret_key="Hercules")
async def on_ready(self):
"""Called upon the bot is ready to use"""
await self.ipc.start() # There were some issues with event loop, so I put the ipc.start() inside the on_ready function which fixed my issue
print("Bot is ready")
async def on_ipc_ready(self):
"""Called upon the ipc server is ready to use"""
print("The ipc server is ready")
async def on_ipc_error(self, endpoint, error):
"""Called upon the endpoint raises an error"""
print(f"{error} was raised by {endpoint}")
bot = BotClass(command_prefix="!", intents=discord.Intents.all())
@bot.ipc.route()
async def get_guild_count(data):
guild_count = len(bot.guilds)
return guild_count
@bot.command()
async def test(ctx):
await ctx.reply("Everything is working perfectly")
if __name__ == "__main__":
bot.run(os.getenv("BOT_TOKEN"))
And here's the error I am getting from bot.py
file.
Traceback (most recent call last):
File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\discord\client.py", line 377, in _run_event
await coro(*args, **kwargs)
File "F:\HS International\XyRic Bot Dashboard\bot.py", line 15, in on_ready
await self.ipc.start() # There were some issues with event loop, so I put the ipc.start() inside the on_ready function which fixed my issue
File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\discord\ext\ipc\server.py", line 262, in start
self.loop.run_until_complete(self.__start(self._multicast_server, self.multicast_port))
File "E:\Python\lib\asyncio\base_events.py", line 617, in run_until_complete
self._check_running()
File "E:\Python\lib\asyncio\base_events.py", line 577, in _check_running
raise RuntimeError('This event loop is already running')
RuntimeError: This event loop is already running
F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\discord\client.py:382: RuntimeWarning: coroutine 'Server.__start' was never awaited
await self.on_error(event_name, *args, **kwargs)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
The ipc server is ready
I know it's telling me to await bot.ipc.start()
, but the documentation doesn't tell me to do it. I am confused about this. If I have to await it then I have to put this in an async function, but I am not supposed to do it like this.
Here goes the code of my webserver.py
.
from quart import Quart, redirect, url_for
from quart_discord import DiscordOAuth2Session, requires_authorization, Unauthorized
from discord.ext import ipc
import os
from dotenv import load_dotenv
load_dotenv()
app = Quart(__name__)
app.secret_key = "Hercules"
ipc_client = ipc.Client(secret_key="Hercules")
app.config["DISCORD_CLIENT_ID"] = os.getenv("CLIENT_ID")
app.config["DISCORD_CLIENT_SECRET"] = os.getenv("CLIENT_SECRET")
app.config["DISCORD_REDIRECT_URI"] = "http://127.0.0.1:5000/callback"
app.config["DISCORD_BOT_TOKEN"] = os.getenv("BOT_TOKEN")
discord = DiscordOAuth2Session(app)
@app.route("/")
async def index():
guild_count = await ipc_client.request("get_guild_count")
return str(guild_count)
@app.route("/login/")
async def login():
return await discord.create_session()
@app.route("/callback/")
async def callback():
try:
await discord.callback()
except:
return redirect(url_for("login"))
return redirect(url_for("select_server"))
@app.route("/select_server/")
async def select_server():
user = await discord.fetch_user()
return f"{user.name}"
if __name__ == "__main__":
app.run()
And here goes the error that I am getting from webserver.py
file.
Traceback (most recent call last):
File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\aiohttp\connector.py", line 980, in _wrap_create_connection
return await self._loop.create_connection(*args, **kwargs) # type: ignore[return-value] # noqa
File "E:\Python\lib\asyncio\base_events.py", line 1055, in create_connection
raise exceptions[0]
File "E:\Python\lib\asyncio\base_events.py", line 1040, in create_connection
sock = await self._connect_sock(
File "E:\Python\lib\asyncio\base_events.py", line 954, in _connect_sock
await self.sock_connect(sock, address)
File "E:\Python\lib\asyncio\proactor_events.py", line 704, in sock_connect
return await self._proactor.connect(sock, address)
File "E:\Python\lib\asyncio\windows_events.py", line 812, in _poll
value = callback(transferred, key, ov)
File "E:\Python\lib\asyncio\windows_events.py", line 599, in finish_connect
ov.getresult()
ConnectionRefusedError: [WinError 1225] The remote computer refused the network connection
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\quart\app.py", line 1629, in handle_request
return await self.full_dispatch_request(request_context)
File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\quart\app.py", line 1654, in full_dispatch_request
result = await self.handle_user_exception(error)
File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\quart\app.py", line 1099, in handle_user_exception
raise error
File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\quart\app.py", line 1652, in full_dispatch_request
result = await self.dispatch_request(request_context)
File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\quart\app.py", line 1697, in dispatch_request
return await self.ensure_async(handler)(**request_.view_args)
File "F:\HS International\XyRic Bot Dashboard\webserver.py", line 21, in index
guild_count = await ipc_client.request("get_guild_count")
File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\discord\ext\ipc\client.py", line 97, in request
await self.init_sock()
File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\discord\ext\ipc\client.py", line 61, in init_sock
self.multicast = await self.session.ws_connect(self.url, autoping=False)
File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\aiohttp\client.py", line 779, in _ws_connect
resp = await self.request(
File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\aiohttp\client.py", line 536, in _request
conn = await self._connector.connect(
File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\aiohttp\connector.py", line 540, in connect
proto = await self._create_connection(req, traces, timeout)
File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\aiohttp\connector.py", line 901, in _create_connection
_, proto = await self._create_direct_connection(req, traces, timeout)
File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\aiohttp\connector.py", line 1206, in _create_direct_connection
raise last_exc
File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\aiohttp\connector.py", line 1175, in _create_direct_connection
transp, proto = await self._wrap_create_connection(
File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\aiohttp\connector.py", line 988, in _wrap_create_connection
raise client_error(req.connection_key, exc) from exc
aiohttp.client_exceptions.ClientConnectorError: Cannot connect to host localhost:20000 ssl:default [The remote computer refused the network connection]
[2022-10-07 21:11:08 +0600] [7028] [INFO] 127.0.0.1:50415 GET /login 1.1 308 243 998
The other routes of the file is working correctly, I only get the error with the index route. Thank you.
I have fixed my issue, let me explain how did I solve my problem. Actually discord-ext-ipc has stopped maintenance, I am not sure if it was the issue of my problem. But all I did was uninstalled discord.py and discord-ext-ipc. Then I installed nextcord and nextcord-ext-ipc (basically I switched to nextcord). But I was still having the same issue. So later what I did was, just changed the name of my ipc server variable. My code looks like this now,
import os
import discord
from nextcord.ext import commands, ipc
from dotenv import load_dotenv
load_dotenv()
class BotClass(commands.Bot):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.ipc_server = ipc.Server(self, secret_key="Hercules")
async def on_ready(self):
"""Called upon the bot is ready to use"""
print("Bot is ready")
async def on_ipc_ready(self):
"""Called upon the ipc server is ready to use"""
print("The ipc server is ready")
async def on_ipc_error(self, endpoint, error):
"""Called upon the endpoint raises an error"""
print(f"{error} was raised by {endpoint}")
bot = BotClass(command_prefix="!", intents=discord.Intents.all())
@bot.ipc_server.route()
async def get_guild_count(data):
guild_count = len(bot.guilds)
return guild_count
@bot.ipc_server.route()
async def get_guild_ids(data):
guild_ids = [int(guild.id) for guild in bot.guilds]
return guild_ids
@bot.command()
async def test(ctx):
await ctx.reply("Everything is working perfectly")
if __name__ == "__main__":
bot.ipc_server.start()
bot.run(os.getenv("BOT_TOKEN"))```
Thank you.