Add new hook that treat all messages, not only PRIVMSG ; can respond with a response.Hook to create a hook
This commit is contained in:
parent
21f2af1cad
commit
dc52593953
11
DCC.py
11
DCC.py
@ -35,7 +35,6 @@ class DCC(server.Server):
|
|||||||
def __init__(self, srv, dest, socket=None):
|
def __init__(self, srv, dest, socket=None):
|
||||||
server.Server.__init__(self)
|
server.Server.__init__(self)
|
||||||
|
|
||||||
self.DCC = False
|
|
||||||
self.error = False # An error has occur, closing the connection?
|
self.error = False # An error has occur, closing the connection?
|
||||||
self.messages = list() # Message queued before connexion
|
self.messages = list() # Message queued before connexion
|
||||||
|
|
||||||
@ -132,9 +131,10 @@ class DCC(server.Server):
|
|||||||
if self.error:
|
if self.error:
|
||||||
self.srv.send_msg_final(self.nick, msg)
|
self.srv.send_msg_final(self.nick, msg)
|
||||||
elif not self.connected or self.s is None:
|
elif not self.connected or self.s is None:
|
||||||
if not self.DCC:
|
try:
|
||||||
self.DCC = True
|
|
||||||
self.start()
|
self.start()
|
||||||
|
except RuntimeError:
|
||||||
|
pass
|
||||||
self.messages.append(msg)
|
self.messages.append(msg)
|
||||||
else:
|
else:
|
||||||
for line in msg.split("\n"):
|
for line in msg.split("\n"):
|
||||||
@ -146,9 +146,10 @@ class DCC(server.Server):
|
|||||||
"""Send a file over DCC"""
|
"""Send a file over DCC"""
|
||||||
if os.path.isfile(filename):
|
if os.path.isfile(filename):
|
||||||
self.messages = filename
|
self.messages = filename
|
||||||
if not self.DCC:
|
try:
|
||||||
self.start()
|
self.start()
|
||||||
self.DCC = True
|
except RuntimeError:
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
print("File not found `%s'" % filename)
|
print("File not found `%s'" % filename)
|
||||||
|
|
||||||
|
30
IRCServer.py
30
IRCServer.py
@ -22,8 +22,9 @@ import socket
|
|||||||
import threading
|
import threading
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
import channel
|
from channel import Channel
|
||||||
from DCC import DCC
|
from DCC import DCC
|
||||||
|
from hooks import Hook
|
||||||
import message
|
import message
|
||||||
import server
|
import server
|
||||||
import xmlparser
|
import xmlparser
|
||||||
@ -56,7 +57,7 @@ class IRCServer(server.Server):
|
|||||||
|
|
||||||
self.channels = dict()
|
self.channels = dict()
|
||||||
for chn in self.node.getNodes("channel"):
|
for chn in self.node.getNodes("channel"):
|
||||||
chan = channel.Channel(chn, self)
|
chan = Channel(chn["name"], chn["password"])
|
||||||
self.channels[chan.name] = chan
|
self.channels[chan.name] = chan
|
||||||
|
|
||||||
|
|
||||||
@ -104,6 +105,23 @@ class IRCServer(server.Server):
|
|||||||
"""Gives the server identifiant"""
|
"""Gives the server identifiant"""
|
||||||
return self.host + ":" + str(self.port)
|
return self.host + ":" + str(self.port)
|
||||||
|
|
||||||
|
def register_hooks(self):
|
||||||
|
self.add_hook(Hook(self.evt_channel, "JOIN"))
|
||||||
|
self.add_hook(Hook(self.evt_channel, "PART"))
|
||||||
|
self.add_hook(Hook(self.evt_server, "NICK"))
|
||||||
|
self.add_hook(Hook(self.evt_server, "QUIT"))
|
||||||
|
self.add_hook(Hook(self.evt_channel, "332"))
|
||||||
|
self.add_hook(Hook(self.evt_channel, "353"))
|
||||||
|
|
||||||
|
def evt_server(self, msg, srv):
|
||||||
|
for chan in self.channels:
|
||||||
|
self.channels[chan].treat(msg.cmd, msg)
|
||||||
|
|
||||||
|
def evt_channel(self, msg, srv):
|
||||||
|
if msg.channel is not None:
|
||||||
|
if msg.channel in self.channels:
|
||||||
|
self.channels[msg.channel].treat(msg.cmd, msg)
|
||||||
|
|
||||||
def accepted_channel(self, chan, sender = None):
|
def accepted_channel(self, chan, sender = None):
|
||||||
"""Return True if the channel (or the user) is authorized"""
|
"""Return True if the channel (or the user) is authorized"""
|
||||||
if self.allow_all:
|
if self.allow_all:
|
||||||
@ -120,11 +138,7 @@ class IRCServer(server.Server):
|
|||||||
"""Join a channel"""
|
"""Join a channel"""
|
||||||
if force or (chan is not None and
|
if force or (chan is not None and
|
||||||
self.connected and chan not in self.channels):
|
self.connected and chan not in self.channels):
|
||||||
chn = xmlparser.module_state.ModuleState("channel")
|
self.channels[chan] = Channel(chan, password)
|
||||||
chn["name"] = chan
|
|
||||||
chn["password"] = password
|
|
||||||
self.node.addChild(chn)
|
|
||||||
self.channels[chan] = channel.Channel(chn, self)
|
|
||||||
if password is not None:
|
if password is not None:
|
||||||
self.s.send(("JOIN %s %s\r\n" % (chan, password)).encode())
|
self.s.send(("JOIN %s %s\r\n" % (chan, password)).encode())
|
||||||
else:
|
else:
|
||||||
@ -136,7 +150,7 @@ class IRCServer(server.Server):
|
|||||||
def leave(self, chan):
|
def leave(self, chan):
|
||||||
"""Leave a channel"""
|
"""Leave a channel"""
|
||||||
if chan is not None and self.connected and chan in self.channels:
|
if chan is not None and self.connected and chan in self.channels:
|
||||||
if chan.instanceof(list):
|
if isinstance(chan, list):
|
||||||
for c in chan:
|
for c in chan:
|
||||||
self.leave(c)
|
self.leave(c)
|
||||||
else:
|
else:
|
||||||
|
165
bot.py
165
bot.py
@ -21,6 +21,7 @@ from datetime import timedelta
|
|||||||
from queue import Queue
|
from queue import Queue
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
import re
|
||||||
|
|
||||||
import consumer
|
import consumer
|
||||||
import event
|
import event
|
||||||
@ -67,6 +68,10 @@ class Bot:
|
|||||||
self.cnsr_thrd = list()
|
self.cnsr_thrd = list()
|
||||||
self.cnsr_thrd_size = -1
|
self.cnsr_thrd_size = -1
|
||||||
|
|
||||||
|
self.hooks.add_hook("irc_hook",
|
||||||
|
hooks.Hook(self.treat_prvmsg, "PRIVMSG"),
|
||||||
|
self)
|
||||||
|
|
||||||
|
|
||||||
def init_ctcp_capabilities(self):
|
def init_ctcp_capabilities(self):
|
||||||
"""Reset existing CTCP capabilities to default one"""
|
"""Reset existing CTCP capabilities to default one"""
|
||||||
@ -98,7 +103,7 @@ class Bot:
|
|||||||
print ("DCC: unable to connect to %s:%s" % (ip, msg.cmds[4]))
|
print ("DCC: unable to connect to %s:%s" % (ip, msg.cmds[4]))
|
||||||
|
|
||||||
|
|
||||||
def add_event(self, evt, eid=None):
|
def add_event(self, evt, eid=None, module_src=None):
|
||||||
"""Register an event and return its identifiant for futur update"""
|
"""Register an event and return its identifiant for futur update"""
|
||||||
if eid is None:
|
if eid is None:
|
||||||
# Find an ID
|
# Find an ID
|
||||||
@ -123,18 +128,26 @@ class Bot:
|
|||||||
if len(self.events) <= 0 or self.events[i+1] != evt:
|
if len(self.events) <= 0 or self.events[i+1] != evt:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
if module_src is not None:
|
||||||
|
module_src.REGISTERED_EVENTS.append(evt.id)
|
||||||
|
|
||||||
return evt.id
|
return evt.id
|
||||||
|
|
||||||
def del_event(self, id):
|
def del_event(self, id, module_src=None):
|
||||||
"""Find and remove an event from list"""
|
"""Find and remove an event from list"""
|
||||||
if len(self.events) > 0 and id == self.events[0].id:
|
if len(self.events) > 0 and id == self.events[0].id:
|
||||||
self.events.remove(self.events[0])
|
self.events.remove(self.events[0])
|
||||||
self.update_timer()
|
self.update_timer()
|
||||||
|
if module_src is not None:
|
||||||
|
module_src.REGISTERED_EVENTS.remove(evt.id)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
for evt in self.events:
|
for evt in self.events:
|
||||||
if evt.id == id:
|
if evt.id == id:
|
||||||
self.events.remove(evt)
|
self.events.remove(evt)
|
||||||
|
|
||||||
|
if module_src is not None:
|
||||||
|
module_src.REGISTERED_EVENTS.remove(evt.id)
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -172,6 +185,8 @@ class Bot:
|
|||||||
def addServer(self, node, nick, owner, realname):
|
def addServer(self, node, nick, owner, realname):
|
||||||
"""Add a new server to the context"""
|
"""Add a new server to the context"""
|
||||||
srv = IRCServer(node, nick, owner, realname)
|
srv = IRCServer(node, nick, owner, realname)
|
||||||
|
srv.add_hook = lambda h: self.hooks.add_hook("irc_hook", h, self)
|
||||||
|
srv.register_hooks()
|
||||||
if srv.id not in self.servers:
|
if srv.id not in self.servers:
|
||||||
self.servers[srv.id] = srv
|
self.servers[srv.id] = srv
|
||||||
if srv.autoconnect:
|
if srv.autoconnect:
|
||||||
@ -326,24 +341,111 @@ class Bot:
|
|||||||
elif isinstance(store, list):
|
elif isinstance(store, list):
|
||||||
store.remove(hook)
|
store.remove(hook)
|
||||||
|
|
||||||
def treat_pre(self, msg):
|
def treat_pre(self, msg, srv):
|
||||||
"""Treat a message before all other treatment"""
|
"""Treat a message before all other treatment"""
|
||||||
for h, lvl, store in self.create_cache("all_pre"):
|
for h, lvl, store in self.create_cache("all_pre"):
|
||||||
h.run(self.create_cache, msg)
|
if h.is_matching(None, server=srv):
|
||||||
self.check_rest_times(store, h)
|
h.run(msg, self.create_cache)
|
||||||
|
self.check_rest_times(store, h)
|
||||||
|
|
||||||
|
|
||||||
def treat_post(self, msg):
|
def treat_post(self, res):
|
||||||
"""Treat a message before send"""
|
"""Treat a message before send"""
|
||||||
for h, lvl, store in self.create_cache("all_post"):
|
for h, lvl, store in self.create_cache("all_post"):
|
||||||
c = h.run(msg)
|
if h.is_matching(None, channel=res.channel, server=res.server):
|
||||||
self.check_rest_times(store, h)
|
c = h.run(msg)
|
||||||
if not c:
|
self.check_rest_times(store, h)
|
||||||
return False
|
if not c:
|
||||||
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def treat_cmd(self, msg):
|
def treat_irc(self, msg, srv):
|
||||||
|
"""Treat all incoming IRC commands"""
|
||||||
|
treated = list()
|
||||||
|
|
||||||
|
irc_hooks = self.create_cache("irc_hook")
|
||||||
|
if msg.cmd in irc_hooks:
|
||||||
|
(hks, lvl, store) = irc_hooks[msg.cmd]
|
||||||
|
for h in hks:
|
||||||
|
if h.is_matching(msg.cmd, server=srv):
|
||||||
|
res = h.run(msg, srv, msg.cmd)
|
||||||
|
if res is not None and res != False:
|
||||||
|
treated.append(res)
|
||||||
|
self.check_rest_times(store, h)
|
||||||
|
|
||||||
|
return treated
|
||||||
|
|
||||||
|
|
||||||
|
def treat_prvmsg_ask(self, msg, srv):
|
||||||
|
# Treat ping
|
||||||
|
if re.match("^ *(m[' ]?entends?[ -]+tu|h?ear me|do you copy|ping)",
|
||||||
|
msg.content, re.I) is not None:
|
||||||
|
return response.Response(msg.sender, message="pong",
|
||||||
|
channel=msg.channel, nick=msg.nick)
|
||||||
|
|
||||||
|
# Ask hooks
|
||||||
|
else:
|
||||||
|
return self.treat_ask(msg, srv)
|
||||||
|
|
||||||
|
def treat_prvmsg(self, msg, srv):
|
||||||
|
# First, treat CTCP
|
||||||
|
if msg.ctcp:
|
||||||
|
if msg.cmds[0] in self.ctcp_capabilities:
|
||||||
|
return self.ctcp_capabilities[msg.cmds[0]](srv, msg)
|
||||||
|
else:
|
||||||
|
return _ctcp_response(msg.sender, "ERRMSG Unknown or unimplemented CTCP request")
|
||||||
|
|
||||||
|
# Treat all messages starting with 'nemubot:' as distinct commands
|
||||||
|
elif msg.content.find("%s:"%srv.nick) == 0:
|
||||||
|
# Remove the bot name
|
||||||
|
msg.content = msg.content[len(srv.nick)+1:].strip()
|
||||||
|
|
||||||
|
return self.treat_prvmsg_ask(msg, srv)
|
||||||
|
|
||||||
|
# Owner commands
|
||||||
|
elif msg.content[0] == '`' and msg.nick == srv.owner:
|
||||||
|
#TODO: owner commands
|
||||||
|
pass
|
||||||
|
|
||||||
|
elif msg.content[0] == '!' and len(msg.content) > 1:
|
||||||
|
# Remove the !
|
||||||
|
msg.cmds[0] = msg.cmds[0][1:]
|
||||||
|
|
||||||
|
if msg.cmds[0] == "help":
|
||||||
|
return _help_msg(msg.sender)
|
||||||
|
|
||||||
|
elif msg.cmds[0] == "more":
|
||||||
|
if msg.channel == srv.nick:
|
||||||
|
if msg.sender in srv.moremessages:
|
||||||
|
return srv.moremessages[msg.sender]
|
||||||
|
else:
|
||||||
|
if msg.channel in srv.moremessages:
|
||||||
|
return srv.moremessages[msg.channel]
|
||||||
|
|
||||||
|
elif msg.cmds[0] == "dcc":
|
||||||
|
print("dcctest for", msg.sender)
|
||||||
|
srv.send_dcc("Hello %s!" % msg.nick, msg.sender)
|
||||||
|
elif msg.cmds[0] == "pvdcctest":
|
||||||
|
print("dcctest")
|
||||||
|
return Response(msg.sender, message="Test DCC")
|
||||||
|
elif msg.cmds[0] == "dccsendtest":
|
||||||
|
print("dccsendtest")
|
||||||
|
conn = DCC(srv, msg.sender)
|
||||||
|
conn.send_file("bot_sample.xml")
|
||||||
|
|
||||||
|
else:
|
||||||
|
return self.treat_cmd(msg, srv)
|
||||||
|
|
||||||
|
else:
|
||||||
|
res = self.treat_answer(msg, srv)
|
||||||
|
# Assume the message starts with nemubot:
|
||||||
|
if (res is None or len(res) <= 0) and msg.private:
|
||||||
|
return self.treat_prvmsg_ask(msg, srv)
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def treat_cmd(self, msg, srv):
|
||||||
"""Treat a command message"""
|
"""Treat a command message"""
|
||||||
treated = list()
|
treated = list()
|
||||||
|
|
||||||
@ -352,15 +454,16 @@ class Bot:
|
|||||||
if msg.cmds[0] in cmd_hook:
|
if msg.cmds[0] in cmd_hook:
|
||||||
(hks, lvl, store) = cmd_hook[msg.cmds[0]]
|
(hks, lvl, store) = cmd_hook[msg.cmds[0]]
|
||||||
for h in hks:
|
for h in hks:
|
||||||
res = h.run(msg)
|
if h.is_matching(msg.cmds[0], channel=msg.channel, server=srv):
|
||||||
if res is not None and res != False:
|
res = h.run(msg, strcmp=msg.cmds[0])
|
||||||
treated.append(res)
|
if res is not None and res != False:
|
||||||
self.check_rest_times(store, h)
|
treated.append(res)
|
||||||
|
self.check_rest_times(store, h)
|
||||||
|
|
||||||
# Then, treat regexp based hook
|
# Then, treat regexp based hook
|
||||||
cmd_rgxp = self.create_cache("cmd_rgxp")
|
cmd_rgxp = self.create_cache("cmd_rgxp")
|
||||||
for hook, lvl, store in cmd_rgxp:
|
for hook, lvl, store in cmd_rgxp:
|
||||||
if hook.is_matching(msg.cmds[0], msg.channel):
|
if hook.is_matching(msg.cmds[0], msg.channel, server=srv):
|
||||||
res = hook.run(msg)
|
res = hook.run(msg)
|
||||||
if res is not None and res != False:
|
if res is not None and res != False:
|
||||||
treated.append(res)
|
treated.append(res)
|
||||||
@ -378,7 +481,7 @@ class Bot:
|
|||||||
|
|
||||||
return treated
|
return treated
|
||||||
|
|
||||||
def treat_ask(self, msg):
|
def treat_ask(self, msg, srv):
|
||||||
"""Treat an ask message"""
|
"""Treat an ask message"""
|
||||||
treated = list()
|
treated = list()
|
||||||
|
|
||||||
@ -387,16 +490,17 @@ class Bot:
|
|||||||
if msg.content in ask_hook:
|
if msg.content in ask_hook:
|
||||||
hks, lvl, store = ask_hook[msg.content]
|
hks, lvl, store = ask_hook[msg.content]
|
||||||
for h in hks:
|
for h in hks:
|
||||||
res = h.run(msg)
|
if h.is_matching(msg.content, channel=msg.channel, server=srv):
|
||||||
if res is not None and res != False:
|
res = h.run(msg, strcmp=msg.content)
|
||||||
treated.append(res)
|
if res is not None and res != False:
|
||||||
self.check_rest_times(store, h)
|
treated.append(res)
|
||||||
|
self.check_rest_times(store, h)
|
||||||
|
|
||||||
# Then, treat regexp based hook
|
# Then, treat regexp based hook
|
||||||
ask_rgxp = self.create_cache("ask_rgxp")
|
ask_rgxp = self.create_cache("ask_rgxp")
|
||||||
for hook, lvl, store in ask_rgxp:
|
for hook, lvl, store in ask_rgxp:
|
||||||
if hook.is_matching(msg.content, msg.channel):
|
if hook.is_matching(msg.content, channel=msg.channel, server=srv):
|
||||||
res = hook.run(msg)
|
res = hook.run(msg, strcmp=msg.content)
|
||||||
if res is not None and res != False:
|
if res is not None and res != False:
|
||||||
treated.append(res)
|
treated.append(res)
|
||||||
self.check_rest_times(store, hook)
|
self.check_rest_times(store, hook)
|
||||||
@ -413,7 +517,7 @@ class Bot:
|
|||||||
|
|
||||||
return treated
|
return treated
|
||||||
|
|
||||||
def treat_answer(self, msg):
|
def treat_answer(self, msg, srv):
|
||||||
"""Treat a normal message"""
|
"""Treat a normal message"""
|
||||||
treated = list()
|
treated = list()
|
||||||
|
|
||||||
@ -422,16 +526,17 @@ class Bot:
|
|||||||
if msg.content in msg_hook:
|
if msg.content in msg_hook:
|
||||||
hks, lvl, store = msg_hook[msg.content]
|
hks, lvl, store = msg_hook[msg.content]
|
||||||
for h in hks:
|
for h in hks:
|
||||||
res = h.run(msg)
|
if h.is_matching(msg.content, channel=msg.channel, server=srv):
|
||||||
if res is not None and res != False:
|
res = h.run(msg, strcmp=msg.content)
|
||||||
treated.append(res)
|
if res is not None and res != False:
|
||||||
self.check_rest_times(store, h)
|
treated.append(res)
|
||||||
|
self.check_rest_times(store, h)
|
||||||
|
|
||||||
# Then, treat regexp based hook
|
# Then, treat regexp based hook
|
||||||
msg_rgxp = self.create_cache("msg_rgxp")
|
msg_rgxp = self.create_cache("msg_rgxp")
|
||||||
for hook, lvl, store in msg_rgxp:
|
for hook, lvl, store in msg_rgxp:
|
||||||
if hook.is_matching(msg.content, msg.channel):
|
if hook.is_matching(msg.content, channel=msg.channel, server=srv):
|
||||||
res = hook.run(msg)
|
res = hook.run(msg, strcmp=msg.content)
|
||||||
if res is not None and res != False:
|
if res is not None and res != False:
|
||||||
treated.append(res)
|
treated.append(res)
|
||||||
self.check_rest_times(store, hook)
|
self.check_rest_times(store, hook)
|
||||||
|
153
channel.py
153
channel.py
@ -1,71 +1,102 @@
|
|||||||
# coding=utf-8
|
# coding=utf-8
|
||||||
|
|
||||||
|
# Nemubot is a modulable IRC bot, built around XML configuration files.
|
||||||
|
# Copyright (C) 2012 Mercier Pierre-Olivier
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
class Channel:
|
class Channel:
|
||||||
def __init__(self, node, srv):
|
def __init__(self, name, password=None):
|
||||||
self.node = node
|
self.name = name
|
||||||
self.name = node["name"]
|
self.password = password
|
||||||
self.password = node["password"]
|
self.people = dict()
|
||||||
self.people = dict()
|
self.topic = ""
|
||||||
self.srv = srv
|
|
||||||
self.topic = ""
|
|
||||||
|
|
||||||
def join(self, nick, level = 0):
|
def treat(self, cmd, msg):
|
||||||
#print ("%s arrive sur %s" % (nick, self.name))
|
if cmd == "353":
|
||||||
self.people[nick] = level
|
self.parse353(msg)
|
||||||
|
elif cmd == "332":
|
||||||
|
self.parse332(msg)
|
||||||
|
elif cmd == "MODE":
|
||||||
|
self.mode(msg)
|
||||||
|
elif cmd == "JOIN":
|
||||||
|
self.join(msg.nick)
|
||||||
|
elif cmd == "NICK":
|
||||||
|
self.nick(msg.nick, msg.content)
|
||||||
|
elif cmd == "PART" or cmd == "QUIT":
|
||||||
|
self.part(msg.nick)
|
||||||
|
elif cmd == "TOPIC":
|
||||||
|
self.topic = self.content
|
||||||
|
|
||||||
def chtopic(self, newtopic):
|
def join(self, nick, level = 0):
|
||||||
"""Send command to change the topic"""
|
"""Someone join the channel"""
|
||||||
self.srv.send_msg(self.name, newtopic, "TOPIC")
|
#print ("%s arrive sur %s" % (nick, self.name))
|
||||||
self.topic = newtopic
|
self.people[nick] = level
|
||||||
|
|
||||||
def nick(self, oldnick, newnick):
|
def chtopic(self, newtopic):
|
||||||
#print ("%s change de nom pour %s" % (oldnick, newnick))
|
"""Send command to change the topic"""
|
||||||
if oldnick in self.people:
|
self.srv.send_msg(self.name, newtopic, "TOPIC")
|
||||||
lvl = self.people[oldnick]
|
self.topic = newtopic
|
||||||
del self.people[oldnick]
|
|
||||||
else:
|
|
||||||
lvl = 0
|
|
||||||
self.people[newnick] = lvl
|
|
||||||
|
|
||||||
def part(self, nick):
|
def nick(self, oldnick, newnick):
|
||||||
#print ("%s vient de quitter %s" % (self.sender, self.channel))
|
"""Someone change his nick"""
|
||||||
if nick in self.people:
|
if oldnick in self.people:
|
||||||
del self.people[nick]
|
#print ("%s change de nom pour %s sur %s" % (oldnick, newnick, self.name))
|
||||||
|
lvl = self.people[oldnick]
|
||||||
|
del self.people[oldnick]
|
||||||
|
self.people[newnick] = lvl
|
||||||
|
|
||||||
def mode(self, msg):
|
def part(self, nick):
|
||||||
if msg.content[0] == "-k":
|
"""Someone leave the channel"""
|
||||||
self.password = ""
|
if nick in self.people:
|
||||||
elif msg.content[0] == "+k":
|
#print ("%s vient de quitter %s" % (nick, self.name))
|
||||||
if len(msg.content) > 1:
|
del self.people[nick]
|
||||||
self.password = ' '.join(msg.content[1:])[1:]
|
|
||||||
else:
|
|
||||||
self.password = msg.content[1]
|
|
||||||
elif msg.content[0] == "+o":
|
|
||||||
self.people[msg.nick] |= 4
|
|
||||||
elif msg.content[0] == "-o":
|
|
||||||
self.people[msg.nick] &= ~4
|
|
||||||
elif msg.content[0] == "+h":
|
|
||||||
self.people[msg.nick] |= 2
|
|
||||||
elif msg.content[0] == "-h":
|
|
||||||
self.people[msg.nick] &= ~2
|
|
||||||
elif msg.content[0] == "+v":
|
|
||||||
self.people[msg.nick] |= 1
|
|
||||||
elif msg.content[0] == "-v":
|
|
||||||
self.people[msg.nick] &= ~1
|
|
||||||
|
|
||||||
def parse332(self, msg):
|
def mode(self, msg):
|
||||||
self.topic = msg.content
|
if msg.content[0] == "-k":
|
||||||
|
self.password = ""
|
||||||
|
elif msg.content[0] == "+k":
|
||||||
|
if len(msg.content) > 1:
|
||||||
|
self.password = ' '.join(msg.content[1:])[1:]
|
||||||
|
else:
|
||||||
|
self.password = msg.content[1]
|
||||||
|
elif msg.content[0] == "+o":
|
||||||
|
self.people[msg.nick] |= 4
|
||||||
|
elif msg.content[0] == "-o":
|
||||||
|
self.people[msg.nick] &= ~4
|
||||||
|
elif msg.content[0] == "+h":
|
||||||
|
self.people[msg.nick] |= 2
|
||||||
|
elif msg.content[0] == "-h":
|
||||||
|
self.people[msg.nick] &= ~2
|
||||||
|
elif msg.content[0] == "+v":
|
||||||
|
self.people[msg.nick] |= 1
|
||||||
|
elif msg.content[0] == "-v":
|
||||||
|
self.people[msg.nick] &= ~1
|
||||||
|
|
||||||
def parse353(self, msg):
|
def parse332(self, msg):
|
||||||
for p in msg.content:
|
self.topic = msg.content
|
||||||
p = p.decode()
|
|
||||||
if p[0] == "@":
|
def parse353(self, msg):
|
||||||
level = 4
|
for p in msg.content:
|
||||||
elif p[0] == "%":
|
p = p.decode()
|
||||||
level = 2
|
if p[0] == "@":
|
||||||
elif p[0] == "+":
|
level = 4
|
||||||
level = 1
|
elif p[0] == "%":
|
||||||
else:
|
level = 2
|
||||||
self.people[p] = 0
|
elif p[0] == "+":
|
||||||
continue
|
level = 1
|
||||||
self.people[p[1:]] = level
|
else:
|
||||||
|
self.join(p, 0)
|
||||||
|
continue
|
||||||
|
self.join(p[1:], level)
|
||||||
|
132
consumer.py
132
consumer.py
@ -25,7 +25,7 @@ import sys
|
|||||||
import bot
|
import bot
|
||||||
from DCC import DCC
|
from DCC import DCC
|
||||||
from message import Message
|
from message import Message
|
||||||
from response import Response
|
import response
|
||||||
import server
|
import server
|
||||||
|
|
||||||
class MessageConsumer:
|
class MessageConsumer:
|
||||||
@ -43,104 +43,48 @@ class MessageConsumer:
|
|||||||
if msg.cmd == "PING":
|
if msg.cmd == "PING":
|
||||||
self.srv.send_pong(msg.content)
|
self.srv.send_pong(msg.content)
|
||||||
else:
|
else:
|
||||||
# TODO: Manage credits here
|
# All messages
|
||||||
context.treat_pre(msg)
|
context.treat_pre(msg, self.srv)
|
||||||
|
|
||||||
if msg.cmd == "PRIVMSG" and msg.ctcp:
|
|
||||||
if msg.cmds[0] in context.ctcp_capabilities:
|
|
||||||
return context.ctcp_capabilities[msg.cmds[0]](self.srv, msg)
|
|
||||||
else:
|
|
||||||
return bot._ctcp_response(msg.sender, "ERRMSG Unknown or unimplemented CTCP request")
|
|
||||||
elif msg.cmd == "PRIVMSG" and self.srv.accepted_channel(msg.channel):
|
|
||||||
return self.treat_prvmsg(context, msg)
|
|
||||||
# TODO: continue here
|
|
||||||
pass
|
|
||||||
|
|
||||||
def treat_prvmsg_ask(self, context, msg):
|
|
||||||
# Treat ping
|
|
||||||
if re.match("^ *(m[' ]?entends?[ -]+tu|h?ear me|do you copy|ping)",
|
|
||||||
msg.content, re.I) is not None:
|
|
||||||
return Response(msg.sender, message="pong",
|
|
||||||
channel=msg.channel, nick=msg.nick)
|
|
||||||
|
|
||||||
# Ask hooks
|
|
||||||
else:
|
|
||||||
return context.treat_ask(msg)
|
|
||||||
|
|
||||||
def treat_prvmsg(self, context, msg):
|
|
||||||
# Treat all messages starting with 'nemubot:' as distinct commands
|
|
||||||
if msg.content.find("%s:"%self.srv.nick) == 0:
|
|
||||||
# Remove the bot name
|
|
||||||
msg.content = msg.content[len(self.srv.nick)+1:].strip()
|
|
||||||
|
|
||||||
return self.treat_prvmsg_ask(context, msg)
|
|
||||||
|
|
||||||
# Owner commands
|
|
||||||
elif msg.content[0] == '`' and msg.nick == self.srv.owner:
|
|
||||||
#TODO: owner commands
|
|
||||||
pass
|
|
||||||
|
|
||||||
elif msg.content[0] == '!' and len(msg.content) > 1:
|
|
||||||
# Remove the !
|
|
||||||
msg.cmds[0] = msg.cmds[0][1:]
|
|
||||||
|
|
||||||
if msg.cmds[0] == "help":
|
|
||||||
return _help_msg(msg.sender)
|
|
||||||
|
|
||||||
elif msg.cmds[0] == "more":
|
|
||||||
if msg.channel == self.srv.nick:
|
|
||||||
if msg.sender in self.srv.moremessages:
|
|
||||||
return self.srv.moremessages[msg.sender]
|
|
||||||
else:
|
|
||||||
if msg.channel in self.srv.moremessages:
|
|
||||||
return self.srv.moremessages[msg.channel]
|
|
||||||
|
|
||||||
elif msg.cmds[0] == "dcc":
|
|
||||||
print("dcctest for", msg.sender)
|
|
||||||
self.srv.send_dcc("Hello %s!" % msg.nick, msg.sender)
|
|
||||||
elif msg.cmds[0] == "pvdcctest":
|
|
||||||
print("dcctest")
|
|
||||||
return Response(msg.sender, message="Test DCC")
|
|
||||||
elif msg.cmds[0] == "dccsendtest":
|
|
||||||
print("dccsendtest")
|
|
||||||
conn = DCC(self.srv, msg.sender)
|
|
||||||
conn.send_file("bot_sample.xml")
|
|
||||||
|
|
||||||
else:
|
|
||||||
return context.treat_cmd(msg)
|
|
||||||
|
|
||||||
else:
|
|
||||||
res = context.treat_answer(msg)
|
|
||||||
# Assume the message starts with nemubot:
|
|
||||||
if (res is None or len(res) <= 0) and self.prvt:
|
|
||||||
return self.treat_prvmsg_ask(context, msg)
|
|
||||||
return res
|
|
||||||
|
|
||||||
|
# TODO: Manage credits
|
||||||
|
return context.treat_irc(msg, self.srv)
|
||||||
|
|
||||||
def treat_out(self, context, res):
|
def treat_out(self, context, res):
|
||||||
"""Treat the output message"""
|
"""Treat the output message"""
|
||||||
|
if isinstance(res, list):
|
||||||
|
for r in res:
|
||||||
|
if r is not None: self.treat_out(context, r)
|
||||||
|
|
||||||
|
elif isinstance(res, response.Response):
|
||||||
# Define the destination server
|
# Define the destination server
|
||||||
if (res.server is not None and
|
if (res.server is not None and
|
||||||
res.server.instanceof(string) and res.server in context.servers):
|
isinstance(res.server, str) and res.server in context.servers):
|
||||||
res.server = context.servers[res.server]
|
res.server = context.servers[res.server]
|
||||||
if (res.server is not None and
|
if (res.server is not None and
|
||||||
not res.server.instanceof(server.Server)):
|
not isinstance(res.server, server.Server)):
|
||||||
print ("\033[1;35mWarning:\033[0m the server defined in this "
|
print ("\033[1;35mWarning:\033[0m the server defined in this "
|
||||||
"response doesn't exist: %s" % (res.server))
|
"response doesn't exist: %s" % (res.server))
|
||||||
res.server = None
|
res.server = None
|
||||||
if res.server is None:
|
if res.server is None:
|
||||||
res.server = self.srv
|
res.server = self.srv
|
||||||
|
|
||||||
# Sent the message only if treat_post authorize it
|
# Sent the message only if treat_post authorize it
|
||||||
if context.treat_post(res):
|
if context.treat_post(res):
|
||||||
res.server.send_response(res, self.data)
|
res.server.send_response(res, self.data)
|
||||||
|
|
||||||
|
elif isinstance(res, response.Hook):
|
||||||
|
context.hooks.add_hook(res.type, res.hook, res.src)
|
||||||
|
|
||||||
|
elif res is not None:
|
||||||
|
print ("\033[1;35mWarning:\033[0m unrecognized response type "
|
||||||
|
": %s" % res)
|
||||||
|
|
||||||
def run(self, context):
|
def run(self, context):
|
||||||
"""Create, parse and treat the message"""
|
"""Create, parse and treat the message"""
|
||||||
try:
|
try:
|
||||||
msg = Message(self.raw, self.time, self.prvt)
|
msg = Message(self.raw, self.time, self.prvt)
|
||||||
msg.is_owner = (msg.nick == self.srv.owner)
|
if msg.cmd == "PRIVMSG":
|
||||||
|
msg.is_owner = (msg.nick == self.srv.owner)
|
||||||
res = self.treat_in(context, msg)
|
res = self.treat_in(context, msg)
|
||||||
except:
|
except:
|
||||||
print ("\033[1;31mERROR:\033[0m occurred during the "
|
print ("\033[1;31mERROR:\033[0m occurred during the "
|
||||||
@ -151,17 +95,7 @@ class MessageConsumer:
|
|||||||
return
|
return
|
||||||
|
|
||||||
# Send message
|
# Send message
|
||||||
if res is not None:
|
self.treat_out(context, res)
|
||||||
if isinstance(res, list):
|
|
||||||
for r in res:
|
|
||||||
if isinstance(r, Response):
|
|
||||||
self.treat_out(context, r)
|
|
||||||
elif isinstance(r, list):
|
|
||||||
for s in r:
|
|
||||||
if isinstance(s, Response):
|
|
||||||
self.treat_out(context, s)
|
|
||||||
elif isinstance(res, Response):
|
|
||||||
self.treat_out(context, res)
|
|
||||||
|
|
||||||
# Inform that the message has been treated
|
# Inform that the message has been treated
|
||||||
self.srv.msg_treated(self.data)
|
self.srv.msg_treated(self.data)
|
||||||
@ -210,7 +144,7 @@ class Consumer(threading.Thread):
|
|||||||
|
|
||||||
def _help_msg(modules, sndr, cmd):
|
def _help_msg(modules, sndr, cmd):
|
||||||
"""Parse and response to help messages"""
|
"""Parse and response to help messages"""
|
||||||
res = Response(sndr)
|
res = response.Response(sndr)
|
||||||
if len(cmd) > 1:
|
if len(cmd) > 1:
|
||||||
if cmd[1] in modules:
|
if cmd[1] in modules:
|
||||||
if len(cmd) > 2:
|
if len(cmd) > 2:
|
||||||
|
70
hooks.py
70
hooks.py
@ -22,16 +22,19 @@ class MessagesHook:
|
|||||||
def __init__(self, context):
|
def __init__(self, context):
|
||||||
self.context = context
|
self.context = context
|
||||||
|
|
||||||
# Store specials hook
|
# Store specials hooks
|
||||||
self.all_pre = list() # Treated before any parse
|
self.all_pre = list() # Treated before any parse
|
||||||
self.all_post = list() # Treated before send message to user
|
self.all_post = list() # Treated before send message to user
|
||||||
|
|
||||||
# Store direct hook
|
# Store IRC commands hooks
|
||||||
|
self.irc_hook = dict()
|
||||||
|
|
||||||
|
# Store direct hooks
|
||||||
self.cmd_hook = dict()
|
self.cmd_hook = dict()
|
||||||
self.ask_hook = dict()
|
self.ask_hook = dict()
|
||||||
self.msg_hook = dict()
|
self.msg_hook = dict()
|
||||||
|
|
||||||
# Store regexp hook
|
# Store regexp hooks
|
||||||
self.cmd_rgxp = list()
|
self.cmd_rgxp = list()
|
||||||
self.ask_rgxp = list()
|
self.ask_rgxp = list()
|
||||||
self.msg_rgxp = list()
|
self.msg_rgxp = list()
|
||||||
@ -61,12 +64,16 @@ class MessagesHook:
|
|||||||
if hook.name not in attr:
|
if hook.name not in attr:
|
||||||
attr[hook.name] = list()
|
attr[hook.name] = list()
|
||||||
attr[hook.name].append(hook)
|
attr[hook.name].append(hook)
|
||||||
|
if hook.end is not None:
|
||||||
|
if hook.end not in attr:
|
||||||
|
attr[hook.end] = list()
|
||||||
|
attr[hook.end].append(hook)
|
||||||
elif isinstance(attr, list):
|
elif isinstance(attr, list):
|
||||||
attr.append(hook)
|
attr.append(hook)
|
||||||
else:
|
else:
|
||||||
print ("\033[1;32mWarning:\033[0m unrecognized hook store type")
|
print ("\033[1;32mWarning:\033[0m unrecognized hook store type")
|
||||||
return
|
return
|
||||||
if module_src is not None:
|
if module_src is not None and hasattr(module_src, "REGISTERED_HOOKS"):
|
||||||
module_src.REGISTERED_HOOKS.append((store, hook))
|
module_src.REGISTERED_HOOKS.append((store, hook))
|
||||||
|
|
||||||
def register_hook_attributes(self, store, module, node):
|
def register_hook_attributes(self, store, module, node):
|
||||||
@ -92,7 +99,7 @@ class MessagesHook:
|
|||||||
node["type"] == "all"):
|
node["type"] == "all"):
|
||||||
self.register_hook_attributes("answer", module, node)
|
self.register_hook_attributes("answer", module, node)
|
||||||
|
|
||||||
def del_hook(self, store, hook):
|
def del_hook(self, store, hook, module_src=None):
|
||||||
"""Remove a registered hook from a given store"""
|
"""Remove a registered hook from a given store"""
|
||||||
if store in self.context.hooks_cache:
|
if store in self.context.hooks_cache:
|
||||||
del self.context.hooks_cache[store]
|
del self.context.hooks_cache[store]
|
||||||
@ -105,33 +112,68 @@ class MessagesHook:
|
|||||||
if isinstance(attr, dict) and hook.name is not None:
|
if isinstance(attr, dict) and hook.name is not None:
|
||||||
if hook.name in attr:
|
if hook.name in attr:
|
||||||
attr[hook.name].remove(hook)
|
attr[hook.name].remove(hook)
|
||||||
|
if hook.end is not None and hook.end in attr:
|
||||||
|
attr[hook.end].remove(hook)
|
||||||
else:
|
else:
|
||||||
attr.remove(hook)
|
attr.remove(hook)
|
||||||
|
|
||||||
|
if module_src is not None:
|
||||||
|
module_src.REGISTERED_HOOKS.remove((store, hook))
|
||||||
|
|
||||||
|
|
||||||
class Hook:
|
class Hook:
|
||||||
"""Class storing hook informations"""
|
"""Class storing hook informations"""
|
||||||
def __init__(self, call, name=None, data=None, regexp=None, channels=list()):
|
def __init__(self, call, name=None, data=None, regexp=None, channels=list(), server=None, end=None, call_end=None):
|
||||||
self.name = name
|
self.name = name
|
||||||
|
self.end = end
|
||||||
self.call = call
|
self.call = call
|
||||||
|
if call_end is None:
|
||||||
|
self.call_end = self.call
|
||||||
|
else:
|
||||||
|
self.call_end = call_end
|
||||||
self.regexp = regexp
|
self.regexp = regexp
|
||||||
self.data = data
|
self.data = data
|
||||||
self.times = -1
|
self.times = -1
|
||||||
|
self.server = server
|
||||||
self.channels = channels
|
self.channels = channels
|
||||||
|
|
||||||
def is_matching(self, strcmp, channel):
|
def is_matching(self, strcmp, channel=None, server=None):
|
||||||
"""Test if the current hook correspond to the message"""
|
"""Test if the current hook correspond to the message"""
|
||||||
return (len(self.channel) <= 0 or channel in self.channels) and (
|
return (channel is None or len(self.channels) <= 0 or
|
||||||
|
channel in self.channels) and (server is None or
|
||||||
|
self.server is None or self.server == server) and (
|
||||||
(self.name is not None and strcmp == self.name) or (
|
(self.name is not None and strcmp == self.name) or (
|
||||||
|
self.end is not None and strcmp == self.end) or (
|
||||||
self.regexp is not None and re.match(self.regexp, strcmp)))
|
self.regexp is not None and re.match(self.regexp, strcmp)))
|
||||||
|
|
||||||
def run(self, msg):
|
def run(self, msg, data2=None, strcmp=None):
|
||||||
"""Run the hook"""
|
"""Run the hook"""
|
||||||
if self.times != 0:
|
if self.times != 0:
|
||||||
self.times -= 1
|
self.times -= 1
|
||||||
|
|
||||||
if self.data is None:
|
if (self.end is not None and strcmp is not None and
|
||||||
return self.call(msg)
|
self.call_end is not None and strcmp == self.end):
|
||||||
elif isinstance(self.data, dict):
|
call = self.call_end
|
||||||
return self.call(msg, **self.data)
|
self.times = 0
|
||||||
else:
|
else:
|
||||||
return self.call(msg, self.data)
|
call = self.call
|
||||||
|
|
||||||
|
if self.data is None:
|
||||||
|
if data2 is None:
|
||||||
|
return call(msg)
|
||||||
|
elif isinstance(data2, dict):
|
||||||
|
return call(msg, **data2)
|
||||||
|
else:
|
||||||
|
return call(msg, data2)
|
||||||
|
elif isinstance(self.data, dict):
|
||||||
|
if data2 is None:
|
||||||
|
return call(msg, **self.data)
|
||||||
|
else:
|
||||||
|
return call(msg, data2, **self.data)
|
||||||
|
else:
|
||||||
|
if data2 is None:
|
||||||
|
return call(msg, self.data)
|
||||||
|
elif isinstance(data2, dict):
|
||||||
|
return call(msg, self.data, **data2)
|
||||||
|
else:
|
||||||
|
return call(msg, self.data, data2)
|
||||||
|
@ -145,6 +145,7 @@ class ModuleLoader(SourceLoader):
|
|||||||
|
|
||||||
# Set module common functions and datas
|
# Set module common functions and datas
|
||||||
module.REGISTERED_HOOKS = list()
|
module.REGISTERED_HOOKS = list()
|
||||||
|
module.REGISTERED_EVENTS = list()
|
||||||
module.DEBUG = False
|
module.DEBUG = False
|
||||||
module.DIR = self.mpath
|
module.DIR = self.mpath
|
||||||
module.name = fullname
|
module.name = fullname
|
||||||
@ -152,6 +153,10 @@ class ModuleLoader(SourceLoader):
|
|||||||
module.print_debug = lambda msg: mod_print_dbg(module, msg)
|
module.print_debug = lambda msg: mod_print_dbg(module, msg)
|
||||||
module.send_response = lambda srv, res: mod_send_response(self.context, srv, res)
|
module.send_response = lambda srv, res: mod_send_response(self.context, srv, res)
|
||||||
module.add_hook = lambda store, hook: self.context.hooks.add_hook(store, hook, module)
|
module.add_hook = lambda store, hook: self.context.hooks.add_hook(store, hook, module)
|
||||||
|
module.del_hook = lambda store, hook: self.context.hooks.del_hook(store, hook)
|
||||||
|
module.add_event = lambda evt: self.context.add_event(evt, module_src=module)
|
||||||
|
module.add_event_eid = lambda evt, eid: self.context.add_event(evt, eid, module_src=module)
|
||||||
|
module.del_event = lambda evt: self.context.add_event(evt, module_src=module)
|
||||||
|
|
||||||
if not hasattr(module, "NODATA"):
|
if not hasattr(module, "NODATA"):
|
||||||
module.DATAS = xmlparser.parse_file(self.context.datas_path
|
module.DATAS = xmlparser.parse_file(self.context.datas_path
|
||||||
|
27
message.py
27
message.py
@ -105,8 +105,8 @@ class Message:
|
|||||||
def parse_content(self):
|
def parse_content(self):
|
||||||
"""Parse or reparse the message content"""
|
"""Parse or reparse the message content"""
|
||||||
# If CTCP, remove 0x01
|
# If CTCP, remove 0x01
|
||||||
#if self.ctcp:
|
if self.ctcp:
|
||||||
# self.content = self.content[1:len(self.content)-1]
|
self.content = self.content[1:len(self.content)-1]
|
||||||
|
|
||||||
# Split content by words
|
# Split content by words
|
||||||
try:
|
try:
|
||||||
@ -146,29 +146,6 @@ class Message:
|
|||||||
return False
|
return False
|
||||||
return self.srv.accepted_channel(self.channel)
|
return self.srv.accepted_channel(self.channel)
|
||||||
|
|
||||||
def treat(self):
|
|
||||||
"""Parse and treat the message"""
|
|
||||||
if self.channel in self.srv.channels:
|
|
||||||
if self.cmd == "353":
|
|
||||||
self.srv.channels[self.channel].parse353(self)
|
|
||||||
elif self.cmd == "332":
|
|
||||||
self.srv.channels[self.channel].parse332(self)
|
|
||||||
elif self.cmd == "MODE":
|
|
||||||
self.srv.channels[self.channel].mode(self)
|
|
||||||
elif self.cmd == "JOIN":
|
|
||||||
self.srv.channels[self.channel].join(self.nick)
|
|
||||||
elif self.cmd == "PART":
|
|
||||||
self.srv.channels[self.channel].part(self.nick)
|
|
||||||
elif self.cmd == "TOPIC":
|
|
||||||
self.srv.channels[self.channel].topic = self.content
|
|
||||||
elif self.cmd == "NICK":
|
|
||||||
for chn in self.srv.channels.keys():
|
|
||||||
self.srv.channels[chn].nick(self.nick, self.content)
|
|
||||||
elif self.cmd == "QUIT":
|
|
||||||
for chn in self.srv.channels.keys():
|
|
||||||
self.srv.channels[chn].part(self.nick)
|
|
||||||
return None
|
|
||||||
|
|
||||||
##############################
|
##############################
|
||||||
# #
|
# #
|
||||||
# Extraction/Format text #
|
# Extraction/Format text #
|
||||||
|
10
response.py
10
response.py
@ -154,3 +154,13 @@ class Response:
|
|||||||
self.pop()
|
self.pop()
|
||||||
self.elt = 0
|
self.elt = 0
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
|
import hooks
|
||||||
|
class Hook:
|
||||||
|
def __init__(self, TYPE, call, name=None, data=None, regexp=None,
|
||||||
|
channels=list(), server=None, end=None, call_end=None,
|
||||||
|
SRC=None):
|
||||||
|
self.hook = hooks.Hook(call, name, data, regexp, channels,
|
||||||
|
server, end, call_end)
|
||||||
|
self.type = TYPE
|
||||||
|
self.src = SRC
|
||||||
|
@ -144,7 +144,10 @@ class Server(threading.Thread):
|
|||||||
self._receive_action = receive_action
|
self._receive_action = receive_action
|
||||||
if not self.connected:
|
if not self.connected:
|
||||||
self.stop = False
|
self.stop = False
|
||||||
self.start()
|
try:
|
||||||
|
self.start()
|
||||||
|
except RuntimeError:
|
||||||
|
pass
|
||||||
elif verb:
|
elif verb:
|
||||||
print (" Already connected.")
|
print (" Already connected.")
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user