Fixed invalid ownerids crashing bot on startup

Updated changelog, version to 6.1.3
This commit is contained in:
Toastie 2025-04-05 19:56:46 +13:00
parent 682ecb6f08
commit 427a011590
Signed by: toastie_t0ast
GPG key ID: 0861BE54AD481DC7
3 changed files with 61 additions and 45 deletions
CHANGELOG.md
src/EllieBot
EllieBot.csproj
Modules/Administration/Self

View file

@ -2,6 +2,12 @@
*a,c,f,r,o* *a,c,f,r,o*
## [6.1.3] - 05.04.2025
### Fixed
- Bot will no longer fail to startup if ownerids are wrong
## [6.1.2] - 03.04.2025 ## [6.1.2] - 03.04.2025
### Fixed ### Fixed

View file

@ -4,7 +4,7 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ImplicitUsings>true</ImplicitUsings> <ImplicitUsings>true</ImplicitUsings>
<SatelliteResourceLanguages>en</SatelliteResourceLanguages> <SatelliteResourceLanguages>en</SatelliteResourceLanguages>
<Version>6.1.2</Version> <Version>6.1.3</Version>
<!-- Output/build --> <!-- Output/build -->
<RunWorkingDirectory>$(MSBuildProjectDirectory)</RunWorkingDirectory> <RunWorkingDirectory>$(MSBuildProjectDirectory)</RunWorkingDirectory>

View file

@ -81,13 +81,13 @@ public sealed class SelfService : IExecNoCommand, IReadyExecutor, IEService
await using var uow = _db.GetDbContext(); await using var uow = _db.GetDbContext();
autoCommands = uow.Set<AutoCommand>() autoCommands = uow.Set<AutoCommand>()
.AsNoTracking() .AsNoTracking()
.Where(x => x.Interval >= 5) .Where(x => x.Interval >= 5)
.AsEnumerable() .AsEnumerable()
.GroupBy(x => x.GuildId) .GroupBy(x => x.GuildId)
.ToDictionary(x => x.Key, .ToDictionary(x => x.Key,
y => y.ToDictionary(x => x.Id, TimerFromAutoCommand).ToConcurrent()) y => y.ToDictionary(x => x.Id, TimerFromAutoCommand).ToConcurrent())
.ToConcurrent(); .ToConcurrent();
var startupCommands = uow.Set<AutoCommand>().AsNoTracking().Where(x => x.Interval == 0); var startupCommands = uow.Set<AutoCommand>().AsNoTracking().Where(x => x.Interval == 0);
foreach (var cmd in startupCommands) foreach (var cmd in startupCommands)
@ -101,8 +101,10 @@ public sealed class SelfService : IExecNoCommand, IReadyExecutor, IEService
} }
} }
if (_client.ShardId == 0) if (_client.ShardId != 0)
await LoadOwnerChannels(); return;
await LoadOwnerChannels();
} }
private Timer TimerFromAutoCommand(AutoCommand x) private Timer TimerFromAutoCommand(AutoCommand x)
@ -165,19 +167,27 @@ public sealed class SelfService : IExecNoCommand, IReadyExecutor, IEService
private async Task LoadOwnerChannels() private async Task LoadOwnerChannels()
{ {
var channels = await _creds.OwnerIds.Select(id => var channels = await _creds.OwnerIds.Select(async id =>
{ {
var user = _client.GetUser(id); var user = _client.GetUser(id);
if (user is null) if (user is null)
return Task.FromResult<IDMChannel>(null); return null;
return user.CreateDMChannelAsync(); try
}) {
.WhenAll(); return await user.CreateDMChannelAsync();
}
catch (Exception)
{
Log.Error("Unable to DM Owner {UserId} - please remove that id from the owner list", user.Id);
return null;
}
})
.WhenAll();
ownerChannels = channels.Where(x => x is not null) ownerChannels = channels.Where(x => x is not null)
.ToDictionary(x => x.Recipient.Id, x => x) .ToDictionary(x => x.Recipient.Id, x => x)
.ToImmutableDictionary(); .ToImmutableDictionary();
if (!ownerChannels.Any()) if (!ownerChannels.Any())
{ {
@ -401,41 +411,41 @@ public sealed class SelfService : IExecNoCommand, IReadyExecutor, IEService
{ {
await using var ctx = _db.GetDbContext(); await using var ctx = _db.GetDbContext();
var presentDbUsers = await ctx.GetTable<DiscordUser>() var presentDbUsers = await ctx.GetTable<DiscordUser>()
.Select(x => new .Select(x => new
{ {
x.UserId, x.UserId,
x.Username, x.Username,
}) })
.Where(x => users.Select(y => y.Id).Contains(x.UserId)) .Where(x => users.Select(y => y.Id).Contains(x.UserId))
.ToArrayAsyncEF(); .ToArrayAsyncEF();
var usersToAdd = users var usersToAdd = users
.Where(x => !presentDbUsers.Select(x => x.UserId).Contains(x.Id)) .Where(x => !presentDbUsers.Select(x => x.UserId).Contains(x.Id))
.Select(x => new DiscordUser() .Select(x => new DiscordUser()
{ {
UserId = x.Id, UserId = x.Id,
AvatarId = x.AvatarId, AvatarId = x.AvatarId,
Username = x.Username, Username = x.Username,
}); });
var added = (await ctx.BulkCopyAsync(usersToAdd)).RowsCopied; var added = (await ctx.BulkCopyAsync(usersToAdd)).RowsCopied;
var toUpdateUserIds = presentDbUsers var toUpdateUserIds = presentDbUsers
.Where(x => x.Username.StartsWith("??")) .Where(x => x.Username.StartsWith("??"))
.Select(x => x.UserId) .Select(x => x.UserId)
.ToArray(); .ToArray();
foreach (var user in users.Where(x => toUpdateUserIds.Contains(x.Id))) foreach (var user in users.Where(x => toUpdateUserIds.Contains(x.Id)))
{ {
await ctx.GetTable<DiscordUser>() await ctx.GetTable<DiscordUser>()
.Where(x => x.UserId == user.Id) .Where(x => x.UserId == user.Id)
.UpdateAsync(x => new DiscordUser() .UpdateAsync(x => new DiscordUser()
{ {
Username = user.Username, Username = user.Username,
// .award tends to set AvatarId and DateAdded to NULL, so account for that. // .award tends to set AvatarId and DateAdded to NULL, so account for that.
AvatarId = user.AvatarId, AvatarId = user.AvatarId,
DateAdded = x.DateAdded ?? DateTime.UtcNow DateAdded = x.DateAdded ?? DateTime.UtcNow
}); });
} }
return (added, toUpdateUserIds.Length); return (added, toUpdateUserIds.Length);