예제 #1
0
    def test_register_twice_different_instance(self):
        '''Register a good username and password twice, from different instances.
        If a user tries to register a username that is already taken, show them
        a meaningful error.'''
        c = clientlib.Client()
        with self.fresh_servers():
            result = c.register(username="******", password="******", email="*****@*****.**")
            self.assertTrue(result)

            c = clientlib.Client()
            with self.assertRaises(clientlib.RegistrationError) as cm:
                c.register(username="******", password="******", email="*****@*****.**")
            self.assertIn('User already exists.', cm.exception.message)
예제 #2
0
    def test_scriptserver(self):
        '''Client can see the ScriptServer updating objects.'''
        with self.fresh_servers():
            c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD)
            character = c.create_character('Graxnor')
            # Override the character's zone:
            zone = 'playerinstance-AdventureDungeon-%s' % character
            c.characters[character].zone = zone
            c.set_online(character)

            print c.get_objects()

            linnea = self.get_linnea(c.objects)

            # Wait a bit for Linnea to wander about.
            time.sleep(0.1)

            c.get_objects()
            updated_linnea = self.get_linnea(c.objects)

        self.assertTrue(updated_linnea)
        self.assertNotEqual(linnea, updated_linnea)
        self.assertNotEqual(linnea['last_modified'], updated_linnea['last_modified'])

        # Any of the three x, y and z values should not match.
        matches = any([linnea['loc_%s'%attr] != updated_linnea['loc_%s'%attr] for attr in ('x', 'y', 'z')])
        self.assertTrue(matches)
예제 #3
0
 def test_register(self):
     '''Register with a good username and password.'''
     c = clientlib.Client()
     with self.fresh_servers():
         result = c.register(username="******", password="******", email="*****@*****.**")
     self.assertTrue(result)
     self.assertEqual(c.last_user, "gooduser")
예제 #4
0
 def test_get_zone_url_no_args(self):
     '''Client can get the url for the last character's zone.'''
     with self.fresh_servers():
         c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD)
         self.character = c.create_character('Graxnor')
         zoneurl = c.get_zone_url()
     self.assertIn('http', zoneurl)
예제 #5
0
 def test_authenticate_bad(self):
     '''Authenticating with bad credentials after init does not succeed.'''
     with self.fresh_servers():
         c = clientlib.Client()
         result = c.authenticate(username='******', password='******')
     self.assertFalse(result)
     self.assertFalse(c.cookies)
예제 #6
0
 def test_authenticate_after_auth(self):
     '''Authenticating after initting Client with auth should work.'''
     with self.fresh_servers():
         c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD)
         result = c.authenticate(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD)
     self.assertTrue(result)
     self.assertTrue(c.cookies['user'])
예제 #7
0
 def test_get_objects(self):
     '''Client can get the objects in our character's zone.'''
     with self.fresh_servers():
         c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD)
         self.character = c.create_character('Graxnor')
         print c.get_objects()
     self.assertTrue(c.objects)
     print c.objects
예제 #8
0
 def test_characters(self):
     '''After authenticating, Client has a dictionary of characters.'''
     with self.fresh_servers():
         c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD)
         self.character = c.create_character('Graxnor')
     self.assertTrue(c.characters)
     self.assertIn(self.character, c.characters)
     self.assertTrue(c.characters[self.character])
예제 #9
0
 def test_bad_ping(self):
     '''Pinging a bogus authserver should return False.'''
     oldserver = settings.AUTHSERVER
     clientlib.settings.AUTHSERVER = "http://127.0.0.1:53000"
     c = clientlib.Client()
     result = c.ping()
     self.assertFalse(result)
     clientlib.settings.AUTHSERVER = oldserver
예제 #10
0
    def test_move_character(self):
        '''Client can move a character.'''
        with self.fresh_servers():
            c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD)
            character = c.create_character('Graxnor')
            c.set_character_status(character, 'online')
            result = c.move_character(character, 100, 100, 100)

        self.assertTrue(result)
예제 #11
0
 def test_set_character_status(self):
     '''Client can update its objects.'''
     with self.fresh_servers():
         c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD)
         self.character = c.create_character('Graxnor')
         c.get_objects()
         result = c.set_character_status(self.character, 'online')
     self.assertTrue(result)
     self.assertTrue(c.characters[self.character].online)
예제 #12
0
 def test_get_objects_verbose(self):
     '''Client can get the objects in our character's zone, when we give it.'''
     with self.fresh_servers():
         c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD)
         self.character = c.create_character('Graxnor')
         zoneid = c.get_zone(self.character)
         zoneurl = c.get_zone_url(zoneid)
         c.get_objects(zoneurl)
     self.assertTrue(c.objects)
예제 #13
0
 def test_authenticate(self):
     '''Authenticating after initting Client should work.'''
     c = clientlib.Client()
     with self.fresh_servers():
         result = c.authenticate(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD)
         self.character = c.create_character('Graxnor')
     self.assertTrue(result)
     self.assertTrue(c.cookies['user'])
     self.assertTrue(c.characters)
예제 #14
0
    def test_move_character_bump(self):
        '''Client can try to move a character, but fail due to physics.'''
        with self.fresh_servers():
            c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD)
            character = c.create_character('Graxnor')
            c.set_character_status(character, 'online')
            result = c.move_character(character)

        self.assertFalse(result)
예제 #15
0
 def test_get_zone_cacheing(self):
     '''Client can get the zone for our character from the cache.'''
     with self.fresh_servers():
         c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD)
         self.character = c.create_character('Graxnor')
         self.assertTrue(c.get_zone(self.character))
         expected = "Expected Zone"
         c.characters[self.character].zone = expected
         result = c.get_zone(self.character)
     self.assertEqual(result, expected)
예제 #16
0
 def test_create(self):
     '''Create a character.
     Not only must the create_character function return the character name
     the server created, but also update the client's characters dict.'''
     with self.fresh_servers():
         c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD)
         expected = "Cuddlepums"
         result = c.create_character(character_name=expected)
     self.assertEqual(result, expected)
     self.assertIn(expected, c.characters)
예제 #17
0
    def test_get_objects_update(self):
        '''Client can update its objects.'''
        with self.fresh_servers():
            c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD)
            self.character = c.create_character('Graxnor')
            self.assertEqual(len(c.objects), 0) 
            orig_objs = c.get_objects()
            result = c.get_objects()

        self.assertEqual(len(c.objects), 11) 
        self.assertEqual(len(result), 0, 'When updating that quickly, there should be no updated objects. {}'.format(str(result)))
예제 #18
0
    def test_get_zone_url_with_cache(self):
        '''Client can get the url for our character's zone from the cache'''
        with self.fresh_servers():
            c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD)
            self.character = c.create_character('Graxnor')
            zoneid = c.get_zone(self.character)
            c.get_zone_url(zoneid)

            expected = "Expected Zone Id"
            c.zones[zoneid] = expected

            result = c.get_zone_url(zoneid)
        self.assertEqual(result, expected)
예제 #19
0
    def test_register_twice(self):
        '''Register with a good username and password, twice!
        If a user tries to register twice, with the same info, their request
        should be squelched and all continues as if nothing went awry.
        (If the user re-instantiates the client, show errors as normal.)
        '''
        c = clientlib.Client()
        with self.fresh_servers():
            first_result = c.register(username="******", password="******", email="*****@*****.**")
            self.assertTrue(first_result)
            self.assertEqual(c.last_user, "gooduser")

            second_result = c.register(username="******", password="******", email="*****@*****.**")
            self.assertTrue(second_result)
예제 #20
0
    def test_get_messages(self):
        with self.fresh_servers():
            c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD)
            character = c.create_character('Graxnor')
            # Override the character's zone:
            zone = 'playerinstance-AdventureDungeon-%s' % character
            c.characters[character].zone = zone
            c.set_online(character)
            c.get_objects()

            # Poke Linnea to make her talk
            linnea = self.get_linnea(c.objects)
            c.activate(linnea['id'])

            c.get_messages()

        self.assertTrue(c.messages)
예제 #21
0
    def test_activation(self):
        '''Client can activate an object.'''
        with self.fresh_servers():
            c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD)
            character = c.create_character('Graxnor')
            print "testing using ", character
            # Override the character's zone:
            zone = 'playerinstance-AdventureDungeon-%s' % character
            c.characters[character].zone = zone
            c.set_online(character)

            c.get_objects()

            linnea = self.get_linnea(c.objects)

            self.assertTrue(linnea)
            self.assertTrue(c.activate(linnea['id']))
예제 #22
0
class InteractiveClient(Cmd):
    client = clientlib.Client()
    quiet = False
    debug = True
    prompt = " > "

    def precmd(self, line):
        self.do_update()
        return line

    def postcmd(self, stop, line):
        self.do_update()
        return stop

    def format_prompt(self, username='', character='', zone=''):
        if not username:
            username = self.client.last_user
        if not character:
            character = self.client.last_character
        if not zone:
            # We want the actual name of the zone instead of the url.
            for zoneid, zone in self.client.zones.iteritems():
                if zone == self.client.last_zone:
                    # The instance type and instance owner are implied,
                    # So we only want the actual zone name.
                    zone = zoneid.split('-')[1]
                    break
            zone = '@{0}'.format(zone) if zone else ''

        prompt_string = " {username}:{character}{zone} ({num_objs})> "
        self.prompt = prompt_string.format(username=username,
                                           character=(character or "No Character Selected"),
                                           zone=zone,
                                           num_objs=len(self.client.objects))
        return self.prompt

    def logged_in(self):
        if not self.client.last_character:
            return False
        else:
            return True

    @options([make_option('-u', '--username', type="string", help="The name of the user you want to register."),
              make_option('-p', '--password', type="string", help="The password for the user."),
              make_option('-e', '--email', type="string", default=None, help="The email for the user."),
             ])
    def do_register(self, args, opts=None):
        '''Register a username and password combination so you can log in.
        You only need to do this once per user you want to create.
        Calling this more than once with the same arguments will generate
        an error at worst, and be ignored at best.'''
        if not opts:
            username, password, email = args.split(" ")
        else:
            username = opts.username
            password = opts.password
            email = opts.email

        try:
            result = self.client.register(username, password, email)
        except clientlib.RegistrationError as exc:
            self.perror("Error: Registration failed: {0}"
                        .format(exc.message))
            return

        if result:
            self.pfeedback(result)

    @options([make_option('-u', '--username', type="string", default=settings.DEFAULT_USERNAME, help="The user you want to log in as."),
              make_option('-p', '--password', type="string", default=settings.DEFAULT_PASSWORD, help="The password for the user."),
             ])
    def do_login(self, args, opts=None):
        '''Log in as a given user.'''
        if not opts:
            username, password = args.split(' ')
        else:
            username = opts.username
            password = opts.password

        return self.login(username, password)

    def login(self, username, password, charnum=None):
        # Sometimes the authserver may not be up.
        if not self.client.ping():
            self.perror("Error: Authentication server is not online.")
            return

        # Let's see if the username and password are right:
        result = self.client.authenticate(username, password)
        if not result:
            self.perror("Authentication failed.")
            return
        else:
            self.pfeedback("Authentication successful. You are now logged in as {0}."
                           .format(repr(username)))

        character = None
        if charnum:
            character = self.client.characters[list(self.client.characters)[int(charnum-1)]].name
        else:
            if self.client.characters:
                if len(self.client.characters) == 1:
                    character = self.client.characters.keys()[0]
                else:
                    character = self.select(self.client.characters, 'Select a Character: ')
        if character:
            self.client.last_character = character
            self.client.set_character_status(character)

            self.client.get_objects()
        else:
            self.pfeedback("No characters found.")
            character_name = raw_input("New character's name: ").strip()
            self.do_create_character(character_name)
            self.login(username, password, charnum)

        self.format_prompt()

    @options([make_option('-n', '--name', type="string", default="Graxnor", help="The name of the character you want to create.."),
             ])
    def do_create_character(self, args, opts=None):
        if not opts:
            (name,) = args.split(' ')
        else:
            name = opts.name

        try:
            result = self.client.create_character(name)
        except (clientlib.ClientError, clientlib.UnexpectedHTTPStatus) as exc:
            self.perror("Error: Character creation failed: {0}".format(exc.message))
            return

        return result

    def do_update(self, args=None):
        '''Update all the things that can be updated.
        This includes objects only at the moment.'''
        if not self.logged_in():
            return

        self.client.get_objects()
        self.client.get_messages()

        for msg in self.format_messages():
            self.pfeedback(msg)

    def format_messages(self):
        for msgid, message in self.client.messages.iteritems():
            if not message.get('read'):
                message['read'] = True
                timestamp = datetime.fromtimestamp(message.get('last_modified', {}).get('$date', 0)/1000)
                yield "[{timestamp:%X}] "\
                    "<{sender}>: "\
                    "{body}".format(sender=message.get('sender'),
                                    body=message.get('body'),
                                    timestamp=timestamp)


    def do_map(self, args):
        '''Renders a map of the zone your character is currently in.
        By default this is ascii, but you can also ask it to render to an image.'''
        if not self.logged_in():
            return

        # Get bounds (maxx, maxy, minx, miny) of all objects in the zone
        maxx = 0
        maxy = 0
        minx = 0
        miny = 0
        goodobjs = []
        for objid, obj in self.client.objects.iteritems():
            try:
                objloc = obj['loc']
            except KeyError:
                # Some objects have no location, so skip em.
                continue

            try:
                if 'hidden' in obj['states']:
                    # Skip hidden objects.
                    continue
            except KeyError:
                # Stuff without states are A-OK
                pass

            maxx = max(maxx, objloc['x'])
            maxy = max(maxy, objloc['y'])
            minx = min(minx, objloc['x'])
            miny = min(miny, objloc['y'])
            goodobjs.append(obj)

        xlen, ylen = maxx-minx, maxy-miny

        deltax = maxx-minx
        deltay = maxy-miny

        if not args:
            # Default is fullscreen
            import os
            rows, columns = os.popen('stty size', 'r').read().split()
            mapsizex = int(rows)-2
            mapsizey = int(columns)-1
        else:
            # Otherwise use whatever args are passed.
            mapsizex, mapsizey = [int(n) for n in args.split()]

        import numpy
        # Build out the default array.
        maparray = numpy.array([['.']*mapsizey]*mapsizex)

        # This places the objects in the array based on their relative position.
        names = {}
        for obj in goodobjs:
            # Stupid rounding here, but good enough.
            x = int(((obj['loc']['x']-minx)/deltax)*mapsizex)
            y = int(((obj['loc']['y']-miny)/deltay)*mapsizey)
            try:
                name = names[obj['resource']]
            except KeyError:
                name = obj['resource'][0]
                names[obj['resource']] = name
            maparray[x-1, y-1] = name

        # Make a string because printing manually is dumb.
        mapstring = '\n'.join([''.join([y for y in x]) for x in maparray])
        self.poutput(mapstring)

    def clean_dict(self, dirty):
        '''Clean up ugly values and drop private keys.'''
        newobj = {}
        for k, v in dirty.iteritems():
            if type(v) == float:
                v = float("%.4f" % v)

            if type(v) == dict:
                v = self.clean_dict(v)

            if not k.startswith("_"):
                newobj[k] = v
        return newobj

    def format_object(self, objdata):
        '''Pretty-print an object from the client.'''
        newobj = {u'id': objdata['_id']['$oid']}
        newobj.update(self.clean_dict(objdata))
        for k, v in objdata.iteritems():
            # Prettify the last modified timestamp
            if k == "last_modified":
                v = datetime.fromtimestamp(v[r'$date']/1000.0)\
                            .strftime(settings.DATETIME_FORMAT)
                newobj[k] = v

        return pformat(newobj)

    def get_match(self, objname):
        '''Get a matching object from the client for a given id or name.
        It matches based on exact matches, starts with or contains,
        in that order.'''
        objname = objname.lower()

        # Try exact match first:
        try:
            obj = self.client.objects[objname]
            return obj
        except KeyError:
            # Couldn't find the exact match.
            pass

        # Try startswith match next:
        for objid, obj in self.client.objects.iteritems():
            if objid.lower().startswith(objname) or obj['name'].lower().startswith(objname):
                return obj

        # Try contains match next:
        for objid, obj in self.client.objects.iteritems():
            if objname in objid.lower() or objname in obj['name'].lower():
                return obj

        # Couldn't find anything.
        return False

    def do_detail(self, args):
        '''Pass in the name or id of the object you want to look at.'''
        objname = args
        if objname:
            obj = self.get_match(objname)

            if obj:
                self.poutput(self.format_object(obj))
            else:
                self.perror("Could not find anything resembling {0}.".format(objname))
예제 #23
0
 def test_get_zone(self):
     '''Client can get the zone for our character.'''
     with self.fresh_servers():
         c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD)
         self.character = c.create_character('Graxnor')
         self.assertTrue(c.get_zone(self.character))
예제 #24
0
 def test___init___autoauth_bad(self):
     '''Initting the Client with a bad user/pass combo will raise an exception. '''
     with self.assertRaises(clientlib.AuthenticationError):
         clientlib.Client(username="******", password="******")
예제 #25
0
 def test___init___autoauth(self):
     '''Init the Client with a known good user/pass combo.'''
     with self.fresh_servers():
         c = clientlib.Client(username=settings.DEFAULT_USERNAME, password=settings.DEFAULT_PASSWORD)
     self.assertTrue(c.cookies)
     self.assertTrue(c.cookies['user'])
예제 #26
0
 def test___init__(self):
     '''Init the Client with no args.'''
     c = clientlib.Client()
     self.assertTrue(c)
예제 #27
0
 def test_ping(self):
     '''Pinging the authserver should work.'''
     with self.fresh_servers():
         c = clientlib.Client()
         result = c.ping()
     self.assertTrue(result)