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); }
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); }
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); }
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(); }
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); }
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); }