public async Task <List <LivestreamQueryResult> > GetTopStreams(TopStreamQuery topStreamQuery)
        {
            if (topStreamQuery == null)
            {
                throw new ArgumentNullException(nameof(topStreamQuery));
            }

            var query = new GetStreamsQuery()
            {
                First = topStreamQuery.Take
            };

            if (!string.IsNullOrWhiteSpace(topStreamQuery.GameName))
            {
                var gameId = await GetGameIdByName(topStreamQuery.GameName);

                query.GameIds.Add(gameId);
            }

            var topStreams = await twitchTvHelixClient.GetStreams(query);

            return(topStreams.Select(x =>
            {
                var channelIdentifier = new ChannelIdentifier(this, x.UserId)
                {
                    DisplayName = x.UserName
                };
                var queryResult = new LivestreamQueryResult(channelIdentifier);
                var livestreamModel = new LivestreamModel(x.UserId, channelIdentifier);
                livestreamModel.PopulateWithStreamDetails(x);

                queryResult.LivestreamModel = livestreamModel;
                return queryResult;
            }).ToList());
        }
        public async Task GetTopGameStreams(string gameId)
        {
            var topStreamsQuery = new GetStreamsQuery()
            {
                GameIds = new List <string>()
                {
                    gameId
                }
            };
            var topStreams = await sut.GetStreams(topStreamsQuery);

            Assert.NotNull(topStreams);
            Assert.NotEmpty(topStreams);

            Assert.All(topStreams, stream => Assert.Equal(gameId, stream.GameId));
        }
예제 #3
0
        public async Task <IActionResult> GetStreams(
            [FromQuery(Name = "game")] string gameName       = null,
            [FromQuery(Name = "pageSize")] int pageSize      = 8,
            [FromQuery(Name = "pageToken")] string pageToken = null)
        {
            var filterOptions = new StreamFilterOptions
            {
                GameName = gameName
            };

            var streamsQuery = new GetStreamsQuery
            {
                StreamPlatformNames = streamService.GetSupportingPlatforms(filterOptions),
                PageSize            = pageSize,
                PageToken           = pageToken,
                Filters             = new StreamFilters {
                    GameName = filterOptions.GameName
                },
            };

            var streams = await streamsQueryHandler.Execute(streamsQuery);

            return(Ok(streams));
        }
        /// <summary> Gets the top streams </summary>
        public async Task <List <Stream> > GetStreams(GetStreamsQuery getStreamsQuery, CancellationToken cancellationToken = default)
        {
            if (getStreamsQuery == null)
            {
                throw new ArgumentNullException(nameof(getStreamsQuery));
            }

            var streams = new List <Stream>();
            var request = $"{RequestConstants.Streams}?first={getStreamsQuery.First}";

            if (!string.IsNullOrWhiteSpace(getStreamsQuery.Pagination.After))
            {
                request += $"&after={getStreamsQuery.Pagination.After}";
            }

            if (getStreamsQuery.GameIds?.Any() == true)
            {
                if (getStreamsQuery.GameIds.Count > MaxItemsPerQuery)
                {
                    throw new ArgumentException($"Max allowed game ids is {MaxItemsPerQuery}, attempted to query {getStreamsQuery.GameIds.Count}");
                }

                foreach (var gameId in getStreamsQuery.GameIds)
                {
                    request += "&game_id=" + gameId;
                }
            }

            if (getStreamsQuery.Languages?.Any() == true)
            {
                if (getStreamsQuery.Languages.Count > MaxItemsPerQuery)
                {
                    throw new ArgumentException($"Max allowed languages is {MaxItemsPerQuery}, attempted to query {getStreamsQuery.Languages.Count}");
                }

                foreach (var language in getStreamsQuery.Languages)
                {
                    request += "&language=" + language;
                }
            }

            if (getStreamsQuery.UserIds?.Any() == true)
            {
                if (getStreamsQuery.UserIds.Count > MaxItemsPerQuery)
                {
                    var nonPagedRequest = request;
                    int taken           = 0;
                    while (taken < getStreamsQuery.UserIds.Count)
                    {
                        var pagedRequest = nonPagedRequest;
                        var pagedIds     = getStreamsQuery.UserIds.Skip(taken).Take(DefaultItemsPerQuery);
                        taken += DefaultItemsPerQuery;
                        foreach (var userId in pagedIds)
                        {
                            pagedRequest += "&user_id=" + userId;
                        }

                        var streamRoot = await ExecuteRequest <StreamsRoot>(pagedRequest, cancellationToken);

                        streams.AddRange(streamRoot.Streams);
                    }
                }
                else
                {
                    foreach (var userId in getStreamsQuery.UserIds)
                    {
                        request += "&user_id=" + userId;
                    }
                }
            }

            if (!streams.Any())
            {
                var streamRoot = await ExecuteRequest <StreamsRoot>(request, cancellationToken);

                streams = streamRoot.Streams;
            }
            return(streams);
        }
        public async Task <List <LivestreamQueryResult> > QueryChannels(CancellationToken cancellationToken)
        {
            var queryResults = new List <LivestreamQueryResult>();

            if (moniteredChannels.Count == 0)
            {
                return(queryResults);
            }

            // Twitch "get streams" call only returns online streams so to determine if the stream actually exists/is still valid, we must specifically ask for channel details.
            List <Stream> onlineStreams = new List <Stream>();

            int  retryCount = 0;
            bool success    = false;

            while (!success && !cancellationToken.IsCancellationRequested && retryCount < 3)
            {
                try
                {
                    var query = new GetStreamsQuery();
                    query.UserIds.AddRange(moniteredChannels.Select(x => x.ChannelId));
                    onlineStreams = await twitchTvHelixClient.GetStreams(query, cancellationToken);

                    success = true;
                }
                catch (HttpRequestWithStatusException ex) when(ex.StatusCode == HttpStatusCode.ServiceUnavailable)
                {
                    await Task.Delay(2000, cancellationToken);

                    retryCount++;
                }
            }

            foreach (var onlineStream in onlineStreams)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    return(queryResults);
                }

                var channelIdentifier = moniteredChannels.First(x => x.ChannelId.IsEqualTo(onlineStream.UserId));
                var gameName          = await GetGameNameById(onlineStream.GameId);

                var livestream = new LivestreamModel(onlineStream.UserId, channelIdentifier);
                livestream.PopulateWithStreamDetails(onlineStream);
                livestream.Game = gameName;
                queryResults.Add(new LivestreamQueryResult(channelIdentifier)
                {
                    LivestreamModel = livestream
                });
            }

            var offlineStreams = moniteredChannels.Where(x => onlineStreams.All(y => y.UserId != x.ChannelId)).ToList();

            foreach (var offlineStream in offlineStreams)
            {
                var queryResult = new LivestreamQueryResult(offlineStream)
                {
                    LivestreamModel = new LivestreamModel(offlineStream.ChannelId, offlineStream)
                    {
                        DisplayName = offlineStream.DisplayName ?? offlineStream.ChannelId
                    }
                };

                queryResults.Add(queryResult);
            }

            return(queryResults);
        }