Ejemplo n.º 1
0
        /// <summary>
        /// Returns the details for a media.
        /// </summary>
        public async Task <MediaVM> GetMediaAsync(string key)
        {
            var id    = PageHelper.GetMediaId(key);
            var media = await _db.Media
                        .Include(x => x.Tags)
                        .ThenInclude(x => x.Object)
                        .Where(x => x.IsDeleted == false)
                        .FirstOrDefaultAsync(x => x.Id == id);

            if (media == null)
            {
                throw new KeyNotFoundException();
            }

            var descr = await _markdown.CompileAsync(media.Description);

            return(new MediaVM
            {
                Type = media.Type,
                IsProcessed = media.IsProcessed,
                Title = media.Title,
                Description = descr,
                Date = FuzzyDate.TryParse(media.Date),
                Tags = GetMediaTagsVMs(media.Tags).ToList(),
                Event = GetPageTitle(media.Tags.FirstOrDefault(x => x.Type == MediaTagType.Event)),
                Location = GetPageTitle(media.Tags.FirstOrDefault(x => x.Type == MediaTagType.Location)),
                OriginalPath = media.FilePath,
                PreviewPath = GetSizedMediaPath(media.FilePath, MediaSize.Large)
            });
        }
Ejemplo n.º 2
0
        public void LeapYearDefinedTest()
        {
            var leapYears = new int[]
            {
                1996,
                2000,
                2004,
                2008,
                2012,
                2016
            };

            for (int year = 1995; year <= 2019; year++)
            {
                var date = new FuzzyDate(year);
                if (leapYears.Contains(year))
                {
                    Assert.IsTrue(date.IsLeapYear());
                }
                else
                {
                    Assert.IsFalse(date.IsLeapYear());
                }
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Applies date filtering to the list of media.
        /// </summary>
        private IReadOnlyList <Media> TryFilterMediaByDate(FolderContentsRequestVM request, IReadOnlyList <Media> source)
        {
            var dateFrom = TryParse(request.From);
            var dateTo   = TryParse(request.To);

            if (dateFrom == null && dateTo == null)
            {
                return(source);
            }

            return(source.Select(x => new
            {
                Date = FuzzyDate.TryParse(x.Date),
                Media = x
            })
                   .Where(x => x.Date != null)
                   .Where(x => (dateFrom == null || x.Date >= dateFrom) && (dateTo == null || x.Date <= dateTo))
                   .Select(x => x.Media)
                   .ToList());

            FuzzyDate?TryParse(string value)
            {
                var date = value?.TryParse <DateTime?>();

                return(date == null ? (FuzzyDate?)null : new FuzzyDate(date.Value));
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Performs additional checks on the registration request.
        /// </summary>
        private async Task ValidateRegisterRequestAsync(RegisterUserVM vm, bool usePasswordAuth)
        {
            var val = new Validator();

            if (FuzzyDate.TryParse(vm.Birthday) == null)
            {
                val.Add(nameof(vm.Birthday), "Дата рождения указана неверно.");
            }

            var emailExists = await _db.Users.AnyAsync(x => x.Email == vm.Email);

            if (emailExists)
            {
                val.Add(nameof(vm.Email), "Адрес электронной почты уже зарегистрирован.");
            }

            if (usePasswordAuth)
            {
                if (vm.Password == null || vm.Password.Length < 6)
                {
                    val.Add(nameof(vm.Password), "Пароль должен содержать как минимум 6 символов.");
                }

                if (vm.Password != vm.PasswordCopy)
                {
                    val.Add(nameof(vm.PasswordCopy), "Пароли не совпадают.");
                }
            }

            val.ThrowIfInvalid();
        }
Ejemplo n.º 5
0
 internal static void RunRules(FuzzyDate date)
 {
     foreach (var rule in _fuzzyDateRules)
     {
         rule.Verify(date);
     }
 }
Ejemplo n.º 6
0
        /// <summary>
        /// Uploads a new media file.
        /// </summary>
        public async Task <MediaUploadResultVM> UploadAsync(MediaUploadRequestVM vm, IFormFile file, ClaimsPrincipal principal)
        {
            var id  = Guid.NewGuid();
            var key = PageHelper.GetMediaKey(id);

            var handler = _mediaHandlers.FirstOrDefault(x => x.SupportedMimeTypes.Contains(file.ContentType));

            if (handler == null)
            {
                throw new UploadException("Неизвестный тип файла!");
            }

            var userId = _userMgr.GetUserId(principal);
            var user   = await _db.Users.GetAsync(x => x.Id == userId, "Пользователь не найден");

            var paths = await SaveUploadAsync(file, key, handler);

            var tags = await GetTagsForUploadedMedia(vm);

            var meta = await handler.ExtractMetadataAsync(paths.LocalPath, file.ContentType);

            var media = new Media
            {
                Id          = id,
                Key         = key,
                Type        = handler.MediaType,
                MimeType    = file.ContentType,
                Title       = vm.Title,
                FilePath    = paths.UrlPath,
                UploadDate  = DateTimeOffset.Now,
                Uploader    = user,
                IsProcessed = handler.IsImmediate,
                Date        = FuzzyDate.TryParse(vm.Date) != null
                    ? vm.Date
                    : meta?.Date?.Date.ToString("yyyy.MM.dd", CultureInfo.InvariantCulture),
                Tags = tags
            };

            _db.Media.Add(media);

            if (!handler.IsImmediate)
            {
                _db.MediaJobs.Add(new MediaEncodingJob
                {
                    Id      = Guid.NewGuid(),
                    MediaId = media.Id
                });
            }

            var changeset = await GetChangesetAsync(null, _mapper.Map <MediaEditorVM>(media), id, principal, null);

            _db.Changes.Add(changeset);

            return(_mapper.Map <MediaUploadResultVM>(media));
        }
 public void YearGreaterThanZeroIsValid()
 {
     try
     {
         _ = new FuzzyDate(1950);
     }
     catch (Exception ex)
     {
         Assert.Fail($"Expect no exception, but got {ex.Message}");
     }
 }
 public void TwentyNinthOfFebruaryInLeapYearIsValid()
 {
     try
     {
         _ = new FuzzyDate(2020, 2, 29);
     }
     catch (Exception ex)
     {
         Assert.Fail($"Expect no exception, but got {ex.Message}");
     }
 }
 public void DayInRangeIsValid()
 {
     try
     {
         _ = new FuzzyDate(2019, 9, 3);
     }
     catch (Exception ex)
     {
         Assert.Fail($"Expect no exception, but got {ex.Message}");
     }
 }
Ejemplo n.º 10
0
        /// <summary>
        /// Infers page-related events for the current month.
        /// </summary>
        private IEnumerable <CalendarEventVM> GetPageEvents(int year, int month, RelationContext context)
        {
            var maxDate = new FuzzyDate(new DateTime(year, month, 1).AddMonths(1).AddSeconds(-1));

            foreach (var page in context.Pages.Values)
            {
                if (page.BirthDate is FuzzyDate birth)
                {
                    var showBirth = birth.Month == month &&
                                    (birth.Year == null || birth.Year <= year) &&
                                    (page.DeathDate == null || page.DeathDate >= maxDate);

                    if (showBirth)
                    {
                        var title = (year == birth.Year && !birth.IsDecade)
                            ? "Дата рождения"
                            : (birth.Year == null || birth.IsDecade)
                                ? "День рождения"
                                : $"День рождения ({year - birth.Year.Value})";

                        yield return(new CalendarEventVM
                        {
                            Day = birth.Day,
                            Title = title,
                            Type = CalendarEventType.Birth,
                            RelatedPage = Map(page)
                        });
                    }
                }

                if (page.DeathDate is FuzzyDate death)
                {
                    var showDeath = death.Month == month &&
                                    (death.Year == null || death.Year <= year);

                    if (showDeath)
                    {
                        var title = (year == death.Year && !death.IsDecade)
                            ? "Дата смерти"
                            : (death.Year == null || death.IsDecade)
                                ? "Годовщина смерти"
                                : (year - death.Year.Value) + "-ая годовщина смерти";

                        yield return(new CalendarEventVM
                        {
                            Day = death.Day,
                            Title = title,
                            Type = CalendarEventType.Death,
                            RelatedPage = Map(page)
                        });
                    }
                }
            }
        }
Ejemplo n.º 11
0
 public void Configure(IProfileExpression profile)
 {
     profile.CreateMap <Data.Models.Media, MediaThumbnailExtendedVM>()
     .MapMember(x => x.Id, x => x.Id)
     .MapMember(x => x.Key, x => x.Key)
     .MapMember(x => x.Type, x => x.Type)
     .MapMember(x => x.Date, x => FuzzyDate.TryParse(x.Date))
     .MapMember(x => x.UploadDate, x => x.UploadDate)
     .MapMember(x => x.Title, x => x.Title)
     .MapMember(x => x.MediaTagsCount, x => x.Tags.Count(y => y.Type == MediaTagType.DepictedEntity))
     .MapMember(x => x.ThumbnailUrl, x => MediaPresenterService.GetSizedMediaPath(x.FilePath, MediaSize.Small));
 }
Ejemplo n.º 12
0
 public void AddToNoDayTest()
 {
     try
     {
         var fd      = new FuzzyDate(2019, 9);
         var newDate = fd.AddDays(10);
         Assert.IsFalse(newDate.Day.HasValue);
     }
     catch (Exception ex)
     {
         Assert.Fail($"Expect no exception, but got {ex.Message}");
     }
 }
Ejemplo n.º 13
0
        /// <summary>
        /// Performs additional checks on the registration request.
        /// </summary>
        private async Task ValidateRegisterRequestAsync(RegisterUserVM vm)
        {
            var val = new Validator();

            if (FuzzyDate.TryParse(vm.Birthday) == null)
                val.Add(nameof(vm.Birthday), "Дата рождения указана неверно.");

            var emailExists = await _db.Users.AnyAsync(x => x.Email == vm.Email);
            if (emailExists)
                val.Add(nameof(vm.Email), "Адрес электронной почты уже зарегистрирован.");

            val.ThrowIfInvalid();
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Infers relation-based events for the current month.
        /// </summary>
        private IEnumerable <CalendarEventVM> GetRelationEvents(int year, int month, RelationContext context)
        {
            var visited = new HashSet <string>();
            var maxDate = new FuzzyDate(CreateDate(year, month).AddMonths(1).AddSeconds(-1));

            foreach (var rel in context.Relations.SelectMany(x => x.Value))
            {
                if (!(rel.Duration is FuzzyRange duration) || !(duration.RangeStart is FuzzyDate start) || start.Month != month)
                {
                    continue;
                }

                if (duration.RangeEnd is FuzzyDate end && end <= maxDate)
                {
                    continue;
                }

                var hash = string.Concat(rel.SourceId.ToString(), rel.DestinationId.ToString(), duration.ToString());
                if (visited.Contains(hash))
                {
                    continue;
                }

                var inverseHash = string.Concat(rel.DestinationId.ToString(), rel.SourceId.ToString(), duration.ToString());
                visited.Add(hash);
                visited.Add(inverseHash);

                var title = (year == start.Year && !start.IsDecade)
                    ? "День свадьбы"
                    : (start.Year == null || start.IsDecade)
                        ? "Годовщина"
                        : (year - start.Year.Value) + "-ая годовщина";

                yield return(new CalendarEventVM
                {
                    Day = start.Day,
                    Title = title,
                    Type = CalendarEventType.Wedding,
                    RelatedPage = rel.EventId == null
                        ? new PageTitleExtendedVM {
                        Title = "Свадьба", MainPhotoPath = "~/assets/img/unknown-event.svg"
                    }
                        : Map(context.Pages[rel.EventId.Value]),
                    OtherPages = new []
                    {
                        Map(context.Pages[rel.SourceId]),
                        Map(context.Pages[rel.DestinationId])
                    }
                });
            }
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Renders the property values.
        /// </summary>
        public async Task <IReadOnlyList <ChangePropertyValue> > RenderValuesAsync(string json)
        {
            var result = new List <ChangePropertyValue>();
            var data   = JsonConvert.DeserializeObject <RelationEditorVM>(StringHelper.Coalesce(json, "{}"));

            if (data.SourceIds == null)
            {
                data.SourceIds = Array.Empty <Guid>();
            }

            var pageIds = data.SourceIds
                          .Concat(new[] { data.DestinationId ?? Guid.Empty, data.EventId ?? Guid.Empty })
                          .ToList();

            var namesLookup = await _db.Pages
                              .Where(x => pageIds.Contains(x.Id))
                              .ToDictionaryAsync(x => x.Id, x => x.Title);

            Add(nameof(RelationEditorVM.DestinationId), "Основная страница", namesLookup.TryGetValue(data.DestinationId ?? Guid.Empty));
            Add(nameof(RelationEditorVM.Type), "Тип связи", string.IsNullOrEmpty(json) ? null : data.Type.GetEnumDescription());

            if (data.SourceIds.Length == 0)
            {
                Add(nameof(RelationEditorVM.SourceIds), "Связанная страница", null);
            }
            else if (data.SourceIds.Length == 1)
            {
                var name = namesLookup.TryGetValue(data.SourceIds[0]);
                Add(nameof(RelationEditorVM.SourceIds), "Связанная страница", name);
            }
            else
            {
                var pageNames = data.SourceIds
                                .Select(x => namesLookup.TryGetValue(x))
                                .Where(x => !string.IsNullOrEmpty(x));

                Add(nameof(RelationEditorVM.SourceIds), "Связанные страницы", ViewHelper.RenderBulletList(_html, pageNames));
            }

            Add(nameof(RelationEditorVM.EventId), "Событие", namesLookup.TryGetValue(data.EventId ?? Guid.Empty));
            Add(nameof(RelationEditorVM.DurationStart), "Начало", FuzzyDate.TryParse(data.DurationStart)?.ReadableDate);
            Add(nameof(RelationEditorVM.DurationEnd), "Конец", FuzzyDate.TryParse(data.DurationEnd)?.ReadableDate);

            return(result);

            void Add(string prop, string name, string value)
            {
                result.Add(new ChangePropertyValue(prop, name, value));
            }
        }
Ejemplo n.º 16
0
 public void ParseFromYearMonthDayAmbiguousTest()
 {
     try
     {
         var date = FuzzyDate.Parse("2019/02/10");
         Assert.AreEqual(2019, date.Year.Value);
         Assert.AreEqual(2, date.Month.Value);
         Assert.AreEqual(10, date.Day.Value);
     }
     catch (Exception ex)
     {
         Assert.Fail($"Expect no exception, but got {ex.Message}");
     }
 }
Ejemplo n.º 17
0
 public void ParseFromMonthDayYearTest()
 {
     try
     {
         var date = FuzzyDate.Parse("09/15/2019");
         Assert.AreEqual(2019, date.Year.Value);
         Assert.AreEqual(9, date.Month.Value);
         Assert.AreEqual(15, date.Day.Value);
     }
     catch (Exception ex)
     {
         Assert.Fail($"Expect no exception, but got {ex.Message}");
     }
 }
Ejemplo n.º 18
0
 public void ParseFromYearMonthTest()
 {
     try
     {
         var date = FuzzyDate.Parse("2019/09");
         Assert.AreEqual(2019, date.Year.Value);
         Assert.AreEqual(9, date.Month.Value);
         Assert.IsFalse(date.Day.HasValue);
     }
     catch (Exception ex)
     {
         Assert.Fail($"Expect no exception, but got {ex.Message}");
     }
 }
Ejemplo n.º 19
0
 public void ParseWithHyphenDelimiterTest()
 {
     try
     {
         var date = FuzzyDate.Parse("09-15-2019");
         Assert.AreEqual(2019, date.Year.Value);
         Assert.AreEqual(9, date.Month.Value);
         Assert.AreEqual(15, date.Day.Value);
     }
     catch (Exception ex)
     {
         Assert.Fail($"Expect no exception, but got {ex.Message}");
     }
 }
Ejemplo n.º 20
0
 public void ParseFromEmptyTest()
 {
     try
     {
         var date = FuzzyDate.Parse("");
         Assert.IsFalse(date.Year.HasValue);
         Assert.IsFalse(date.Month.HasValue);
         Assert.IsFalse(date.Day.HasValue);
     }
     catch (Exception ex)
     {
         Assert.Fail($"Expect no exception, but got {ex.Message}");
     }
 }
Ejemplo n.º 21
0
 public void AddPositiveDaysTest()
 {
     try
     {
         var fd      = new FuzzyDate(2019, 9, 29);
         var newDate = fd.AddDays(10);
         Assert.AreEqual(2019, newDate.Year);
         Assert.AreEqual(10, newDate.Month);
         Assert.AreEqual(9, newDate.Day);
     }
     catch (Exception ex)
     {
         Assert.Fail($"Expect no exception, but got {ex.Message}");
     }
 }
Ejemplo n.º 22
0
 public void AddPositiveMonthsTest()
 {
     try
     {
         var fd      = new FuzzyDate(2019, 9);
         var newDate = fd.AddMonths(10);
         Assert.AreEqual(2020, newDate.Year);
         Assert.AreEqual(7, newDate.Month);
         Assert.IsFalse(newDate.Day.HasValue);
     }
     catch (Exception ex)
     {
         Assert.Fail($"Expect no exception, but got {ex.Message}");
     }
 }
Ejemplo n.º 23
0
 public void AddZeroYearsTest()
 {
     try
     {
         var fd      = new FuzzyDate(2019);
         var newDate = fd.AddYears(0);
         Assert.AreEqual(2019, newDate.Year);
         Assert.IsFalse(newDate.Month.HasValue);
         Assert.IsFalse(newDate.Day.HasValue);
     }
     catch (Exception ex)
     {
         Assert.Fail($"Expect no exception, but got {ex.Message}");
     }
 }
Ejemplo n.º 24
0
 /// <summary>
 /// Returns the last N uploaded images.
 /// </summary>
 public async Task <IReadOnlyList <MediaThumbnailVM> > GetLastUploadedMediaAsync(int count)
 {
     return(await _db.Media
            .Where(x => !x.IsDeleted)
            .OrderByDescending(x => x.UploadDate)
            .Take(count)
            .Select(x => new MediaThumbnailVM
     {
         Key = x.Key,
         Type = x.Type,
         ThumbnailUrl = GetSizedMediaPath(x.FilePath, MediaSize.Small),
         Date = FuzzyDate.TryParse(x.Date),
     })
            .ToListAsync());
 }
Ejemplo n.º 25
0
 public void AddToNullTest()
 {
     try
     {
         var fd      = new FuzzyDate();
         var newDate = fd.AddYears(10);
         Assert.IsFalse(newDate.Year.HasValue);
         Assert.IsFalse(newDate.Month.HasValue);
         Assert.IsFalse(newDate.Day.HasValue);
     }
     catch (Exception ex)
     {
         Assert.Fail($"Expect no exception, but got {ex.Message}");
     }
 }
Ejemplo n.º 26
0
        /// <summary>
        /// Returns the photo model.
        /// </summary>
        public static MediaThumbnailVM GetMediaThumbnail(Media media, MediaSize size = MediaSize.Small)
        {
            if (media == null)
            {
                return(null);
            }

            return(new MediaThumbnailVM
            {
                Type = media.Type,
                Key = media.Key,
                ThumbnailUrl = GetSizedMediaPath(media.FilePath, size),
                Date = FuzzyDate.TryParse(media.Date)
            });
        }
Ejemplo n.º 27
0
 public void ConvertNormalDateToDateTimeTest()
 {
     try
     {
         var fDate     = new FuzzyDate(2019, 9, 3);
         var converted = fDate.ToDateTime();
         Assert.AreEqual(fDate.Year.Value, converted.Year);
         Assert.AreEqual(fDate.Month.Value, converted.Month);
         Assert.AreEqual(fDate.Day.Value, converted.Day);
     }
     catch (Exception ex)
     {
         Assert.Fail($"Expect no exception, but got {ex.Message}");
     }
 }
Ejemplo n.º 28
0
        /// <summary>
        /// Returns the media details.
        /// </summary>
        public async Task <MediaVM> GetMediaAsync(string key, UserContext ctx)
        {
            var errorKey = $"Media ({key})";

            var media = await _db.Media
                        .AsNoTracking()
                        .Include(x => x.Tags)
                        .ThenInclude(x => x.Tag)
                        .Include(x => x.Folder)
                        .GetAsync(x => x.Key == key, errorKey);

            if (ctx.Link != null)
            {
                // subfolders disallowed: only media immediately inside current folder are available
                if (ctx.Link.Scope == SearchScope.CurrentFolder && media.FolderKey != ctx.Link.Folder.Key)
                {
                    throw new NotFoundException(errorKey);
                }

                // inside subfolder
                if (!media.Folder.Path.StartsWith(ctx.Link.Folder.Path))
                {
                    throw new NotFoundException(errorKey);
                }

                // must have tags
                if (!string.IsNullOrEmpty(ctx.Link.Tags))
                {
                    var tagIds = ctx.Link.Tags.TryParseList <int>(",");
                    if (!media.Tags.Any(x => tagIds.Contains(x.TagId)))
                    {
                        throw new NotFoundException(errorKey);
                    }
                }

                var mediaDate = FuzzyDate.TryParse(media.Date);
                var dateFrom  = FuzzyDate.TryParse(ctx.Link.DateFrom);
                var dateTo    = FuzzyDate.TryParse(ctx.Link.DateTo);

                if ((dateFrom != null && !(mediaDate >= dateFrom)) || (dateTo != null && !(mediaDate <= dateTo)))
                {
                    throw new NotFoundException(errorKey);
                }
            }

            return(_mapper.Map <MediaVM>(media));
        }
Ejemplo n.º 29
0
        private void TestGenerator()
        {
            var dateNames = new string[]
            {
                "_fdNone",
                "_fdYear",
                "_fdMonth",
                "_fdDay"
            };

            var dates = new FuzzyDate[]
            {
                _fdNone,
                _fdYear,
                _fdMonth,
                _fdDay
            };

            for (int firstFrom = 0; firstFrom < dates.Length; firstFrom++)
            {
                var firstFromDate = dates[firstFrom];
                var firstFromName = dateNames[firstFrom];

                for (int firstTo = 0; firstTo < dates.Length; firstTo++)
                {
                    var firstToDate = dates[firstTo];
                    var firstToName = dateNames[firstTo];

                    for (int secondFrom = 0; secondFrom < dates.Length; secondFrom++)
                    {
                        var secondFromDate = dates[secondFrom];
                        var secondFromName = dateNames[secondFrom];

                        for (int secondTo = 0; secondTo < dates.Length; secondTo++)
                        {
                            var secondToDate = dates[secondTo];
                            var secondToName = dateNames[secondTo];

                            var compareResult = new FuzzyDateRange(firstFromDate, firstToDate).CompareTo(new FuzzyDateRange(secondFromDate, secondToDate));

                            Trace.WriteLine($"Assert.AreEqual({compareResult}, new FuzzyDateRange({firstFromName}, {firstToName}).CompareTo(new FuzzyDateRange({secondFromName}, {secondToName})));");
                        }
                    }
                }
            }
        }
Ejemplo n.º 30
0
        public void ConvertToTimeSpanTest()
        {
            try
            {
                var dayFrom = 2;
                var dayTo   = 15;

                var from      = new FuzzyDate(2019, 9, dayFrom);
                var to        = new FuzzyDate(2019, 9, dayTo);
                var range     = new FuzzyDateRange(from, to);
                var converted = range.ToTimeSpan();
                Assert.AreEqual(dayTo - dayFrom, converted.TotalDays);
            }
            catch (Exception ex)
            {
                Assert.Fail($"Expect no exception, but got {ex.Message}");
            }
        }