Ejemplo n.º 1
0
        /// <summary>
        /// 获取时间轴卡片列表
        /// </summary>
        /// <param name="before">起始位置</param>
        /// <param name="take">获取数量</param>
        /// <param name="dbContext"><see cref="KeylolDbContext"/></param>
        /// <param name="cachedData"><see cref="CachedDataProvider"/></param>
        /// <returns><see cref="TimelineCardList"/></returns>
        public static async Task <TimelineCardList> GetCards(int before, int take, [Injected] KeylolDbContext dbContext,
                                                             [Injected] CachedDataProvider cachedData)
        {
            var currentUserId = StateTreeHelper.GetCurrentUserId();

            return(await TimelineCardList.CreateAsync(SubscriptionStream.Name(currentUserId), currentUserId,
                                                      take, false, dbContext, cachedData, before));
        }
Ejemplo n.º 2
0
 /// <summary>
 /// 创建 <see cref="TimelinePage"/>
 /// </summary>
 /// <param name="currentUserId">当前登录用户 ID</param>
 /// <param name="dbContext"><see cref="KeylolDbContext"/></param>
 /// <param name="cachedData"><see cref="CachedDataProvider"/></param>
 /// <returns><see cref="TimelinePage"/></returns>
 public static async Task <TimelinePage> CreateAsync(string currentUserId, KeylolDbContext dbContext,
                                                     CachedDataProvider cachedData)
 {
     return(new TimelinePage
     {
         Cards = await TimelineCardList.CreateAsync(SubscriptionStream.Name(currentUserId), currentUserId,
                                                    18, false, dbContext, cachedData)
     });
 }
Ejemplo n.º 3
0
        protected override void OnStart(string[] args)
        {
            _mqChannel.BasicQos(0, 5, false);
            var consumer = new EventingBasicConsumer(_mqChannel);

            consumer.Received += async(sender, eventArgs) =>
            {
                try
                {
                    using (var streamReader = new StreamReader(new MemoryStream(eventArgs.Body)))
                        using (var dbContext = new KeylolDbContext())
                        {
                            var serializer = new JsonSerializer();
                            var requestDto =
                                serializer.Deserialize <PushHubRequestDto>(new JsonTextReader(streamReader));

                            string            entryId;
                            FeedEntryType     entryType;
                            List <string>     pointsToPush;
                            List <UserToPush> usersToPush = new List <UserToPush>();
                            var count = 0;
                            switch (requestDto.Type)
                            {
                            case ContentPushType.Article:
                            {
                                var article = await dbContext.Articles.Where(a => a.Id == requestDto.ContentId)
                                              .Select(a => new
                                    {
                                        a.Id,
                                        a.AuthorId,
                                        a.AttachedPoints,
                                        a.TargetPointId
                                    }).SingleAsync();

                                usersToPush.Add(new UserToPush
                                    {
                                        UserId = article.AuthorId,
                                        SubscriberTimelineReason = "author"
                                    });
                                entryId      = article.Id;
                                entryType    = FeedEntryType.ArticleId;
                                pointsToPush = Helpers.SafeDeserialize <List <string> >(article.AttachedPoints) ??
                                               new List <string>();
                                pointsToPush.Add(article.TargetPointId);
                                break;
                            }

                            case ContentPushType.Activity:
                            {
                                var activity = await dbContext.Activities.Where(a => a.Id == requestDto.ContentId)
                                               .Select(a => new
                                    {
                                        a.Id,
                                        a.AuthorId,
                                        a.AttachedPoints,
                                        a.TargetPointId
                                    }).SingleAsync();

                                usersToPush.Add(new UserToPush
                                    {
                                        UserId = activity.AuthorId,
                                        SubscriberTimelineReason = "author"
                                    });
                                entryId      = activity.Id;
                                entryType    = FeedEntryType.ActivityId;
                                pointsToPush = Helpers.SafeDeserialize <List <string> >(activity.AttachedPoints) ??
                                               new List <string>();
                                pointsToPush.Add(activity.TargetPointId);
                                if (await AddOrUpdateFeedAsync(LatestActivityStream.Name, entryId, entryType, null,
                                                               dbContext))
                                {
                                    count++;
                                }
                                break;
                            }

                            case ContentPushType.Like:
                            {
                                var like = await dbContext.Likes.FindAsync(requestDto.ContentId);

                                entryId      = like.TargetId;
                                pointsToPush = new List <string>();
                                usersToPush.Add(new UserToPush
                                    {
                                        UserId                   = like.OperatorId,
                                        UserTimelineReason       = "like",
                                        SubscriberTimelineReason = $"like:{like.OperatorId}"
                                    });
                                switch (like.TargetType)
                                {
                                case LikeTargetType.Article:
                                    entryType = FeedEntryType.ArticleId;
                                    break;

                                case LikeTargetType.Activity:
                                    entryType = FeedEntryType.ActivityId;
                                    break;

                                default:
                                    _mqChannel.BasicAck(eventArgs.DeliveryTag, false);
                                    return;
                                }
                                break;
                            }

                            default:
                                throw new ArgumentOutOfRangeException();
                            }

                            foreach (var user in usersToPush)
                            {
                                if (await AddOrUpdateFeedAsync(UserStream.Name(user.UserId),
                                                               entryId, entryType, user.UserTimelineReason, dbContext))
                                {
                                    count++;
                                }

                                foreach (var subscriberId in await dbContext.Subscriptions
                                         .Where(s => s.TargetId == user.UserId &&
                                                s.TargetType == SubscriptionTargetType.User)
                                         .Select(s => s.SubscriberId).ToListAsync())
                                {
                                    if (await AddOrUpdateFeedAsync(SubscriptionStream.Name(subscriberId),
                                                                   entryId, entryType, user.SubscriberTimelineReason, dbContext))
                                    {
                                        count++;
                                    }
                                }
                            }


                            foreach (var pointId in pointsToPush)
                            {
                                var point = await dbContext.Points.Where(p => p.Id == pointId)
                                            .Select(p => new { p.Id }).SingleOrDefaultAsync();

                                if (point == null)
                                {
                                    continue;
                                }
                                if (await AddOrUpdateFeedAsync(PointStream.Name(point.Id),
                                                               entryId, entryType, null, dbContext))
                                {
                                    count++;
                                }

                                foreach (var subscriberId in await dbContext.Subscriptions
                                         .Where(s => s.TargetId == point.Id &&
                                                s.TargetType == SubscriptionTargetType.Point)
                                         .Select(s => s.SubscriberId).ToListAsync())
                                {
                                    if (await AddOrUpdateFeedAsync(SubscriptionStream.Name(subscriberId),
                                                                   entryId, entryType, $"point:{point.Id}", dbContext))
                                    {
                                        count++;
                                    }
                                }
                            }

                            _mqChannel.BasicAck(eventArgs.DeliveryTag, false);
                            _logger.Info($"{count} feeds pushed. Content: ({requestDto.Type}) {requestDto.ContentId}");
                        }
                }
                catch (Exception e)
                {
                    _mqChannel.BasicNack(eventArgs.DeliveryTag, false, false);
                    _logger.Fatal("RabbitMQ unhandled callback exception.", e);
                }
            };
            _mqChannel.BasicConsume(MqClientProvider.PushHubRequestQueue, false, consumer);
        }
        private static void AutoSubscribe(string userId)
        {
            Task.Run(async() =>
            {
                using (var dbContext = new KeylolDbContext())
                    using (var userManager = new KeylolUserManager(dbContext))
                    {
                        var redis      = Global.Container.GetInstance <RedisProvider>();
                        var cachedData = new CachedDataProvider(dbContext, redis);
                        if (await SteamCrawlerProvider.UpdateUserSteamGameRecordsAsync(userId, dbContext, userManager,
                                                                                       redis, cachedData))
                        {
                            var games = await(from record in dbContext.UserSteamGameRecords
                                              where record.UserId == userId
                                              join point in dbContext.Points on record.SteamAppId equals point.SteamAppId
                                              orderby record.TotalPlayedTime
                                              select new
                            {
                                PointId = point.Id,
                                record.LastPlayTime
                            }).ToListAsync();

                            var gamePointIds         = games.Select(g => g.PointId).ToList();
                            var mostPlayedPointIds   = gamePointIds.Take(3).ToList();
                            var recentPlayedPointIds = games.Where(g => !mostPlayedPointIds.Contains(g.PointId))
                                                       .OrderByDescending(g => g.LastPlayTime)
                                                       .Select(g => g.PointId).Take(3).ToList();
                            var categoryPointIds = await(from relationship in dbContext.PointRelationships
                                                         where gamePointIds.Contains(relationship.SourcePointId) &&
                                                         (relationship.Relationship == PointRelationshipType.Tag ||
                                                          relationship.Relationship == PointRelationshipType.Series)
                                                         group 1 by relationship.TargetPointId
                                                         into g
                                                         orderby g.Count() descending
                                                         select g.Key).Take(3).ToListAsync();

                            var pointIds = mostPlayedPointIds.Concat(recentPlayedPointIds).Concat(categoryPointIds).ToList();
                            foreach (var pointId in pointIds)
                            {
                                await cachedData.Subscriptions.AddAsync(userId, pointId, SubscriptionTargetType.Point);
                            }

                            var pointFeedStreams = pointIds.Select(PointStream.Name).ToList();
                            var feeds            = await(from feed in dbContext.Feeds
                                                         where pointFeedStreams.Contains(feed.StreamName)
                                                         orderby feed.Id descending
                                                         group new { feed.Id, feed.StreamName } by new { feed.Entry, feed.EntryType }
                                                         into g
                                                         orderby g.Max(f => f.Id)
                                                         select g).Take(120).ToListAsync();
                            var subscriptionStream = SubscriptionStream.Name(userId);
                            foreach (var feed in feeds)
                            {
                                var properties = new SubscriptionStream.FeedProperties
                                {
                                    Reasons = feed.Select(f => f.StreamName.Split(':')[1]).Distinct()
                                              .Select(id => $"point:{id}").ToList()
                                };
                                dbContext.Feeds.Add(new Models.Feed
                                {
                                    StreamName = subscriptionStream,
                                    Entry      = feed.Key.Entry,
                                    EntryType  = feed.Key.EntryType,
                                    Properties = JsonConvert.SerializeObject(properties)
                                });
                            }
                            await dbContext.SaveChangesAsync();
                        }
                    }
            });
        }