From e36c7d5cc10e766d37d3cbbc627dfbd96114e9b8 Mon Sep 17 00:00:00 2001 From: Griatch Date: Sat, 21 Sep 2013 17:33:48 +0200 Subject: [PATCH] Cleaned up worst instability. Test suite does validate yet. --- contrib/lineeditor.py | 2 +- game/gamesrc/objects/examples/object.py | 8 +-- game/gamesrc/objects/examples/player.py | 2 +- src/commands/cmdhandler.py | 4 +- src/commands/command.py | 4 +- src/commands/default/admin.py | 5 +- src/commands/default/comms.py | 6 +- src/commands/default/player.py | 4 +- src/commands/default/system.py | 4 +- src/commands/default/tests.py | 4 +- src/comms/models.py | 2 +- src/objects/models.py | 35 +++++---- src/objects/objects.py | 14 ++-- src/players/models.py | 17 +++-- src/players/player.py | 10 +-- src/server/amp.py | 86 ++++------------------- src/server/portal/portalsessionhandler.py | 25 ++----- src/server/portal/ssh.py | 18 ++--- src/server/portal/telnet.py | 25 ++++--- src/server/portal/webclient.py | 31 +++----- src/server/serversession.py | 82 ++++----------------- src/server/session.py | 21 +----- src/server/sessionhandler.py | 22 +----- src/typeclasses/models.py | 3 + 24 files changed, 134 insertions(+), 300 deletions(-) diff --git a/contrib/lineeditor.py b/contrib/lineeditor.py index c0c64b472d..bd16679034 100644 --- a/contrib/lineeditor.py +++ b/contrib/lineeditor.py @@ -190,7 +190,7 @@ class CmdEditorGroup(CmdEditorBase): string = editor.display_buffer(buf=buf, offset=lstart, linenums=False) else: string = editor.display_buffer(linenums=False) - self.caller.msg(string, data={"raw":True}) + self.caller.msg(string, raw=True) return elif cmd == ":::": # Insert single colon alone on a line diff --git a/game/gamesrc/objects/examples/object.py b/game/gamesrc/objects/examples/object.py index 5593ed3fc0..0b52c473b5 100644 --- a/game/gamesrc/objects/examples/object.py +++ b/game/gamesrc/objects/examples/object.py @@ -71,8 +71,8 @@ class ExampleObject(Object): search(ostring, global_search=False, attribute_name=None, use_nicks=False, location=None, ignore_errors=False, player=False) execute_cmd(raw_string) - msg(message, from_obj=None, data=None) - msg_contents(message, exclude=None, from_obj=None, data=None) + msg(text=None, **kwargs) + msg_contents(message, exclude=None, from_obj=None, **kwargs) move_to(destination, quiet=False, emit_to_obj=None, use_destination=True) copy(new_key=None) delete() @@ -113,9 +113,9 @@ class ExampleObject(Object): at_after_traverse(traversing_object, source_location) - (exit-objects only) called just after a traversal has happened. at_failed_traverse(traversing_object) - (exit-objects only) called if traversal fails and property err_traverse is not defined. - at_msg_receive(self, msg, from_obj=None, data=None) - called when a message (via self.msg()) is sent to this obj. + at_msg_receive(self, msg, from_obj=None, **kwargs) - called when a message (via self.msg()) is sent to this obj. If returns false, aborts send. - at_msg_send(self, msg, to_obj=None, data=None) - called when this objects sends a message to someone via self.msg(). + at_msg_send(self, msg, to_obj=None, **kwargs) - called when this objects sends a message to someone via self.msg(). return_appearance(looker) - describes this object. Used by "look" command by default at_desc(looker=None) - called by 'look' whenever the appearance is requested. diff --git a/game/gamesrc/objects/examples/player.py b/game/gamesrc/objects/examples/player.py index 1f9450f974..ceded805f1 100644 --- a/game/gamesrc/objects/examples/player.py +++ b/game/gamesrc/objects/examples/player.py @@ -59,7 +59,7 @@ class ExamplePlayer(Player): * Helper methods - msg(outgoing_string, from_obj=None, data=None) + msg(text=None, **kwargs) swap_character(new_character, delete_old_character=False) execute_cmd(raw_string, sessid=None) search(ostring, global_search=False, attribute_name=None, use_nicks=False, location=None, ignore_errors=False, player=False) diff --git a/src/commands/cmdhandler.py b/src/commands/cmdhandler.py index 91291088da..b39b106cf6 100644 --- a/src/commands/cmdhandler.py +++ b/src/commands/cmdhandler.py @@ -343,11 +343,11 @@ def cmdhandler(called_on, raw_string, testing=False, callertype="session", sessi cmd.cmdstring = cmdname cmd.args = args cmd.cmdset = cmdset + cmd.sessid = session.sessid if session else sessid cmd.session = session cmd.player = player - #cmd.obj # set via command handler - cmd.sessid = session.sessid if session else sessid cmd.raw_string = unformatted_raw_string + #cmd.obj # set via command handler if hasattr(cmd, 'obj') and hasattr(cmd.obj, 'scripts'): # cmd.obj is automatically made available by the cmdhandler. diff --git a/src/commands/command.py b/src/commands/command.py index 0c65a90873..280788515d 100644 --- a/src/commands/command.py +++ b/src/commands/command.py @@ -206,7 +206,7 @@ class Command(object): """ return self.lockhandler.check(srcobj, access_type, default=default) - def msg(self, msg="", to_obj=None, from_obj=None, data=None, sessid=None, all_sessions=False): + def msg(self, msg="", to_obj=None, from_obj=None, sessid=None, all_sessions=False, **kwargs): """ This is a shortcut instad of calling msg() directly on an object - it will detect if caller is an Object or a Player and also appends self.sessid @@ -234,7 +234,7 @@ class Command(object): # if to_obj is a different Player, all their sessions # will be notified unless sessid was given specifically sessid = None - to_obj.msg(msg, from_obj=from_obj, data=data, sessid=sessid) + to_obj.msg(msg, from_obj=from_obj, sessid=sessid, **kwargs) # Common Command hooks diff --git a/src/commands/default/admin.py b/src/commands/default/admin.py index e004c3e6bf..5598776d48 100644 --- a/src/commands/default/admin.py +++ b/src/commands/default/admin.py @@ -416,9 +416,8 @@ class CmdEmit(MuxCommand): continue if obj.access(caller, 'tell'): obj.msg(message) - if send_to_contents: - for content in obj.contents: - content.msg(message) + if send_to_contents and hasattr(obj, "msg_contents"): + obj.msg_contents(message) caller.msg("Emitted to %s and its contents." % objname) else: caller.msg("Emitted to %s." % objname) diff --git a/src/commands/default/comms.py b/src/commands/default/comms.py index 700466d377..13d1bf961e 100644 --- a/src/commands/default/comms.py +++ b/src/commands/default/comms.py @@ -155,7 +155,7 @@ class CmdDelCom(MuxPlayerCommand): return else: # we are removing a channel nick - channame = caller.nicks.get_replace(key=ostring, category="channel") + channame = caller.nicks.get(key=ostring, category="channel") channel = find_channel(caller, channame, silent=True) if not channel: self.msg("No channel with alias '%s' was found." % ostring) @@ -949,7 +949,7 @@ class CmdIMCInfo(MuxCommand): return from src.comms.imc2 import IMC2_CLIENT self.msg("Sending IMC whois request. If you receive no response, no matches were found.") - IMC2_CLIENT.msg_imc2(None, from_obj=self.caller, packet_type="imcwhois", data={"target":self.args}) + IMC2_CLIENT.msg_imc2(None, from_obj=self.caller, packet_type="imcwhois", target=self.args) elif not self.switches or "channels" in self.switches or self.cmdstring == "@imcchanlist": # show channels @@ -1007,7 +1007,7 @@ class CmdIMCTell(MuxCommand): data = {"target":target, "destination":destination} # send to imc2 - IMC2_CLIENT.msg_imc2(message, from_obj=self.caller, packet_type="imctell", data=data) + IMC2_CLIENT.msg_imc2(message, from_obj=self.caller, packet_type="imctell", **data) self.msg("You paged {c%s@%s{n (over IMC): '%s'." % (target, destination, message)) diff --git a/src/commands/default/player.py b/src/commands/default/player.py index 51c8f1c479..c0889b7316 100644 --- a/src/commands/default/player.py +++ b/src/commands/default/player.py @@ -628,10 +628,10 @@ class CmdQuell(MuxPlayerCommand): player.attributes.remove('_quell') self.msg("Player permissions%s restored." % permstr) else: - if player.get('_quell'): + if player.attributes.get('_quell'): self.msg("Already quelling Player%s permissions." % permstr) return - player.add('_quell', True) + player.attributes.add('_quell', True) self.msg("Quelling Player permissions%s. Use @unquell to get them back." % permstr) self._recache_locks(player) diff --git a/src/commands/default/system.py b/src/commands/default/system.py index da57382afe..265bc24f48 100644 --- a/src/commands/default/system.py +++ b/src/commands/default/system.py @@ -163,9 +163,9 @@ class CmdPy(MuxCommand): 'inherits_from':utils.inherits_from} try: - self.msg(">>> %s" % pycode, data={"raw":True}, sessid=self.sessid) + self.msg(">>> %s" % pycode, raw=True, sessid=self.sessid) except TypeError: - self.msg(">>> %s" % pycode, data={"raw":True}) + self.msg(">>> %s" % pycode, raw=True) mode = "eval" diff --git a/src/commands/default/tests.py b/src/commands/default/tests.py index 4508d1802e..5bbccce26e 100644 --- a/src/commands/default/tests.py +++ b/src/commands/default/tests.py @@ -78,9 +78,11 @@ class CommandTest(TestCase): cmdobj.cmdstring = cmdobj.key cmdobj.args = args cmdobj.cmdset = cmdset + cmdobj.sessid = 1 + cmdobj.session = None + cmdobj.player = self.player cmdobj.raw_string = cmdobj.key + " " + args cmdobj.obj = self.char1 - cmdobj.sessid = 1 # test self.char1.player.ndb.stored_msg = [] cmdobj.at_pre_cmd() diff --git a/src/comms/models.py b/src/comms/models.py index d9f91a67e3..593c485c64 100644 --- a/src/comms/models.py +++ b/src/comms/models.py @@ -591,7 +591,7 @@ class Channel(SharedMemoryModel): # get all players connected to this channel and send to them for conn in Channel.objects.get_all_connections(self, online=online): try: - conn.player.msg(msg, from_object=senders) + conn.player.msg(msg, from_obj=senders) except AttributeError: try: conn.to_external(msg, from_object=senders, from_channel=self) diff --git a/src/objects/models.py b/src/objects/models.py index d536ce7165..ead4f91d2f 100644 --- a/src/objects/models.py +++ b/src/objects/models.py @@ -658,7 +658,7 @@ class ObjectDB(TypedObject): break return cmdhandler.cmdhandler(_GA(self, "typeclass"), raw_string, callertype="object", sessid=sessid) - def msg(self, text=None, **kwargs):#from_obj=None, data=None, sessid=0): + def msg(self, text=None, from_obj=None, sessid=0, **kwargs): """ Emits something to a session attached to the object. @@ -670,22 +670,24 @@ class ObjectDB(TypedObject): If set to 0 (default), use either from_obj.sessid (if set) or self.sessid automatically If None, echo to all connected sessions """ + if "data" in kwargs: + from src.utils import logger + logger.log_depmsg("ObjectDB.msg(): 'data'-dict keyword is deprecated. Use **kwargs instead.") + data = kwargs.pop("data") + if isinstance(data, dict): + kwargs.update(data) + + if _GA(self, 'player'): # note that we must call the player *typeclass'* msg(), otherwise one couldn't overload it. - if kwargs.get("sessid",0) == 0: - sessid = None - if "from_obj" in kwargs and hasattr(kwargs["from_obj"], "sessid"): - kwargs["sessid"] = from_obj.sessid + if not sessid: + if from_obj and hasattr(from_obj, "sessid"): + sessid = from_obj.sessid elif hasattr(self, "sessid"): - kwargs["sessid"] = self.sessid - _GA(_GA(self, 'player'), "typeclass").msg(text=text, **kwargs)#from_obj=from_obj, data=data, sessid=sessid) + sessid = self.sessid + _GA(_GA(self, 'player'), "typeclass").msg(text=text, from_obj=from_obj, sessid=sessid, **kwargs) - def emit_to(self, message, from_obj=None, data=None): - "Deprecated. Alias for msg" - logger.log_depmsg("emit_to() is deprecated. Use msg() instead.") - _GA(self, "msg")(message, from_obj, data) - - def msg_contents(self, message, exclude=None, from_obj=None, data=None): + def msg_contents(self, message, exclude=None, from_obj=None, **kwargs): """ Emits something to all objects inside an object. @@ -697,12 +699,7 @@ class ObjectDB(TypedObject): contents = [obj for obj in contents if (obj not in exclude and obj not in exclude)] for obj in contents: - obj.msg(message, from_obj=from_obj, data=data) - - def emit_to_contents(self, message, exclude=None, from_obj=None, data=None): - "Deprecated. Alias for msg_contents" - logger.log_depmsg("emit_to_contents() is deprecated. Use msg_contents() instead.") - self.msg_contents(message, exclude=exclude, from_obj=from_obj, data=data) + obj.msg(message, from_obj=from_obj, **kwargs) def move_to(self, destination, quiet=False, emit_to_obj=None, use_destination=True, to_none=False): diff --git a/src/objects/objects.py b/src/objects/objects.py index 2eea10dc86..e090be4c59 100644 --- a/src/objects/objects.py +++ b/src/objects/objects.py @@ -87,8 +87,8 @@ class Object(TypeClass): search(ostring, global_search=False, global_dbref=False, attribute_name=None, use_nicks=False, location=None, ignore_errors=False, player=False) execute_cmd(raw_string) - msg(message, from_obj=None, data=None) - msg_contents(message, exclude=None, from_obj=None, data=None) + msg(message, **kwargs) + msg_contents(message, exclude=None, from_obj=None, **kwargs) move_to(destination, quiet=False, emit_to_obj=None, use_destination=True, to_none=False) copy(new_key=None) delete() @@ -222,7 +222,7 @@ class Object(TypeClass): """ return self.dbobj.execute_cmd(raw_string, sessid=sessid) - def msg(self, text=None, **kwargs):#message, from_obj=None, data=None, sessid=0): + def msg(self, text=None, from_obj=None, sessid=None, **kwargs): """ Emits something to any sessions attached to the object. @@ -235,13 +235,13 @@ class Object(TypeClass): """ self.dbobj.msg(text=text, **kwargs)#message, from_obj=from_obj, data=data, sessid=0) - def msg_contents(self, message, exclude=None, from_obj=None, data=None): + def msg_contents(self, text=None, exclude=None, from_obj=None, **kwargs): """ Emits something to all objects inside an object. exclude is a list of objects not to send to. See self.msg() for more info. """ - self.dbobj.msg_contents(message, exclude=exclude, from_obj=from_obj, data=data) + self.dbobj.msg_contents(text, exclude=exclude, from_obj=from_obj, **kwargs) def move_to(self, destination, quiet=False, emit_to_obj=None, use_destination=True, to_none=False): @@ -653,7 +653,7 @@ class Object(TypeClass): """ pass - def at_msg_receive(self, text=None, **kwargs):#from_obj=None, data=None): + def at_msg_receive(self, text=None, **kwargs): """ This hook is called whenever someone sends a message to this object. @@ -674,7 +674,7 @@ class Object(TypeClass): """ return True - def at_msg_send(self, text=None, **kwargs):#msg, to_obj=None, data=None): + def at_msg_send(self, text=None, to_obj=None, **kwargs): """ This is a hook that is called when /this/ object sends a message to another object with obj.msg() diff --git a/src/players/models.py b/src/players/models.py index 2e38cc4d0b..52ef760879 100644 --- a/src/players/models.py +++ b/src/players/models.py @@ -248,26 +248,31 @@ class PlayerDB(TypedObject, AbstractUser): # PlayerDB class access methods # - def msg(self, text=None, **kwargs):#outgoing_string, from_obj=None, data=None, sessid=None): + def msg(self, text=None, from_obj=None, sessid=None, **kwargs): """ Evennia -> User This is the main route for sending data back to the user from the server. outgoing_string (string) - text data to send from_obj (Object/Player) - source object of message to send - data (dict) - arbitrary data object containing eventual protocol-specific options sessid - the session id of the session to send to. If not given, return to all sessions connected to this player. This is usually only relevant when using msg() directly from a player-command (from a command on a Character, the character automatically stores and handles the sessid). + kwargs (dict) - All other keywords are parsed as extra data. """ - from_obj = kwargs.pop("from_obj", None) - sessid = kwargs.pop("sessid", 0) + if "data" in kwargs: + from src.utils import logger + logger.log_depmsg("PlayerDB:msg() 'data'-dict keyword is deprecated. Use **kwargs instead.") + data = kwargs.pop("data") + if isinstance(data, dict): + kwargs.update(data) + if from_obj: # call hook try: - _GA(from_obj, "at_msg_send")(text=text, to_obj=self, data=data) + _GA(from_obj, "at_msg_send")(text=text, to_obj=self, **kwargs) except Exception: pass outgoing_string = utils.to_str(text, force_string=True) @@ -275,7 +280,7 @@ class PlayerDB(TypedObject, AbstractUser): session = _MULTISESSION_MODE == 2 and sessid and _GA(self, "get_session")(sessid) or None if session: obj = session.puppet - if obj and not obj.at_msg_receive(text, **kwargs): + if obj and not obj.at_msg_receive(text=text, **kwargs): # if hook returns false, cancel send return session.msg(text=text, **kwargs) diff --git a/src/players/player.py b/src/players/player.py index 6f1c4c8b58..dc2b5cdeb4 100644 --- a/src/players/player.py +++ b/src/players/player.py @@ -64,7 +64,7 @@ class Player(TypeClass): * Helper methods - msg(outgoing_string, from_obj=None, data=None) + msg(outgoing_string, from_obj=None, **kwargs) swap_character(new_character, delete_old_character=False) execute_cmd(raw_string) search(ostring, global_search=False, attribute_name=None, use_nicks=False, location=None, ignore_errors=False, player=False) @@ -96,21 +96,21 @@ class Player(TypeClass): ## methods inherited from database model - def msg(self, text=None, **kwargs):#outgoing_string, from_obj=None, data=None, sessid=None): + def msg(self, text=None, from_obj=None, sessid=None, **kwargs): """ Evennia -> User This is the main route for sending data back to the user from the server. - outgoing_string (string) - text data to send + text (string) - text data to send from_obj (Object/Player) - source object of message to send - data (dict) - arbitrary data object containing eventual protocol-specific options sessid - the session id of the session to send to. If not given, return to all sessions connected to this player. This is usually only relevant when using msg() directly from a player-command (from a command on a Character, the character automatically stores and handles the sessid). + kwargs - extra data to send through protocol """ - self.dbobj.msg(text=text, **kwargs)#outgoing_string, from_obj=from_obj, data=data, sessid=sessid) + self.dbobj.msg(text=text, from_obj=from_obj, sessid=sessid, **kwargs) def swap_character(self, new_character, delete_old_character=False): """ diff --git a/src/server/amp.py b/src/server/amp.py index 7f4cffbdfa..ecfe130189 100644 --- a/src/server/amp.py +++ b/src/server/amp.py @@ -151,24 +151,6 @@ class MsgServer2Portal(amp.Command): errors = [(Exception, 'EXCEPTION')] response = [] -class OOBPortal2Server(amp.Command): - """ - OOB data portal -> server - """ - arguments = [('sessid', amp.Integer()), - ('data', amp.String())] - errors = [(Exception, "EXCEPTION")] - response = [] - -class OOBServer2Portal(amp.Command): - """ - OOB data server -> portal - """ - arguments = [('sessid', amp.Integer()), - ('data', amp.String())] - errors = [(Exception, "EXCEPTION")] - response = [] - class ServerAdmin(amp.Command): """ Portal -> Server @@ -289,7 +271,7 @@ class AMPProtocol(amp.AMP): msg=to_str(msg), ipart=icall, nparts=nmsglist, - data=dumps(data)).addErrback(self.errback, "OOBServer2Portal") + data=dumps(data)).addErrback(self.errback, "MsgServer2Portal") for icall, (msg, data) in enumerate(zip(msglist, datalist))] # Message definition + helper methods to call/create each message type @@ -317,11 +299,11 @@ class AMPProtocol(amp.AMP): data = "".join(t[2] for t in sorted(MSGBUFFER[sessid], key=lambda o:o[0])) del MSGBUFFER[sessid] # call session hook with the data - self.factory.server.sessions.data_in(sessid, msg, loads(data)) + self.factory.server.sessions.data_in(sessid, text=msg, **loads(data)) return {} MsgPortal2Server.responder(amp_msg_portal2server) - def call_remote_MsgPortal2Server(self, sessid, msg, data=""): + def call_remote_MsgPortal2Server(self, sessid, msg, **kwargs): """ Access method called by the Portal and executed on the Portal. """ @@ -332,10 +314,10 @@ class AMPProtocol(amp.AMP): msg=msg, ipart=0, nparts=1, - data=dumps(data)).addErrback(self.errback, "MsgPortal2Server") + data=dumps(kwargs)).addErrback(self.errback, "MsgPortal2Server") except amp.TooLong: # the msg (or data) was too long for AMP to send. We need to send in blocks. - return self.send_split_msg(sessid, msg, data, MsgPortal2Server) + return self.send_split_msg(sessid, msg, kwargs, MsgPortal2Server) # Server -> Portal message @@ -357,11 +339,11 @@ class AMPProtocol(amp.AMP): data = "".join(t[2] for t in sorted(MSGBUFFER[sessid], key=lambda o:o[0])) del MSGBUFFER[sessid] # call session hook with the data - self.factory.portal.sessions.data_out(sessid, msg, loads(data)) + self.factory.portal.sessions.data_out(sessid, text=msg, **loads(data)) return {} MsgServer2Portal.responder(amp_msg_server2portal) - def call_remote_MsgServer2Portal(self, sessid, msg, data=""): + def call_remote_MsgServer2Portal(self, sessid, msg, **kwargs): """ Access method called by the Server and executed on the Server. """ @@ -372,52 +354,10 @@ class AMPProtocol(amp.AMP): msg=to_str(msg), ipart=0, nparts=1, - data=dumps(data)).addErrback(self.errback, "OOBServer2Portal") + data=dumps(kwargs)).addErrback(self.errback, "MsgServer2Portal") except amp.TooLong: # the msg (or data) was too long for AMP to send. We need to send in blocks. - return self.send_split_msg(sessid, msg, data, MsgServer2Portal) - - # OOB Portal -> Server - - # Portal -> Server Msg - - def amp_oob_portal2server(self, sessid, data): - """ - Relays out-of-band data to server. This method is executed on the Server. - """ - #print "oob portal -> server (server side):", sessid, loads(data) - self.factory.server.sessions.oob_data_in(sessid, loads(data)) - return {} - OOBPortal2Server.responder(amp_oob_portal2server) - - def call_remote_OOBPortal2Server(self, sessid, data=""): - """ - Access method called by the Portal and executed on the Portal. - """ - #print "oob portal->server (portal side):", sessid, data - self.callRemote(OOBPortal2Server, - sessid=sessid, - data=dumps(data)).addErrback(self.errback, "OOBPortal2Server") - - # OOB Server -> Portal message - - def amp_oob_server2portal(self, sessid, data): - """ - Relays out-of-band data to Portal. This method is executed on the Portal. - """ - #print "oob server->portal (portal side):", sessid, data - self.factory.portal.sessions.oob_data_out(sessid, loads(data)) - return {} - OOBServer2Portal.responder(amp_oob_server2portal) - - def call_remote_OOBServer2Portal(self, sessid, data=""): - """ - Access method called by the Server and executed on the Portal. - """ - #print "oob server->portal (server side):", sessid, data - return self.callRemote(OOBServer2Portal, - sessid=sessid, - data=dumps(data)).addErrback(self.errback, "OOBServer2Portal") + return self.send_split_msg(sessid, msg, kwargs, MsgServer2Portal) # Server administration from the Portal side @@ -501,21 +441,19 @@ class AMPProtocol(amp.AMP): return {} PortalAdmin.responder(amp_portal_admin) - def call_remote_PortalAdmin(self, sessid, operation="", data=""): + def call_remote_PortalAdmin(self, sessid, operation="", **kwargs): """ Access method called by the server side. """ #print "portaladmin (server side):", sessid, ord(operation), data - data = dumps(data) - return self.callRemote(PortalAdmin, sessid=sessid, operation=operation, - data=data).addErrback(self.errback, "PortalAdmin") + data=dumps(kwargs)).addErrback(self.errback, "PortalAdmin") # Extra functions - def amp_function_call(self, module, function, args, kwargs): + def amp_function_call(self, module, function, args, **kwargs): """ This allows Portal- and Server-process to call an arbitrary function in the other process. It is intended for use by plugin modules. diff --git a/src/server/portal/portalsessionhandler.py b/src/server/portal/portalsessionhandler.py index 04228933f8..2424e14641 100644 --- a/src/server/portal/portalsessionhandler.py +++ b/src/server/portal/portalsessionhandler.py @@ -121,7 +121,7 @@ class PortalSessionHandler(SessionHandler): return [sess for sess in self.get_sessions(include_unloggedin=True) if hasattr(sess, 'suid') and sess.suid == suid] - def data_in(self, session, string="", data=""): + def data_in(self, session, string="", **kwargs): """ Called by portal sessions for relaying data coming in from the protocol to the server. data is @@ -130,7 +130,7 @@ class PortalSessionHandler(SessionHandler): #print "portal_data_in:", string self.portal.amp_protocol.call_remote_MsgPortal2Server(session.sessid, msg=string, - data=data) + data=kwargs) def announce_all(self, message): """ Send message to all connection sessions @@ -138,30 +138,13 @@ class PortalSessionHandler(SessionHandler): for session in self.sessions.values(): session.data_out(message) - def data_out(self, sessid, string="", data=""): + def data_out(self, sessid, text=None, **kwargs): """ Called by server for having the portal relay messages and data to the correct session protocol. """ session = self.sessions.get(sessid, None) if session: - session.data_out(string, data=data) - - def oob_data_in(self, session, data): - """ - OOB (Out-of-band) data Portal -> Server - """ - print "portal_oob_data_in:", data - self.portal.amp_protocol.call_remote_OOBPortal2Server(session.sessid, - data=data) - - def oob_data_out(self, sessid, data): - """ - OOB (Out-of-band) data Server -> Portal - """ - print "portal_oob_data_out:", data - session = self.sessions.get(sessid, None) - if session: - session.oob_data_out(data) + session.data_out(text=text, **kwargs) PORTAL_SESSIONS = PortalSessionHandler() diff --git a/src/server/portal/ssh.py b/src/server/portal/ssh.py index 84bbc3cc22..d179526ff6 100644 --- a/src/server/portal/ssh.py +++ b/src/server/portal/ssh.py @@ -173,22 +173,22 @@ class SshProtocol(Manhole, session.Session): self.data_out(reason) self.connectionLost(reason) - def data_out(self, string, data=None): + def data_out(self, text=None, **kwargs): """ Data Evennia -> Player access hook. 'data' argument is a dict parsed for string settings. + + ssh flags: + raw=True - leave all ansi markup and tokens unparsed + nomarkup=True - remove all ansi markup + """ try: - string = utils.to_str(string, encoding=self.encoding) + text = utils.to_str(text if text else "", encoding=self.encoding) except Exception, e: self.lineSend(str(e)) return - nomarkup = False - raw = False - if type(data) == dict: - # check if we want escape codes to go through unparsed. - raw = data.get("raw", False) - # check if we want to remove all markup - nomarkup = data.get("nomarkup", False) + raw = kwargs.get("raw", False) + nomarkup = kwargs.get("nomarkup", False) if raw: self.lineSend(string) else: diff --git a/src/server/portal/telnet.py b/src/server/portal/telnet.py index 0812d305f7..b264e1a382 100644 --- a/src/server/portal/telnet.py +++ b/src/server/portal/telnet.py @@ -141,28 +141,31 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session): self.data_out(reason) self.connectionLost(reason) - def data_out(self, string, data=None): + def data_out(self, text=None, **kwargs): """ generic hook method for engine to call in order to send data through the telnet connection. Data Evennia -> Player. - data argument may contain a dict with output flags. + + valid telnet kwargs: + raw=True - pass string through without any ansi processing (i.e. include Evennia + ansi markers but do not convert them into ansi tokens) + nomarkup=True - strip all ansi markup + + The telnet ttype negotiation flags, if any, are used if no kwargs are given. """ try: - string = utils.to_str(string, encoding=self.encoding) + text = utils.to_str(text if text else "", encoding=self.encoding) except Exception, e: self.sendLine(str(e)) return ttype = self.protocol_flags.get('TTYPE', {}) + raw = kwargs.get("raw", False) nomarkup = not (ttype or ttype.get('256 COLORS') or ttype.get('ANSI') or not ttype.get("init_done")) - raw = False - if type(data) == dict: - # check if we want escape codes to go through unparsed. - raw = data.get("raw", False) - # check if we want to remove all markup (TTYPE override) - nomarkup = data.get("nomarkup", False) + nomarkup = kwargs.get("nomarkup", nomarkup) if raw: - self.sendLine(string) + # no processing whatsoever + self.sendLine(text) else: # we need to make sure to kill the color at the end in order to match the webclient output. - self.sendLine(ansi.parse_ansi(_RE_N.sub("", string) + "{n", strip_ansi=nomarkup, xterm256=ttype.get('256 COLORS'))) + self.sendLine(ansi.parse_ansi(_RE_N.sub("", text) + "{n", strip_ansi=nomarkup, xterm256=ttype.get('256 COLORS'))) diff --git a/src/server/portal/webclient.py b/src/server/portal/webclient.py index 746d20d749..3737efb633 100644 --- a/src/server/portal/webclient.py +++ b/src/server/portal/webclient.py @@ -224,33 +224,24 @@ class WebClientSession(session.Session): self.client.lineSend(self.suid, reason) self.client.client_disconnect(self.suid) - def data_out(self, string='', data=None): + def data_out(self, text=None, **kwargs): """ Data Evennia -> Player access hook. - data argument may be used depending on - the client-server implementation. + webclient flags checked are + raw=True - no parsing at all (leave ansi-to-html markers unparsed) + nomarkup=True - clean out all ansi/html markers and tokens + """ - - if data: - # treat data? - pass - # string handling is similar to telnet try: - string = utils.to_str(string, encoding=self.encoding) - - nomarkup = False - raw = False - if type(data) == dict: - # check if we want escape codes to go through unparsed. - raw = data.get("raw", False) - # check if we want to remove all markup - nomarkup = data.get("nomarkup", False) + text = utils.to_str(text if text else "", encoding=self.encoding) + raw = kwargs.get("raw", False) + nomarkup = kwargs.get("nomarkup", False) if raw: - self.client.lineSend(self.suid, string) + self.client.lineSend(self.suid, text) else: - self.client.lineSend(self.suid, parse_html(string, strip_ansi=nomarkup)) + self.client.lineSend(self.suid, parse_html(text, strip_ansi=nomarkup)) return - except Exception, e: + except Exception: logger.log_trace() diff --git a/src/server/serversession.py b/src/server/serversession.py index 88efd1ef77..1952778582 100644 --- a/src/server/serversession.py +++ b/src/server/serversession.py @@ -13,7 +13,7 @@ from django.conf import settings from src.scripts.models import ScriptDB from src.comms.models import Channel from src.utils import logger, utils -from src.utils.utils import make_iter +from src.utils.utils import make_iter, to_str from src.commands import cmdhandler, cmdsethandler from src.server.session import Session @@ -162,25 +162,25 @@ class ServerSession(Session): # Player-visible idle time, not used in idle timeout calcs. self.cmd_last_visible = time.time() - def data_in(self, command_string): + def data_in(self, text=None, **kwargs): """ Send Player->Evennia. This will in effect execute a command string on the server. Eventual extra data moves through oob_data_in """ - # handle the 'idle' command - if str(command_string).strip() == IDLE_COMMAND: - self.update_session_counters(idle=True) - return - cmdhandler.cmdhandler(self, command_string, callertype="session", sessid=self.sessid) - #if self.logged_in: - # # the inmsg handler will relay to the right place - # self.player.inmsg(command_string, self) - #else: - # # we are not logged in. Execute cmd with the the session directly - # # (it uses the settings.UNLOGGEDIN cmdset) - # cmdhandler.cmdhandler(self, command_string, sessid=self.sessid) - self.update_session_counters() + if text: + # this is treated as a command input + text = to_str(text) + # handle the 'idle' command + if text.strip() == IDLE_COMMAND: + self.update_session_counters(idle=True) + return + cmdhandler.cmdhandler(self, text, callertype="session", sessid=self.sessid) + self.update_session_counters() + if "oob" in kwargs: + # relay to OOB handler + pass + execute_cmd = data_in # alias def data_out(self, text=None, **kwargs): @@ -189,58 +189,6 @@ class ServerSession(Session): """ self.sessionhandler.data_out(self, text=text, **kwargs) - def oob_data_in(self, data): - """ - This receives out-of-band data from the Portal. - - OBS - preliminary. OOB not yet functional in Evennia. Don't use. - - This method parses the data input (a dict) and uses - it to launch correct methods from those plugged into - the system. - - data = {oobkey: (funcname, (args), {kwargs}), - oobkey: (funcname, (args), {kwargs}), ...} - - example: - data = {"get_hp": ("oob_get_hp, [], {}), - "update_counter", ("counter", ["counter1"], {"now":True}) } - - All function names must be defined in settings.OOB_PLUGIN_MODULE. Each - function will be called with the oobkey and a back-reference to this session - as their first two arguments. - """ - - outdata = {} - - for oobkey, functuple in data.items(): - # loop through the data, calling available functions. - func = OOB_PLUGIN_MODULE.__dict__.get(functuple[0]) - if func: - try: - outdata[functuple[0]] = func(oobkey, self, *functuple[1], **functuple[2]) - except Exception: - logger.log_trace() - else: - logger.log_errmsg("oob_data_in error: funcname '%s' not found in OOB_PLUGIN_MODULE." % functuple[0]) - if outdata: - # we have a direct result - send it back right away - self.oob_data_out(outdata) - - - def oob_data_out(self, data): - """ - This sends data from Server to the Portal across the AMP connection. - - OBS - preliminary. OOB not yet functional in Evennia. Don't use. - - data = {oobkey: (funcname, (args), {kwargs}), - oobkey: (funcname, (args), {kwargs}), ...} - - """ - self.sessionhandler.oob_data_out(self, data) - - def __eq__(self, other): return self.address == other.address diff --git a/src/server/session.py b/src/server/session.py index 5cfed71b9c..536177a8a5 100644 --- a/src/server/session.py +++ b/src/server/session.py @@ -111,7 +111,7 @@ class Session(object): """ pass - def data_out(self, msg, data=None): + def data_out(self, text=None, **kwargs): """ generic hook for sending data out through the protocol. Server protocols can use this right away. Portal sessions @@ -119,26 +119,9 @@ class Session(object): """ pass - def data_in(self, msg, data=None): + def data_in(self, text=None, **kwargs): """ hook for protocols to send incoming data to the engine. """ pass - def oob_data_out(self, data): - """ - for Portal, this receives out-of-band data from Server across the AMP. - for Server, this sends out-of-band data to Portal. - - data is a dictionary - """ - pass - - def oob_data_in(self, data): - """ - for Portal, this sends out-of-band requests to Server over the AMP. - for Server, this receives data from Portal. - - data is a dictionary - """ - pass diff --git a/src/server/sessionhandler.py b/src/server/sessionhandler.py index d8778ce854..a0fc4d3645 100644 --- a/src/server/sessionhandler.py +++ b/src/server/sessionhandler.py @@ -367,31 +367,13 @@ class ServerSessionHandler(SessionHandler): self.server.amp_protocol.call_remote_MsgServer2Portal(sessid=session.sessid, msg=text, data=kwargs) - def data_in(self, sessid, text="", data=""): + def data_in(self, sessid, text="", **kwargs): """ Data Portal -> Server """ session = self.sessions.get(sessid, None) if session: - kwargs = data if data else {} - session.data_in(text, **kwargs) + session.data_in(text=text, **kwargs) - # ignore 'data' argument for now; this is otherwise the place - # to put custom effects on the server due to data input, e.g. - # from a custom client. - def oob_data_in(self, sessid, data): - """ - OOB (Out-of-band) Data Portal -> Server - """ - session = self.sessions.get(sessid, None) - if session: - session.oob_data_in(data) - - def oob_data_out(self, session, data): - """ - OOB (Out-of-band) Data Server -> Portal - """ - self.server.amp_protocol.call_remote_OOBServer2Portal(session.sessid, - data=data) SESSIONS = ServerSessionHandler() diff --git a/src/typeclasses/models.py b/src/typeclasses/models.py index 4b425a5595..060785f062 100644 --- a/src/typeclasses/models.py +++ b/src/typeclasses/models.py @@ -428,6 +428,9 @@ class NickHandler(AttributeHandler): """ Handles the addition and removal of Nicks (uses Attributes' strvalue and category fields) + + Nicks are stored as Attributes + with categories nick_ """ def has(self, key, category="inputline"): categry = "nick_%s" % category