用 gui 制作一个 irc 机器人。在切换按钮切换上断开连接的困难
Posted
技术标签:
【中文标题】用 gui 制作一个 irc 机器人。在切换按钮切换上断开连接的困难【英文标题】:Making a irc bot with a gui. Difficulties with disconnecting on toggle button toggle 【发布时间】:2016-02-16 22:40:32 【问题描述】:我只是根据需要学习python,所以请坚持住,因为这段代码会很乱!...
所以我与 glade 合作为我的客户端 twitch irc 聊天机器人创建了一个 gui,并在工具栏中创建了这个切换按钮:
<object class="GtkToggleToolButton" id="tool_deploy_toggle">
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Connect</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-jump-to</property>
<signal name="toggled" handler="on_tool_deploy_toggle_toggled" swapped="no"/>
</object>
当按钮被“向下”切换时,我希望这个切换按钮打开一个套接字并将机器人部署到 twitch irc 聊天中(并且还可以执行一些定义和加载内容,如您所见):
irc = botOpenSocket()
joinRoom(irc)
readbuffer = ""
irc.send("CAP REQ :twitch.tv/membership\r\n")
irc.send("CAP REQ :twitch.tv/commands\r\n")
irc.send("CAP REQ :twitch.tv/tags\r\n")
try:
with file("commands.json","r") as commandsDatabase:
commands = json.load(commandsDatabase)
except IOError:
commands =
with file("commands.json","w") as commandsDatabase:
json.dump(commands, commandsDatabase)
globalcommands = "spank": True
moderatorcommands = "addcom": True, "delcom": True
stringspace = " "
nothing = ""
now = time.time()
cooldown = lambda: time.time() > now + 1
然后我希望它继续循环这段代码(忽略他们在葡萄牙语中的 cmets)(也是的,我知道我的代码不是最好的,我只是在学习):
while True:
readbuffer = readbuffer + irc.recv(1024)
temp = string.split(readbuffer, "\n")
readbuffer = temp.pop()
for line in temp:
###Essenciais###--------------------------------------------------------------------------------------------------------------------------------------------
#Mostra a linha que e dada pelo servidor de IRC (So pelo sim pelo nao).-----------------------------------------------------------------------
print (line)
#---------------------------------------------------------------------------------------------------------------------------------------------
#Impede que seja desconectado pelo servidor de IRC.-------------------------------------------------------------------------------------------
if line.startswith('PING'):
irc.send('PONG ' + line.split( ) [ 1 ] + '\r\n')
print "PONGED BACK"
break
#---------------------------------------------------------------------------------------------------------------------------------------------
#Le a linha que e dada pelo servidor de IRC e devevole o utilizador, a menssagem e o canal. Volta se algum for nulo.--------------------------
user = getUser(line)
message = getMessage(line)
channel = getChannel(line)
moderator = getModerator(line)
if channel == None or user == None or message == None:
break
#---------------------------------------------------------------------------------------------------------------------------------------------
#Formata o texto e mostra mostra na consola.--------------------------------------------------------------------------------------------------
print channel + ": " + user + " > " + message
#---------------------------------------------------------------------------------------------------------------------------------------------
###Essenciais END###----------------------------------------------------------------------------------------------------------------------------------------
if message == "!commands\r":
globalcommandskeys = str(globalcommands.keys()).replace("[", "").replace("]", "")
moderatorcommandskeys = str(moderatorcommands.keys()).replace("[", "").replace("]", "")
channelcommandskeys = str(commands.keys()).replace("[", "").replace("]", "")
sendMessage(irc, "Global commands: " + globalcommandskeys)
if channelcommandskeys != "":
sendMessage(irc, "Channel specific commands: " + channelcommandskeys )
if moderator == "1":
sendMessage(irc, "Moderator commands: " + moderatorcommandskeys)
break
if message.startswith("!addcom ") and (moderator == "1" or user == channel):
if message.count(" ") >= 2:
try:
commandadd = command_add(message)
answer = command_answer(message)
except IndexError:
sendMessage(irc, user + " the command is used this way !addcom !<command_name> <command_answer>")
break
if globalcommands.has_key(commandadd) or moderatorcommands.has_key(commandadd):
sendMessage(irc, user + " you can't add the command " + '"!' + commandadd + '" !!!')
break
try:
commands[commandadd]
except KeyError:
commands[commandadd] = answer
sendMessage(irc, user + " the command !" + commandadd + " has been added!!!")
with file("commands.json","w") as commandsDatabase:
json.dump(commands, commandsDatabase)
break
sendMessage(irc, user + " the command you tried to add alredy exists!!!")
break
sendMessage(irc, user + " the command is used this way !addcom !<command_name> <command_answer>")
break
if message.startswith("!delcom ") and (moderator == "1" or user == channel):
if message.count(" ") == 1:
try:
commanddel = command_del(message)
except IndexError:
sendMessage(irc, user + "the command is used this way !delcom !<command_name>")
break
if globalcommands.has_key(commanddel) or moderatorcommands.has_key(commanddel):
sendMessage(irc, user + " you can't delete the command " + '"!' + commanddel + '" !!!')
break
try:
commands[commanddel]
except KeyError:
sendMessage(irc, user + " the command you tried to delete doens't exist!!!")
break
del commands[commanddel]
sendMessage(irc, user + " the command !" + commanddel + " has been deleted!!!")
with file("commands.json","w") as commandsDatabase:
json.dump(commands, commandsDatabase)
break
sendMessage(irc, user + " the command is used this way !delcom !<command_name>")
break
if message.startswith("!"):
if cooldown() == True:
if message.count(" ") == 0:
try:
command = getCommand(message)
except IndexError:
break
try:
sendMessage(irc, commands[command])
now = time.time()
cooldown = lambda: time.time() > now + 10
except KeyError:
break
if message.count(" ") == 1:
try:
command = getCommandSpaced(message)
target = getString(message)
except IndexError:
break
try:
replacing = commands[command]
sendMessage(irc, replacing.replace("$target", target))
now = time.time()
cooldown = lambda: time.time() > now + 10
except KeyError:
break
break
最后,当按钮“向上”切换时,我想关闭套接字,以便机器人离开 irc 服务器:
irc.close()
我希望能够在不关闭和重新打开脚本的情况下完成上述所有操作。
所以问题是我不能这样做。
如果我放入主脚本(连接来自 GUI 的按钮信号的脚本),它将打破 gtk 主循环并且 GUI 将崩溃。
我尝试过使用线程,但我似乎不理解它们。
【问题讨论】:
所以您的选择是:1)使用已经与 mainlop 集成的第三方库。 2)重写你的使用 Gio 进行网络(与主循环集成)。 3)手动将普通套接字与主循环集成。 Twisted 是一个具有 GLib 主循环集成并处理 IRC 的库的示例。对于简单的机器人来说,这可能是一个不错的选择。 我已经对线程进行了足够深入的研究,并从另一个 *** 帖子中获得了一个线程示例。有了这一切,我能够让它工作。但仍然感谢您尝试帮助我。 【参考方案1】:状态更新我对线程进行了更多研究,并从另一个 *** 帖子中获得了一个线程示例并让它工作!
我创建了这个线程(请注意,在joinRoom(irc, self)
之后,如果连接成功,则套接字设置为非阻塞,否则它会执行loop.clear()
,这使它永远不会进入机器人主循环并直接进入irc.close()
) :
gobject.threads_init()
class T(threading.Thread):
loop = threading.Event()
stop = False
def start(self, *args):
super(T, self).start()
def run(self):
while not self.stop:
#Waits for button to be clicked.#
self.loop.wait()
#Bot Startup sequence.#
deploy_button.set_label('Disconnect')
irc = botOpenSocket()
joinRoom(irc, self)
readbuffer = ""
irc.send("CAP REQ :twitch.tv/membership\r\n")
irc.send("CAP REQ :twitch.tv/commands\r\n")
irc.send("CAP REQ :twitch.tv/tags\r\n")
try:
with file("commands.json","r") as commandsDatabase:
commands = json.load(commandsDatabase)
except IOError:
commands =
with file("commands.json","w") as commandsDatabase:
json.dump(commands, commandsDatabase)
globalcommands = "spank": True
moderatorcommands = "addcom": True, "delcom": True
stringspace = " "
nothing = ""
now = time.time()
cooldown = lambda: time.time() > now + 1
#Keeps reading chat and awsering.#
while self.loop.is_set():
try:
readbuffer = readbuffer + irc.recv(1024)
temp = string.split(readbuffer, "\n")
readbuffer = temp.pop()
except:
pass
else:
for line in temp:
###Essenciais###--------------------------------------------------------------------------------------------------------------------------------------------
#Mostra a linha que e dada pelo servidor de IRC (So pelo sim pelo nao).-----------------------------------------------------------------------
print (line)
#---------------------------------------------------------------------------------------------------------------------------------------------
#Impede que seja desconectado pelo servidor de IRC.-------------------------------------------------------------------------------------------
if line.startswith('PING'):
irc.send('PONG ' + line.split( ) [ 1 ] + '\r\n')
print "PONGED BACK"
break
#---------------------------------------------------------------------------------------------------------------------------------------------
#Le a linha que e dada pelo servidor de IRC e devevole o utilizador, a menssagem e o canal. Volta se algum for nulo.--------------------------
user = getUser(line)
message = getMessage(line)
channel = getChannel(line)
moderator = getModerator(line)
if channel == None or user == None or message == None:
break
#---------------------------------------------------------------------------------------------------------------------------------------------
#Formata o texto e mostra mostra na consola.--------------------------------------------------------------------------------------------------
print channel + ": " + user + " > " + message
#---------------------------------------------------------------------------------------------------------------------------------------------
###Essenciais END###----------------------------------------------------------------------------------------------------------------------------------------
if message == "!commands\r":
globalcommandskeys = str(globalcommands.keys()).replace("[", "").replace("]", "")
moderatorcommandskeys = str(moderatorcommands.keys()).replace("[", "").replace("]", "")
channelcommandskeys = str(commands.keys()).replace("[", "").replace("]", "")
sendMessage(irc, "Global commands: " + globalcommandskeys)
if channelcommandskeys != "":
sendMessage(irc, "Channel specific commands: " + channelcommandskeys )
if moderator == "1":
sendMessage(irc, "Moderator commands: " + moderatorcommandskeys)
break
if message.startswith("!addcom ") and (moderator == "1" or user == channel):
if message.count(" ") >= 2:
try:
commandadd = command_add(message)
answer = command_answer(message)
except IndexError:
sendMessage(irc, user + " the command is used this way !addcom !<command_name> <command_answer>")
break
if globalcommands.has_key(commandadd) or moderatorcommands.has_key(commandadd):
sendMessage(irc, user + " you can't add the command " + '"!' + commandadd + '" !!!')
break
try:
commands[commandadd]
except KeyError:
commands[commandadd] = answer
sendMessage(irc, user + " the command !" + commandadd + " has been added!!!")
with file("commands.json","w") as commandsDatabase:
json.dump(commands, commandsDatabase)
break
sendMessage(irc, user + " the command you tried to add alredy exists!!!")
break
sendMessage(irc, user + " the command is used this way !addcom !<command_name> <command_answer>")
break
if message.startswith("!delcom ") and (moderator == "1" or user == channel):
if message.count(" ") == 1:
try:
commanddel = command_del(message)
except IndexError:
sendMessage(irc, user + "the command is used this way !delcom !<command_name>")
break
if globalcommands.has_key(commanddel) or moderatorcommands.has_key(commanddel):
sendMessage(irc, user + " you can't delete the command " + '"!' + commanddel + '" !!!')
break
try:
commands[commanddel]
except KeyError:
sendMessage(irc, user + " the command you tried to delete doens't exist!!!")
break
del commands[commanddel]
sendMessage(irc, user + " the command !" + commanddel + " has been deleted!!!")
with file("commands.json","w") as commandsDatabase:
json.dump(commands, commandsDatabase)
break
sendMessage(irc, user + " the command is used this way !delcom !<command_name>")
break
if message.startswith("!"):
if cooldown() == True:
if message.count(" ") == 0:
try:
command = getCommand(message)
except IndexError:
break
try:
sendMessage(irc, commands[command])
now = time.time()
cooldown = lambda: time.time() > now + 10
except KeyError:
break
if message.count(" ") == 1:
try:
command = getCommandSpaced(message)
target = getString(message)
except IndexError:
break
try:
replacing = commands[command]
sendMessage(irc, replacing.replace("$target", target))
now = time.time()
cooldown = lambda: time.time() > now + 10
except KeyError:
break
break
#When button is clicked again do the shutdown sequence.#
print "coming here"
irc.close()
deploy_button.set_label('Connect')
#Waits for 0.1 seconds before going to the top again, just to be sure.#
time.sleep(0.1)
并创建了这个按钮(我改为普通按钮而不是切换按钮,因为我觉得它看起来更好,我很确定它也可以与切换按钮一起使用):
<object class="GtkToolButton" id="tool_deploy_button">
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Connect</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-jump-to</property>
<signal name="clicked" handler="on_tool_deploy_button_clicked" swapped="no"/>
</object>
并定义它:
#Defines builder and glade file.#
builder = gtk.Builder()
builder.add_from_file("GUI.glade")
#Gets the main widow and shows it.#
main_Window = builder.get_object("blasterbot_mainwindow")
main_Window.show_all()
#Gets some buttons.#
deploy_button = builder.get_object("tool_deploy_button")
#Starts the thread and the main loop.#
thread = T()
def bot_thread(*args):
if not thread.is_alive():
thread.start()
thread.loop.set()
#deploy_button.set_label('Disconnect') - Old Sutff
return
if thread.loop.is_set():
thread.loop.clear()
#deploy_button.set_label('Connect') - Old Sutff
else:
thread.loop.set()
#deploy_button.set_label('Disconnect') - Old Sutff
并连接处理程序:
#Handler Connection.#
handlers =
"on_blasterbot_mainwindow_destroy": gtk.main_quit,
"on_tool_deploy_button_clicked": bot_thread
builder.connect_signals(handlers)
#Stuff I know I need but don't know what is for.#
gtk.main()
【讨论】:
以上是关于用 gui 制作一个 irc 机器人。在切换按钮切换上断开连接的困难的主要内容,如果未能解决你的问题,请参考以下文章
Python3 webserver 在 IRC bot 的线程之间进行通信