public async Task SubscribeToLedgerStream()
        {
            SubscriptionStream stream = await this.client.Subscribe(new Requests.Subscription.SubscriptionRequest {
                Streams = new List <string>()
                {
                    "ledger"
                }
            });

            int i = 0;

            while (true)
            {
                if (i >= 3)
                {
                    await this.client.Unsubscribe();

                    break;
                }

                IDictionary <string, object> nextItem = await stream.Next();

                string json = nextItem.ToString();

                i++;
            }

            await this.client.Ping();
        }
Exemple #2
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));
        }
Exemple #3
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)
     });
 }
Exemple #4
0
        private void MessageReceived(string s, WebSocketClient client)
        {
            JObject jResponse = JObject.Parse(s);

            // if the response does not have an id field, it is not a RippleResponse.
            // it is most likely a stream from the subscribe API
            if (jResponse["id"] == null)
            {
                if (!jResponse.HasValues)
                {
                    return;
                }

                // if there is no active subscriptionStream
                // disregard the message
                if (this.subscriptionStream == null)
                {
                    return;
                }

                this.subscriptionStream.Push(this.ConvertJObjectToDictionary(jResponse));

                return;
            }

            RippleResponse response = jResponse.ToObject <RippleResponse>();

            var taskInfoResult = tasks.TryGetValue(response.Id, out var taskInfo);

            if (taskInfoResult == false)
            {
                throw new Exception("Task not found");
            }

            if (response.Status == "success")
            {
                if (taskInfo.Type != typeof(SubscriptionStream))
                {
                    if (taskInfo.IsUnsubscribe)
                    {
                        this.subscriptionStream = null;
                    }

                    object deserialized = JsonConvert.DeserializeObject(response.Result.ToString(), taskInfo.Type, serializerSettings);

                    MethodInfo setResult = taskInfo.TaskCompletionResult.GetType().GetMethod("SetResult");
                    setResult.Invoke(taskInfo.TaskCompletionResult, new[] { deserialized });
                }
                else
                {
                    TaskCompletionSource <SubscriptionStream> taskCompletionSource = taskInfo.TaskCompletionResult as TaskCompletionSource <SubscriptionStream>;
                    this.subscriptionStream = taskCompletionSource.Task.Result;

                    // since subscriptionStream is not null, MessageReceived will push the first subscription to the SubscriptionStream
                    this.MessageReceived(response.Result.ToString(), client);
                }

                if (taskInfo.RemoveUponCompletion)
                {
                    tasks.TryRemove(response.Id, out taskInfo);
                }
            }
            else if (response.Status == "error")
            {
                var setException = taskInfo.TaskCompletionResult.GetType().GetMethod("SetException", new Type[] { typeof(Exception) }, null);

                RippleException exception = new RippleException(response.Error);
                setException.Invoke(taskInfo.TaskCompletionResult, new[] { exception });

                tasks.TryRemove(response.Id, out taskInfo);
            }
        }
        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);
        }
        public async Task SubscribeToAccountStream()
        {
            /*{
             * "engine_result": "tesSUCCESS",
             * "engine_result_code": 0,
             * "engine_result_message": "The transaction was applied. Only final in a validated ledger.",
             * "ledger_hash": "A4A35B9C23EFF806BAFAED1D4F63475E10002E40B0A409718F8507320024C0A3",
             * "ledger_index": 42577394,
             * "meta": {
             * "AffectedNodes": [
             * {
             * "ModifiedNode": {
             * "FinalFields": {
             * "Account": "rK7D3QnTrYdkp1fGKKzHFNXZpqN8dUCfaf",
             * "Balance": "1582570858693",
             * "Flags": 1179648,
             * "OwnerCount": 5,
             * "Sequence": 682
             * },
             * "LedgerEntryType": "AccountRoot",
             * "LedgerIndex": "56C6890B573E333E7CF18DFA1DAB581595F14C218FA33068D5379B33AC49BA2B",
             * "PreviousFields": {
             * "Balance": "1582470858693"
             * },
             * "PreviousTxnID": "FDDBFDE3091B64F3AEFCE522D4DFE55D67F68F168DFA574118DB7086B982EE4C",
             * "PreviousTxnLgrSeq": 42575220
             * }
             * },
             * {
             * "ModifiedNode": {
             * "FinalFields": {
             * "Account": "rDsbeomae4FXwgQTJp9Rs64Qg9vDiTCdBv",
             * "Balance": "2748465618040",
             * "Flags": 131072,
             * "OwnerCount": 0,
             * "Sequence": 636135
             * },
             * "LedgerEntryType": "AccountRoot",
             * "LedgerIndex": "C3B625B296E95A21D7BBBB7E3D343AF423B463B87B5D56EE7F79C8E16A47A6F5",
             * "PreviousFields": {
             * "Balance": "2748565678040",
             * "Sequence": 636134
             * },
             * "PreviousTxnID": "48F4B2D79D1AE3B26D70DE6D26F4988FD9B4643410BDED41F49BCADB9D850875",
             * "PreviousTxnLgrSeq": 42577122
             * }
             * }
             * ],
             * "TransactionIndex": 0,
             * "TransactionResult": "tesSUCCESS"
             * },
             * "status": "closed",
             * "transaction": {
             * "Account": "rDsbeomae4FXwgQTJp9Rs64Qg9vDiTCdBv",
             * "Amount": "100000000",
             * "Destination": "rK7D3QnTrYdkp1fGKKzHFNXZpqN8dUCfaf",
             * "DestinationTag": 153,
             * "Fee": "60000",
             * "Flags": 2147483648,
             * "LastLedgerSequence": 42578393,
             * "Sequence": 636134,
             * "SigningPubKey": "03D847C2DBED3ABF0453F71DCD7641989136277218DF516AD49519C9693F32727E",
             * "TransactionType": "Payment",
             * "TxnSignature": "3045022100BFE470C6E3284808DEB5FE56097E9AD8EE616E3CE250524AEE3D3FC7811E33160220527FDAEAE5D09B2D949E0DF3A2DF2994A4F2FA43A0D17261C4029703CF885052",
             * "date": 594087992,
             * "hash": "5510C05D76FBC5259141222623C45D59F5DB50C46D8222516813A35403F65D97"
             * },
             * "type": "transaction",
             * "validated": true
             * }
             */

            const string bitstampHotWallet = "rDsbeomae4FXwgQTJp9Rs64Qg9vDiTCdBv";

            this.client = new RippleClient(mainNetUrl);
            await this.client.Connect();

            SubscriptionStream stream = await this.client.Subscribe(new Requests.Subscription.SubscriptionRequest {
                Accounts = new List <string>()
                {
                    bitstampHotWallet
                }
            });

            int i = 0;

            while (true)
            {
                if (i >= 3)
                {
                    await this.client.Unsubscribe();

                    break;
                }

                IDictionary <string, object> nextItem = await stream.Next();

                string json = JsonConvert.SerializeObject(nextItem);

                i++;
            }

            await this.client.Ping();
        }
        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();
                        }
                    }
            });
        }