Made irc bot connect, but scripthandler lookup is causing traceback when searching for a player)

This commit is contained in:
Griatch 2014-02-24 00:37:32 +01:00
parent 8b52591c2f
commit 6c45d76b56
11 changed files with 70 additions and 37 deletions

View file

@ -826,7 +826,7 @@ class CmdIRC2Chan(MuxCommand):
if('disconnect' in self.switches or 'remove' in self.switches or if('disconnect' in self.switches or 'remove' in self.switches or
'delete' in self.switches): 'delete' in self.switches):
matches = PlayerDB.filter(db_isbot=True, db_key=botname) matches = PlayerDB.objects.filter(db_is_bot=True, db_key=botname)
if matches: if matches:
matches[0].delete() matches[0].delete()
self.msg("IRC connection destroyed.") self.msg("IRC connection destroyed.")
@ -835,7 +835,15 @@ class CmdIRC2Chan(MuxCommand):
return return
# create a new bot # create a new bot
bot = create.create_player(botname, None, None, typeclass=bots.IRCBot) bot = PlayerDB.objects.filter(username__iexact=botname)
if bot:
# re-use an existing bot
bot = bot[0].typeclass
if not bot.is_bot:
self.msg("Player '%s', which is not a bot, already exists." % botname)
return
else:
bot = create.create_player(botname, None, None, typeclass=bots.IRCBot)
bot.start(ev_channel=channel, irc_botname=irc_botname, irc_channel=irc_channel, bot.start(ev_channel=channel, irc_botname=irc_botname, irc_channel=irc_channel,
irc_network=irc_network, irc_port=irc_port) irc_network=irc_network, irc_port=irc_port)
self.msg("Connection created. Starting IRC bot.") self.msg("Connection created. Starting IRC bot.")

View file

@ -172,12 +172,8 @@ class Channel(TypeClass):
# note our addition of the from_channel keyword here. This could be checked # note our addition of the from_channel keyword here. This could be checked
# by a custom player.msg() to treat channel-receives differently. # by a custom player.msg() to treat channel-receives differently.
player.msg(msg.message, from_obj=msg.senders, from_channel=self.id) player.msg(msg.message, from_obj=msg.senders, from_channel=self.id)
except AttributeError: except AttributeError, e:
try: logger.log_trace("%s\nCannot send msg to connection '%s'" % (e, player))
player.to_external(msg.message,
senders=msg.senders, from_channel=self)
except Exception:
logger.log_trace("Cannot send msg to connection '%s'" % player)
def msg(self, msgobj, header=None, senders=None, sender_strings=None, def msg(self, msgobj, header=None, senders=None, sender_strings=None,
persistent=False, online=False, emit=False, external=False): persistent=False, online=False, emit=False, external=False):

View file

@ -201,6 +201,8 @@ class LockHandler(object):
elist = [] # errors elist = [] # errors
wlist = [] # warnings wlist = [] # warnings
for raw_lockstring in storage_lockstring.split(';'): for raw_lockstring in storage_lockstring.split(';'):
if not raw_lockstring:
continue
lock_funcs = [] lock_funcs = []
try: try:
access_type, rhs = (part.strip() for part in raw_lockstring.split(':', 1)) access_type, rhs = (part.strip() for part in raw_lockstring.split(':', 1))

View file

@ -31,7 +31,7 @@ class BotStarter(Script):
def at_start(self): def at_start(self):
"Kick bot into gear" "Kick bot into gear"
if not self.db.started: if not self.db.started:
self.obj.start() self.player.start()
self.db.started = False self.db.started = False
def at_server_reload(self): def at_server_reload(self):
@ -56,7 +56,7 @@ class CmdBotListen(Command):
key = CMD_NOMATCH key = CMD_NOMATCH
def func(self): def func(self):
text = self.cmdname + self.args text = self.cmdstring + self.args
self.obj.execute_cmd(text, sessid=self.sessid) self.obj.execute_cmd(text, sessid=self.sessid)
@ -84,7 +84,7 @@ class Bot(Player):
# the text encoding to use. # the text encoding to use.
self.db.encoding = "utf-8" self.db.encoding = "utf-8"
# A basic security setup # A basic security setup
lockstring = "examine:perm(Wizards);edit:perm(Wizards);delete:perm(Wizards);boot:perm(Wizards);msg:all()" lockstring = "examine:perm(Wizards);edit:perm(Wizards);delete:perm(Wizards);boot:perm(Wizards);msg:false()"
self.locks.add(lockstring) self.locks.add(lockstring)
# set the basics of being a bot # set the basics of being a bot
self.cmdset.add_default(BotCmdSet) self.cmdset.add_default(BotCmdSet)
@ -134,12 +134,16 @@ class IRCBot(Bot):
# if keywords are given, store (the BotStarter script # if keywords are given, store (the BotStarter script
# will not give any keywords, so this should normally only # will not give any keywords, so this should normally only
# happen at initialization) # happen at initialization)
self.db.irc_botname = irc_botname if irc_botname else self.key if irc_botname:
self.db.irc_botname = irc_botname
elif not self.db.irc_botname:
self.db.irc_botname = self.key
if ev_channel: if ev_channel:
# connect to Evennia channel # connect to Evennia channel
channel = search.channel_search(ev_channel) channel = search.channel_search(ev_channel)
if not channel: if not channel:
raise RuntimeError("Evennia Channel '%s' not found." % ev_channel) raise RuntimeError("Evennia Channel '%s' not found." % ev_channel)
channel = channel[0]
channel.connect(self) channel.connect(self)
self.db.ev_channel = channel self.db.ev_channel = channel
if irc_channel: if irc_channel:
@ -154,11 +158,12 @@ class IRCBot(Bot):
# instruct the server and portal to create a new session with # instruct the server and portal to create a new session with
# the stored configuration # the stored configuration
configdict = {"botname": self.db.irc_botname, configdict = {"uid":self.dbid,
"botname": self.db.irc_botname,
"channel": self.db.irc_channel , "channel": self.db.irc_channel ,
"network": self.db.irc_network, "network": self.db.irc_network,
"port": self.db.irc_port} "port": self.db.irc_port}
_SESSIONS.start_bot_session("src.server.portal.irc.IRCClient", self.id, configdict) _SESSIONS.start_bot_session("src.server.portal.irc.IRCBotFactory", configdict)
def msg(self, text=None, **kwargs): def msg(self, text=None, **kwargs):
""" """

View file

@ -415,7 +415,7 @@ class PlayerDB(TypedObject, AbstractUser):
# deleting command) # deleting command)
self.unpuppet_object(session.sessid) self.unpuppet_object(session.sessid)
session.sessionhandler.disconnect(session, reason=_("Player being deleted.")) session.sessionhandler.disconnect(session, reason=_("Player being deleted."))
self.scripts.stop()
super(PlayerDB, self).delete(*args, **kwargs) super(PlayerDB, self).delete(*args, **kwargs)
def execute_cmd(self, raw_string, sessid=None): def execute_cmd(self, raw_string, sessid=None):

View file

@ -44,13 +44,22 @@ class ScriptManager(TypedObjectManager):
if not obj: if not obj:
return [] return []
obj = obj.dbobj obj = obj.dbobj
player = obj.__class__.__name__ == "PlayerDB"
print "get_all_scripts_on_obj:", obj, player
if key: if key:
dbref = self.dbref(key) dbref = self.dbref(key)
if dbref or dbref == 0: if dbref or dbref == 0:
script = self.filter(db_obj=obj, id=dbref) if player:
script = self.filter(db_player=obj, id=dbref)
else:
script = self.filter(db_obj=obj, id=dbref)
if script: if script:
return script return script
elif player:
return self.filter(db_player=obj, db_key=key)
return self.filter(db_obj=obj.dbobj, db_key=key) return self.filter(db_obj=obj.dbobj, db_key=key)
if player:
self.filter(db_player=obj)
return self.filter(db_obj=obj) return self.filter(db_obj=obj)
@returns_typeclass_list @returns_typeclass_list

View file

@ -58,7 +58,13 @@ class ScriptHandler(object):
definition) definition)
autostart - start the script upon adding it autostart - start the script upon adding it
""" """
script = create.create_script(scriptclass, key=key, obj=self.obj, if self.obj.dbobj.__class__.__name__ == "PlayerDB":
# we add to a Player, not an Object
script = create.create_script(scriptclass, key=key, player=self.obj,
autostart=autostart)
else:
# the normal - adding to an Object
script = create.create_script(scriptclass, key=key, obj=self.obj,
autostart=autostart) autostart=autostart)
if not script: if not script:
logger.log_errmsg("Script %s could not be created and/or started." % scriptclass) logger.log_errmsg("Script %s could not be created and/or started." % scriptclass)
@ -75,12 +81,13 @@ class ScriptHandler(object):
num += script.start() num += script.start()
return num return num
def delete(self, scriptid): def delete(self, scriptid=None):
""" """
Forcibly delete a script from this object. Forcibly delete a script from this object.
scriptid can be a script key or the path to a script (in the scriptid can be a script key or the path to a script (in the
latter case all scripts with this path will be deleted!) latter case all scripts with this path will be deleted!)
If no scriptid is set, delete all scripts on the object.
""" """
delscripts = ScriptDB.objects.get_all_scripts_on_obj(self.obj, key=scriptid) delscripts = ScriptDB.objects.get_all_scripts_on_obj(self.obj, key=scriptid)
@ -91,7 +98,7 @@ class ScriptHandler(object):
num += script.stop() num += script.stop()
return num return num
def stop(self, scriptid): def stop(self, scriptid=None):
""" """
Alias for delete. scriptid can be a script key or a script path string. Alias for delete. scriptid can be a script key or a script path string.
""" """

View file

@ -472,8 +472,10 @@ class AMPProtocol(amp.AMP):
portal_sessionhandler.server_session_sync(data) portal_sessionhandler.server_session_sync(data)
# set a flag in case we are about to shut down soon # set a flag in case we are about to shut down soon
self.factory.server_restart_mode = True self.factory.server_restart_mode = True
elif operation == SCONN: # server_force_connection (for irc/imc2 etc) elif operation == SCONN: # server_force_connection (for irc/imc2 etc)
portal_sessionhandler.server_connect(**data) portal_sessionhandler.server_connect(**data)
else: else:
raise Exception("operation %(op)s not recognized." % {'op': operation}) raise Exception("operation %(op)s not recognized." % {'op': operation})
return {} return {}

View file

@ -30,11 +30,16 @@ class IRCBot(irc.IRCClient, Session):
def signedOn(self): def signedOn(self):
""" """
This is called when we successfully connect to This is called when we successfully connect to
the network. We make sure to store ourself the network. We make sure to now register with
on the factory. the game as a full session.
""" """
self.join(self.channel) self.join(self.channel)
self.factory.bot = self self.factory.bot = self
self.init_session("ircbot", self.network, self.factory.sessionhandler)
# we link back to our bot and log in
self.uid = self.factory.uid
self.logged_in = True
self.factory.sessionhandler.connect(self)
def privmsg(self, user, channel, msg): def privmsg(self, user, channel, msg):
"A message was sent to channel" "A message was sent to channel"
@ -55,11 +60,6 @@ class IRCBot(irc.IRCClient, Session):
"Data from server-> IRC" "Data from server-> IRC"
self.say(self.channel, text) self.say(self.channel, text)
def start(self):
"Connect session to sessionhandler"
service = internet.TCPClient(self.network, int(self.port), self)
self.sessionhandler.portal.services.addService(service)
self.sessionhandler.connect(self)
class IRCBotFactory(protocol.ReconnectingClientFactory): class IRCBotFactory(protocol.ReconnectingClientFactory):
""" """
@ -71,14 +71,14 @@ class IRCBotFactory(protocol.ReconnectingClientFactory):
factor = 1.5 factor = 1.5
maxDelay = 60 maxDelay = 60
def __init__(self, botname=None, channel=None, network=None, port=None): def __init__(self, uid=None, botname=None, channel=None, network=None, port=None):
"Storing some important protocol properties" "Storing some important protocol properties"
self.nickname = botname self.uid = int(uid)
self.logger = logger self.nickname = str(botname)
self.channel = channel self.channel = str(channel)
self.network = network self.network = str(network)
self.port = port self.port = int(port)
self.bots = None self.bot = None
def buildProtocol(self, addr): def buildProtocol(self, addr):
"Build the protocol and assign it some properties" "Build the protocol and assign it some properties"
@ -94,6 +94,10 @@ class IRCBotFactory(protocol.ReconnectingClientFactory):
"Tracks reconnections for debugging" "Tracks reconnections for debugging"
logger.log_infomsg("(re)connecting to %s" % self.channel) logger.log_infomsg("(re)connecting to %s" % self.channel)
def start(self):
"Connect session to sessionhandler"
service = internet.TCPClient(self.network, self.port, self)
self.sessionhandler.portal.services.addService(service)
# #

View file

@ -69,7 +69,7 @@ class PortalSessionHandler(SessionHandler):
operation=PDISCONN) operation=PDISCONN)
def server_connect(self, protocol_path="", uid=None, config=dict()): def server_connect(self, protocol_path="", config=dict()):
""" """
Called by server to force the initialization of a new Called by server to force the initialization of a new
protocol instance. Server wants this instance to get protocol instance. Server wants this instance to get
@ -79,7 +79,6 @@ class PortalSessionHandler(SessionHandler):
protocol_path - full python path to the class factory protocol_path - full python path to the class factory
for the protocol used, eg for the protocol used, eg
'src.server.portal.irc.IRCClientFactory' 'src.server.portal.irc.IRCClientFactory'
uid - database uid to the connected player-bot
config - dictionary of configuration options, fed as **kwarg config - dictionary of configuration options, fed as **kwarg
to protocol class' __init__ method. to protocol class' __init__ method.
@ -91,6 +90,8 @@ class PortalSessionHandler(SessionHandler):
from src.utils.utils import variable_from_module as _MOD_IMPORT from src.utils.utils import variable_from_module as _MOD_IMPORT
path, clsname = protocol_path.rsplit(".", 1) path, clsname = protocol_path.rsplit(".", 1)
cls = _MOD_IMPORT(path, clsname) cls = _MOD_IMPORT(path, clsname)
if not cls:
raise RuntimeError("ServerConnect: protocol factory '%s' not found." % protocol_path)
protocol = cls(**config) protocol = cls(**config)
protocol.sessionhandler = self protocol.sessionhandler = self
protocol.start() protocol.start()

View file

@ -259,7 +259,7 @@ class ServerSessionHandler(SessionHandler):
# server-side access methods # server-side access methods
def start_bot_session(self, protocol_path, uid, configdict): def start_bot_session(self, protocol_path, configdict):
""" """
This method allows the server-side to force the Portal to create This method allows the server-side to force the Portal to create
a new bot session using the protocol specified by protocol_path, a new bot session using the protocol specified by protocol_path,
@ -271,7 +271,6 @@ class ServerSessionHandler(SessionHandler):
Server. Server.
""" """
data = {"protocol_path":protocol_path, data = {"protocol_path":protocol_path,
"uid":uid,
"config":configdict} "config":configdict}
self.server.amp_protocol.call_remote_PortalAdmin(0, self.server.amp_protocol.call_remote_PortalAdmin(0,
operation=SCONN, operation=SCONN,