2012-04-30 16:22:10 +00:00
|
|
|
import sys
|
|
|
|
import traceback
|
2012-04-09 02:19:39 +00:00
|
|
|
import socket
|
2012-05-21 10:21:14 +00:00
|
|
|
import threading
|
2012-04-09 02:19:39 +00:00
|
|
|
import time
|
2012-05-21 16:14:33 +00:00
|
|
|
import imp
|
2012-04-09 02:19:39 +00:00
|
|
|
|
2012-05-21 16:14:33 +00:00
|
|
|
message = __import__("message")
|
|
|
|
imp.reload(message)
|
2012-06-23 13:14:36 +00:00
|
|
|
channel = __import__("channel")
|
|
|
|
imp.reload(channel)
|
2012-04-09 02:19:39 +00:00
|
|
|
|
2012-05-21 10:21:14 +00:00
|
|
|
class Server(threading.Thread):
|
2012-06-23 11:38:34 +00:00
|
|
|
def __init__(self, node, nick, owner, realname, socket = None):
|
2012-05-21 10:21:14 +00:00
|
|
|
self.stop = False
|
|
|
|
self.stopping = threading.Event()
|
2012-04-09 02:19:39 +00:00
|
|
|
self.nick = nick
|
|
|
|
self.owner = owner
|
|
|
|
self.realname = realname
|
2012-06-23 11:38:34 +00:00
|
|
|
self.s = socket
|
|
|
|
self.connected = self.s is not None
|
|
|
|
self.node = node
|
2012-04-09 02:19:39 +00:00
|
|
|
|
2012-04-30 16:22:10 +00:00
|
|
|
self.listen_nick = True
|
|
|
|
|
2012-06-23 13:14:36 +00:00
|
|
|
self.channels = dict()
|
|
|
|
for chn in node.getNodes("channel"):
|
|
|
|
chan = channel.Channel(chn)
|
|
|
|
self.channels[chan.name] = chan
|
2012-04-09 02:19:39 +00:00
|
|
|
|
2012-05-21 10:21:14 +00:00
|
|
|
threading.Thread.__init__(self)
|
|
|
|
|
2012-06-23 11:38:34 +00:00
|
|
|
@property
|
|
|
|
def host(self):
|
|
|
|
if self.node.hasAttribute("server"):
|
|
|
|
return self.node["server"]
|
|
|
|
else:
|
|
|
|
return "localhost"
|
|
|
|
|
|
|
|
@property
|
|
|
|
def port(self):
|
|
|
|
if self.node.hasAttribute("port"):
|
|
|
|
return self.node.getInt("port")
|
|
|
|
else:
|
|
|
|
return "6667"
|
|
|
|
|
|
|
|
@property
|
|
|
|
def password(self):
|
|
|
|
if self.node.hasAttribute("password"):
|
|
|
|
return self.node["password"]
|
|
|
|
else:
|
|
|
|
return None
|
|
|
|
|
|
|
|
@property
|
|
|
|
def partner(self):
|
|
|
|
if self.node.hasAttribute("partner"):
|
|
|
|
return self.node["partner"]
|
|
|
|
else:
|
|
|
|
return None
|
|
|
|
|
2012-06-28 23:02:15 +00:00
|
|
|
@property
|
|
|
|
def autoconnect(self):
|
|
|
|
if self.node.hasAttribute("autoconnect"):
|
|
|
|
value = self.node["autoconnect"].lower()
|
|
|
|
return value != "no" and value != "off" and value != "false"
|
|
|
|
else:
|
|
|
|
return False
|
|
|
|
|
2012-05-14 15:50:11 +00:00
|
|
|
@property
|
|
|
|
def id(self):
|
|
|
|
return self.host + ":" + str(self.port)
|
|
|
|
|
2012-05-21 16:14:33 +00:00
|
|
|
def send_ctcp_response(self, me, to, msg, cmd = "NOTICE", endl = "\r\n"):
|
|
|
|
if msg is not None and channel is not None:
|
|
|
|
for line in msg.split("\n"):
|
|
|
|
if line != "":
|
|
|
|
self.s.send ((":%s %s %s :%s%s" % (me, cmd, to, line, endl)).encode ())
|
|
|
|
|
2012-04-30 16:22:10 +00:00
|
|
|
def send_msg_final(self, channel, msg, cmd = "PRIVMSG", endl = "\r\n"):
|
2012-06-23 11:38:34 +00:00
|
|
|
if channel == self.nick:
|
|
|
|
print ("\033[1;35mWarning:\033[0m Nemubot talks to himself: %s" % msg)
|
2012-04-18 21:35:58 +00:00
|
|
|
if msg is not None and channel is not None:
|
|
|
|
for line in msg.split("\n"):
|
2012-04-30 16:22:10 +00:00
|
|
|
if line != "":
|
2012-04-18 21:35:58 +00:00
|
|
|
self.s.send (("%s %s :%s%s" % (cmd, channel, line, endl)).encode ())
|
2012-04-09 02:19:39 +00:00
|
|
|
|
2012-05-14 15:50:11 +00:00
|
|
|
def send_msg_prtn (self, msg):
|
|
|
|
self.send_msg_final(self.partner, msg)
|
|
|
|
|
2012-04-30 16:22:10 +00:00
|
|
|
def send_msg_usr (self, user, msg):
|
|
|
|
if user is not None and user[0] != "#":
|
|
|
|
self.send_msg_final(user, msg)
|
|
|
|
|
2012-04-09 02:19:39 +00:00
|
|
|
def send_msg (self, channel, msg, cmd = "PRIVMSG", endl = "\r\n"):
|
2012-04-30 16:22:10 +00:00
|
|
|
if self.accepted_channel(channel):
|
|
|
|
self.send_msg_final(channel, msg, cmd, endl)
|
2012-04-09 02:19:39 +00:00
|
|
|
|
|
|
|
def send_global (self, msg, cmd = "PRIVMSG", endl = "\r\n"):
|
2012-06-23 13:14:36 +00:00
|
|
|
for channel in self.channels.keys():
|
2012-04-18 21:35:58 +00:00
|
|
|
self.send_msg (channel, msg, cmd, endl)
|
2012-04-09 02:19:39 +00:00
|
|
|
|
|
|
|
|
2012-06-23 13:14:36 +00:00
|
|
|
def accepted_channel(self, chan):
|
2012-04-30 16:22:10 +00:00
|
|
|
if self.listen_nick:
|
2012-06-23 13:14:36 +00:00
|
|
|
return chan in self.channels or chan == self.nick
|
2012-04-30 16:22:10 +00:00
|
|
|
else:
|
2012-06-23 13:14:36 +00:00
|
|
|
return chan in self.channels
|
2012-04-09 02:19:39 +00:00
|
|
|
|
2012-05-21 10:21:14 +00:00
|
|
|
def disconnect(self):
|
|
|
|
if self.connected:
|
|
|
|
self.stop = True
|
|
|
|
self.s.shutdown(socket.SHUT_RDWR)
|
|
|
|
self.stopping.wait()
|
|
|
|
return True
|
|
|
|
else:
|
|
|
|
return False
|
|
|
|
|
2012-06-23 11:38:34 +00:00
|
|
|
def kill(self):
|
|
|
|
if self.connected:
|
|
|
|
self.stop = True
|
|
|
|
self.connected = False
|
|
|
|
#Send a message in order to close the socket
|
|
|
|
self.s.send(("WHO %s\r\n" % self.nick).encode ())
|
|
|
|
self.stopping.wait()
|
|
|
|
return True
|
|
|
|
else:
|
|
|
|
return False
|
|
|
|
|
2012-06-23 13:14:36 +00:00
|
|
|
def join(self, chan, password = None):
|
|
|
|
if chan is not None and self.connected and chan not in self.channels:
|
|
|
|
chn = xmlparser.module_state.Module_State("channel")
|
|
|
|
chn["name"] = chan
|
|
|
|
chn["password"] = password
|
|
|
|
self.node.addChild(chn)
|
|
|
|
self.channels[chan] = channel.Channel(chn)
|
|
|
|
if password is not None:
|
|
|
|
self.s.send(("JOIN %s %s\r\n" % (chan, password)).encode ())
|
|
|
|
else:
|
|
|
|
self.s.send(("JOIN %s\r\n" % chan).encode ())
|
2012-05-21 17:08:41 +00:00
|
|
|
return True
|
|
|
|
else:
|
|
|
|
return False
|
|
|
|
|
2012-06-23 13:14:36 +00:00
|
|
|
def leave(self, chan):
|
|
|
|
if chan is not None and self.connected and chan in self.channels:
|
|
|
|
self.s.send(("PART %s\r\n" % self.channels[chan].name).encode ())
|
|
|
|
del self.channels[chan]
|
2012-05-21 17:08:41 +00:00
|
|
|
return True
|
|
|
|
else:
|
|
|
|
return False
|
|
|
|
|
2012-05-30 09:58:27 +00:00
|
|
|
def update_mods(self, mods):
|
|
|
|
self.mods = mods
|
|
|
|
|
2012-05-21 10:21:14 +00:00
|
|
|
def launch(self, mods):
|
|
|
|
if not self.connected:
|
|
|
|
self.stop = False
|
|
|
|
self.mods = mods
|
|
|
|
self.start()
|
|
|
|
else:
|
|
|
|
print (" Already connected.")
|
2012-04-09 02:19:39 +00:00
|
|
|
|
2012-05-21 10:21:14 +00:00
|
|
|
def run(self):
|
2012-06-23 11:38:34 +00:00
|
|
|
if not self.connected:
|
|
|
|
self.s = socket.socket() #Create the socket
|
|
|
|
self.s.connect((self.host, self.port)) #Connect to server
|
|
|
|
self.stopping.clear()
|
|
|
|
self.connected = True
|
|
|
|
|
|
|
|
if self.password != None:
|
|
|
|
self.s.send(b"PASS " + self.password.encode () + b"\r\n")
|
|
|
|
self.s.send(("NICK %s\r\n" % self.nick).encode ())
|
|
|
|
self.s.send(("USER %s %s bla :%s\r\n" % (self.nick, self.host, self.realname)).encode ())
|
|
|
|
print ("Connection to %s:%d completed" % (self.host, self.port))
|
|
|
|
|
|
|
|
if len(self.channels) > 0:
|
2012-06-23 13:14:36 +00:00
|
|
|
for chn in self.channels.keys():
|
|
|
|
if self.channels[chn].password is not None:
|
|
|
|
self.s.send(("JOIN %s %s\r\n" % (self.channels[chn].name, self.channels[chn].password)).encode ())
|
|
|
|
else:
|
|
|
|
self.s.send(("JOIN %s\r\n" % self.channels[chn].name).encode ())
|
|
|
|
print ("Listen to channels: %s" % ' '.join (self.channels.keys()))
|
2012-04-09 02:19:39 +00:00
|
|
|
|
2012-05-21 10:21:14 +00:00
|
|
|
readbuffer = "" #Here we store all the messages from server
|
|
|
|
while not self.stop:
|
|
|
|
try:
|
2012-06-16 20:45:20 +00:00
|
|
|
raw = self.s.recv(1024) #recieve server messages
|
|
|
|
data = raw.decode()
|
|
|
|
if not data:
|
|
|
|
break
|
2012-05-21 10:21:14 +00:00
|
|
|
except UnicodeDecodeError:
|
2012-06-16 20:45:20 +00:00
|
|
|
try:
|
|
|
|
data = raw.decode("utf-8", "replace")
|
|
|
|
except UnicodeDecodeError:
|
|
|
|
print ("\033[1;31mERROR:\033[0m while decoding of: %s"%data)
|
|
|
|
continue
|
|
|
|
readbuffer = readbuffer + data
|
2012-05-21 10:21:14 +00:00
|
|
|
temp = readbuffer.split("\n")
|
|
|
|
readbuffer = temp.pop( )
|
|
|
|
|
|
|
|
for line in temp:
|
|
|
|
try:
|
2012-05-21 16:14:33 +00:00
|
|
|
msg = message.Message (self, line)
|
2012-05-21 10:21:14 +00:00
|
|
|
msg.treat (self.mods)
|
|
|
|
except:
|
2012-06-16 20:45:20 +00:00
|
|
|
print ("\033[1;31mERROR:\033[0m occurred during the processing of the message: %s"%line)
|
2012-05-21 10:21:14 +00:00
|
|
|
exc_type, exc_value, exc_traceback = sys.exc_info()
|
|
|
|
traceback.print_exception(exc_type, exc_value, exc_traceback)
|
2012-06-23 11:38:34 +00:00
|
|
|
if self.connected:
|
|
|
|
self.s.close()
|
|
|
|
self.connected = False
|
|
|
|
print ("Server `%s' successfully stopped." % self.id)
|
2012-05-21 10:21:14 +00:00
|
|
|
self.stopping.set()
|
|
|
|
#Rearm Thread
|
|
|
|
threading.Thread.__init__(self)
|