Пример #1
0
        public async Task <GameInfo> RefreshCategory(string broadcasterId, CancellationToken cancellationToken = default)
        {
            _logger.LogInformation("Starting category refresh for channelId {broadcasterId}", broadcasterId);

            try
            {
                var results = await _twitchAPIClient.SearchChannelsAsync(broadcasterId, cancellationToken);

                var newResults = results.First(c => c.BroadcasterLogin == broadcasterId);

                if (newResults.GameId != _lastResult?.GameId)
                {
                    _lastInfo = await _twitchAPIClient.GetChannelInfoAsync(newResults.Id, cancellationToken);

                    _gameInfo = await _gameLocalization.ResolveLocalizedGameInfoAsync(newResults.BroadcasterLanguage, newResults.GameId, cancellationToken);

                    if (OnUpdate != null)
                    {
                        OnUpdate(this, _gameInfo);
                    }
                }

                _lastResult      = newResults;
                _broacasterLogin = broadcasterId;
                _lastCheck       = DateTime.UtcNow;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error refreshing category for channelId {broadcasterId}", broadcasterId);
            }

            return(_gameInfo);
        }
Пример #2
0
        async Task IChannelGrain.Activate(string userToken)
        {
            var userAuthenticated = Twitch.Authenticate()
                                    .FromOAuthToken(userToken)
                                    .Build();
            var userClient = TwitchAPIClient.CreateFromBase(_appClient, userAuthenticated);
            var validated  = await userClient.ValidateToken();

            if (validated == null || validated.UserId != _channelId || validated.ExpiresIn == 0)
            {
                throw new ArgumentException("Could not validate token");
            }
            _userClient = userClient;

            var channelInfoTask = _userClient.GetChannelInfoAsync(_channelId);
            List <HelixChannelModerator> moderators = new List <HelixChannelModerator>();
            var editorsTask = _userClient.GetHelixChannelEditorsAsync(_channelId);

            await foreach (var moderator in _userClient.EnumerateChannelModeratorsAsync(_channelId))
            {
                moderators.Add(moderator);
            }
            _channelState.State.BroadcasterToken = userToken;
            _channelState.State.Editors          = (await editorsTask).ToList();
            _channelState.State.Moderators       = moderators.ToList();
            await _channelState.WriteStateAsync();

            var editorsTasks = _channelState.State.Editors.Select(editor =>
                                                                  GrainFactory.GetGrain <IUserGrain>(editor.UserId).SetRole(new UserRole
            {
                Role        = ChannelRole.Editor,
                ChannelId   = _channelId,
                ChannelName = _channelInfo.BroadcasterName,
            })
                                                                  );

            var modsTasks = _channelState.State.Moderators.Select(moderator =>
                                                                  GrainFactory.GetGrain <IUserGrain>(moderator.UserId).SetRole(new UserRole
            {
                Role        = ChannelRole.Moderator,
                ChannelId   = _channelId,
                ChannelName = _channelInfo.BroadcasterName,
            })
                                                                  );

            await Task.WhenAll(editorsTasks);

            await Task.WhenAll(modsTasks);

            _channelInfo = await channelInfoTask;
            await RegisterEventSubSubscriptions(CancellationToken.None);
        }
Пример #3
0
        public override async Task <IProcessorSettings> LoadSettings(Guid processorId, string broadcasterId, CommandOptions options)
        {
            _settings = new GameSynopsisCommandSettings();
            _settings.LoadFromOptions(options);

            await base.CreateSettings(processorId, broadcasterId, _settings);

            var context = await _twitchAPIClient.GetChannelInfoAsync(broadcasterId);

            _gameInfo = await _twitchCategoryProvider.FetchChannelInfo(context.GameId, context.BroadcasterLanguage);

            return(_settings);
        }
Пример #4
0
        async Task IUserGrain.AllowAsBot(string channelId)
        {
            var validatedToken = await _twitchAPIClient.ValidateToken();

            if (validatedToken == null || validatedToken.UserId != UserId)
            {
                throw new InvalidOperationException("Missing active user token");
            }

            if (!_profile.State.CurrentScopes.Contains(TwitchConstants.TwitchOAuthScopes.ChatEdit))
            {
                throw new Exception("Missing chat permission, authorize bot account first.");
            }

            var channel = await _twitchAPIClient.GetChannelInfoAsync(channelId);

            if (channel == null)
            {
                _logger.LogError("AllowAsBot: invalid channel provider");
                throw new ArgumentException("Cannot find channel {channelId}", channelId);
            }

            if (!_profile.State.CanBeBotOnChannels.Any(c => c.BroadcasterId == channelId))
            {
                var channelInfo = await _twitchAPIClient.GetChannelInfoAsync(channelId);

                _profile.State.CanBeBotOnChannels.Add(channelInfo);
            }

            var channelGrain = GrainFactory.GetGrain <IChannelGrain>(channelId);
            await channelGrain.AllowBotAccount(
                new BotServiceGrainInterface.Model.BotAccountInfo {
                UserId    = UserId,
                UserLogin = _tokenInfo.Login,
            });

            await _profile.WriteStateAsync();
        }
Пример #5
0
        public Task StartAsync(CancellationToken externalCancellationToken)
        {
            var botChatClientBuilder = TwitchChatClientBuilder.Create()
                                       .WithAuthenticatedUser(_authenticated)
                                       .WithLoggerFactory(_serviceProvider.GetRequiredService <ILoggerFactory>());
            var orleansTaskScheduler = TaskScheduler.Current;

            _botCancellationSource = CancellationTokenSource.CreateLinkedTokenSource(externalCancellationToken);
            var cancellationToken = _botCancellationSource.Token;

            _botTask = Task.Run(async() =>
            {
                try
                {
                    var channelId   = await _channelIdCompletionSource.Task;
                    var channelInfo = await _twitchAPIClient.GetChannelInfoAsync(channelId, cancellationToken);

                    var channelName = channelInfo.BroadcasterName.ToLowerInvariant();

                    var botContext = new ProcessorContext
                    {
                        ChannelId   = channelId,
                        ChannelName = channelInfo.BroadcasterName,
                        Language    = channelInfo.BroadcasterLanguage,
                        CategoryId  = channelInfo.GameId,
                    };

                    using (var ircClient = botChatClientBuilder.Build())
                    {
                        await ircClient.ConnectAsync(cancellationToken);
                        await ircClient.JoinAsync(channelName, cancellationToken);
                        while (!cancellationToken.IsCancellationRequested)
                        {
                            await ircClient.ReceiveIRCMessage(botContext, _commandProcessors.Values, cancellationToken);
                        }
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Error in channel listener");
                }
            });

            return(Task.CompletedTask);
        }
Пример #6
0
        public override async Task OnActivateAsync()
        {
            _channelId = this.GetPrimaryKeyString();
            _logger.LogInformation("Activating channel grain {channelId}", _channelId);

            if (!_channelBotState.RecordExists)
            {
                var defaultBotInfo = new BotAccountInfo
                {
                    IsActive  = true,
                    UserId    = _options.TokenInfo.UserId,
                    UserLogin = _options.TokenInfo.Login,
                };
                _channelBotState.State.AllowedBotAccounts.Add(defaultBotInfo);
                _channelBotState.State.Commands = new Dictionary <Guid, Conceptoire.Twitch.Commands.CommandOptions>();
            }
            else
            {
                // Temps: fix existing ids
                foreach ((var id, var command) in _channelBotState.State.Commands)
                {
                    command.Id = id;
                    if (command.Type == "MessageTracer")
                    {
                        command.Type = "Logger";
                    }
                }
                // Activate bot if it is supposed to be running
                if (_channelBotState.State.IsActive)
                {
                    await RegisterEventSubSubscriptions(CancellationToken.None);
                    await StartBot(_channelState.State.BroadcasterToken);
                }
            }

            await base.OnActivateAsync();

            _channelInfo = await _appClient.GetChannelInfoAsync(_channelId);
            await OnChannelUpdate(_channelInfo);
        }