Use control panel for discord bot with PyQt5

Viewed 1321

I want to do a control panel for my discord bot in python with PyQt5. I have already my window:

from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1023, 457)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
       
#some other widgets

        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(330, 30, 91, 31))
        font = QtGui.QFont()
        font.setPointSize(16)
        self.pushButton.setFont(font)
        self.pushButton.setObjectName("pushButton")

#some other widgets         

and the main code :

import discord
import sys
from window import Ui_MainWindow
from PyQt5 import QtCore, QtGui, QtWidgets

prefix = ""
bot = discord.Client

class MyClient(bot):

    async def on_connect(self):
        print("Bot connected to")

    async def on_ready(self):
        print('Logged on as {0}!'.format(self.user))

        for guild in self.guilds:
            if guild.id == 354061299596132392:
                print("guild find")


    async def on_message(self, message):
        print(message.content)

    async def on_diconnect(self):
        print("bot disconnected")



def launcher():
    client = MyClient()
    client.run('TOKEN')



def windowLauncher():



    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    ui.pushButton.clicked.connect(launcher)
    MainWindow.show()
    sys.exit(app.exec_())


windowLauncher()

but when I execute this main code, the window is started and when I push the button to start the bot, the window crash, but the bot is running. I have already try to use threading but without success.

1 Answers

discord uses async which has its own event loop and Qt handles another event loop causing one to block the other. In this case, the solution is that both use the same event loop and there are several libraries that implement it:

  • qasync (python -m pip install qasync)
  • asyncqt (python -m pip install asyncqt)

Considering the above, the solution is:

import asyncio
import sys

import discord
from qasync import QEventLoop, asyncSlot
# or
# from asyncqt import QEventLoop, asyncSlot

from PyQt5 import QtCore, QtGui, QtWidgets

from window import Ui_MainWindow


prefix = ""


class MyClient(discord.Client):
    async def on_connect(self):
        print("Bot connected to")

    async def on_ready(self):
        print("Logged on as {0}!".format(self.user))

        for guild in self.guilds:
            if guild.id == 354061299596132392:
                print("guild find")

    async def on_message(self, message):
        print(message.content)

    async def on_diconnect(self):
        print("bot disconnected")


class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setupUi(self)
        self.client = MyClient()
        self.pushButton.clicked.connect(self.on_clicked)

    @asyncSlot()
    async def on_clicked(self):
        await self.client.start("YOUR_TOKEN")


def windowLauncher():

    app = QtWidgets.QApplication(sys.argv)
    loop = QEventLoop(app)
    asyncio.set_event_loop(loop)

    w = MainWindow()
    w.show()
    loop.run_forever()


if __name__ == "__main__":
    windowLauncher()
Related