-2

I am creating a Twitch.tv chat bot and whenever I click 'Start' under the 'File' menu, running 'startSpenbot', I get the 'This program has stopped responding' error.

I have uploaded the full source code to GitHub, however I have deleted the entry for the file 'password.txt'. You can find it here - https://github.com/spencermehta/spenbot/tree/v0.0.8

Here is the 'startSpenbot' function

def startSpenbot(self):
        fileBotOwner = open('botOwner.txt', 'r')
        fileNick = open('nick.txt', 'r')
        fileChannel = open('channel.txt', 'r')
        filePassword = open('password.txt', 'r')
        fileCommands = open('commands.txt', 'r')

        for line in fileBotOwner:
            botOwner = str(line)
        for line in fileNick:
            nick = str(line)
        for line in fileChannel:
            channel = str(line)
        for line in filePassword:
            password = str(line)

        lines = 0
        for line in fileCommands:
            lines += 1
            line = line.split('~')
            if lines == 1:
                command1 = line[0]
                command1R = line[1]


        fileBotOwner.close()
        fileNick.close()
        fileChannel.close()
        filePassword.close()
        fileCommands.close()

        server = 'irc.twitch.tv'
        keyword = ''
        rafflelist = []
        raffleshowjoin = 'hide'

        irc = socket.socket()
        irc.connect((server, 6667))

        irc.send(bytes("PASS " + password + "\r\n", "utf-8"))
        irc.send(bytes("USER " + nick + " 0 * :" + botOwner + "\r\n", "utf-8"))
        irc.send(bytes("NICK " + nick + "\r\n", "utf-8"))
        irc.send(bytes("JOIN " + channel + "\r\n", "utf-8"))

        def message(msg): #function for sending messages to the IRC chat
            global queue
            queue += 1
            if queue < 20:
                irc.send(bytes("PRIVMSG " + channel + " :" + msg + "\r\n", "utf-8"))
            else:
                print("Spamming. Message not sent")

        def queuetimer():
            global queue
            queue = 0
            threading.Timer(30,queuetimer).start()
        queuetimer()
        exceptions = 0

        while True:
            twitchdata = irc.recv(1204)
            data = twitchdata.decode().split(":")[1]
            twitchuser = data.split("!")[0]
            twitchmsg = twitchdata.decode().split(":")[2]

            if twitchdata.find(bytes("PING", "utf-8")) != -1:
                irc.send(twitchdata.replace("PING", "PONG")) #responds to PINGS from the server

            if twitchmsg.lower() == command1 + "\r\n":
                message(command1R)

            if "!raffle" in twitchmsg.lower() and twitchuser == botOwner:
                rafflelist = []
                twitchmsg = twitchmsg.split(" ")
                try:
                    keyword = twitchmsg[1]
                    message("Raffle started with keyword " + keyword + ". Defaulting to not showing raffle join messages")
                except:
                    message("You didn't specify a keyword for the raffle")

            if "!draw" in twitchmsg and twitchuser == botOwner:
                message("Drawing winner...")
                message(random.choice(rafflelist) + " has won the raffle!")

            if twitchmsg == keyword and twitchuser not in rafflelist:
                rafflelist.append(twitchuser)

However, this code runs fine when the program runs in command line, and only crashes now I am using PyQT

Update: The program still runs fine after the crash - its only the GUI which crashes. Here is the rest of the code:

import socket #imports module allowing connection to IRC
import threading #imports module allowing timing functions
from PyQt4 import QtGui, QtCore
import sys
import random

class Spenbot(QtGui.QMainWindow):

    def __init__(self):
        super(Spenbot, self).__init__()

        self.spenbotUI()


    def spenbotUI(self):

        exitAction = QtGui.QAction('Exit', self)
        exitAction.setStatusTip('Exit Application')
        exitAction.triggered.connect(self.close)

        configureAction = QtGui.QAction('Configure', self)
        configureAction.setStatusTip('Configure login data and commands')
        configureAction.triggered.connect(self.spenbotConfigure)

        startAction = QtGui.QAction('Start', self)
        startAction.setStatusTip('Start Spenbot')
        startAction.triggered.connect(self.startSpenbot)

        self.statusBar()

        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&File')
        fileMenu.addAction(exitAction)
        fileMenu.addAction(startAction)
        settingsMenu = menubar.addMenu('&Settings')
        settingsMenu.addAction(configureAction)

        self.setGeometry(300, 300, 400, 300)
        self.setWindowTitle('Spenbot')
        self.setWindowIcon(QtGui.QIcon('logo.png'))
        self.show()


    def spenbotConfigure(self):
        self.configWidget = configWidget()
        self.configWidget.show()

    def closeEvent(self, event):

        reply = QtGui.QMessageBox.question(self, 'Spenbot', 'Are you sure want to quit?', QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)

        if reply == QtGui.QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()

    def startSpenbot(self):
        fileBotOwner = open('botOwner.txt', 'r')
        fileNick = open('nick.txt', 'r')
        fileChannel = open('channel.txt', 'r')
        filePassword = open('password.txt', 'r')
        fileCommands = open('commands.txt', 'r')

        for line in fileBotOwner:
            botOwner = str(line)
        for line in fileNick:
            nick = str(line)
        for line in fileChannel:
            channel = str(line)
        for line in filePassword:
            password = str(line)

        lines = 0
        for line in fileCommands:
            lines += 1
            line = line.split('~')
            if lines == 1:
                command1 = line[0]
                command1R = line[1]


        fileBotOwner.close()
        fileNick.close()
        fileChannel.close()
        filePassword.close()
        fileCommands.close()

        print('Files opened and variables saved')
        server = 'irc.twitch.tv'
        keyword = ''
        rafflelist = []
        raffleshowjoin = 'hide'

        irc = socket.socket()
        irc.connect((server, 6667))

        irc.send(bytes("PASS " + password + "\r\n", "utf-8"))
        irc.send(bytes("USER " + nick + " 0 * :" + botOwner + "\r\n", "utf-8"))
        irc.send(bytes("NICK " + nick + "\r\n", "utf-8"))
        irc.send(bytes("JOIN " + channel + "\r\n", "utf-8"))

        print('Connected to irc')

        def message(msg): #function for sending messages to the IRC chat
            global queue
            queue += 1
            if queue < 20:
                irc.send(bytes("PRIVMSG " + channel + " :" + msg + "\r\n", "utf-8"))
            else:
                print("Spamming. Message not sent")

        def queuetimer():
            global queue
            queue = 0
            threading.Timer(30,queuetimer).start()
        queuetimer()
        exceptions = 0

        print('Queuetimer set')

        while True:
            twitchdata = irc.recv(1204)
            data = twitchdata.decode().split(":")[1]
            twitchuser = data.split("!")[0]
            twitchmsg = twitchdata.decode().split(":")[2]

            if twitchdata.find(bytes("PING", "utf-8")) != -1:
                irc.send(twitchdata.replace("PING", "PONG")) #responds to PINGS from the server

            print('ping pong')
            if twitchmsg.lower() == command1 + "\r\n":
                message(command1R)

            print('command1')

            if "!raffle" in twitchmsg.lower() and twitchuser == botOwner:
                rafflelist = []
                twitchmsg = twitchmsg.split(" ")
                try:
                    keyword = twitchmsg[1]
                    message("Raffle started with keyword " + keyword + ". Defaulting to not showing raffle join messages")
                except:
                    message("You didn't specify a keyword for the raffle")

            if "!draw" in twitchmsg and twitchuser == botOwner:
                message("Drawing winner...")
                message(random.choice(rafflelist) + " has won the raffle!")

            if twitchmsg == keyword and twitchuser not in rafflelist:
                rafflelist.append(twitchuser)

            print('end')

class configWidget(QtGui.QWidget):

    def __init__(self):
        super(configWidget, self).__init__()

        self.configUI()


    def configUI(self):

        fileBotOwner = open('botOwner.txt', 'r')
        fileNick = open('nick.txt', 'r')
        fileChannel = open('channel.txt', 'r')
        filePassword = open('password.txt', 'r')
        fileCommands = open('commands.txt', 'r')

        for line in fileBotOwner:
            botOwner = str(line)
        for line in fileNick:
            nick = str(line)
        for line in fileChannel:
            channel = line[1:]
        for line in filePassword:
            password = str(line)

        lines = 0
        for line in fileCommands:
            lines += 1
            line = line.split('~')
            if lines == 1:
                command1 = line[0]
                command1R = line[1]

        fileBotOwner.close()
        fileNick.close()
        fileChannel.close()
        filePassword.close()
        fileCommands.close()

        inputBotOwner = QtGui.QLabel('Your Twitch Username')
        inputNick = QtGui.QLabel('Your bot\'s Twitch Username')
        inputChannel = QtGui.QLabel('Channel you want bot to join')
        inputPassword = QtGui.QLabel('Enter the bot account\'s OAuth Code (Find it at twitchapps.com/tmi)')
        inputCommand1 = QtGui.QLabel('Command 1 keyword')
        inputCommand1R = QtGui.QLabel('Command 1 response')

        try:
            self.botOwnerEdit = QtGui.QLineEdit(botOwner)
        except:
            self.botOwnerEdit = QtGui.QLineEdit()
        try:
            self.nickEdit = QtGui.QLineEdit(nick)
        except:
            self.nickEdit = QtGui.QLineEdit()
        try:
            self.channelEdit = QtGui.QLineEdit(channel)
        except:
            self.channelEdit = QtGui.QLineEdit()
        try:
            self.passwordEdit = QtGui.QLineEdit(password)
        except:
            self.passwordEdit = QtGui.QLineEdit()
        try:
            self.command1Edit = QtGui.QLineEdit(command1)
        except:
            self.command1Edit = QtGui.QLineEdit()
        try:
            self.command1REdit = QtGui.QLineEdit(command1R)
        except:
            self.command1REdit = QtGui.QLineEdit()

        btn = QtGui.QPushButton('OK', self)
        btn.clicked.connect(self.getResponses)

        grid = QtGui.QGridLayout()
        grid.setSpacing(1)

        grid.addWidget(inputBotOwner, 1, 0)
        grid.addWidget(self.botOwnerEdit, 1, 1)

        grid.addWidget(inputNick, 2, 0)
        grid.addWidget(self.nickEdit, 2, 1)

        grid.addWidget(inputChannel, 3, 0)
        grid.addWidget(self.channelEdit, 3, 1)

        grid.addWidget(inputPassword, 4, 0)
        grid.addWidget(self.passwordEdit, 4, 1)

        grid.addWidget(inputCommand1, 5, 0)
        grid.addWidget(self.command1Edit, 5, 1)
        grid.addWidget(inputCommand1R, 6, 0)
        grid.addWidget(self.command1REdit, 6, 1)

        grid.addWidget(btn)

        self.setLayout(grid)
        self.setGeometry(300, 300, 600, 200)
        self.setWindowTitle('Spenbot - Configuration')
        self.setWindowIcon(QtGui.QIcon('logo.png'))
        self.show()

    def getResponses(self):
            botOwner = self.botOwnerEdit.text()
            nick = self.nickEdit.text()
            channel = self.channelEdit.text()
            channel = '#' + channel
            password = self.passwordEdit.text()
            command1 = self.command1Edit.text()
            command1R = self.command1REdit.text()

            fileBotOwner = open('botOwner.txt', 'w')
            fileNick = open('nick.txt', 'w')
            fileChannel = open('channel.txt', 'w')
            filePassword = open('password.txt', 'w')
            fileCommands = open('commands.txt', 'w')

            fileBotOwner.write(botOwner)
            fileNick.write(nick)
            fileChannel.write(channel)
            filePassword.write(password)
            fileCommands.write(command1 + '~' + command1R)
            self.close()


def main():
    app = QtGui.QApplication(sys.argv)
    ex = Spenbot()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()
spencermehta
  • 639
  • 1
  • 5
  • 10
  • Nvm, that's not long at all. You should try debugging it though. You can try step by through it line by line with a real debugger, or guess where the problem is and used print statement debugging. – Carcigenicate May 03 '15 at 11:05
  • I don't know what the chunk of `for` loops at the top are supposed to do. They seem to just constantly reassign some variables, then leave them as the last line of the file. Probably isn't causing your problem, but I don't think it does what you intend. – Carcigenicate May 03 '15 at 11:08
  • By 'real debugger', do you mean a third-party debuggin application for Python or can I just use the built-in IDLE debugger or from my IDE – spencermehta May 03 '15 at 11:09
  • I have the variables required to log into IRC written to files. The for loops get the text from the files. This is the only way I know how to get information from files – spencermehta May 03 '15 at 11:10
  • Doesn't matter what debugger you use; you just want to be able to go through the function line by line to see exactly where it crashes. My favourite for small things like this is actually just to scatter some descriptive print statements around and see which is the last to execute. – Carcigenicate May 03 '15 at 11:10
  • Like I said though, you're only ever saving the last line. For example, in the `password` loop, you assign password to a line, but then immediately overwrite it with the next line. Did you want to accumulate a list of passwords? – Carcigenicate May 03 '15 at 11:12
  • Nope, there is only one line in that file. I just didn't know how you extract a single line from a file. – spencermehta May 03 '15 at 11:14
  • Also, I tried what you said with the descriptive print statements, and it reaches the end of the code before crashing. I should also mention, it is only the GUI window that crashes, the console seems to keep running. – spencermehta May 03 '15 at 11:15
  • Oh. If there's only one line in the file, ya, that will work. I'm almost certain there's a way to read a single line though (something like `readline`?). And by "end of code", do you mean the end of this function, or the end of all of your code? – Carcigenicate May 03 '15 at 11:19
  • End of this function – spencermehta May 03 '15 at 11:20
  • Update: Only the GUI crashes. This program responds to IRC messages, in this instance Twitch.tv. When the GUI crashes, the program still responds to the messages as its supposed to. – spencermehta May 03 '15 at 11:22
  • Than you will need to broaden your search. If it happens after calling this function, it's probably something that `startSpenbot` sets in motion. Unfortunately, you seem to use a few globals in this function which means it could happen anywhere they're used. – Carcigenicate May 03 '15 at 11:23
  • Start looking in your GUI code then. – Carcigenicate May 03 '15 at 11:23
  • I updated the question to include the full code – spencermehta May 03 '15 at 11:25
  • Sorry, I don't know enough about QT to be able to debug it visually. At this point, I'd probably break out a debugger, riddle the program with breakpoints, and sift through it. You need to narrow your search. – Carcigenicate May 03 '15 at 11:34
  • Ok, thanks for the help so far anyway – spencermehta May 03 '15 at 11:34
  • Np. Good luck with your project. – Carcigenicate May 03 '15 at 11:36

1 Answers1

0

Disclamer: I have no experience with threads and Qt. However it seems to me that the problem is that the startSpenbot function contains an infinite while loop and thus doesn't give the control back at the main event loop. This makes your GUI hang.

If I were you I would use QThreads instead of the threading package of the standard library since at some point you may want your thread to interact with the user interface (see #1 and #2). A good starting point (next to the Qt documentation of course) is the mandelbrot example.

Community
  • 1
  • 1
titusjan
  • 5,376
  • 2
  • 24
  • 43