def do_skill(self, action, caller, obj, **kwargs): """ Do a function. Args: action: (string) statements separated by ";" caller: (object) statement's caller obj: (object) caller's current target Returns: None """ if not action: return # execute the statement functions = action.split(";") results = [] for function in functions: try: result = exec_function(self.skill_func_set, function, caller, obj, **kwargs) if result: results.append(result) except Exception, e: logger.log_errmsg("Exec function error: %s %s" % (function, repr(e))) traceback.print_exc()
def exec_function(func_set, func_word, caller, obj, **kwargs): """ Do function. Args: func_set: (object) function set func_word: (string) function string, such as: func("value") caller: (object) statement's caller obj: (object) caller's target Returns: function result """ # separate function's key and args try: pos = func_word.index("(") func_key = func_word[:pos] func_args = ast.literal_eval(func_word[pos:]) if type(func_args) != tuple: func_args = (func_args,) except ValueError: func_key = func_word func_args = () func_class = func_set.get_func_class(func_key) if not func_class: logger.log_errmsg("Statement error: Can not find function: %s of %s." % (func_key, func_word)) return func_obj = func_class() func_obj.set(caller, obj, func_args, **kwargs) return func_obj.func()
def msg(self, text=None, from_obj=None, session=None, **kwargs): """ Emits something to a session attached to the object. Args: text (str, optional): The message to send from_obj (obj, optional): object that is sending. If given, at_msg_send will be called session (Session or list, optional): Session or list of Sessions to relay data to, if any. If set, will force send to these sessions. If unset, who receives the message depends on the MULTISESSION_MODE. Notes: `at_msg_receive` will be called on this Object. All extra kwargs will be passed on to the protocol. """ # Send messages to the client. Messages are in format of JSON. raw = kwargs.get("raw", False) if not raw: try: text = json.dumps(text) except Exception, e: text = json.dumps({"err": "There is an error occurred while outputing messages."}) logger.log_errmsg("json.dumps failed: %s" % e)
def load_data_fields(self, key): """ Get object's data record from database. Args: key: (String) object's data key. Returns: None """ # Get model and key names. if not key: key = self.get_data_key() if not key: raise MudderyError("No data key.") for data_model in self.get_models(): # Get db model model_obj = apps.get_model(settings.WORLD_DATA_APP, data_model) if not model_obj: logger.log_errmsg("%s can not open model %s" % (key, data_model)) continue # Get data record. try: data = model_obj.objects.get(key=key) except Exception, e: logger.log_errmsg("%s can not find key %s" % (key, key)) continue # Set data. for field in data._meta.fields: setattr(self.dfield, field.name, data.serializable_value(field.name))
def load_data_fields(self): """ Get object's data record from database. """ # Get model and key names. key = self.get_data_key() if not key: return models = OBJECT_KEY_HANDLER.get_models(key) for model in models: # Get db model model_obj = apps.get_model(settings.WORLD_DATA_APP, model) if not model_obj: logger.log_errmsg("%s can not open model %s" % (key, model)) continue # Get data record. try: data = model_obj.objects.get(key=key) except Exception, e: logger.log_errmsg("%s can not find key %s" % (key, key)) continue # Set data. for field in data._meta.fields: setattr(self.dfield, field.name, data.serializable_value(field.name))
def set_home(self, home): """ Set object's home. Args: home: (string) Home's name. Must be the key of data info. """ home_obj = None if home: # If has home, search home object. home_obj = utils.search_obj_data_key(home) if not home_obj: logger.log_errmsg("%s can't find home %s!" % (self.get_data_key(), home)) return home_obj = home_obj[0] if self.home == home_obj: # No change. return if self == home_obj: # Can't set home to itself. logger.log_errmsg("%s can't set home to itself!" % self.get_data_key()) return self.home = home_obj
def set_location(self, location): """ Set object's location. Args: location: (string) Location's name. Must be the key of data info. """ location_obj = None if location: # If has location, search location object. location_obj = utils.search_obj_data_key(location) if not location_obj: logger.log_errmsg("%s can't find location %s!" % (self.get_data_key(), location)) return location_obj = location_obj[0] if self.location == location_obj: # No change. return if self == location_obj: # Can't set location to itself. logger.log_errmsg("%s can't teleport itself to itself!" % self.get_data_key()) return # try the teleport self.move_to(location_obj, quiet=True, to_none=True)
def attack_clone_target(self, target_key, target_level=0, desc=""): """ Attack the image of a target. This creates a new character object for attack. The origin target will not be affected. Args: target_key: (string) the info key of the target. target_level: (int) target's level desc: (string) string to describe this attack Returns: (boolean) fight begins """ if target_level == 0: # Find the target and get its level. obj = utils.search_obj_data_key(target_key) if not obj: logger.log_errmsg("Can not find the target %s." % target_key) return False obj = obj[0] target_level = obj.db.level # Create a target. target = build_object(target_key, set_location=False) if not target: logger.log_errmsg("Can not create the target %s." % target_key) return False target.set_level(target_level) target.is_clone = True return self.attack_target(target, desc)
def set_obj_destination(self, destination): """ Set object's destination Args: destination: (string) Destination's name. Must be the key of data info. """ if not destination: # remove destination self.destination = destination return # set new destination destination_obj = None if destination: # If has destination, search destination object. destination_obj = utils.search_obj_data_key(destination) if not destination_obj: logger.log_errmsg("%s can't find destination %s!" % (self.get_data_key(), destination)) return destination_obj = destination_obj[0] if self.destination == destination_obj: # No change. return if self == destination_obj: # Can't set destination to itself. logger.log_errmsg("%s can't set destination to itself!" % self.get_data_key()) return self.destination = destination_obj
def func(self): "Do checks, create account and login." session = self.caller args = self.args try: playername = args["playername"] password = args["password"] connect = args["connect"] except Exception: string = 'Syntax error!' string += '\nUsage:' string += '\n {"cmd":"create_connect",' string += '\n "args":{' string += '\n "playername":<playername>,' string += '\n "password":<password>,' string += '\n "connect":<connect>' string += '\n }' logger.log_errmsg(string) session.msg({"alert":string}) return new_player = create_normal_player(session, playername, password) if new_player: if connect: session.msg({"login":{"name": playername, "dbref": new_player.dbref}}) session.sessionhandler.login(session, new_player) else: session.msg({"created":{"name": playername, "dbref": new_player.dbref}})
def load_shops(self): """ Load character's shop. """ # shops records shop_records = NPC_SHOPS.filter(self.get_data_key()) shop_keys = set([record.shop for record in shop_records]) # remove old shops for shop_key in self.db.shops: if shop_key not in shop_keys: # remove this shop self.db.shops[shop_key].delete() del self.db.shops[shop_key] # add new shop for shop_record in shop_records: shop_key = shop_record.shop if shop_key not in self.db.shops: # Create shop object. shop_obj = build_object(shop_key) if not shop_obj: logger.log_errmsg("Can't create shop: %s" % shop_key) continue self.db.shops[shop_key] = shop_obj
def load_goods(self): """ Load shop goods. """ # shops records goods_records = DATA_SETS.shop_goods.objects.filter(shop=self.get_data_key()) goods_keys = set([record.key for record in goods_records]) # search current goods current_goods = set() for item in self.contents: key = item.get_data_key() if key in goods_keys: current_goods.add(key) else: # remove goods that is not in goods_keys item.delete() # add new goods for goods_record in goods_records: goods_key = goods_record.key if goods_key not in current_goods: # Create shop_goods object. goods_obj = build_object(goods_key) if not goods_obj: logger.log_errmsg("Can't create goods: %s" % goods_key) continue goods_obj.move_to(self, quiet=True)
def create_help_entry(key, entrytext, category="General", locks=None): """ Create a static help entry in the help database. Note that Command help entries are dynamic and directly taken from the __doc__ entries of the command. The database-stored help entries are intended for more general help on the game, more extensive info, in-game setting information and so on. """ global _HelpEntry if not _HelpEntry: from evennia.help.models import HelpEntry as _HelpEntry try: new_help = _HelpEntry() new_help.key = key new_help.entrytext = entrytext new_help.help_category = category if locks: new_help.locks.add(locks) new_help.save() return new_help except IntegrityError: string = "Could not add help entry: key '%s' already exists." % key logger.log_errmsg(string) return None except Exception: logger.log_trace() return None
def attack_clone_target(self, target_key, target_level=0, desc=""): """ Attack the image of a target. This creates a new character object for attack. The origin target will not be affected. Args: target_key: (string) the info key of the target. target_level: (int) target's level desc: (string) string to describe this attack Returns: None """ if target_level == 0: # find the target and get level obj = utils.search_obj_info_key(target_key) if not obj: logger.log_errmsg("Can not find the target %s." % target_key) return obj = obj[0] target_level = obj.db.level # Create a target. target = build_object(target_key) if not target: logger.log_errmsg("Can not create the target %s." % target_key) return target.set_level(target_level) self.attack_target(target, desc)
def load_data(self): """ Set data_info to the object." """ super(MudderyObjectCreator, self).load_data() # Load creator info. self.loot_verb = getattr(self.dfield, "loot_verb", None) if not self.loot_verb: self.loot_verb = LS("Loot") self.loot_condition = getattr(self.dfield, "loot_condition", None) # Load loot list. loot_list = [] try: model_obj = apps.get_model(settings.WORLD_DATA_APP, settings.LOOT_LIST) loot_records = model_obj.objects.filter(provider=self.get_data_key()) for loot_record in loot_records: loot_object = {"object": loot_record.serializable_value("object"), "number": loot_record.number, "odds": loot_record.odds, "quest": loot_record.serializable_value("quest"), "condition": loot_record.condition} loot_list.append(loot_object) except Exception, e: logger.log_errmsg("Can't load loot info %s: %s" % (self.get_data_key(), e))
def add(self, scriptclass, key=None, autostart=True): """ Add a script to this object. Args: scriptclass (Scriptclass, Script or str): Either a class object inheriting from DefaultScript, an instantiated script object or a python path to such a class object. key (str, optional): Identifier for the script (often set in script definition and listings) autostart (bool, optional): Start the script upon adding it. """ if self.obj.__dbclass__.__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) if not script: logger.log_errmsg("Script %s could not be created and/or started." % scriptclass) return False return True
def match_condition(self, condition, caller, obj, **kwargs): """ Check a condition. Args: condition: (string) a condition expression caller: (object) statement's caller obj: (object) caller's current target Returns: (boolean) the result of the condition """ if not condition: return True # calculate functions first exec_string = exec_condition(self.condition_func_set, condition, caller, obj, **kwargs) try: # do condition result = eval(exec_string) except Exception, e: logger.log_errmsg("Exec function error: %s %s" % (function, repr(e))) traceback.print_exc() return False
def get_objs_with_db_property_value(self, property_name, property_value, candidates=None, typeclasses=None): """ Get objects with a specific field name and value. Args: property_name (str): Field name to search for. property_value (any): Value required for field with `property_name` to have. candidates (list, optional): List of objects to limit search to. typeclasses (list, optional): List of typeclass-path strings to restrict matches with """ if isinstance(property_value, basestring): property_value = to_unicode(property_value) if isinstance(property_name, basestring): if not property_name.startswith("db_"): property_name = "db_%s" % property_name querykwargs = {property_name: property_value} cand_restriction = ( candidates != None and Q(pk__in=[_GA(obj, "id") for obj in make_iter(candidates) if obj]) or Q() ) type_restriction = typeclasses and Q(db_typeclass_path__in=make_iter(typeclasses)) or Q() try: return list(self.filter(cand_restriction & type_restriction & Q(**querykwargs))) except exceptions.FieldError: return [] except ValueError: from evennia.utils import logger logger.log_errmsg( "The property '%s' does not support search criteria of the type %s." % (property_name, type(property_value)) ) return []
def process(self, request): """ Process a request by the func key. Args: request: HTTP request. """ if request.method == "OPTIONS": return HttpResponse() path = request.path_info if self.path_prefix: if path.find(self.path_prefix) == 0: path = path[len(self.path_prefix):] data = {} func = "" args = {} if request.POST: data = request.POST.dict() print("data: %s" % data) func = data.get("func", "") args_text = data.get("args", None) if args_text: args = json.loads(args_text) if not data: try: data = json.loads(request.body) func = data.get("func", "") args = data.get("args", {}) except Exception, e: logger.log_errmsg("Parse request body error: %s" % e) pass
def cast_skill(self, target): """ Cast this skill. """ if self.passive: if self.db.owner: self.db.owner.msg({"alert":LS("You can not cast a passive skill.")}) return self.db.target = target if self.cd > 0: if time.time() < self.db.cd_end_time: if self.db.owner: self.db.owner.msg({"msg":LS("This skill is not ready yet!")}) return try: function = getattr(skills, self.get_info_key()) result = function(self.db.owner, self.db.target, effect=self.effect) # set cd if self.cd > 0: self.db.cd_end_time = time.time() + self.cd except Exception, e: ostring = "Can not cast skill %s: %s" % (self.get_info_key(), e) logger.log_errmsg(ostring) print traceback.format_exc() if self.db.owner: self.db.owner.msg({"msg":LS("Can not cast this skill!")}) return
def __value_set(self, value): "Setter. Allows for self.value = value" if utils.has_parent('django.db.models.base.Model', value): # we have to protect against storing db objects. logger.log_errmsg("ServerConfig cannot store db objects! (%s)" % value) return self.db_value = pickle.dumps(value) self.save()
def _save_tree(self): "recursively traverse back up the tree, save when we reach the root" if self._parent: self._parent._save_tree() elif self._db_obj: self._db_obj.value = self else: logger.log_errmsg("_SaverMutable %s has no root Attribute to save to." % self)
def __location_set(self, location): "Set location, checking for loops and allowing dbref" if isinstance(location, (basestring, int)): # allow setting of #dbref dbid = dbref(location, reqhash=False) if dbid: try: location = ObjectDB.objects.get(id=dbid) except ObjectDoesNotExist: # maybe it is just a name that happens to look like a dbid pass try: def is_loc_loop(loc, depth=0): "Recursively traverse target location, trying to catch a loop." if depth > 10: return elif loc == self: raise RuntimeError elif loc == None: raise RuntimeWarning return is_loc_loop(loc.db_location, depth + 1) try: is_loc_loop(location) except RuntimeWarning: pass # if we get to this point we are ready to change location old_location = self.db_location # this is checked in _db_db_location_post_save below self._safe_contents_update = True # actually set the field (this will error if location is invalid) self.db_location = location self.save(update_fields=["db_location"]) # remove the safe flag del self._safe_contents_update # update the contents cache if old_location: old_location.contents_cache.remove(self) if self.db_location: self.db_location.contents_cache.add(self) except RuntimeError: errmsg = "Error: %s.location = %s creates a location loop." % (self.key, location) logger.log_errmsg(errmsg) raise # RuntimeError(errmsg) except Exception, e: errmsg = "Error (%s): %s is not a valid location." % (str(e), location) logger.log_errmsg(errmsg) raise # Exception(errmsg)
def func(err, *args, **kwargs): err.trap(Exception) err = err.getErrorMessage() if use_timeout and err == _PROC_ERR: err = "Process took longer than %ss and timed out." % use_timeout if f: return f(err, *args, **kwargs) else: err = "Error reported from subprocess: '%s'" % err logger.log_errmsg(err)
def func(self): """ Uses the Django admin api. Note that unlogged-in commands have a unique position in that their func() receives a session object instead of a source_object like all other types of logged-in commands (this is because there is no object yet before the player has logged in) """ session = self.caller try: playername = self.args["playername"] password = self.args["password"] except Exception: string = 'Syntax error!' string += '\nUsage:' string += '\n {"cmd":"create_account",' string += '\n "args":{' string += '\n "playername":<playername>,' string += '\n "password":<password>' string += '\n }' logger.log_errmsg(string) session.msg({"alert":string}) return # check for too many login errors too quick. if _throttle(session, maxlim=5, timeout=5*60, storage=_LATEST_FAILED_LOGINS): # timeout is 5 minutes. session.msg({"alert":LS("{RYou made too many connection attempts. Try again in a few minutes.{n")}) return # Guest login if playername.lower() == "guest": enabled, new_player = create_guest_player(session) if new_player: session.msg({"login":{"name": playername, "dbref": new_player.dbref}}) session.sessionhandler.login(session, new_player) if enabled: return if not password: session.msg({"alert":LS("{Please input password.")}) return player = create_normal_player(session, playername, password) if player: # actually do the login. This will call all other hooks: # session.at_login() # player.at_init() # always called when object is loaded from disk # player.at_first_login() # only once, for player-centric setup # player.at_pre_login() # player.at_post_login(session=session) session.msg({"login":{"name": playername, "dbref": player.dbref}}) session.sessionhandler.login(session, player)
def _cache_lockfuncs(): "Updates the cache." global _LOCKFUNCS _LOCKFUNCS = {} for modulepath in settings.LOCK_FUNC_MODULES: mod = utils.mod_import(modulepath) if mod: for tup in (tup for tup in inspect.getmembers(mod) if callable(tup[1])): _LOCKFUNCS[tup[0]] = tup[1] else: logger.log_errmsg("Couldn't load %s from PERMISSION_FUNC_MODULES." % modulepath)
def cast_skill(self, target): """ Cast this skill. Args: target: (object) skill's target Returns: (result, cd): result: (dict) skill's result cd: (dice) skill's cd """ owner = self.db.owner time_now = time.time() if not self.passive: if owner: gcd = getattr(owner, "gcd_finish_time", 0) if time_now < gcd: owner.msg({"msg": LS("This skill is not ready yet!")}) return if time_now < self.db.cd_finish_time: # skill in CD if owner: owner.msg({"msg": LS("This skill is not ready yet!")}) return if not self.function_call: logger.log_errmsg("Can not find skill function: %s" % self.get_data_key()) if owner: owner.msg({"msg": LS("Can not cast this skill!")}) return result = {} cd = {} try: # call skill function result = self.function_call(owner, target, effect=self.effect) if not self.passive: # set cd time_now = time.time() if self.cd > 0: self.db.cd_finish_time = time_now + self.cd cd = {"skill": self.get_data_key(), # skill's key "cd": self.cd} # global cd except Exception, e: ostring = "Can not cast skill %s: %s" % (self.get_data_key(), e) logger.log_tracemsg(ostring) if owner: owner.msg({"msg": LS("Can not cast this skill!")}) return
def set_lock(self, lock): """ Set object's lock. Args: lock: (string) Object's lock string. """ if lock: try: self.locks.add(lock) except Exception: logger.log_errmsg("%s can't set lock %s." % (self.get_info_key(), lock))
def func(self): "Implement the command" caller = self.caller try: import_all() build_all(caller) except Exception, e: ostring = "Can't build world: %s" % e caller.msg(ostring) logger.log_errmsg(ostring) logger.log_errmsg(traceback.format_exc())
def data_out(self, text=None, **kwargs): """ Send Evennia -> User Convert to JSON. """ raw = kwargs.get("raw", False) if not raw: try: text = json.dumps(text) except Exception, e: text = json.dumps({"err": "There is an error occurred while outputing messages."}) logger.log_errmsg("json.dumps failed: %s" % e)
class Processer(object): """ HTTP request processer. """ def __init__(self, path_prefix=None): if path_prefix: if path_prefix[0] != "/": path_prefix = "/" + path_prefix self.path_prefix = path_prefix @csrf_exempt def process(self, request): """ Process a request by the func key. Args: request: HTTP request. """ if request.method == "OPTIONS": return HttpResponse() path = request.path_info if self.path_prefix: if path.find(self.path_prefix) == 0: path = path[len(self.path_prefix):] data = {} func = "" args = {} if request.POST: data = request.POST.dict() print("data: %s" % data) func = data.get("func", "") args_text = data.get("args", None) if args_text: args = json.loads(args_text) if not data: try: data = json.loads(request.body) func = data.get("func", "") args = data.get("args", {}) except Exception, e: logger.log_errmsg("Parse request body error: %s" % e) pass print("request: '%s' '%s' '%s'" % (path, func, args)) processor = REQUEST_SET.get(path, func) if not processor: logger.log_errmsg("Can not find API: %s %s" % (path, func)) return error_response(ERR.no_api, msg="Can not find API: %s %s" % (path, func)) # check authentication if processor.login and not request.user.is_authenticated: logger.log_errmsg("Need authentication.") return error_response(ERR.no_authentication, msg="Need authentication.") # check staff if processor.staff and not request.user.is_staff and not request.user.is_superuser: return error_response(ERR.no_permission, msg="No permission.") # call function try: response = processor.func(args, request) except MudderyError, e: logger.log_errmsg("Error: %s, %s" % (e.code, e.message)) response = error_response(e.code, msg=e.message, data=e.data)
# Set attributes. attr = {} try: # Convert string to dict attributes = ast.literal_eval(attributes) except Exception, e: logger.log_errmsg("%s can't load attributes %s: %s" % (self.get_info_key(), attributes, e)) for key in attr: # Add attributes. try: self.attributes.add(key, attr[key]) except Exception: logger.log_errmsg("%s can't set attribute %s!" % (self.get_info_key(), key)) def set_obj_destination(self, destination): """ Set object's destination Args: destination: (string) Destination's name. Must be the key of data info. """ destination_obj = None if destination: # If has destination, search destination object. destination_obj = utils.search_obj_info_key(destination) if not destination_obj:
def func(self): """ Uses the Django admin api. Note that unlogged-in commands have a unique position in that their func() receives a session object instead of a source_object like all other types of logged-in commands (this is because there is no object yet before the player has logged in) """ session = self.caller # check for too many login errors too quick. # if _throttle(session, maxlim=5, timeout=5, storage=_LATEST_FAILED_LOGINS): # # timeout is 5 minutes. # session.msg("{RYou made too many connection attempts. Try again in a few minutes.{n") # return args = self.args # extract quoted parts parts = [ part.strip() for part in re.split(r"\"|\'", args) if part.strip() ] if len(parts) == 1: # this was (hopefully) due to no quotes being found, or a guest login parts = parts[0].split(None, 1) # Guest login if len(parts) == 1 and parts[0].lower( ) == "guest" and settings.GUEST_ENABLED: try: # Find an available guest name. for playername in settings.GUEST_LIST: if not PlayerDB.objects.filter( username__iexact=playername): break playername = None if playername == None: session.msg( "All guest accounts are in use. Please try again later." ) return password = "******" % getrandbits(64) home = ObjectDB.objects.get_id(settings.GUEST_HOME) permissions = settings.PERMISSION_GUEST_DEFAULT typeclass = settings.BASE_CHARACTER_TYPECLASS ptypeclass = settings.BASE_GUEST_TYPECLASS new_player = _create_player(session, playername, password, permissions, ptypeclass) if new_player: _create_character(session, new_player, typeclass, home, permissions) session.sessionhandler.login(session, new_player) except Exception: # We are in the middle between logged in and -not, so we have # to handle tracebacks ourselves at this point. If we don't, # we won't see any errors at all. string = "%s\nThis is a bug. Please e-mail an admin if the problem persists." session.msg(string % (traceback.format_exc())) logger.log_errmsg(traceback.format_exc()) finally: return if len(parts) != 2: session.msg("\n\r Usage (without <>): connect <name> <password>") return playername, password = parts # Match account name and check password player = PlayerDB.objects.get_player_from_name(playername) pswd = None if player: pswd = player.check_password(password) if not (player and pswd): # No playername or password match string = "Wrong login information given.\nIf you have spaces in your name or " \ "password, don't forget to enclose it in quotes. Also capitalization matters." \ "\nIf you are new you should first create a new account " \ "using the 'create' command." session.msg(string) # this just updates the throttle _throttle(session, storage=_LATEST_FAILED_LOGINS) return # Check IP and/or name bans bans = ServerConfig.objects.conf("server_bans") if bans and (any(tup[0] == player.name.lower() for tup in bans) or any(tup[2].match(session.address) for tup in bans if tup[2])): # this is a banned IP or name! string = "{rYou have been banned and cannot continue from here." \ "\nIf you feel this ban is in error, please email an admin.{x" session.msg(string) session.execute_cmd("quit") return # actually do the login. This will call all other hooks: # session.at_login() # player.at_init() # always called when object is loaded from disk # player.at_pre_login() # player.at_first_login() # only once # player.at_post_login(sessid=sessid) session.sessionhandler.login(session, player)
def func(self): "Do checks and create account" session = self.caller try: playername = self.args["playername"] nickname = self.args["nickname"] password = self.args["password"] except Exception: string = 'Syntax error!' string += '\nUsage:' string += '\n {"cmd":"create_account",' string += '\n "args":{' string += '\n "playername":<playername>,' string += '\n "nickname":<nickname>,' string += '\n "password":<password>' string += '\n }' logger.log_errmsg(string) self.caller.msg({"alert": string}) return # sanity checks if not re.findall(r'^[\w. @+-]+$', playername) or not (0 < len(playername) <= 30): # this echoes the restrictions made by django's auth # module (except not allowing spaces, for convenience of # logging in). string = "\n\r Playername can max be 30 characters or fewer. Letters, spaces, digits and @/./+/-/_ only." session.msg({"alert": string}) return # strip excessive spaces in playername playername = re.sub(r"\s+", " ", playername).strip() if PlayerDB.objects.filter(username__iexact=playername): # player already exists (we also ignore capitalization here) session.msg({ "alert": "Sorry, there is already a player with the name '%s'." % playername }) return # Reserve playernames found in GUEST_LIST if settings.GUEST_LIST and playername.lower() in map( str.lower, settings.GUEST_LIST): string = "\n\r That name is reserved. Please choose another Playername." session.msg({"alert": string}) return # sanity checks if not (0 < len(nickname) <= 30): # Nickname's length string = "\n\r Nickname can max be 30 characters or fewer." session.msg({"alert": string}) return # strip excessive spaces in playername nickname = re.sub(r"\s+", " ", nickname).strip() if not re.findall(r'^[\w. @+-]+$', password) or not (3 < len(password)): string = "\n\r Password should be longer than 3 characers. Letters, spaces, " \ "digits and @\\.\\+\\-\\_ only." \ "\nFor best security, make it longer than 8 characters. You can also use a phrase of" \ "\nmany words if you enclose the password in quotes." session.msg({"alert": string}) return # Check IP and/or name bans bans = ServerConfig.objects.conf("server_bans") if bans and (any(tup[0] == playername.lower() for tup in bans) or any(tup[2].match(session.address) for tup in bans if tup[2])): # this is a banned IP or name! string = "{rYou have been banned and cannot continue from here." \ "\nIf you feel this ban is in error, please email an admin.{x" session.msg({"alert": string}) session.execute_cmd('{"cmd":"quit","args":""}') return # everything's ok. Create the new player account. try: permissions = settings.PERMISSION_PLAYER_DEFAULT typeclass = settings.BASE_CHARACTER_TYPECLASS new_player = _create_player(session, playername, password, permissions) if new_player: if MULTISESSION_MODE < 2: default_home = ObjectDB.objects.get_id( settings.DEFAULT_PLAYER_HOME) _create_character(settings.DEFAULT_PLAYER_CHARACTER_KEY, 1, session, new_player, typeclass, default_home, permissions, nickname) # tell the caller everything went well. session.msg({"created": playername}) except Exception: # We are in the middle between logged in and -not, so we have # to handle tracebacks ourselves at this point. If we don't, # we won't see any errors at all. string = "%s\nThis is a bug. Please e-mail an admin if the problem persists." session.msg({"alert": string % (traceback.format_exc())}) logger.log_errmsg(traceback.format_exc())
def func(self): """ Uses the Django admin api. Note that unlogged-in commands have a unique position in that their func() receives a session object instead of a source_object like all other types of logged-in commands (this is because there is no object yet before the player has logged in) """ session = self.caller # check for too many login errors too quick. if _throttle(session, maxlim=5, timeout=5 * 60, storage=_LATEST_FAILED_LOGINS): # timeout is 5 minutes. session.msg( "{RВы совершаете слишклм много подключений. Подождите пару минут и попробуйте снова.{n" ) return args = self.args # extract quoted parts parts = [ part.strip() for part in re.split(r"\"|\'", args) if part.strip() ] if len(parts) == 1: # this was (hopefully) due to no quotes being found, or a guest login parts = parts[0].split(None, 1) # Guest login if len(parts) == 1 and parts[0].lower( ) == "guest" and settings.GUEST_ENABLED: try: # Find an available guest name. for playername in settings.GUEST_LIST: if not PlayerDB.objects.filter( username__iexact=playername): break playername = None if playername == None: session.msg( "Все гостевые аккаунты сейчас используются. Попробуйте немного позже." ) return password = "******" % getrandbits(64) home = ObjectDB.objects.get_id(settings.GUEST_HOME) permissions = settings.PERMISSION_GUEST_DEFAULT typeclass = settings.BASE_CHARACTER_TYPECLASS ptypeclass = settings.BASE_GUEST_TYPECLASS new_player = _create_player(session, playername, password, permissions, ptypeclass) if new_player: _create_character(session, new_player, typeclass, home, permissions) session.sessionhandler.login(session, new_player) except Exception: # We are in the middle between logged in and -not, so we have # to handle tracebacks ourselves at this point. If we don't, # we won't see any errors at all. string = "%s\nЭто баг. Напишите пожалуйста на почту администратора." session.msg(string % (traceback.format_exc())) logger.log_errmsg(traceback.format_exc()) finally: return if len(parts) != 2: session.msg( "\n\r Использование (без <>): коннект <имя пользователя> <пароль>. Сокашенные варианты: кон, ко, войти" ) return playername, password = parts # Match account name and check password player = PlayerDB.objects.get_player_from_name(playername) pswd = None if player: pswd = player.check_password(password) if not (player and pswd): # No playername or password match string = "Неверные логин или пароль.\nЕсли в вашем логине или " \ "пароле есть пробелы, поместите их в кавычки." \ "\nЕсли вы новичек, создайте аккаунт при помощи" \ "команды 'создать'." session.msg(string) # this just updates the throttle _throttle(session, storage=_LATEST_FAILED_LOGINS) # calls player hook for a failed login if possible. if player: player.at_failed_login(session) return # Check IP and/or name bans bans = ServerConfig.objects.conf("server_bans") if bans and (any(tup[0] == player.name.lower() for tup in bans) or any(tup[2].match(session.address) for tup in bans if tup[2])): # this is a banned IP or name! string = "{rВы были забанены." \ "\nЕсли считате, что мы были не правы, пишите на е-маил администратора.{x" session.msg(string) session.execute_cmd("quit") return # actually do the login. This will call all other hooks: # session.at_login() # player.at_init() # always called when object is loaded from disk # player.at_pre_login() # player.at_first_login() # only once # player.at_post_login(sessid=sessid) session.sessionhandler.login(session, player)
def func(self): "Do checks and create account" session = self.caller args = self.args.strip() # extract quoted parts parts = [ part.strip() for part in re.split(r"\"|\'", args) if part.strip() ] if len(parts) == 1: # this was (hopefully) due to no quotes being found parts = parts[0].split(None, 1) if len(parts) != 2: string = u"\n Использование (без <>): создать <имя персонажа> <пароль>" \ u"\nЕсли <имя персонажа> или <пароль> содержат пробелы, нужно взять их в ковычки" session.msg(string) return playername, password = parts # sanity checks if not re.findall('^[\w. @+-]+$', playername, re.UNICODE) or not (0 < len(playername) <= 30): # this echoes the restrictions made by django's auth # module (except not allowing spaces, for convenience of # logging in). string = u"\n\r Имя персонажа не должно превышать 30 символов. Имя может содержать только, буквы пробелы, цифры и @/./+/-/_" #string = "\n\r Playername can max be 30 characters or fewer. Letters, spaces, digits and @/./+/-/_ only." session.msg(string) return # strip excessive spaces in playername playername = re.sub(r"\s+", " ", playername).strip() if PlayerDB.objects.filter(username__iexact=playername): # player already exists (we also ignore capitalization here) session.msg(u"Игрок с таким именем '%s' уже есть." % playername) return # Reserve playernames found in GUEST_LIST if settings.GUEST_LIST and playername.lower() in map( str.lower, settings.GUEST_LIST): string = u"\n\r Это имя зарезервировано. Пожалуйста выберите другое имя." session.msg(string) return if not re.findall('^[\w. @+-]+$', password, re.UNICODE) or not (3 < len(password)): string = u"\n\r Пароль должен быть больше трех символов и может состоять только из пробелов, цифр @\.\+\-\_" \ u"\nДля лучшей безопасности выберите пароль от 8 символов " session.msg(string) return # Check IP and/or name bans bans = ServerConfig.objects.conf("server_bans") if bans and (any(tup[0] == playername.lower() for tup in bans) or any(tup[2].match(session.address) for tup in bans if tup[2])): # this is a banned IP or name! string = u"{rТы забанен{x" session.msg(string) session.execute_cmd("quit") return # everything's ok. Create the new player account. try: permissions = settings.PERMISSION_PLAYER_DEFAULT typeclass = settings.BASE_CHARACTER_TYPECLASS new_player = _create_player(session, playername, password, permissions) if new_player: if MULTISESSION_MODE < 2: default_home = ObjectDB.objects.get_id( settings.DEFAULT_HOME) _create_character(session, new_player, typeclass, default_home, permissions) # tell the caller everything went well. string = u"Новый аккаунт создан Добро пожаловать %%USERNAME%%" if " " in playername: string += u"\n\nТеперь можно войти в игру 'connect \"%s\" <пароль>'." else: string += u"\n\nТеперь можно войти в игру 'connect %s <пароль>'." session.msg(string % (playername)) except Exception: # We are in the middle between logged in and -not, so we have # to handle tracebacks ourselves at this point. If we don't, # we won't see any errors at all. string = u"%s\nСлучилась проблема, чиним." session.msg(string % (traceback.format_exc())) logger.log_errmsg(traceback.format_exc())
def cmdhandler(called_by, raw_string, _testing=False, callertype="session", sessid=None, **kwargs): """ This is the main function to handle any string sent to the engine. called_by - object on which this was called from. This is either a Session, a Player or an Object. raw_string - the command string given on the command line _testing - if we should actually execute the command or not. if True, the command instance will be returned instead. callertype - this is one of "session", "player" or "object", in decending order. So when the Session is the caller, it will merge its own cmdset into cmdsets from both Player and eventual puppeted Object (and cmdsets in its room etc). A Player will only include its own cmdset and the Objects and so on. Merge order is the same order, so that Object cmdsets are merged in last, giving them precendence for same-name and same-prio commands. sessid - Relevant if callertype is "player" - the session id will help retrieve the correct cmdsets from puppeted objects. **kwargs - other keyword arguments will be assigned as named variables on the retrieved command object *before* it is executed. This is unuesed in default Evennia but may be used by code to set custom flags or special operating conditions for a command as it executes. Note that this function returns a deferred! """ @inlineCallbacks def _run_command(cmd, cmdname, args): """ This initializes and runs the Command instance once the parser has identified it as either a normal command or one of the system commands. Args: cmd (Command): command object cmdname (str): name of command args (str): extra text entered after the identified command Returns: deferred (Deferred): this will fire when the func() method returns. """ try: # Assign useful variables to the instance cmd.caller = caller cmd.cmdstring = cmdname cmd.args = args cmd.cmdset = cmdset cmd.sessid = session.sessid if session else sessid cmd.session = session cmd.player = player cmd.raw_string = unformatted_raw_string #cmd.obj # set via on-object cmdset handler for each command, # since this may be different for every command when # merging multuple cmdsets if hasattr(cmd, 'obj') and hasattr(cmd.obj, 'scripts'): # cmd.obj is automatically made available by the cmdhandler. # we make sure to validate its scripts. yield cmd.obj.scripts.validate() if _testing: # only return the command instance returnValue(cmd) # assign custom kwargs to found cmd object for key, val in kwargs.items(): setattr(cmd, key, val) # pre-command hook abort = yield cmd.at_pre_cmd() if abort: # abort sequence returnValue(abort) # Parse and execute yield cmd.parse() # main command code # (return value is normally None) ret = yield cmd.func() # post-command hook yield cmd.at_post_cmd() if cmd.save_for_next: # store a reference to this command, possibly # accessible by the next command. caller.ndb.last_cmd = yield copy(cmd) else: caller.ndb.last_cmd = None # return result to the deferred returnValue(ret) except Exception: logger.log_trace() _msg_err(caller, _ERROR_UNTRAPPED) raise ErrorReported raw_string = to_unicode(raw_string, force_string=True) session, player, obj = None, None, None if callertype == "session": session = called_by player = session.player if player: obj = yield player.get_puppet(session.sessid) elif callertype == "player": player = called_by if sessid: session = player.get_session(sessid) obj = yield player.get_puppet(sessid) elif callertype == "object": obj = called_by else: raise RuntimeError("cmdhandler: callertype %s is not valid." % callertype) # the caller will be the one to receive messages and excert its permissions. # we assign the caller with preference 'bottom up' caller = obj or player or session # The error_to is the default recipient for errors. Tries to make sure a player # does not get spammed for errors while preserving character mirroring. error_to = obj or session or player try: # catch bugs in cmdhandler itself try: # catch special-type commands cmdset = yield get_and_merge_cmdsets(caller, session, player, obj, callertype, sessid) if not cmdset: # this is bad and shouldn't happen. raise NoCmdSets unformatted_raw_string = raw_string raw_string = raw_string.strip() if not raw_string: # Empty input. Test for system command instead. syscmd = yield cmdset.get(CMD_NOINPUT) sysarg = "" raise ExecSystemCommand(syscmd, sysarg) # Parse the input string and match to available cmdset. # This also checks for permissions, so all commands in match # are commands the caller is allowed to call. matches = yield _COMMAND_PARSER(raw_string, cmdset, caller) # Deal with matches if len(matches) > 1: # We have a multiple-match syscmd = yield cmdset.get(CMD_MULTIMATCH) sysarg = _("There were multiple matches.") if syscmd: # use custom CMD_MULTIMATCH syscmd.matches = matches else: # fall back to default error handling sysarg = yield at_multimatch_cmd(caller, matches) raise ExecSystemCommand(syscmd, sysarg) if len(matches) == 1: # We have a unique command match. But it may still be invalid. match = matches[0] cmdname, args, cmd = match[0], match[1], match[2] # check if we allow this type of command if cmdset.no_channels and hasattr( cmd, "is_channel") and cmd.is_channel: matches = [] if cmdset.no_exits and hasattr(cmd, "is_exit") and cmd.is_exit: matches = [] if not matches: # No commands match our entered command syscmd = yield cmdset.get(CMD_NOMATCH) if syscmd: # use custom CMD_NOMATCH command sysarg = raw_string else: # fallback to default error text sysarg = _("Command '%s' is not available.") % raw_string suggestions = string_suggestions( raw_string, cmdset.get_all_cmd_keys_and_aliases(caller), cutoff=0.7, maxnum=3) if suggestions: sysarg += _( " Maybe you meant %s?") % utils.list_to_string( suggestions, _('or'), addquote=True) else: sysarg += _(" Type \"help\" for help.") raise ExecSystemCommand(syscmd, sysarg) # Check if this is a Channel-cmd match. if hasattr(cmd, 'is_channel') and cmd.is_channel: # even if a user-defined syscmd is not defined, the # found cmd is already a system command in its own right. syscmd = yield cmdset.get(CMD_CHANNEL) if syscmd: # replace system command with custom version cmd = syscmd cmd.sessid = session.sessid if session else None sysarg = "%s:%s" % (cmdname, args) raise ExecSystemCommand(cmd, sysarg) # A normal command. ret = yield _run_command(cmd, cmdname, args) returnValue(ret) except ErrorReported: # this error was already reported, so we # catch it here and don't pass it on. pass except ExecSystemCommand, exc: # Not a normal command: run a system command, if available, # or fall back to a return string. syscmd = exc.syscmd sysarg = exc.sysarg if syscmd: ret = yield _run_command(syscmd, syscmd.key, sysarg) returnValue(ret) elif sysarg: # return system arg error_to.msg(exc.sysarg, _nomulti=True) except NoCmdSets: # Critical error. logger.log_errmsg("No cmdsets found: %s" % caller) error_to.msg(_ERROR_NOCMDSETS, _nomulti=True) except Exception: # We should not end up here. If we do, it's a programming bug. logger.log_trace() _msg_err(error_to, _ERROR_UNTRAPPED)
def func(self): """ Uses the Django admin api. Note that unlogged-in commands have a unique position in that their func() receives a session object instead of a source_object like all other types of logged-in commands (this is because there is no object yet before the player has logged in) """ session = self.caller try: playername = self.args["playername"] password = self.args["password"] except Exception: string = 'Syntax error!' string += '\nUsage:' string += '\n {"cmd":"create_account",' string += '\n "args":{' string += '\n "playername":<playername>,' string += '\n "password":<password>' string += '\n }' logger.log_errmsg(string) self.caller.msg({"alert": string}) return # check for too many login errors too quick. if _throttle(session, maxlim=5, timeout=5 * 60, storage=_LATEST_FAILED_LOGINS): # timeout is 5 minutes. session.msg({ "alert": "{RYou made too many connection attempts. Try again in a few minutes.{n" }) return # Guest login if playername.lower() == "guest" and settings.GUEST_ENABLED: try: # Find an available guest name. for playername in settings.GUEST_LIST: if not PlayerDB.objects.filter( username__iexact=playername): break playername = None if playername == None: session.msg({ "alert": "All guest accounts are in use. Please try again later." }) return password = "******" % getrandbits(64) home = ObjectDB.objects.get_id(settings.GUEST_HOME) permissions = settings.PERMISSION_GUEST_DEFAULT typeclass = settings.BASE_CHARACTER_TYPECLASS ptypeclass = settings.BASE_GUEST_TYPECLASS new_player = _create_player(session, playername, password, permissions, ptypeclass) if new_player: _create_character(settings.DEFAULT_PLAYER_CHARACTER_KEY, 1, session, new_player, typeclass, home, permissions, "GUEST") session.sessionhandler.login(session, new_player) except Exception: # We are in the middle between logged in and -not, so we have # to handle tracebacks ourselves at this point. If we don't, # we won't see any errors at all. string = "%s\nThis is a bug. Please e-mail an admin if the problem persists." session.msg({"alert": string % (traceback.format_exc())}) logger.log_errmsg(traceback.format_exc()) return # Match account name and check password player = PlayerDB.objects.get_player_from_name(playername) pswd = None if player: pswd = player.check_password(password) if not (player and pswd): # No playername or password match string = "Wrong login information given.\nIf you have spaces in your name or " \ "password, don't forget to enclose it in quotes. Also capitalization matters." \ "\nIf you are new you should first create a new account " \ "using the 'create' command." session.msg({"alert": string}) # this just updates the throttle _throttle(session, storage=_LATEST_FAILED_LOGINS) return # Check IP and/or name bans bans = ServerConfig.objects.conf("server_bans") if bans and (any(tup[0] == player.name.lower() for tup in bans) or any(tup[2].match(session.address) for tup in bans if tup[2])): # this is a banned IP or name! string = "{rYou have been banned and cannot continue from here." \ "\nIf you feel this ban is in error, please email an admin.{x" session.msg({"alert": string}) session.execute_cmd('{"cmd":"quit","args":""}') return # actually do the login. This will call all other hooks: # session.at_login() # player.at_init() # always called when object is loaded from disk # player.at_pre_login() # player.at_first_login() # only once # player.at_post_login(sessid=sessid) session.msg({"login": {"name": playername, "dbref": player.dbref}}) session.sessionhandler.login(session, player)
def _errback(self, fail): "Report error" logger.log_errmsg("RSS feed error: %s" % fail.value)
# Get goods record. goods_record = None try: goods_model = apps.get_model(settings.WORLD_DATA_APP, settings.SHOP_GOODS) if goods_model: # Get records. goods_record = goods_model.objects.get(shop=shop_key, goods=goods_key) except Exception, e: logger.log_errmsg("Can not find goods %s in shop %s." % (shop_key, goods_key)) return # get price unit information unit_name = None unit_record = get_object_record(goods_record.unit) if not unit_record: logger.log_errmsg("Can not find %s price unit %s." % (goods_key, goods_record.unit)) return unit_name = unit_record.name # load goods object goods = self.db.goods if goods: if goods.get_data_key == goods_key: goods.load_data() else: goods.set_data_key(goods_key) else: goods = build_object(goods_key) if goods: self.db.goods = goods else:
def func(self): "Do checks and create account" session = self.caller try: playername, email, password = self.playerinfo except ValueError: string = "\n\r Usage (without <>): create \"<playername>\" <email> <password>" session.msg(string) return if not re.findall('^[\w. @+-]+$', playername) or not (0 < len(playername) <= 30): session.msg( "\n\r Playername can be max 30 characters, or less. Letters, spaces, dig\ its and @/./+/-/_ only." ) # this echoes the restrictions made by django's auth module. return if not email or not password: session.msg( "\n\r You have to supply an e-mail address followed by a password." ) return if not utils.validate_email_address(email): # check so the email at least looks ok. session.msg("'%s' is not a valid e-mail address." % email) return # Run sanity and security checks if PlayerDB.objects.filter(username=playername): # player already exists session.msg( "Sorry, there is already a player with the name '%s'." % playername) return if PlayerDB.objects.get_player_from_email(email): # email already set on a player session.msg( "Sorry, there is already a player with that email address.") return if len(password) < 3: # too short password string = "Your password must be at least 3 characters or longer." string += "\n\rFor best security, make it at least 8 characters long, " string += "avoid making it a real word and mix numbers into it." session.msg(string) return # everything's ok. Create the new player account. try: default_home = ObjectDB.objects.get_id(settings.DEFAULT_HOME) typeclass = settings.BASE_CHARACTER_TYPECLASS permissions = settings.PERMISSION_PLAYER_DEFAULT try: new_player = create.create_player(playername, email, password, permissions=permissions) except Exception, e: session.msg( "There was an error creating the default Player/Character:\n%s\n If this problem persists, contact an admin." % e) logger.log_trace() return # This needs to be called so the engine knows this player is # logging in for the first time. (so it knows to call the right # hooks during login later) utils.init_new_player(new_player) # join the new player to the public channel pchanneldef = settings.CHANNEL_PUBLIC if pchanneldef: pchannel = ChannelDB.objects.get_channel(pchanneldef[0]) if not pchannel.connect(new_player): string = "New player '%s' could not connect to public channel!" % new_player.key logger.log_errmsg(string) if MULTISESSION_MODE < 2: # if we only allow one character, create one with the same name as Player # (in mode 2, the character must be created manually once logging in) new_character = create.create_object(typeclass, key=playername, location=default_home, home=default_home, permissions=permissions) # set playable character list new_player.db._playable_characters.append(new_character) # allow only the character itself and the player to puppet this character (and Immortals). new_character.locks.add( "puppet:id(%i) or pid(%i) or perm(Immortals) or pperm(Immortals)" % (new_character.id, new_player.id)) # If no description is set, set a default description if not new_character.db.desc: new_character.db.desc = "This is a Player." # We need to set this to have @ic auto-connect to this character new_player.db._last_puppet = new_character # tell the caller everything went well. string = "A new account '%s' was created. Welcome!" if " " in playername: string += "\n\nYou can now log in with the command 'connect %s <your password>'." else: string += "\n\nYou can now log with the command 'connect %s <your password>'." session.msg(string % (playername, email))
def func(self): "Do checks, create account and login." session = self.caller try: playername = self.args["playername"] nickname = self.args["nickname"] password = self.args["password"] except Exception: string = 'Syntax error!' string += '\nUsage:' string += '\n {"cmd":"create_connect",' string += '\n "args":{' string += '\n "playername":<playername>,' string += '\n "nickname":<nickname>,' string += '\n "password":<password>' string += '\n }' logger.log_errmsg(string) self.caller.msg({"alert": string}) return # sanity checks if not re.findall('^[\w. @+-]+$', playername) or not (0 < len(playername) <= 30): # this echoes the restrictions made by django's auth # module (except not allowing spaces, for convenience of # logging in). string = "\n\r Playername can max be 30 characters or fewer. Letters, spaces, digits and @/./+/-/_ only." session.msg({"alert": string}) return # strip excessive spaces in playername playername = re.sub(r"\s+", " ", playername).strip() if PlayerDB.objects.filter(username__iexact=playername): # player already exists (we also ignore capitalization here) session.msg({ "alert": "Sorry, there is already a player with the name '%s'." % playername }) return # Reserve playernames found in GUEST_LIST if settings.GUEST_LIST and playername.lower() in ( guest.lower() for guest in settings.GUEST_LIST): string = "\n\r That name is reserved. Please choose another Playername." session.msg({"alert": string}) return # sanity checks if not (0 < len(nickname) <= 30): # Nickname's length string = "\n\r Nickname can max be 30 characters or fewer." session.msg({"alert": string}) return # strip excessive spaces in playername nickname = re.sub(r"\s+", " ", nickname).strip() if not re.findall('^[\w. @+-]+$', password) or not (3 < len(password)): string = "\n\r Password should be longer than 3 characers. Letters, spaces, digits and @\.\+\-\_ only." \ "\nFor best security, make it longer than 8 characters. You can also use a phrase of" \ "\nmany words if you enclose the password in quotes." session.msg({"alert": string}) return # Check IP and/or name bans bans = ServerConfig.objects.conf("server_bans") if bans and (any(tup[0] == playername.lower() for tup in bans) or any(tup[2].match(session.address) for tup in bans if tup[2])): # this is a banned IP or name! string = "{rYou have been banned and cannot continue from here." \ "\nIf you feel this ban is in error, please email an admin.{x" session.msg({"alert": string}) session.execute_cmd('{"cmd":"quit","args":""}') return # everything's ok. Create the new player account. try: permissions = settings.PERMISSION_PLAYER_DEFAULT typeclass = settings.BASE_CHARACTER_TYPECLASS new_player = _create_player(session, playername, password, permissions) if new_player: if MULTISESSION_MODE < 2: default_home = ObjectDB.objects.get_id( settings.DEFAULT_PLAYER_HOME) start_location = None start_location_key = GAME_SETTINGS.get( "start_location_key") if start_location_key: start_location = search_obj_data_key( start_location_key) if start_location: start_location = start_location[0] else: start_location = default_home _create_character( GAME_SETTINGS.get("default_player_model_key"), 1, session, new_player, typeclass, start_location, default_home, permissions, nickname) # tell the caller everything went well. # string = "A new account '%s' was created. Welcome!" # if " " in playername: # string += "\n\nYou can now log in with the command 'connect \"%s\" <your password>'." # else: # string += "\n\nYou can now log with the command 'connect %s <your password>'." # session.msg(string % (playername, playername)) # actually do the login. This will call all other hooks: # session.at_login() # player.at_init() # always called when object is loaded from disk # player.at_pre_login() # player.at_first_login() # only once # player.at_post_login(sessid=sessid) session.msg( {"login": { "name": playername, "dbref": new_player.dbref }}) session.sessionhandler.login(session, new_player) except Exception: # We are in the middle between logged in and -not, so we have # to handle tracebacks ourselves at this point. If we don't, # we won't see any errors at all. string = "%s\nThis is a bug. Please e-mail an admin if the problem persists." session.msg({"alert": string % (traceback.format_exc())}) logger.log_tracemsg()
def func(self): """ Uses the Django admin api. Note that unlogged-in commands have a unique position in that their func() receives a session object instead of a source_object like all other types of logged-in commands (this is because there is no object yet before the player has logged in) """ session = self.caller try: playername = self.args["playername"] password = self.args["password"] except Exception: string = 'Syntax error!' string += '\nUsage:' string += '\n {"cmd":"create_account",' string += '\n "args":{' string += '\n "playername":<playername>,' string += '\n "password":<password>' string += '\n }' logger.log_errmsg(string) session.msg({"alert": string}) return # check for too many login errors too quick. if _throttle(session, maxlim=5, timeout=5 * 60, storage=_LATEST_FAILED_LOGINS): # timeout is 5 minutes. session.msg({ "alert": LS("{RYou made too many connection attempts. Try again in a few minutes.{n" ) }) return # Guest login if playername.lower() == "guest": enabled, new_player = create_guest_player(session) if new_player: session.msg( {"login": { "name": playername, "dbref": new_player.dbref }}) session.sessionhandler.login(session, new_player) if enabled: return if not password: session.msg({"alert": LS("{Please input password.")}) return player = create_normal_player(session, playername, password) if player: # actually do the login. This will call all other hooks: # session.at_login() # player.at_init() # always called when object is loaded from disk # player.at_first_login() # only once, for player-centric setup # player.at_pre_login() # player.at_post_login(session=session) session.msg({"login": {"name": playername, "dbref": player.dbref}}) session.sessionhandler.login(session, player)
#logger.log_trace() errstring += _("Error in loading cmdset: No cmdset class '{classname}' in {path}.") errstring = errstring.format(classname=classname, path=python_path) except SyntaxError, e: #logger.log_trace() errstring += _("SyntaxError encountered when loading cmdset '{path}': {error}.") errstring = errstring.format(path=python_path, error=e) except Exception, e: #logger.log_trace() errstring += _("Compile/Run error when loading cmdset '{path}': {error}.") errstring = errstring.format(path=python_path, error=e) if errstring: # returning an empty error cmdset if not no_logging: logger.log_errmsg(errstring) if emit_to_obj and not ServerConfig.objects.conf("server_starting_mode"): emit_to_obj.msg(errstring) err_cmdset = _ErrorCmdSet() err_cmdset.errmessage = errstring + _("\n (See log for details.)") return err_cmdset # classes class CmdSetHandler(object): """ The CmdSetHandler is always stored on an object, this object is supplied as an argument. The 'current' cmdset is the merged set currently active for this object.
def errback(fail): logger.log_errmsg(fail.value)
typeclass_path = data.path except Exception, e: pass if not typeclass_path: if typeclass: typeclass_path = typeclass else: typeclass_path = settings.BASE_OBJECT_TYPECLASS if self.is_typeclass(typeclass_path, exact=True): # No change. return if not hasattr(self, 'swap_typeclass'): logger.log_errmsg("%s cannot have a type at all!" % self.get_data_key()) return # Set new typeclass. self.swap_typeclass(typeclass_path, clean_attributes=False) if typeclass_path != self.typeclass_path: logger.log_errmsg("%s's typeclass %s is wrong!" % (self.get_data_key(), typeclass_path)) return def set_name(self, name): """ Set object's name. Args: name: (string) Name of the object.
"There was an error creating the Player:\n%s\n If this problem persists, contact an admin." % e) logger.log_trace() return False # This needs to be called so the engine knows this player is # logging in for the first time. (so it knows to call the right # hooks during login later) utils.init_new_player(new_player) # join the new player to the public channel pchannel = ChannelDB.objects.get_channel( settings.DEFAULT_CHANNELS[0]["key"]) if not pchannel.connect(new_player): string = "New player '%s' could not connect to public channel!" % new_player.key logger.log_errmsg(string) return new_player def _create_character(session, new_player, typeclass, home, permissions): """ Helper function, creates a character based on a player's name. This is meant for Guest and MULTISESSION_MODE < 2 situations. """ try: new_character = create.create_object(typeclass, key=new_player.key, home=home, permissions=permissions) # set playable character list new_player.db._playable_characters.append(new_character)
def import_file(file_name, model_name, widecard=True, clear=True): """ Import data from a data file to the db model Args: file_name: (string) file's name model_name: (string) db model's name. widecard: (bool) add widecard as ext name or not. clear: (boolean) clear old data or not. """ imported = False try: # get file list if widecard: file_names = glob.glob(file_name + ".*") else: file_names = [file_name] for file_name in file_names: # get file's extension name ext_name = os.path.splitext(file_name)[1].lower() reader = None if ext_name == ".csv": reader = readers.csv_reader(file_name) elif ext_name == ".xls" or ext_name == ".xlsx": reader = readers.xls_reader(file_name) if not reader: # does support this file type, read next one. continue imported = True # get model model_obj = apps.get_model(settings.WORLD_DATA_APP, model_name) if clear: # clear old data model_obj.objects.all().delete() try: # read title title = reader.next() # get field types # type = 0 means common field # type = 1 means Boolean field # type = 2 means Integer field # type = 3 means Float field # type = 4 means ForeignKey field # type = 5 means ManyToManyField field, not support # type = -1 means field does not exist field_types = [] related_fields = [] for field_name in title: field_type = -1 related_field = 0 try: # get field info field = model_obj._meta.get_field(field_name) if isinstance(field, models.BooleanField): field_type = 1 elif isinstance(field, models.IntegerField): field_type = 2 elif isinstance(field, models.FloatField): field_type = 3 elif isinstance(field, models.ForeignKey): field_type = 4 related_field = field.related_field elif isinstance(field, models.ManyToManyField): field_type = 5 else: field_type = 0 except Exception, e: logger.log_errmsg("Field error: %s" % e) field_types.append(field_type) related_fields.append(related_field) # import values # read next line values = reader.next() while values: try: record = {} for item in zip(title, field_types, values, related_fields): field_name = item[0] # skip "id" field if field_name == "id": continue field_type = item[1] value = item[2] related_field = item[3] try: # set field values if field_type == 0: # default record[field_name] = value elif field_type == 1: # boolean value if value: if value == 'True': record[field_name] = True elif value == 'False': record[field_name] = False else: record[field_name] = (int(value) != 0) elif field_type == 2: # interger value if value: record[field_name] = int(value) elif field_type == 3: # float value if value: record[field_name] = float(value) elif field_type == 4: # foreignKey if value: arg = {related_field.name: value} record[ field_name] = related_field.model.objects.get( **arg) except Exception, e: print("value error: %s - '%s'" % (field_name, value)) # create new record data = model_obj.objects.create(**record) data.save() except Exception, e: print("Can not load %s %s: %s" % (file_name, values, e))
def func(self): "Do checks and create account" session = self.caller args = self.args.strip() # extract quoted parts parts = [ part.strip() for part in re.split(r"\"|\'", args) if part.strip() ] if len(parts) == 1: # this was (hopefully) due to no quotes being found parts = parts[0].split(None, 1) if len(parts) != 2: string = "\n Usage (without <>): create <name> <password>" \ "\nIf <name> or <password> contains spaces, enclose it in quotes." session.msg(string) return playername, password = parts # sanity checks if not re.findall('^[\w. @+-]+$', playername) or not (0 < len(playername) <= 30): # this echoes the restrictions made by django's auth # module (except not allowing spaces, for convenience of # logging in). string = "\n\r Playername can max be 30 characters or fewer. Letters, spaces, digits and @/./+/-/_ only." session.msg(string) return # strip excessive spaces in playername playername = re.sub(r"\s+", " ", playername).strip() if PlayerDB.objects.filter(username__iexact=playername): # player already exists (we also ignore capitalization here) session.msg( "Sorry, there is already a player with the name '%s'." % playername) return # Reserve playernames found in GUEST_LIST if settings.GUEST_LIST and playername.lower() in map( str.lower, settings.GUEST_LIST): string = "\n\r That name is reserved. Please choose another Playername." session.msg(string) return if not re.findall('^[\w. @+-]+$', password) or not (3 < len(password)): string = "\n\r Password should be longer than 3 characers. Letters, spaces, digits and @\.\+\-\_ only." \ "\nFor best security, make it longer than 8 characters. You can also use a phrase of" \ "\nmany words if you enclose the password in quotes." session.msg(string) return # Check IP and/or name bans bans = ServerConfig.objects.conf("server_bans") if bans and (any(tup[0] == playername.lower() for tup in bans) or any(tup[2].match(session.address) for tup in bans if tup[2])): # this is a banned IP or name! string = "{rYou have been banned and cannot continue from here." \ "\nIf you feel this ban is in error, please email an admin.{x" session.msg(string) session.execute_cmd("quit") return # everything's ok. Create the new player account. try: permissions = settings.PERMISSION_PLAYER_DEFAULT typeclass = settings.BASE_CHARACTER_TYPECLASS new_player = _create_player(session, playername, password, permissions) if new_player: if MULTISESSION_MODE < 2: default_home = ObjectDB.objects.get_id( settings.DEFAULT_HOME) _create_character(session, new_player, typeclass, default_home, permissions) # tell the caller everything went well. string = "A new account '%s' was created. Welcome!" if " " in playername: string += "\n\nYou can now log in with the command 'connect \"%s\" <your password>'." else: string += "\n\nYou can now log with the command 'connect %s <your password>'." session.msg(string % (playername, playername)) except Exception: # We are in the middle between logged in and -not, so we have # to handle tracebacks ourselves at this point. If we don't, # we won't see any errors at all. string = "%s\nThis is a bug. Please e-mail an admin if the problem persists." session.msg(string % (traceback.format_exc())) logger.log_errmsg(traceback.format_exc())
def import_csv(file_name, model_name): """ Import data from a csv file to the db model Args: file_name: (string) CSV file's name. app_name: (string) Db app's name. model_name: (string) Db model's name. """ try: # load file csvfile = open(file_name, 'r') reader = csv.reader(csvfile) # get model model_obj = get_model(settings.WORLD_DATA_APP, model_name) # clear old data model_obj.objects.all().delete() # read title title = reader.next() # get field types # type = 0 means common field # type = 1 means Boolean field # type = 2 means Integer field # type = 3 means Float field # type = 4 means ForeignKey field # type = 5 means ManyToManyField field, not support # type = -1 means field does not exist field_types = [] related_fields = [] for field_name in title: field_type = -1 related_field = 0 try: # get field info field = model_obj._meta.get_field(field_name) if isinstance(field, models.BooleanField): field_type = 1 elif isinstance(field, models.IntegerField): field_type = 2 elif isinstance(field, models.FloatField): field_type = 3 elif isinstance(field, models.ForeignKey): field_type = 4 related_field = field.related_field elif isinstance(field, models.ManyToManyField): field_type = 5 else: field_type = 0 except Exception, e: logger.log_errmsg("Field error: %s" % e) field_types.append(field_type) related_fields.append(related_field) # import values # read next line values = reader.next() while values: try: record = {} for item in zip(title, field_types, values, related_fields): field_name = item[0] field_type = item[1] value = item[2].decode(settings.WORLD_DATA_FILE_ENCODING) related_field = item[3] try: # set field values if field_type == 0: # default record[field_name] = value elif field_type == 1: # boolean value if value: record[field_name] = (int(value) != 0) elif field_type == 2: # interger value if value: record[field_name] = int(value) elif field_type == 3: # float value if value: record[field_name] = float(value) elif field_type == 4: # foreignKey if value: arg = {} arg[related_field.name] = value record[ field_name] = related_field.model.objects.get( **arg) except Exception, e: print "value error: %s - '%s'" % (field_name, value) # create new record data = model_obj.objects.create(**record) data.save() except Exception, e: print "Can't load %s %s: %s" % (file_name, values, e)