public async Task AddPhotoAsync(Stream photo)
        {
            var newDetailsTask  = this.photoFactory.NewPhotoAsync();
            var currentUserTask = this.userClient.GetCurrentUserAsync();

            await Task.WhenAll(newDetailsTask, currentUserTask);

            var currentUser = await currentUserTask;

            currentUser.PhotoKeys = currentUser.PhotoKeys == null ?
                                    new List <NovelGramPhotoDetails>() :
                                    new List <NovelGramPhotoDetails>(currentUser.PhotoKeys);

            var newDetails = await newDetailsTask;
            var thumbnail  = ProcessThumbnail(photo, out var format);

            var details = new NovelGramPhotoDetails
            {
                Format    = format.Name,
                Key       = newDetails.Key,
                Timestamp = newDetails.Timestamp.ToUnixTimeSeconds()
            };

            currentUser.PhotoKeys.Add(details);

            var uploadThumbnailTask = this.UploadToS3(thumbnail, newDetails, isThumbnail: true);
            var uploadPhotoTask     = this.UploadToS3(photo, newDetails, isThumbnail: false);
            var saveUserTask        = this.userClient.SaveUserAsync(currentUser);

            await Task.WhenAll(uploadPhotoTask, uploadThumbnailTask, saveUserTask);
        }
        public NovelGramPhoto BuildPhoto(string userId, NovelGramPhotoDetails details)
        {
            var timestamp = DateTimeOffset.FromUnixTimeSeconds(details.Timestamp);

            return(new NovelGramPhoto(this.root, userId, details.Key, timestamp));
        }