From cefcde84b738288a73c5f756124f038a823752f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=E2=96=88=E2=96=88=E2=96=88=E2=96=88=E2=96=88?= Date: Wed, 5 Mar 2025 12:52:40 -0500 Subject: [PATCH] feat: only joining registered user channels We joined all channels we were a mod in just to be nice to users that haven't touched the site in a while and may have fallen out of the database. The result is that startup has gotten quite long as the bot has to join hundreds of channels. This code will allow us to join channels as they go live resulting in a faster startup. --- .../Services/MainService.cs | 59 ++++++++----------- 1 file changed, 26 insertions(+), 33 deletions(-) diff --git a/src/Nullinside.Api.TwitchBot/Services/MainService.cs b/src/Nullinside.Api.TwitchBot/Services/MainService.cs index 214cc23..5859b05 100644 --- a/src/Nullinside.Api.TwitchBot/Services/MainService.cs +++ b/src/Nullinside.Api.TwitchBot/Services/MainService.cs @@ -31,11 +31,21 @@ public class MainService : BackgroundService { /// private static IBotRule[]? _botRules; + /// + /// The twitch api. + /// + private readonly ITwitchApiProxy _api; + /// /// Handles the enforcing rules on chat messages. /// private readonly TwitchChatMessageMonitorConsumer _chatMessageConsumer; + /// + /// The twitch client for sending/receiving chat messages. + /// + private readonly ITwitchClientProxy _client; + /// /// The database. /// @@ -79,16 +89,6 @@ public class MainService : BackgroundService { /// private readonly IServiceScopeFactory _serviceScopeFactory; - /// - /// The twitch api. - /// - private readonly ITwitchApiProxy _api; - - /// - /// The twitch client for sending/receiving chat messages. - /// - private readonly ITwitchClientProxy _client; - /// /// Initializes a new instance of the class. /// @@ -115,8 +115,8 @@ protected override Task ExecuteAsync(CancellationToken stoppingToken) { throw new Exception("Unable to log in as bot user"); } - this._client.TwitchUsername = Constants.BotUsername; - this._client.TwitchOAuthToken = botApi.OAuth?.AccessToken; + _client.TwitchUsername = Constants.BotUsername; + _client.TwitchOAuthToken = botApi.OAuth?.AccessToken; _botRules = AppDomain.CurrentDomain.GetAssemblies() .SelectMany(a => a.GetTypes()) @@ -152,13 +152,6 @@ protected override Task ExecuteAsync(CancellationToken stoppingToken) { if (null == usersWithBotEnabled) { continue; } - - // Get the list of users that are banned. - List? bannedUsers = await GetBannedUsers(db, stoppingToken); - if (null == bannedUsers) { - bannedUsers = Enumerable.Empty().ToList(); - } - var bannedUserIds = bannedUsers.Select(u => u.TwitchId).ToList(); // Get the bot user's information. User? botUser = await db.Users.AsNoTracking() @@ -167,11 +160,11 @@ protected override Task ExecuteAsync(CancellationToken stoppingToken) { throw new Exception("No bot user in database"); } - ITwitchApiProxy? botApi = await db.ConfigureApiAndRefreshToken(botUser, this._api, stoppingToken); + ITwitchApiProxy? botApi = await db.ConfigureApiAndRefreshToken(botUser, _api, stoppingToken); if (null != botApi) { // Ensure the twitch client has the most up-to-date password - this._client.TwitchOAuthToken = botApi.OAuth?.AccessToken; - + _client.TwitchOAuthToken = botApi.OAuth?.AccessToken; + // Trim channels that aren't live IEnumerable liveUsers = await botApi.GetChannelsLive(usersWithBotEnabled .Where(u => null != u.TwitchId) @@ -180,20 +173,20 @@ protected override Task ExecuteAsync(CancellationToken stoppingToken) { // Trim channels we aren't a mod in IEnumerable moddedChannels = await botApi.GetUserModChannels(Constants.BotId); - moddedChannels = moddedChannels.Where(m => !bannedUserIds.Contains(m.broadcaster_id)).ToList(); - usersWithBotEnabled = usersWithBotEnabled - .Where(u => moddedChannels - .Select(m => m.broadcaster_id) - .Contains(u.TwitchId)) + .Where(u => moddedChannels.Select(m => m.broadcaster_id).Contains(u.TwitchId)) .ToList(); // Join all the channels we're a mod in. Why do we limit it to channels we are a mod in? Twitch changed // its chat limits so that "verified bots" like us don't get special treatment anymore. The only thing // that skips the chat limits is if it's a channel you're a mod in. - foreach (TwitchModeratedChannel channel in moddedChannels) { - await this._client.AddMessageCallback(channel.broadcaster_login, OnTwitchMessageReceived); - await this._client.AddBannedCallback(channel.broadcaster_login, OnTwitchBanReceived); + foreach (User channel in usersWithBotEnabled) { + if (string.IsNullOrWhiteSpace(channel.TwitchUsername)) { + continue; + } + + await _client.AddMessageCallback(channel.TwitchUsername, OnTwitchMessageReceived); + await _client.AddBannedCallback(channel.TwitchUsername, OnTwitchBanReceived); } } @@ -290,7 +283,7 @@ orderby user.TwitchLastScanned .AsNoTracking() .ToListAsync(stoppingToken); } - + /// /// Retrieve all users that are banned from using the bot. /// @@ -325,7 +318,7 @@ private async Task DoScan(User user, User botUser, CancellationToken stoppingTok using (IServiceScope scope = _serviceScopeFactory.CreateAsyncScope()) { await using (var db = scope.ServiceProvider.GetRequiredService()) { // Get the API - this._api.Configure(botUser); + _api.Configure(botUser); if (null == _botRules || null == user.TwitchConfig) { return; } @@ -334,7 +327,7 @@ private async Task DoScan(User user, User botUser, CancellationToken stoppingTok foreach (IBotRule rule in _botRules) { try { if (rule.ShouldRun(user.TwitchConfig)) { - await rule.Handle(user, user.TwitchConfig, this._api, db, stoppingToken); + await rule.Handle(user, user.TwitchConfig, _api, db, stoppingToken); } } catch (Exception e) {