def getUserAvatar(context, request): """ Get user avatar """ base_folder = request.registry.settings.get('avatar_folder') username = request.matchdict['username'] named_size = request.matchdict.get('size', '') filename = '' # First attempt to find an existing named size avatar # If image is not sized, this will fallback to regular avatar. avatar_folder = get_avatar_folder(base_folder, 'people', username, size=named_size) if os.path.exists(os.path.join(avatar_folder, username)): filename = username # If we were loking for a named size avatar, reaching here # menans we did not found it, so fallback to base avatar elif named_size: avatar_folder = get_avatar_folder(base_folder, 'people', username) if os.path.exists(os.path.join(avatar_folder, username)): filename = username # At this point we should have a filename set, if not, it means that we # couldn't locate any size of the requested avatar. In this case, set the # missing avatar filename, based on context and size and located at root # avatars folder avatar_folder = avatar_folder if filename else get_avatar_folder(base_folder) named_size_sufix = '-{}'.format(named_size) if named_size else '' filename = filename if filename else 'missing-people.png'.format(context, named_size_sufix) data = open(os.path.join(avatar_folder, filename)).read() image = Response(data, status_int=200) image.content_type = 'image/png' return image
def getContextAvatar(context, request): """ Get context avatar To the date, this is only implemented to work integrated with Twitter. """ chash = context['hash'] twitter_username = context['twitterUsername'] base_folder = request.registry.settings.get('avatar_folder') avatar_folder = get_avatar_folder(base_folder, 'contexts', chash) context_image_filename = '%s/%s' % (avatar_folder, chash) api = get_twitter_api(request.registry) if not os.path.exists(context_image_filename): download_twitter_user_image(api, twitter_username, context_image_filename) if os.path.exists(context_image_filename): # Calculate time since last download and set if we have to re-download or not modification_time = os.path.getmtime(context_image_filename) hours_since_last_modification = (time.time() - modification_time) / 60 / 60 if hours_since_last_modification > 3: download_twitter_user_image(api, twitter_username, context_image_filename) else: context_image_filename = '{}/missing-context.png'.format(base_folder) data = open(context_image_filename).read() image = Response(data, status_int=200) image.content_type = 'image/png' return image
def get_user_avatar_dimensions(self, username, size=''): """ Returns the (width, height) of an image for a especifi user, located in the designated folder for that user. """ avatar_folder = get_avatar_folder(self.avatar_folder, 'people', username, size=size) return Image.open('{}/{}'.format(avatar_folder, username)).size
def get_context_avatar_modification_time(self, context): """ Returns the (width, height) of an image for a especifi user, located in the designated folder for that user. """ avatar_folder = get_avatar_folder(self.avatar_folder, 'contexts', context) filename = '{}/{}'.format(avatar_folder, context) return os.path.getmtime(filename)
def rewind_context_avatar_mod_time(self, context, hours): """ Changes the contex's avatar file modifcation time x hours back in time """ avatar_folder = get_avatar_folder(self.avatar_folder, 'contexts', context) filename = '{}/{}'.format(avatar_folder, context) modification_time = os.path.getmtime(filename) new_time = modification_time - (hours * 60 * 60) os.utime(filename, (new_time, new_time))
def test_avatar_folder_with_context(self): """ Given a base folder And a context with no extra params Then the subfolder contains the context """ folder = get_avatar_folder(self.folder, 'people') expected_folder = '{}/people'.format(self.folder) self.assertEqual(folder, expected_folder) self.assertFileExists(expected_folder)
def test_avatar_folder_without_params(self): """ Given a base folder And no extra params Then there are no subfolders """ folder = get_avatar_folder(self.folder) expected_folder = self.folder self.assertEqual(folder, expected_folder) self.assertFileExists(expected_folder)
def test_get_user_avatar_large_missing_all(self): """ Given a user without avatar When I retrieve the large avatar And the large avatars has disappeared Then I get the 48x48 version of that avatar """ username = '******' self.create_user(username) self.upload_user_avatar(username, "avatar.png") avatar_folder = get_avatar_folder(self.avatar_folder, 'people', username, size='large') os.remove('{}/{}'.format(avatar_folder, username)) avatar_folder = get_avatar_folder(self.avatar_folder, 'people', username) os.remove('{}/{}'.format(avatar_folder, username)) response = self.testapp.get('/people/%s/avatar/%s' % (username, 'large'), '', {}, status=200) self.assertIn('image', response.content_type) self.assertIn('image', response.content_type) self.assertEqual(self.get_image_dimensions_from(response), (48, 48))
def test_avatar_folder_with_context_and_id_2(self): """ Given a base folder And a context and identifier Then the first subfolder contains the context And the second subfolder the trimmed identifier correspondint to the context """ folder = get_avatar_folder(self.folder, 'contexts', 'e6847aed3105e85ae603c56eb2790ce85e212997') expected_folder = '{}/contexts/e6/84/7a'.format(self.folder) self.assertEqual(folder, expected_folder) self.assertFileExists(expected_folder)
def test_avatar_folder_with_context_and_id(self): """ Given a base folder And a context and identifier Then the first subfolder contains the context And the second subfolder the trimmed identifier correspondint to the context """ folder = get_avatar_folder(self.folder, 'people', 'sheldon') expected_folder = '{}/people/sh'.format(self.folder) self.assertEqual(folder, expected_folder) self.assertFileExists(expected_folder)
def test_avatar_folder_with_context_and_size(self): """ Given a base folder And a context and size Then the first subfolder contains the context And the second subfolder contains the size """ folder = get_avatar_folder(self.folder, 'people', size='large') expected_folder = '{}/people/large'.format(self.folder) self.assertEqual(folder, expected_folder) self.assertFileExists(expected_folder)
def test_avatar_folder_with_unknown_context_and_id(self): """ Given a base folder And a context and identifier And there is no identifier splitter for that context Then the first subfolder contains the context And the identifier is not used """ folder = get_avatar_folder(self.folder, 'unknown', 'sheldon') expected_folder = '{}/unknown'.format(self.folder) self.assertEqual(folder, expected_folder) self.assertFileExists(expected_folder)
def postUserAvatar(user, request): """ Upload user avatar """ base_folder = request.registry.settings.get('avatar_folder') AVATAR_SIZE = (48, 48) LARGE_SIZE = (250, 250) username = request.matchdict['username'] if request.content_type != 'multipart/form-data' and \ len(request.POST.keys()) != 1: raise ValidationError('Not supported upload method.') file_key = request.POST.keys()[0] input_file = request.POST[file_key].file # Saving the standard avatar image in png format, resize if needed regular_avatar_folder = get_avatar_folder(base_folder, 'people', username) file_path = os.path.join(regular_avatar_folder, username) input_file.seek(0) image = Image.open(input_file) avatar = ImageOps.fit(image, AVATAR_SIZE, method=Image.ANTIALIAS, centering=(0, 0)) avatar.save(file_path, 'PNG') # Saving the large avatar image in png format, resize if needed large_avatar_folder = get_avatar_folder(base_folder, 'people', username, size='large') file_path = os.path.join(large_avatar_folder, username) input_file.seek(0) image = Image.open(input_file) medium = ImageOps.fit(image, LARGE_SIZE, method=Image.ANTIALIAS, centering=(0, 0)) medium.save(file_path, 'PNG') return Response("Uploaded", status_int=201)
def getConversationUserAvatar(conversation, request): """ Get conversation avatar Returns conversation avatar. Public endpoint. """ cid = request.matchdict['id'] base_folder = request.registry.settings.get('avatar_folder') avatar_folder = get_avatar_folder('conversations', cid) missing_avatar = os.path.join(base_folder, 'missing-conversation.png') conversation_avatar = os.path.join(avatar_folder, cid) filename = conversation_avatar if os.path.exists(conversation_avatar) else missing_avatar data = open(filename).read() image = Response(data, status_int=200) image.content_type = 'image/png' return image
def test_get_context_twitter_download_avatar(self): """ Given a context with twitter username When i retrieve the context's avatar Then the twitter's user avatar is downloaded and stored """ from hashlib import sha1 from .mockers import create_context_full avatar_image = os.path.join(self.conf_dir, "avatar.png") http_mock_twitter_user_image(avatar_image) self.testapp.post('/contexts', json.dumps(create_context_full), oauth2Header(test_manager), status=201) url_hash = sha1(create_context_full['url']).hexdigest() response = self.testapp.get('/contexts/%s/avatar' % url_hash, '', {}, status=200) self.assertEqual(self.get_image_dimensions_from(response), (98, 98)) avatar_folder = get_avatar_folder(self.avatar_folder, 'contexts', url_hash) self.assertFileExists(os.path.join(avatar_folder, url_hash))
if not excluded(filename): name = '' context = '' if SHA1_REGEX.match(filename): name = SHA1_REGEX.match(filename).groups()[0] context = 'contexts' size = '' elif OBJECT_ID_REGEX.match(filename): name = OBJECT_ID_REGEX.match(filename).groups()[0] context = 'conversations' size = '' elif USER_REGEX.match(filename): name, size = USER_REGEX.match(filename).groups() context = 'people' size = '' if size is None else size if name: avatar_folder = get_avatar_folder(os.getcwd(), context, name, size) new_filename = os.path.join(avatar_folder, name) shutil.move(filename, new_filename) print "MOVED {} --> {}".format(filename, new_filename) else: exclusions.append(filename) else: exclusions.append(filename) print for filename in exclusions: print 'EXCLUDED {}'.format(filename)