Merge pull request #22 from NoiTheCat/dev/fixes

Various fixes
This commit is contained in:
Noi 2022-04-21 18:41:42 -07:00 committed by GitHub
commit 2ae4d71e8b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 46 additions and 14 deletions

View file

@ -14,6 +14,7 @@ public class BirthdayModule : BotModuleBase {
public const string HelpCmdGet = "Gets a user's birthday."; public const string HelpCmdGet = "Gets a user's birthday.";
public const string HelpCmdNearest = "Get a list of users who recently had or will have a birthday."; public const string HelpCmdNearest = "Get a list of users who recently had or will have a birthday.";
public const string HelpCmdExport = "Generates a text file with all known and available birthdays."; public const string HelpCmdExport = "Generates a text file with all known and available birthdays.";
public const string ErrNotSetFk = $":x: The bot has not yet been set up. Please configure a birthday role."; // foreign key violation
// Note that these methods have largely been copied to BirthdayOverrideModule. Changes here should be reflected there as needed. // Note that these methods have largely been copied to BirthdayOverrideModule. Changes here should be reflected there as needed.
@ -47,10 +48,16 @@ public class BirthdayModule : BotModuleBase {
user.BirthMonth = inmonth; user.BirthMonth = inmonth;
user.BirthDay = inday; user.BirthDay = inday;
user.TimeZone = inzone; user.TimeZone = inzone;
try {
await db.SaveChangesAsync(); await db.SaveChangesAsync();
} catch (Microsoft.EntityFrameworkCore.DbUpdateException e)
when (e.InnerException is Npgsql.PostgresException ex && ex.SqlState == Npgsql.PostgresErrorCodes.ForeignKeyViolation) {
await RespondAsync(ErrNotSetFk);
return;
}
await RespondAsync($":white_check_mark: Your birthday has been set to **{FormatDate(inmonth, inday)}**" + await RespondAsync($":white_check_mark: Your birthday has been set to **{FormatDate(inmonth, inday)}**" +
(inzone == null ? "" : $", with time zone {inzone}") + ".").ConfigureAwait(false); (inzone == null ? "" : $" at time zone **{inzone}**") + ".").ConfigureAwait(false);
} }
[SlashCommand("timezone", HelpCmdSetZone)] [SlashCommand("timezone", HelpCmdSetZone)]

View file

@ -29,7 +29,13 @@ public class BirthdayOverrideModule : BotModuleBase {
if (user.IsNew) db.UserEntries.Add(user); if (user.IsNew) db.UserEntries.Add(user);
user.BirthMonth = inmonth; user.BirthMonth = inmonth;
user.BirthDay = inday; user.BirthDay = inday;
try {
await db.SaveChangesAsync(); await db.SaveChangesAsync();
} catch (Microsoft.EntityFrameworkCore.DbUpdateException e)
when (e.InnerException is Npgsql.PostgresException ex && ex.SqlState == Npgsql.PostgresErrorCodes.ForeignKeyViolation) {
await RespondAsync(BirthdayModule.ErrNotSetFk);
return;
}
await RespondAsync($":white_check_mark: {Common.FormatName(target, false)}'s birthday has been set to " + await RespondAsync($":white_check_mark: {Common.FormatName(target, false)}'s birthday has been set to " +
$"**{FormatDate(inmonth, inday)}**.").ConfigureAwait(false); $"**{FormatDate(inmonth, inday)}**.").ConfigureAwait(false);

View file

@ -122,13 +122,21 @@ public class ConfigModule : BotModuleBase {
[Group("role", HelpPfxModOnly + HelpCmdRole)] [Group("role", HelpPfxModOnly + HelpCmdRole)]
public class SubCmdsConfigRole : BotModuleBase { public class SubCmdsConfigRole : BotModuleBase {
[SlashCommand("set-birthday-role", HelpPfxModOnly + "Set the role given to users having a birthday.")] [SlashCommand("set-birthday-role", HelpPfxModOnly + "Set the role given to users having a birthday.")]
public async Task CmdSetBRole([Summary(description: HelpOptRole)] SocketRole role) { public async Task CmdSetBRole([Summary(description: HelpOptRole)]SocketRole role) {
if (role.IsEveryone || role.IsManaged) {
await RespondAsync(":x: This role cannot be used for this setting.", ephemeral: true);
return;
}
await DoDatabaseUpdate(Context, s => s.RoleId = (long)role.Id); await DoDatabaseUpdate(Context, s => s.RoleId = (long)role.Id);
await RespondAsync($":white_check_mark: The birthday role has been set to **{role.Name}**.").ConfigureAwait(false); await RespondAsync($":white_check_mark: The birthday role has been set to **{role.Name}**.").ConfigureAwait(false);
} }
[SlashCommand("set-moderator-role", HelpPfxModOnly + "Designate a role whose members can configure the bot." + HelpPofxBlankUnset)] [SlashCommand("set-moderator-role", HelpPfxModOnly + "Designate a role whose members can configure the bot." + HelpPofxBlankUnset)]
public async Task CmdSetModRole([Summary(description: HelpOptRole)]SocketRole? role = null) { public async Task CmdSetModRole([Summary(description: HelpOptRole)]SocketRole? role = null) {
if (role != null && (role.IsEveryone || role.IsManaged)) {
await RespondAsync(":x: This role cannot be used for this setting.", ephemeral: true);
return;
}
await DoDatabaseUpdate(Context, s => s.ModeratorRole = (long?)role?.Id); await DoDatabaseUpdate(Context, s => s.ModeratorRole = (long?)role?.Id);
await RespondAsync(":white_check_mark: The moderator role has been " + await RespondAsync(":white_check_mark: The moderator role has been " +
(role == null ? "unset." : $"set to **{role.Name}**.")); (role == null ? "unset." : $"set to **{role.Name}**."));
@ -188,7 +196,7 @@ public class ConfigModule : BotModuleBase {
using var db = new BotDatabaseContext(); using var db = new BotDatabaseContext();
var guildconf = guild.GetConfigOrNew(db); var guildconf = guild.GetConfigOrNew(db);
await db.Entry(guildconf).Collection(t => t.UserEntries).LoadAsync(); if (!guildconf.IsNew) await db.Entry(guildconf).Collection(t => t.UserEntries).LoadAsync();
var result = new StringBuilder(); var result = new StringBuilder();
@ -200,14 +208,16 @@ public class ConfigModule : BotModuleBase {
bool hasMembers = Common.HasMostMembersDownloaded(guild); bool hasMembers = Common.HasMostMembersDownloaded(guild);
result.Append(DoTestFor("Bot has obtained the user list", () => hasMembers)); result.Append(DoTestFor("Bot has obtained the user list", () => hasMembers));
result.AppendLine($" - Has `{guild.DownloadedMemberCount}` of `{guild.MemberCount}` members."); result.AppendLine($" - Has `{guild.DownloadedMemberCount}` of `{guild.MemberCount}` members.");
int bdayCount = -1; int bdayCount = default;
result.Append(DoTestFor("Birthday processing", delegate { result.Append(DoTestFor("Birthday processing", delegate {
if (!hasMembers) return false; if (!hasMembers) return false;
if (guildconf.IsNew) return false;
bdayCount = BackgroundServices.BirthdayRoleUpdate.GetGuildCurrentBirthdays(guildconf.UserEntries, guildconf.TimeZone).Count; bdayCount = BackgroundServices.BirthdayRoleUpdate.GetGuildCurrentBirthdays(guildconf.UserEntries, guildconf.TimeZone).Count;
return true; return true;
})); }));
if (hasMembers) result.AppendLine($" - `{bdayCount}` user(s) currently having a birthday."); if (!hasMembers) result.AppendLine(" - Previous step failed.");
else result.AppendLine(" - Previous step failed."); else if (guildconf.IsNew) result.AppendLine(" - No data.");
else result.AppendLine($" - `{bdayCount}` user(s) currently having a birthday.");
result.AppendLine(); result.AppendLine();
result.AppendLine(DoTestFor("Birthday role set with `bb.config role`", delegate { result.AppendLine(DoTestFor("Birthday role set with `bb.config role`", delegate {

View file

@ -40,6 +40,13 @@ class BirthdayRoleUpdate : BackgroundService {
if (role == null if (role == null
|| !guild.CurrentUser.GuildPermissions.ManageRoles || !guild.CurrentUser.GuildPermissions.ManageRoles
|| role.Position >= guild.CurrentUser.Hierarchy) continue; || role.Position >= guild.CurrentUser.Hierarchy) continue;
if (role.IsEveryone || role.IsManaged) {
// Invalid role was configured. Clear the setting and quit.
settings.RoleId = null;
db.Update(settings);
await db.SaveChangesAsync();
continue;
}
// Load up user configs and begin processing birthdays // Load up user configs and begin processing birthdays
await db.Entry(settings).Collection(t => t.UserEntries).LoadAsync(CancellationToken.None); await db.Entry(settings).Collection(t => t.UserEntries).LoadAsync(CancellationToken.None);
@ -132,10 +139,8 @@ class BirthdayRoleUpdate : BackgroundService {
if (!toApply.Contains(user.Id)) removals.Add(user); if (!toApply.Contains(user.Id)) removals.Add(user);
else no_ops.Add(user.Id); else no_ops.Add(user.Id);
} }
int removalAllowance = 15; // Limit removals per run, to not get continuously stuck on rate limits in misconfigured servers
foreach (var user in removals) { foreach (var user in removals) {
await user.RemoveRoleAsync(r); await user.RemoveRoleAsync(r);
if (--removalAllowance == 0) break;
} }
foreach (var target in toApply) { foreach (var target in toApply) {

View file

@ -92,14 +92,18 @@ public sealed class ShardInstance : IDisposable {
case "Disconnected": case "Disconnected":
case "Resumed previous session": case "Resumed previous session":
case "Failed to resume previous session": case "Failed to resume previous session":
case "Discord.WebSocket.GatewayReconnectException: Server requested a reconnect": case "Serializer Error": // The exception associated with this log appears a lot as of v3.2-ish
return Task.CompletedTask; return Task.CompletedTask;
} }
Log("Discord.Net", $"{arg.Severity}: {arg.Message}"); Log("Discord.Net", $"{arg.Severity}: {arg.Message}");
} }
if (arg.Exception != null) Log("Discord.Net exception", arg.Exception.ToString()); if (arg.Exception != null) {
if (arg.Exception is GatewayReconnectException
|| arg.Exception.Message == "WebSocket connection was closed") return Task.CompletedTask;
Log("Discord.Net exception", arg.Exception.ToString());
}
return Task.CompletedTask; return Task.CompletedTask;
} }

View file

@ -113,7 +113,7 @@ class ShardManager : IDisposable {
ShardId = shardId, ShardId = shardId,
TotalShards = Config.ShardTotal, TotalShards = Config.ShardTotal,
LogLevel = LogSeverity.Info, LogLevel = LogSeverity.Info,
DefaultRetryMode = RetryMode.AlwaysRetry, DefaultRetryMode = RetryMode.Retry502 | RetryMode.RetryTimeouts,
GatewayIntents = GatewayIntents.Guilds | GatewayIntents.GuildMembers | GatewayIntents.GuildMessages GatewayIntents = GatewayIntents.Guilds | GatewayIntents.GuildMembers | GatewayIntents.GuildMessages
}; };
var services = new ServiceCollection() var services = new ServiceCollection()