def func(self): """ Main puppet method """ player = self.player session = self.session new_character = None if not self.args: new_character = player.db._last_puppet if not new_character: self.msg("Usage: @ic <character>") return if not new_character: # search for a matching character new_character = search.object_search(self.args) if new_character: new_character = new_character[0] else: self.msg("That is not a valid character choice.") return try: player.puppet_object(session, new_character) player.db._last_puppet = new_character except RuntimeError as exc: self.msg("{rYou cannot become {C%s{n: %s" % (new_character.name, exc))
def func(self): """ Main puppet method """ session = self.session player = self.account args = self.args # Find the character to puppet. new_character = None if args: # search for a matching character new_character = [char for char in search.object_search(args) if char.access(player, "puppet")] if not new_character: session.msg({"alert":_("That is not a valid character choice.")}) return new_character = new_character[0] else: # Puppet last character. new_character = player.db._last_puppet if not new_character: session.msg({"alert":_("You should puppet a character.")}) return try: player.puppet_object(session, new_character) player.db._last_puppet = new_character except RuntimeError as exc: session.msg({"alert":_("{rYou cannot become {C%s{n: %s") % (new_character.name, exc)})
def func(self): """ Main puppet method """ account = self.account session = self.session new_character = None if not self.args: new_character = account.db._last_puppet if not new_character: self.msg("Usage: @ic <character>") return if not new_character: # search for a matching character new_character = [char for char in search.object_search(self.args) if char.access(account, "puppet")] if not new_character: self.msg("That is not a valid character choice.") return if len(new_character) > 1: self.msg("Multiple targets with the same name:\n %s" % ", ".join("%s(#%s)" % (obj.key, obj.id) for obj in new_character)) return else: new_character = new_character[0] try: account.puppet_object(session, new_character) account.db._last_puppet = new_character except RuntimeError as exc: self.msg("|rYou cannot become |C%s|n: %s" % (new_character.name, exc))
def func(self): """ Main puppet method """ player = self.player sessid = self.sessid new_character = None if not self.args: new_character = player.db._last_puppet if not new_character: self.msg("Usage: @ic <character>") return if not new_character: # search for a matching character new_character = search.object_search(self.args) if new_character: new_character = new_character[0] else: self.msg("That is not a valid character choice.") return try: player.puppet_object(sessid, new_character) player.db._last_puppet = new_character except RuntimeError, exc: self.msg("{rYou cannot become {C%s{n: %s" % (new_character.name, exc))
def func(self): """ Main puppet method """ player = self.player session = self.session new_character = None if not self.args: new_character = player.db._last_puppet if not new_character: self.msg("Usage: @ic <character>") return if not new_character: # search for a matching character new_character = [ char for char in search.object_search(self.args) if char.access(player, "puppet") ] if not new_character: self.msg("That is not a valid character choice.") return if len(new_character) > 1: self.msg("Multiple targets with the same name:\n %s" % ", ".join("%s(#%s)" % (obj.key, obj.id) for obj in new_character)) return else: new_character = new_character[0] try: player.puppet_object(session, new_character) player.db._last_puppet = new_character except RuntimeError as exc: self.msg("{rYou cannot become {C%s{n: %s" % (new_character.name, exc))
def sheet(request, object_id): object_id = '#' + object_id try: character = object_search(object_id)[0] except IndexError: raise Http404("I couldn't find a character with that ID.") if not inherits_from(character, settings.BASE_CHARACTER_TYPECLASS): raise Http404("I couldn't find a character with that ID. " "Found something else instead.") return render(request, 'character/sheet.html', {'character': character})
def func(self): """Don't allow puppeting unless the chargen_complete attribute is set.""" if self.args: new_character = search.object_search(self.args) if new_character: new_character = new_character[0] if (new_character.is_typeclass('typeclasses.characters.Character') and not new_character.db.chargen_complete): self.session.execute_cmd('@charcreate {}'.format( new_character.key )) return else: self.msg("That is not a valid character choice.") return super(CmdIC, self).func()
def func(self): """Don't allow puppeting unless the chargen_complete attribute is set.""" if self.args: new_character = search.object_search(self.args) if new_character: new_character = new_character[0] if (new_character.is_typeclass( 'typeclasses.characters.Character') and not new_character.db.chargen_complete): self.session.execute_cmd('@charcreate {}'.format( new_character.key)) return else: self.msg("That is not a valid character choice.") return super(CmdIC, self).func()
def func(self): """ Main puppet method """ account = self.account session = self.session new_character = None if not self.args: new_character = account.db._last_puppet if not new_character: self.msg("Usage: ic <character>") return if not new_character: # search for a matching character new_character = [ char for char in search.object_search(self.args) if char.access(account, "puppet") ] if not new_character: self.msg("That is not a valid character choice.") return if len(new_character) > 1: self.msg( "Multiple targets with the same name:\n %s" % ", ".join("%s(#%s)" % (obj.key, obj.id) for obj in new_character) ) return else: new_character = new_character[0] try: account.puppet_object(session, new_character) account.db._last_puppet = new_character logger.log_sec( "Puppet Success: (Caller: %s, Target: %s, IP: %s)." % (account, new_character, self.session.address) ) except RuntimeError as exc: self.msg("|rYou cannot become |C%s|n: %s" % (new_character.name, exc)) logger.log_sec( "Puppet Failed: %s (Caller: %s, Target: %s, IP: %s)." % (exc, account, new_character, self.session.address) )
def prep_listener(self): """ Obtain, or create, a listener object to be placed in the target room. Triggered when first connecting to a IRC channel. """ # Search for listener. listener = search.object_search(self.key + "-listener", typeclass=DefaultListener) if listener: # Use an existing listener. listener = listener[0] listener.move_to(self.db.ev_location, quiet=True) self.db.listener = listener listener.db.bot = self else: # Create a new listener. listener = create.create_object(DefaultListener, key=self.key + "-listener", location=self.db.ev_location) self.db.listener = listener listener.db.bot = self
def func(self): """ Main puppet method """ account = self.account session = self.session new_character = None character_candidates = [] if not self.args: character_candidates = [account.db._last_puppet ] if account.db._last_puppet else [] if not character_candidates: self.msg("Usage: ic <character>") return else: # argument given if account.db._playable_characters: # look at the playable_characters list first character_candidates.extend( account.search( self.args, candidates=account.db._playable_characters, search_object=True, quiet=True, )) if account.locks.check_lockstring(account, "perm(Builder)"): # builders and higher should be able to puppet more than their # playable characters. if session.puppet: # start by local search - this helps to avoid the user # getting locked into their playable characters should one # happen to be named the same as another. We replace the suggestion # from playable_characters here - this allows builders to puppet objects # with the same name as their playable chars should it be necessary # (by going to the same location). character_candidates = [ char for char in session.puppet.search(self.args, quiet=True) if char.access(account, "puppet") ] if not character_candidates: # fall back to global search only if Builder+ has no # playable_characers in list and is not standing in a room # with a matching char. character_candidates.extend([ char for char in search.object_search(self.args) if char.access(account, "puppet") ]) # handle possible candidates if not character_candidates: self.msg("That is not a valid character choice.") return if len(character_candidates) > 1: self.msg("Multiple targets with the same name:\n %s" % ", ".join("%s(#%s)" % (obj.key, obj.id) for obj in character_candidates)) return else: new_character = character_candidates[0] # do the puppet puppet try: account.puppet_object(session, new_character) account.db._last_puppet = new_character logger.log_sec( "Puppet Success: (Caller: %s, Target: %s, IP: %s)." % (account, new_character, self.session.address)) except RuntimeError as exc: self.msg("|rYou cannot become |C%s|n: %s" % (new_character.name, exc)) logger.log_sec( "Puppet Failed: %s (Caller: %s, Target: %s, IP: %s)." % (exc, account, new_character, self.session.address))
def execute_cmd(self, session=None, txt=None, **kwargs): """ Take incoming data and make the appropriate action. This acts as a CommandHandler of sorts for the various "type" of actions the Portal bot returns to the Server. This is triggered by the bot_data_in Inputfunc. Args: session (Session, optional): Session responsible for this command. Note that this is the bot. txt (str, optional): Command string. Kwargs: user (str): The name of the user who sent the message. channel (str): The name of channel the message was sent to. nicklist (list, optional): Set if `type='nicklist'`. This is a list of nicks returned by calling the `self.get_nicklist`. It must look for a list `self._nicklist_callers` which will contain all callers waiting for the nicklist. timings (float, optional): Set if `type='ping'`. This is the return (in seconds) of a ping request triggered with `self.ping`. The return must look for a list `self._ping_callers` which will contain all callers waiting for the ping return. type (str): The type of response returned by the IRC bot. Including: "nicklist": Returned when first joining a channel. "joined": Returned when a new user joins a channel. "left": Returned when a user leaves a channel. "privmsg": Returned when the bot is directly messaged. "action": Returned when a user uses /me in IRC Everything else is assumed to be text to speak. """ if kwargs["type"] == "nicklist": """ Returned when first joining a channel. """ # Send Nicklist to requesting players if hasattr(self, "_nicklist_callers") and self._nicklist_callers: chstr = "%s (%s:%s)" % (self.db.irc_channel, self.db.irc_network, self.db.irc_port) nicklist = ", ".join( sorted(kwargs["nicklist"], key=lambda n: n.lower())) for obj in self._nicklist_callers: obj.msg("Nicks at %s:\n %s" % (chstr, nicklist)) self._nicklist_callers = [] return # Called by AccountBot to initiate puppets. else: self.prep_listener() # Prepare puppets self.db.puppetdict = {} for nick in kwargs["nicklist"]: self.prep_puppet(ansi.strip_ansi(nick)) # Hide stale puppets. for puppet in search.search_tag(self.key + "-puppet"): if puppet.location is not None \ and puppet not in self.db.puppetdict.values(): puppet.move_to(None, to_none=True) return elif kwargs["type"] == "ping": """ Returned by the ping command. """ if hasattr(self, "_ping_callers") and self._ping_callers: chstr = "%s (%s:%s)" % (self.db.irc_channel, self.db.irc_network, self.db.irc_port) for obj in self._ping_callers: obj.msg("IRC ping return from %s took %ss." % (chstr, kwargs["timing"])) self._ping_callers = [] return elif kwargs["type"] == "joined": """ Returned when a new user joins a channel - Prepare Puppet """ for nick in kwargs["nicklist"]: self.prep_puppet(ansi.strip_ansi(nick)) return elif kwargs["type"] == "renamed": """ Returned when IRC user changes nick. """ puppetdict = self.db.puppetdict newname = kwargs["newname"] oldname = kwargs["oldname"] # List of puppet objects matching newname. puppetlist = [ puppet for puppet in search.search_tag(self.key + "-puppet") if puppet.key == newname ] # Use an existing puppet. if puppetlist: # Set up new puppet puppetdict[newname] = puppetlist[0] if not puppetdict[newname].location == self.db.ev_location: puppetdict[newname].move_to(self.db.ev_location, quiet=True) self.db.ev_location.msg_contents(oldname + " has become " + newname) # Pack up old puppet self.db.puppetdict[oldname].move_to(None, to_none=True) del self.db.puppetdict[oldname] # Else recycle old puppet. elif oldname in puppetdict: puppetdict[oldname].key = newname puppetdict[newname] = puppetdict.pop(oldname) self.db.ev_location.msg_contents(oldname + " has become " + newname) return elif kwargs["type"] == "left": """ Returned when a user leaves a channel - Pack up puppet. """ for nick in kwargs["nicklist"]: nick = ansi.strip_ansi(nick) if nick in self.db.puppetdict: self.db.puppetdict[nick].move_to(None, to_none=True) self.db.ev_location.msg_contents( self.db.puppetdict[nick].key + self.db.puppetdict[nick].db.exit) del self.db.puppetdict[nick] return elif kwargs["type"] == "action": """ Returned when a user uses /me in IRC Causes in-game puppet to act out pose. """ nick = ansi.strip_ansi(kwargs["user"]) if nick in self.db.puppetdict: self.db.puppetdict[nick].execute_cmd("pose " + txt) return elif kwargs["type"] == "msg": """ Returned when a user speaks in the IRC channel. Causes in-game puppet to say the message. """ nick = ansi.strip_ansi(kwargs["user"]) if nick in self.db.puppetdict: self.db.puppetdict[nick].execute_cmd("say " + txt) return elif kwargs["type"] == "privmsg": """ Returned when the bot is directly messaged. Users can issue commands to the Server bot through IRC PM. "Look" - Look at the Evennia location and those within it. "whisper" - Whisper in-game account "whisper user = msg" All other messages return a help message. """ user = ansi.strip_ansi(kwargs["user"]) # Look command - Look at the Evennia location and those within it. if txt.lower().startswith("look"): # If given input:'look target' use target else use location. try: txt = txt.split(" ", 1)[1] result = search.object_search( txt, candidates=self.db.ev_location.contents) target = result[0] if result else None except IndexError: target = self.db.ev_location if not target: text = "'%s' could not be located." % txt else: text = target.return_appearance(self.db.puppetdict[user]) self.msg((text, {"type": "privmsg"}), from_obj=self, user=user) return # Whisper command - Whisper a user in game through a puppet. elif txt.lower().startswith("whisper"): # Parse input. Must be in form 'whisper nick = msg' txt = txt.split(" ", 1)[1] try: nick, msg = txt.split("=") except Exception: text = "Whisper Usage: 'Whisper Character = Msg'" self.msg((text, { "type": "privmsg" }), from_obj=self, user=user) return if not nick or not msg: text = "Whisper Usage: 'Whisper Character = Msg'" self.msg((text, { "type": "privmsg" }), from_obj=self, user=user) return puppet = self.db.puppetdict[ansi.strip_ansi(user)] target = puppet.search(nick) if not target: text = "Whisper Aborted: Character could not be found." self.msg((text, { "type": "privmsg" }), from_obj=self, user=user) return puppet.execute_cmd("whisper " + nick + "=" + msg) return # Default message - Acts as help information. else: text = """\ Command list: -"Look": Look at the Evennia location and those within it. "look [object]" -"whisper": Whisper an in-game character as your puppet. "whisper Character = msg" - All other messages return this help message.\ """ # Return Message. self.msg((text, {"type": "privmsg"}), from_obj=self, user=user)
def execute_cmd(self, session=None, txt=None, **kwargs): """ Take incoming data and make the appropriate action. This acts as a CommandHandler of sorts for the various "type" of actions the Portal bot returns to the Server. This is triggered by the bot_data_in Inputfunc. Args: session (Session, optional): Session responsible for this command. Note that this is the bot. txt (str, optional): Command string. Kwargs: user (str): The name of the user who sent the message. channel (str): The name of channel the message was sent to. nicklist (list, optional): Set if `type='nicklist'`. This is a list of nicks returned by calling the `self.get_nicklist`. It must look for a list `self._nicklist_callers` which will contain all callers waiting for the nicklist. timings (float, optional): Set if `type='ping'`. This is the return (in seconds) of a ping request triggered with `self.ping`. The return must look for a list `self._ping_callers` which will contain all callers waiting for the ping return. type (str): The type of response returned by the IRC bot. Including: "nicklist": Returned when first joining a channel. "joined": Returned when a new user joins a channel. "left": Returned when a user leaves a channel. "privmsg": Returned when the bot is directly messaged. "action": Returned when a user uses /me in IRC Everything else is assumed to be text to speak. """ if kwargs["type"] == "nicklist": """ Returned when first joining a channel. """ if hasattr(self, "_nicklist_callers") and self._nicklist_callers: chstr = "%s (%s:%s)" % (self.db.irc_channel, self.db.irc_network, self.db.irc_port) nicklist = ", ".join( sorted(kwargs["nicklist"], key=lambda n: n.lower())) for obj in self._nicklist_callers: obj.msg("Nicks at %s:\n %s" % (chstr, nicklist)) self._nicklist_callers = [] return else: # Prepare blank reference dictionary. self.db.puppetdict = {} # Prepare listener. self.prep_listener() # Prepare puppets. for nick in kwargs["nicklist"]: self.prep_puppet(ansi.strip_ansi(nick)) # Hide stale puppets. for puppet in search.search_tag(self.key + "-puppet"): if puppet.location is not None \ and puppet not in self.db.puppetdict.values(): puppet.move_to(None, to_none=True) return elif kwargs["type"] == "ping": """ Returned by the ping command. """ if hasattr(self, "_ping_callers") and self._ping_callers: chstr = "%s (%s:%s)" % (self.db.irc_channel, self.db.irc_network, self.db.irc_port) for obj in self._ping_callers: obj.msg("IRC ping return from %s took %ss." % (chstr, kwargs["timing"])) self._ping_callers = [] return elif kwargs["type"] == "joined": """ Returned when a new user joins a channel. """ # Prepare puppet. for nick in kwargs["nicklist"]: self.prep_puppet(ansi.strip_ansi(nick)) return elif kwargs["type"] == "renamed": """ Returned when IRC user changes nick. """ puppetdict = self.db.puppetdict newname = kwargs["newname"] oldname = kwargs["oldname"] newkey = self.db.puppetprefix + newname + self.db.puppetsuffix oldkey = self.db.puppetprefix + oldname + self.db.puppetsuffix # List of puppet objects matching newname. puppetlist = [ puppet for puppet in search.search_tag(self.key + "-puppet") if puppet.key == newkey ] # Use an existing puppet. if puppetlist: # Set up new puppet puppetdict[newname] = puppetlist[0] if not puppetdict[newname].location == self.db.ev_location: puppetdict[newname].move_to(self.db.ev_location, quiet=True) self.db.ev_location.msg_contents(oldkey + " has become " + newkey) # Pack up old puppet self.db.puppetdict[oldname].move_to(None, to_none=True) del self.db.puppetdict[oldname] # Else recycle old puppet. elif oldname in puppetdict: print('Reusing puppetbot from puppetdict: ', oldname, puppetdict[oldname]) puppetdict[oldname].key = newkey puppetdict[newname] = puppetdict.pop(oldname) self.db.ev_location.msg_contents(oldkey + " has become " + newkey) return elif kwargs["type"] == "left": """ Returned when a user leaves a channel. """ # Pack up puppet. for nick in kwargs["nicklist"]: nick = ansi.strip_ansi(nick) if nick in self.db.puppetdict: self.db.puppetdict[nick].move_to(None, to_none=True) self.db.ev_location.msg_contents( self.db.puppetdict[nick].key + self.db.puppetexitmsg) del self.db.puppetdict[nick] return elif kwargs["type"] == "privmsg": """ Returned when the bot is directly messaged. Users can issue commands to the Server bot through IRC PM. "Who" - Return a list of current users in the MUD "About" - Describes the bot and the connected MUD "Look" - Look at the Evennia location and those within it. "whisper" - Whisper in-game account "whisper user = msg" "Desc" - If empty, shows in-game bots description. Else, sets bots in-game bot description to given value. All other messages return a help message. """ user = kwargs["user"] # Who command - Returns online users in game. if txt.lower().startswith("who"): # return server WHO list (abbreviated for IRC) global _SESSIONS if not _SESSIONS: from evennia.server.sessionhandler import \ SESSIONS as _SESSIONS whos = [] t0 = time.time() for sess in _SESSIONS.get_sessions(): delta_cmd = t0 - sess.cmd_last_visible delta_conn = t0 - session.conn_time account = sess.get_account() whos.append("%s (%s/%s)" % (utils.crop("|w%s|n" % account.name, width=25), utils.time_format(delta_conn, 0), utils.time_format(delta_cmd, 1))) text = "Who list (online/idle): %s" % ", ".join( sorted(whos, key=lambda w: w.lower())) # Return Message. super(ServerBot, self).msg(privmsg=((text, ), {"user": user})) # About command - Return a blurb explaining origin of bot. elif txt.lower().startswith("about"): # some bot info text = self.db.botdesc # Return Message. super(ServerBot, self).msg(privmsg=((text, ), {"user": user})) # Look command - Look at the Evennia location and those within it. elif txt.lower().startswith("look"): # Mirror in-game look command. txt = txt.partition(" ")[2] if not txt: target = self.db.ev_location else: result = search.object_search( txt, candidates=self.db.ev_location.contents) target = result[0] if len(result) > 0 else None if not target: text = "'%s' could not be located." % txt else: text = target.return_appearance( self.db.puppetdict[user]).replace('\n', ' ') # Return Message. super(ServerBot, self).msg(privmsg=((text, ), {"user": user})) # Desc command - If empty, shows in-game bots description. Else, # sets bots in-game bot description to given value. elif txt.lower().startswith("desc"): # Split text - set desc as text or return current desc if none. txt = txt.partition(" ")[2] if not txt: text = self.db.puppetdict[user].db.desc else: self.db.puppetdict[user].db.desc = txt text = "Desc changed to: " + txt # Return Message. super(ServerBot, self).msg(privmsg=((text, ), {"user": user})) # Whisper command - Whisper a user in game through a puppet. elif txt.lower().startswith("whisper"): # Parse input. Must be in form 'whisper nick = msg' txt = txt.split(" ", 1)[1] try: nick, msg = txt.split("=") except Exception: text = "Whisper Usage: 'Whisper Character = Msg'" super(ServerBot, self).msg(privmsg=((text, ), { "user": user })) return if not nick or not msg: text = "Whisper Usage: 'Whisper Character = Msg'" super(ServerBot, self).msg(privmsg=((text, ), { "user": user })) return puppet = self.db.puppetdict[ansi.strip_ansi(user)] target = puppet.search(nick) if not target: text = "Whisper Aborted: Character could not be found." # Return Message. super(ServerBot, self).msg(privmsg=((text, ), { "user": user })) return puppet.execute_cmd("whisper " + nick + "=" + msg) text = 'You whisper to ' + nick + ', "' + msg + '"' super(ServerBot, self).msg(privmsg=((text, ), {"user": user})) return # Default message - Acts as help information. else: text = ( "Command list: \n" ' "Who": Return a list of online users on %s.\n' ' "About": Returns information about %s.\n' ' "Look": Look at the Evennia location and those within it.\n' ' "Desc": If empty, shows in-game bots description. Else, sets\n' ' "whisper" - Whisper in-game account "whisper user = msg"\n' ' bots in-game bot description to given value.\n' ' All other messages return this help message.') % ( settings.SERVERNAME, settings.SERVERNAME) # Return Message. super(ServerBot, self).msg(privmsg=((text, ), {"user": user})) elif kwargs["type"] == "action": """ Returned when a user uses /me in IRC """ # Cause puppet to act out pose. if ansi.strip_ansi(kwargs["user"]) in self.db.puppetdict: user = ansi.strip_ansi(kwargs["user"]) self.db.puppetdict[user].execute_cmd("pose " + txt) return else: """ Everything else is assumed to be text to speak. """ # Cause the puppet to say the message. if ansi.strip_ansi(kwargs["user"]) in self.db.puppetdict: user = ansi.strip_ansi(kwargs["user"]) self.db.puppetdict[user].execute_cmd("say " + txt) return