mirror of
https://github.com/NoiTheCat/BirthdayBot.git
synced 2024-11-22 05:54:36 +00:00
commit
2ae4d71e8b
6 changed files with 46 additions and 14 deletions
|
@ -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)]
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
|
Loading…
Reference in a new issue