public async Task <List <BkTag> > GetHotAsync() { var sw = Stopwatch.StartNew(); var re = await GetHotAsyncCore(); _logger.LogInformation("Get Hot Tags cost {Time} ms", sw.ElapsedMilliseconds); return(re); async Task <List <BkTag> > GetHotAsyncCore() { var options = await _userOptionsService.GetOptionsAsync(); var all = await _tagsRepo.GetAllAsync(); var result = all .Where(x => x.RelatedBkCount > 0) .OrderByDescending(x => x.ClickedCount) .ThenByDescending(x => x.LastClickTime) .ThenByDescending(x => x.RelatedBkCount) .Take(options.HotTagsFeature?.ListCount ?? 10) .ToList(); return(result); } }
public async Task AddAsync(MsgItem item) { var records = await _notificationRepo.GetAllAsync(); var groupName = item.Type.ToString(); var record = records.FirstOrDefault(x => x.Group == groupName); var now = _clock.UtcNow; item.CreatedTime = now; if (record == null) { record = new NotificationRecord { Group = groupName, Id = now, Items = new List <MsgItem> { item }, UpdateTime = now }; } else { record.Items.Insert(0, item); while (record.Items.Count > 10) { record.Items.RemoveAt(record.Items.Count - 1); } record.UpdateTime = now; } await _notificationRepo.UpsertAsync(record); var status = await _simpleDataStorage.GetOrDefaultAsync <NotificationCenterStatus>(); status.NewMessage = true; await _simpleDataStorage.SaveAsync(status); await _afEventHub.PublishAsync(new NewNotificationEvent()); }
public async ValueTask StartAsync() { var list = await _bkRepo.GetAllAsync(); foreach (var bk in list) { if (string.IsNullOrEmpty(bk.UrlHash)) { bk.UrlHash = _urlHashService.GetHash(bk.Url); await _bkRepo.UpsertAsync(bk); } } }
public async Task AppendBookmarksAsync(IEnumerable <BookmarkNode> nodes) { var updated = false; var bkDic = nodes.ToLookup(x => x.Url, x => new Bk { Title = x.Title, TitleLastUpdateTime = _clock.UtcNow, Url = x.Url, UrlHash = _urlHashService.GetHash(x.Url), LastCreateTime = x.DateAdded.HasValue ? DateTimeOffset.FromUnixTimeMilliseconds((long)x.DateAdded.Value).ToUnixTimeSeconds() : 0L, Tags = x.Tags.Distinct().ToList(), Offset = GetOffset(x.Deepth, x.ParentNodeOffset, x.Offset), }); var bookmarksKeys = bkDic.Select(x => x.Key).ToHashSet(); _logger.LogDebug("Found {Count} bookmark", bookmarksKeys.Count); foreach (var grouping in bkDic) { var url = grouping.Key; var node = grouping.First(); var bk = await _bkRepo.GetAsync(url); if (bk != null) { if (bk.Title != node.Title) { bk.Title = node.Title; bk.TitleLastUpdateTime = _clock.UtcNow; await _bkRepo.UpsertAsync(bk); updated = true; } } } var bks = await _bkRepo.GetAllAsync(); var newKeys = bookmarksKeys.Except(bks.Select(x => x.Url)).ToArray(); if (newKeys.Length > 0) { foreach (var key in newKeys) { var bk = bkDic[key].First(); _logger.LogInformation($"Current Upsert Node :{bk.Title}"); await _bkRepo.UpsertAsync(bk); if (bk.Tags?.Any() == true) { foreach (var tag in bk.Tags) { await AppendTagsAsync(tag); } } updated = true; } _logger.LogInformation("There are {Count} links new, add to storage", newKeys.Length); } if (updated) { await UpdateMetadataAsync(); } }
private async Task <IEnumerable <SearchResultItem> > SearchCore(string searchText) { var source = await _bkRepo.GetAllAsync(); var tags = await _tagRepo.GetAllAsync(); if (string.IsNullOrWhiteSpace(searchText)) { var latest = source .Where(x => x.LastClickTime > 0 && x.ClickedCount > 0) .OrderByDescending(x => x.LastClickTime) .ThenByDescending(x => x.ClickedCount) .Select(x => x.Id) .Take(LatestCount) .ToList(); return(source .Select(x => { var r = new SearchResultItem(x) { LastClickTime = x.LastClickTime }; r.AddScore(ScoreReason.Const, 10); if (latest.FirstOrDefault(a => a == r.Bk.Id) != null) { r.AddScore(ScoreReason.Latest, 10 - latest.FindIndex(a => a == r.Bk.Id)); } return r; })); } var input = SearchInput.Parse(searchText); _logger.LogInformation( "Search text parse result, SourceText: {SearchInput} Keywords: {Keywords}, Tags: {Tags}", input.SourceText, input.Keywords, input.Tags); var tagDict = tags.ToDictionary(x => x.Tag); var matchTags = tagDict .Where(tag => input.Tags.Contains(tag.Key) || input.Keywords.Any(keyword => StringContains(tag.Key, keyword))) .Select(x => x.Key) .ToHashSet(); var matchTagAlias = tagDict .Where(tag => input.Keywords.Any(keyword => tag.Value.TagAlias.Values.Any(tagAlias => StringContains(tagAlias.Alias, keyword)))) .Select(x => x.Key) .ToHashSet(); var re = source .Select(MatchBk) .Where(x => x.Matched); return(re); SearchResultItem MatchBk(Bk item) { var result = new SearchResultItem(item) { ClickCount = item.ClickedCount, LastClickTime = item.LastClickTime }; result.AddScore(ScoreReason.Title, input.Keywords.Any(x => StringContains(item.Title, x))); result.AddScore(ScoreReason.TitleAlias, item.TitleAlias?.Values != null && item.TitleAlias.Values.Any(al => input.Keywords.Any(x => StringContains(al.Alias, x)))); result.AddScore(ScoreReason.Url, input.Keywords.Any(x => StringContains(item.Url, x))); if (item.Tags?.Any() == true) { result.AddScore(ScoreReason.Tags, item.Tags.Any(matchTags.Contains)); result.AddScore(ScoreReason.TagAlias, item.Tags.Any(matchTagAlias.Contains)); } if (result.Score > 0) { result.AddScore(ScoreReason.ClickCount, item.ClickedCount); } return(result); }