Skip to content

Commit b85a564

Browse files
fix: race condition when setting bot token and ignoring banned users
There is still another race condition but this should severly limit the surface area of the issue. We need to centralize where the bot token is refreshed instead of allowing 2 separate threads to compete for it. We always wanted to ignore banned users but I forget to exclude them from the mod list.
1 parent 9ae0c72 commit b85a564

File tree

1 file changed

+29
-3
lines changed

1 file changed

+29
-3
lines changed

src/Nullinside.Api.TwitchBot/Services/MainService.cs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,13 @@ protected override Task ExecuteAsync(CancellationToken stoppingToken) {
152152
if (null == usersWithBotEnabled) {
153153
continue;
154154
}
155+
156+
// Get the list of users that are banned.
157+
List<User>? bannedUsers = await GetBannedUsers(db, stoppingToken);
158+
if (null == bannedUsers) {
159+
bannedUsers = Enumerable.Empty<User>().ToList();
160+
}
161+
var bannedUserIds = bannedUsers.Select(u => u.TwitchId).ToList();
155162

156163
// Get the bot user's information.
157164
User? botUser = await db.Users.AsNoTracking()
@@ -173,6 +180,8 @@ protected override Task ExecuteAsync(CancellationToken stoppingToken) {
173180

174181
// Trim channels we aren't a mod in
175182
IEnumerable<TwitchModeratedChannel> moddedChannels = await botApi.GetUserModChannels(Constants.BotId);
183+
moddedChannels = moddedChannels.Where(m => !bannedUserIds.Contains(m.broadcaster_id)).ToList();
184+
176185
usersWithBotEnabled = usersWithBotEnabled
177186
.Where(u => moddedChannels
178187
.Select(m => m.broadcaster_id)
@@ -281,6 +290,23 @@ orderby user.TwitchLastScanned
281290
.AsNoTracking()
282291
.ToListAsync(stoppingToken);
283292
}
293+
294+
/// <summary>
295+
/// Retrieve all users that are banned from using the bot.
296+
/// </summary>
297+
/// <param name="db">The database.</param>
298+
/// <param name="stoppingToken">The stopping token.</param>
299+
/// <returns>The list of users with the bot enabled.</returns>
300+
private async Task<List<User>?> GetBannedUsers(INullinsideContext db, CancellationToken stoppingToken) {
301+
return await
302+
(from user in db.Users
303+
orderby user.TwitchLastScanned
304+
where user.TwitchId != Constants.BotId &&
305+
user.IsBanned
306+
select user)
307+
.AsNoTracking()
308+
.ToListAsync(stoppingToken);
309+
}
284310

285311
/// <summary>
286312
/// Performs the scan on a user.
@@ -299,16 +325,16 @@ private async Task DoScan(User user, User botUser, CancellationToken stoppingTok
299325
using (IServiceScope scope = _serviceScopeFactory.CreateAsyncScope()) {
300326
await using (var db = scope.ServiceProvider.GetRequiredService<INullinsideContext>()) {
301327
// Get the API
302-
ITwitchApiProxy? botApi = await db.ConfigureApiAndRefreshToken(botUser, this._api, stoppingToken);
303-
if (null == _botRules || null == user.TwitchConfig || null == botApi) {
328+
this._api.Configure(botUser);
329+
if (null == _botRules || null == user.TwitchConfig) {
304330
return;
305331
}
306332

307333
// Run the rules that scan the chats and the accounts.
308334
foreach (IBotRule rule in _botRules) {
309335
try {
310336
if (rule.ShouldRun(user.TwitchConfig)) {
311-
await rule.Handle(user, user.TwitchConfig, botApi, db, stoppingToken);
337+
await rule.Handle(user, user.TwitchConfig, this._api, db, stoppingToken);
312338
}
313339
}
314340
catch (Exception e) {

0 commit comments

Comments
 (0)