Example #1
0
        public async Task <TimelinePostEntity> CreatePostAsync(long timelineId, long authorId, TimelinePostCreateRequest request)
        {
            if (request is null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            if (request.Color is not null)
            {
                CheckColor(request.Color, nameof(request));
            }

            if (request.DataList is null)
            {
                throw new ArgumentException(Resource.ExceptionDataListNull, nameof(request));
            }

            if (request.DataList.Count == 0)
            {
                throw new ArgumentException(Resource.ExceptionDataListEmpty, nameof(request));
            }

            if (request.DataList.Count > 100)
            {
                throw new ArgumentException(Resource.ExceptionDataListTooLarge, nameof(request));
            }

            for (int index = 0; index < request.DataList.Count; index++)
            {
                var data = request.DataList[index];

                switch (data.ContentType)
                {
                case MimeTypes.ImageGif:
                case MimeTypes.ImageJpeg:
                case MimeTypes.ImagePng:
                case MimeTypes.ImageWebp:
                    try
                    {
                        await _imageValidator.ValidateAsync(data.Data, data.ContentType);
                    }
                    catch (ImageException e)
                    {
                        throw new TimelinePostCreateDataException(index, Resource.ExceptionPostDataImageInvalid, e);
                    }
                    break;

                case MimeTypes.TextPlain:
                case MimeTypes.TextMarkdown:
                    try
                    {
                        new UTF8Encoding(false, true).GetString(data.Data);
                    }
                    catch (DecoderFallbackException e)
                    {
                        throw new TimelinePostCreateDataException(index, Resource.ExceptionPostDataNotValidUtf8, e);
                    }
                    break;

                default:
                    throw new TimelinePostCreateDataException(index, Resource.ExceptionPostDataUnsupportedType);
                }
            }

            request.Time = request.Time?.MyToUtc();

            await _basicTimelineService.ThrowIfTimelineNotExist(timelineId);

            await _basicUserService.ThrowIfUserNotExist(authorId);

            var currentTime = _clock.GetCurrentTime();
            var finalTime   = request.Time ?? currentTime;

            await using var transaction = await _database.Database.BeginTransactionAsync();

            var postEntity = new TimelinePostEntity
            {
                AuthorId    = authorId,
                TimelineId  = timelineId,
                Time        = finalTime,
                LastUpdated = currentTime,
                Color       = request.Color
            };

            var timelineEntity = await _database.Timelines.Where(t => t.Id == timelineId).SingleAsync();

            timelineEntity.CurrentPostLocalId += 1;
            postEntity.LocalId = timelineEntity.CurrentPostLocalId;
            _database.TimelinePosts.Add(postEntity);
            await _database.SaveChangesAsync();

            List <string> dataTags = new List <string>();

            for (int index = 0; index < request.DataList.Count; index++)
            {
                var data = request.DataList[index];

                var tag = await _dataManager.RetainEntryAsync(data.Data);

                _database.TimelinePostData.Add(new TimelinePostDataEntity
                {
                    DataTag     = tag,
                    Kind        = data.ContentType,
                    Index       = index,
                    PostId      = postEntity.Id,
                    LastUpdated = currentTime,
                });
            }

            await _database.SaveChangesAsync();

            await transaction.CommitAsync();

            _logger.LogInformation(Resource.LogTimelinePostCreated, timelineId, postEntity.Id);

            return(postEntity);
        }
 private Task <HttpTimelinePost> Map(TimelinePostEntity post)
 {
     return(_mapper.MapAsync <HttpTimelinePost>(post, Url, User));
 }