2012-05-21 10:21:14 +00:00
|
|
|
import sys
|
|
|
|
import shlex
|
|
|
|
import traceback
|
2012-05-21 16:14:33 +00:00
|
|
|
import imp
|
2012-05-21 10:21:14 +00:00
|
|
|
|
2012-05-21 16:14:33 +00:00
|
|
|
server = __import__("server")
|
|
|
|
imp.reload(server)
|
2012-05-21 10:21:14 +00:00
|
|
|
|
2012-05-30 09:58:27 +00:00
|
|
|
xmlparser = __import__("module_states_file")
|
|
|
|
imp.reload(xmlparser)
|
2012-06-16 20:46:49 +00:00
|
|
|
server.message.xmlparser = xmlparser
|
|
|
|
xmlparser.module_state.xmlparser = xmlparser
|
2012-05-30 09:58:27 +00:00
|
|
|
|
2012-05-21 10:21:14 +00:00
|
|
|
selectedServer = None
|
2012-05-30 09:58:27 +00:00
|
|
|
modules_path = "./modules/"
|
|
|
|
datas_path = "./datas/"
|
|
|
|
|
2012-05-21 10:21:14 +00:00
|
|
|
MODS = list()
|
|
|
|
|
|
|
|
def parsecmd(msg):
|
|
|
|
"""Parse the command line"""
|
|
|
|
try:
|
|
|
|
cmds = shlex.split(msg)
|
|
|
|
if len(cmds) > 0:
|
|
|
|
cmds[0] = cmds[0].lower()
|
|
|
|
return cmds
|
|
|
|
except:
|
|
|
|
exc_type, exc_value, exc_traceback = sys.exc_info()
|
|
|
|
sys.stdout.write (traceback.format_exception_only(exc_type, exc_value)[0])
|
|
|
|
return None
|
|
|
|
|
|
|
|
def run(cmds, servers):
|
|
|
|
"""Launch the command"""
|
|
|
|
if cmds[0] in CAPS:
|
|
|
|
return CAPS[cmds[0]](cmds, servers)
|
|
|
|
else:
|
|
|
|
print ("Unknown command: `%s'" % cmds[0])
|
|
|
|
return ""
|
|
|
|
|
|
|
|
def getPS1():
|
|
|
|
"""Get the PS1 associated to the selected server"""
|
|
|
|
if selectedServer is None:
|
|
|
|
return "nemubot"
|
|
|
|
else:
|
|
|
|
return selectedServer.id
|
|
|
|
|
|
|
|
def launch(servers):
|
|
|
|
"""Launch the prompt"""
|
2012-06-16 20:46:49 +00:00
|
|
|
#Load messages module
|
|
|
|
server.message.load(datas_path + "general.xml")
|
|
|
|
|
|
|
|
#Update launched servers
|
2012-05-30 09:58:27 +00:00
|
|
|
for srv in servers:
|
|
|
|
servers[srv].update_mods(MODS)
|
|
|
|
|
2012-05-21 10:21:14 +00:00
|
|
|
ret = ""
|
|
|
|
cmds = list()
|
|
|
|
while ret != "quit" and ret != "reset":
|
2012-05-30 09:58:27 +00:00
|
|
|
sys.stdout.write("\033[0;33m%s§\033[0m " % getPS1())
|
|
|
|
sys.stdout.flush()
|
2012-06-16 20:46:49 +00:00
|
|
|
#TODO: Don't split here, a ; in a quoted string will be splited :s
|
|
|
|
try:
|
|
|
|
d = sys.stdin.readline().strip()
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
d = "quit"
|
|
|
|
for k in d.split(";"):
|
2012-05-21 10:21:14 +00:00
|
|
|
try:
|
2012-05-30 09:58:27 +00:00
|
|
|
cmds = parsecmd(k)
|
2012-05-21 14:38:17 +00:00
|
|
|
except:
|
|
|
|
exc_type, exc_value, exc_traceback = sys.exc_info()
|
|
|
|
sys.stdout.write (traceback.format_exception_only(exc_type, exc_value)[0])
|
2012-05-21 10:21:14 +00:00
|
|
|
if cmds is not None and len(cmds) > 0:
|
|
|
|
try:
|
|
|
|
ret = run(cmds, servers)
|
|
|
|
except:
|
|
|
|
exc_type, exc_value, exc_traceback = sys.exc_info()
|
|
|
|
sys.stdout.write (traceback.format_exception_only(exc_type, exc_value)[0])
|
|
|
|
return ret == "reset"
|
|
|
|
|
|
|
|
|
2012-06-16 20:46:49 +00:00
|
|
|
##########################
|
|
|
|
# #
|
|
|
|
# Module functions #
|
|
|
|
# #
|
|
|
|
##########################
|
|
|
|
|
|
|
|
def mod_save(mod, datas_path, config):
|
|
|
|
mod.DATAS.save(datas_path + "/" + config["name"] + ".xml")
|
|
|
|
mod.print ("Saving!")
|
|
|
|
|
|
|
|
def mod_has_access(mod, config, msg):
|
|
|
|
if config.hasNode("channel"):
|
|
|
|
for chan in config.getChilds("channel"):
|
|
|
|
if (chan["server"] is None or chan["server"] == msg.srv.id) and (chan["channel"] is None or chan["channel"] == msg.channel):
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
else:
|
|
|
|
return True
|
|
|
|
|
2012-05-21 10:21:14 +00:00
|
|
|
##########################
|
|
|
|
# #
|
|
|
|
# Permorming functions #
|
|
|
|
# #
|
|
|
|
##########################
|
|
|
|
|
2012-05-30 09:58:27 +00:00
|
|
|
def load_module(config, servers):
|
|
|
|
global MODS
|
|
|
|
if config.hasAttribute("name"):
|
|
|
|
try:
|
|
|
|
#Import the module code
|
|
|
|
mod = imp.load_source(config["name"], modules_path + "/" + config["name"] + ".py")
|
|
|
|
try:
|
|
|
|
if mod.nemubotversion < 3.0:
|
|
|
|
print (" Module `%s' is not compatible with this version." % config["name"])
|
|
|
|
return
|
|
|
|
|
|
|
|
#Set module common functions and datas
|
|
|
|
mod.name = config["name"]
|
|
|
|
mod.print = lambda msg: print("[%s] %s"%(mod.name, msg))
|
|
|
|
mod.DATAS = xmlparser.parse_file(datas_path + "/" + config["name"] + ".xml")
|
|
|
|
mod.CONF = config
|
2012-06-19 19:40:59 +00:00
|
|
|
mod.SRVS = servers
|
2012-06-16 20:46:49 +00:00
|
|
|
mod.has_access = lambda msg: mod_has_access(mod, config, msg)
|
|
|
|
mod.save = lambda: mod_save(mod, datas_path, config)
|
|
|
|
|
|
|
|
#Load dependancies
|
|
|
|
if mod.CONF.hasNode("dependson"):
|
|
|
|
mod.MODS = dict()
|
|
|
|
for depend in mod.CONF.getNodes("dependson"):
|
|
|
|
for md in MODS:
|
|
|
|
if md.name == depend["name"]:
|
|
|
|
mod.MODS[md.name] = md
|
|
|
|
break
|
|
|
|
if depend["name"] not in mod.MODS:
|
|
|
|
print ("\033[1;35mERROR:\033[0m in module `%s', module `%s' require by this module but is not loaded." % (mod.name,depend["name"]))
|
|
|
|
return
|
|
|
|
|
|
|
|
try:
|
|
|
|
test = mod.parseask
|
|
|
|
except AttributeError:
|
|
|
|
print ("\033[1;35mWarning:\033[0m in module `%s', no function parseask defined." % mod.name)
|
|
|
|
mod.parseask = lambda x: False
|
|
|
|
|
|
|
|
try:
|
|
|
|
test = mod.parseanswer
|
|
|
|
except AttributeError:
|
|
|
|
print ("\033[1;35mWarning:\033[0m in module `%s', no function parseanswer defined." % mod.name)
|
|
|
|
mod.parseanswer = lambda x: False
|
|
|
|
|
|
|
|
try:
|
|
|
|
test = mod.parselisten
|
|
|
|
except AttributeError:
|
|
|
|
print ("\033[1;35mWarning:\033[0m in module `%s', no function parselisten defined." % mod.name)
|
|
|
|
mod.parselisten = lambda x: False
|
2012-05-30 09:58:27 +00:00
|
|
|
|
|
|
|
try:
|
|
|
|
mod.load()
|
|
|
|
print (" Module `%s' successfully loaded." % config["name"])
|
|
|
|
except AttributeError:
|
|
|
|
print (" Module `%s' successfully added." % config["name"])
|
2012-06-16 20:46:49 +00:00
|
|
|
#TODO: don't append already running modules
|
2012-05-30 09:58:27 +00:00
|
|
|
MODS.append(mod)
|
|
|
|
except AttributeError:
|
|
|
|
print (" Module `%s' is not a nemubot module." % config["name"])
|
|
|
|
for srv in servers:
|
|
|
|
servers[srv].update_mods(MODS)
|
|
|
|
except IOError:
|
|
|
|
print (" Module `%s' not loaded: unable to find module implementation." % config["name"])
|
|
|
|
|
|
|
|
|
2012-05-21 10:21:14 +00:00
|
|
|
def load(cmds, servers):
|
2012-05-30 09:58:27 +00:00
|
|
|
"""Load an XML configuration file"""
|
2012-05-21 10:21:14 +00:00
|
|
|
if len(cmds) > 1:
|
|
|
|
for f in cmds[1:]:
|
2012-05-30 09:58:27 +00:00
|
|
|
config = xmlparser.parse_file(f)
|
|
|
|
if config.getName() == "nemubotconfig" or config.getName() == "config":
|
|
|
|
#Preset each server in this file
|
|
|
|
for serveur in config.getChilds():
|
|
|
|
srv = server.Server(serveur, config.getAttribute('nick'), config.getAttribute('owner'), config.getAttribute('realname'))
|
|
|
|
if srv.id not in servers:
|
|
|
|
servers[srv.id] = srv
|
|
|
|
print (" Server `%s' successfully added." % srv.id)
|
|
|
|
else:
|
|
|
|
print (" Server `%s' already added, skiped." % srv.id)
|
|
|
|
|
|
|
|
elif config.getName() == "nemubotmodule":
|
|
|
|
load_module(config, servers)
|
|
|
|
else:
|
|
|
|
print (" Can't load `%s'; this is not a valid nemubot configuration file." % f)
|
2012-05-21 10:21:14 +00:00
|
|
|
else:
|
|
|
|
print ("Not enough arguments. `load' takes an filename.")
|
|
|
|
return
|
|
|
|
|
2012-05-30 09:58:27 +00:00
|
|
|
def unload(cmds, servers):
|
|
|
|
"""Unload a module"""
|
|
|
|
global MODS
|
|
|
|
if len(cmds) == 2 and cmds[1] == "all":
|
|
|
|
for mod in MODS:
|
|
|
|
try:
|
|
|
|
mod.unload()
|
|
|
|
except AttributeError:
|
|
|
|
continue
|
|
|
|
while len(MODS) > 0:
|
|
|
|
MODS.pop()
|
|
|
|
elif len(cmds) > 1:
|
|
|
|
print("Ok")
|
|
|
|
|
2012-05-21 14:38:17 +00:00
|
|
|
def close(cmds, servers):
|
2012-05-30 09:58:27 +00:00
|
|
|
"""Disconnect and forget (remove from the servers list) the server"""
|
2012-05-21 16:14:33 +00:00
|
|
|
global selectedServer
|
2012-05-21 14:38:17 +00:00
|
|
|
if len(cmds) > 1:
|
|
|
|
for s in cmds[1:]:
|
|
|
|
if s in servers:
|
|
|
|
servers[s].disconnect()
|
|
|
|
del servers[s]
|
|
|
|
else:
|
|
|
|
print ("close: server `%s' not found." % s)
|
|
|
|
elif selectedServer is not None:
|
|
|
|
selectedServer.disconnect()
|
|
|
|
del servers[selectedServer.id]
|
|
|
|
selectedServer = None
|
|
|
|
return
|
|
|
|
|
2012-05-21 10:21:14 +00:00
|
|
|
def select(cmds, servers):
|
2012-05-30 09:58:27 +00:00
|
|
|
"""Select the current server"""
|
2012-05-21 10:21:14 +00:00
|
|
|
global selectedServer
|
|
|
|
if len(cmds) == 2 and cmds[1] != "None" and cmds[1] != "nemubot" and cmds[1] != "none":
|
|
|
|
if cmds[1] in servers:
|
|
|
|
selectedServer = servers[cmds[1]]
|
|
|
|
else:
|
|
|
|
print ("select: server `%s' not found." % cmds[1])
|
|
|
|
else:
|
|
|
|
selectedServer = None
|
|
|
|
return
|
|
|
|
|
|
|
|
def liste(cmds, servers):
|
2012-05-30 09:58:27 +00:00
|
|
|
"""Show some lists"""
|
2012-05-21 10:21:14 +00:00
|
|
|
if len(cmds) > 1:
|
|
|
|
for l in cmds[1:]:
|
|
|
|
l = l.lower()
|
|
|
|
if l == "server" or l == "servers":
|
|
|
|
for srv in servers.keys():
|
|
|
|
print (" - %s ;" % srv)
|
2012-05-30 09:58:27 +00:00
|
|
|
elif l == "mod" or l == "mods" or l == "module" or l == "modules":
|
|
|
|
for mod in MODS:
|
|
|
|
print (" - %s ;" % mod.name)
|
2012-06-16 20:46:49 +00:00
|
|
|
elif l == "ban" or l == "banni":
|
|
|
|
for ban in server.message.BANLIST:
|
|
|
|
print (" - %s ;" % ban)
|
|
|
|
elif l == "credit" or l == "credits":
|
|
|
|
for name in server.message.CREDITS.keys:
|
|
|
|
print (" - %s: %s ;" % (name, server.message.CREDITS[name]))
|
2012-05-21 17:08:41 +00:00
|
|
|
elif l == "chan" or l == "channel" or l == "channels":
|
|
|
|
if selectedServer is not None:
|
|
|
|
for chn in selectedServer.channels:
|
|
|
|
print (" - %s ;" % chn)
|
|
|
|
else:
|
|
|
|
print (" Please SELECT a server before ask for channels list.")
|
2012-05-21 10:21:14 +00:00
|
|
|
else:
|
|
|
|
print (" Unknown list `%s'" % l)
|
|
|
|
else:
|
|
|
|
print (" Please give a list to show: servers, ...")
|
|
|
|
|
|
|
|
def connect(cmds, servers):
|
2012-05-30 09:58:27 +00:00
|
|
|
"""Make the connexion to a server"""
|
2012-05-21 10:21:14 +00:00
|
|
|
if len(cmds) > 1:
|
|
|
|
for s in cmds[1:]:
|
|
|
|
if s in servers:
|
|
|
|
servers[s].launch(MODS)
|
|
|
|
else:
|
|
|
|
print ("connect: server `%s' not found." % s)
|
|
|
|
|
|
|
|
elif selectedServer is not None:
|
|
|
|
selectedServer.launch(MODS)
|
|
|
|
else:
|
|
|
|
print (" Please SELECT a server or give its name in argument.")
|
|
|
|
|
2012-05-21 17:08:41 +00:00
|
|
|
def join(cmds, servers):
|
2012-05-30 09:58:27 +00:00
|
|
|
"""Join or leave a channel"""
|
2012-05-21 17:08:41 +00:00
|
|
|
rd = 1
|
|
|
|
if len(cmds) <= rd:
|
|
|
|
print ("%s: not enough arguments." % cmds[0])
|
|
|
|
return
|
|
|
|
|
|
|
|
if cmds[rd] in servers:
|
|
|
|
srv = servers[cmds[rd]]
|
|
|
|
rd += 1
|
|
|
|
elif selectedServer is not None:
|
|
|
|
srv = selectedServer
|
|
|
|
else:
|
|
|
|
print (" Please SELECT a server or give its name in argument.")
|
|
|
|
return
|
|
|
|
|
|
|
|
if len(cmds) <= rd:
|
|
|
|
print ("%s: not enough arguments." % cmds[0])
|
|
|
|
return
|
|
|
|
|
|
|
|
if cmds[0] == "join":
|
|
|
|
srv.join(cmds[rd])
|
|
|
|
elif cmds[0] == "leave" or cmds[0] == "part":
|
|
|
|
srv.leave(cmds[rd])
|
|
|
|
|
2012-05-21 14:38:17 +00:00
|
|
|
def send(cmds, servers):
|
2012-05-30 09:58:27 +00:00
|
|
|
"""Built-on that send a message on a channel"""
|
2012-05-21 14:38:17 +00:00
|
|
|
rd = 1
|
|
|
|
if len(cmds) <= rd:
|
|
|
|
print ("send: not enough arguments.")
|
|
|
|
return
|
|
|
|
|
|
|
|
if cmds[rd] in servers:
|
|
|
|
srv = servers[cmds[rd]]
|
|
|
|
rd += 1
|
|
|
|
elif selectedServer is not None:
|
|
|
|
srv = selectedServer
|
|
|
|
else:
|
|
|
|
print (" Please SELECT a server or give its name in argument.")
|
|
|
|
return
|
|
|
|
|
|
|
|
if len(cmds) <= rd:
|
|
|
|
print ("send: not enough arguments.")
|
|
|
|
return
|
|
|
|
|
|
|
|
#Check the server is connected
|
|
|
|
if not srv.connected:
|
|
|
|
print ("send: server `%s' not connected." % srv.id)
|
|
|
|
return
|
|
|
|
|
|
|
|
if cmds[rd] in srv.channels:
|
|
|
|
chan = cmds[rd]
|
|
|
|
rd += 1
|
|
|
|
else:
|
|
|
|
print ("send: channel `%s' not authorized in server `%s'." % (cmds[rd], srv.id))
|
|
|
|
return
|
|
|
|
|
|
|
|
if len(cmds) <= rd:
|
|
|
|
print ("send: not enough arguments.")
|
|
|
|
return
|
|
|
|
|
|
|
|
srv.send_msg_final(chan, cmds[rd])
|
|
|
|
return "done"
|
|
|
|
|
2012-05-21 10:21:14 +00:00
|
|
|
def disconnect(cmds, servers):
|
2012-05-30 09:58:27 +00:00
|
|
|
"""Close the connection to a server"""
|
2012-05-21 10:21:14 +00:00
|
|
|
if len(cmds) > 1:
|
|
|
|
for s in cmds[1:]:
|
|
|
|
if s in servers:
|
|
|
|
if not servers[s].disconnect():
|
|
|
|
print ("disconnect: server `%s' already disconnected." % s)
|
|
|
|
else:
|
|
|
|
print ("disconnect: server `%s' not found." % s)
|
|
|
|
elif selectedServer is not None:
|
|
|
|
if not selectedServer.disconnect():
|
|
|
|
print ("disconnect: server `%s' already disconnected." % selectedServer.id)
|
|
|
|
else:
|
|
|
|
print (" Please SELECT a server or give its name in argument.")
|
|
|
|
|
2012-05-21 14:38:17 +00:00
|
|
|
def zap(cmds, servers):
|
2012-05-30 09:58:27 +00:00
|
|
|
"""Hard change connexion state"""
|
2012-05-21 14:38:17 +00:00
|
|
|
if len(cmds) > 1:
|
|
|
|
for s in cmds[1:]:
|
|
|
|
if s in servers:
|
|
|
|
servers[s].connected = not servers[s].connected
|
|
|
|
else:
|
|
|
|
print ("disconnect: server `%s' not found." % s)
|
|
|
|
elif selectedServer is not None:
|
|
|
|
selectedServer.connected = not selectedServer.connected
|
|
|
|
else:
|
|
|
|
print (" Please SELECT a server or give its name in argument.")
|
|
|
|
|
2012-05-21 10:21:14 +00:00
|
|
|
def end(cmds, servers):
|
2012-05-30 09:58:27 +00:00
|
|
|
"""Quit the prompt for reload or exit"""
|
2012-05-21 10:21:14 +00:00
|
|
|
if cmds[0] == "reset":
|
|
|
|
return "reset"
|
|
|
|
else:
|
|
|
|
for srv in servers.keys():
|
|
|
|
servers[srv].disconnect()
|
|
|
|
return "quit"
|
|
|
|
|
|
|
|
#Register build-ins
|
|
|
|
CAPS = {
|
2012-05-21 14:38:17 +00:00
|
|
|
'quit': end, #Disconnect all server and quit
|
|
|
|
'exit': end, #Alias for quit
|
|
|
|
'reset': end, #Reload the prompt
|
2012-05-30 09:58:27 +00:00
|
|
|
'load': load, #Load a servers or module configuration file
|
2012-05-21 16:14:33 +00:00
|
|
|
'close': close, #Disconnect and remove a server from the list
|
2012-05-30 09:58:27 +00:00
|
|
|
'unload': unload, #Unload a module and remove it from the list
|
2012-05-21 14:38:17 +00:00
|
|
|
'select': select, #Select a server
|
|
|
|
'list': liste, #Show lists
|
|
|
|
'connect': connect, #Connect to a server
|
2012-05-21 17:08:41 +00:00
|
|
|
'join': join, #Join a new channel
|
|
|
|
'leave': join, #Leave a channel
|
2012-05-21 14:38:17 +00:00
|
|
|
'send': send, #Send a message on a channel
|
|
|
|
'disconnect': disconnect, #Disconnect from a server
|
|
|
|
'zap': zap, #Reverse internal connection state without check
|
2012-05-21 10:21:14 +00:00
|
|
|
}
|