mirror of
https://github.com/NoiTheCat/BirthdayBot.git
synced 2024-11-25 01:44:12 +00:00
Various changes
-Remove webhook logging references --Including config line. Idea is abandoned for now. -Remove unneeded comments -Remove diagnostic messages --Corresponding problems were solved by moving to dedicated hardware -Update style on all affected files
This commit is contained in:
parent
3741222c68
commit
578f2545f2
9 changed files with 298 additions and 385 deletions
|
@ -119,7 +119,6 @@ class BirthdayRoleUpdate : BackgroundService {
|
||||||
else roleKeeps.Add(member.Id);
|
else roleKeeps.Add(member.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Can we remove during the iteration instead of after? investigate later...
|
|
||||||
foreach (var user in roleRemoves) {
|
foreach (var user in roleRemoves) {
|
||||||
await user.RemoveRoleAsync(r).ConfigureAwait(false);
|
await user.RemoveRoleAsync(r).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,6 @@ class ShardBackgroundWorker : IDisposable {
|
||||||
_tickCount++;
|
_tickCount++;
|
||||||
await service.OnTick(_tickCount, _workerCanceller.Token).ConfigureAwait(false);
|
await service.OnTick(_tickCount, _workerCanceller.Token).ConfigureAwait(false);
|
||||||
} catch (Exception ex) when (ex is not TaskCanceledException) {
|
} catch (Exception ex) when (ex is not TaskCanceledException) {
|
||||||
// TODO webhook log
|
|
||||||
Instance.Log(nameof(WorkerLoop), $"{CurrentExecutingService} encountered an exception:\n" + ex.ToString());
|
Instance.Log(nameof(WorkerLoop), $"{CurrentExecutingService} encountered an exception:\n" + ex.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<Version>3.2.3</Version>
|
<Version>3.2.4</Version>
|
||||||
<Authors>NoiTheCat</Authors>
|
<Authors>NoiTheCat</Authors>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@
|
||||||
<PackageReference Include="Discord.Net" Version="3.0.0-dev-20210822.1" />
|
<PackageReference Include="Discord.Net" Version="3.0.0-dev-20210822.1" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
<PackageReference Include="NodaTime" Version="3.0.9" />
|
<PackageReference Include="NodaTime" Version="3.0.9" />
|
||||||
<PackageReference Include="Npgsql" Version="6.0.0" />
|
<PackageReference Include="Npgsql" Version="6.0.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
using BirthdayBot.Data;
|
using BirthdayBot.Data;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using Npgsql;
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using CommandLine;
|
using CommandLine;
|
||||||
using CommandLine.Text;
|
using CommandLine.Text;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Npgsql;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace BirthdayBot;
|
namespace BirthdayBot;
|
||||||
|
|
||||||
|
@ -22,7 +20,6 @@ class Configuration {
|
||||||
const string KeyShardRange = "ShardRange";
|
const string KeyShardRange = "ShardRange";
|
||||||
|
|
||||||
public string BotToken { get; }
|
public string BotToken { get; }
|
||||||
public string LogWebhook { get; }
|
|
||||||
public string? DBotsToken { get; }
|
public string? DBotsToken { get; }
|
||||||
public bool QuitOnFails { get; }
|
public bool QuitOnFails { get; }
|
||||||
|
|
||||||
|
@ -41,7 +38,6 @@ class Configuration {
|
||||||
var jc = JObject.Parse(File.ReadAllText(confPath));
|
var jc = JObject.Parse(File.ReadAllText(confPath));
|
||||||
|
|
||||||
BotToken = ReadConfKey<string>(jc, nameof(BotToken), true);
|
BotToken = ReadConfKey<string>(jc, nameof(BotToken), true);
|
||||||
LogWebhook = ReadConfKey<string>(jc, nameof(LogWebhook), true);
|
|
||||||
DBotsToken = ReadConfKey<string>(jc, nameof(DBotsToken), false);
|
DBotsToken = ReadConfKey<string>(jc, nameof(DBotsToken), false);
|
||||||
QuitOnFails = ReadConfKey<bool?>(jc, nameof(QuitOnFails), false) ?? false;
|
QuitOnFails = ReadConfKey<bool?>(jc, nameof(QuitOnFails), false) ?? false;
|
||||||
|
|
||||||
|
|
|
@ -50,41 +50,27 @@ class ShardInstance : IDisposable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Does all necessary steps to stop this shard. This method may block for a few seconds as it waits
|
/// Does all necessary steps to stop this shard, including canceling background tasks and disconnecting.
|
||||||
/// for the process to finish, but will force its disposal after at most 30 seconds.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Dispose() {
|
public void Dispose() {
|
||||||
// Unsubscribe from own events
|
|
||||||
DiscordClient.Log -= Client_Log;
|
DiscordClient.Log -= Client_Log;
|
||||||
DiscordClient.Ready -= Client_Ready;
|
DiscordClient.Ready -= Client_Ready;
|
||||||
DiscordClient.MessageReceived -= Client_MessageReceived;
|
DiscordClient.MessageReceived -= Client_MessageReceived;
|
||||||
|
|
||||||
_background.Dispose();
|
_background.Dispose();
|
||||||
try {
|
DiscordClient.LogoutAsync().Wait(5000);
|
||||||
if (!DiscordClient.LogoutAsync().Wait(15000))
|
DiscordClient.StopAsync().Wait(5000);
|
||||||
Log("Instance", "Warning: Client has not yet logged out. Continuing cleanup.");
|
DiscordClient.Dispose();
|
||||||
} catch (Exception ex) {
|
Log(nameof(ShardInstance), "Shard instance disposed.");
|
||||||
Log("Instance", "Warning: Client threw an exception when logging out: " + ex.Message);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (!DiscordClient.StopAsync().Wait(5000))
|
|
||||||
Log("Instance", "Warning: Client has not yet stopped. Continuing cleanup.");
|
|
||||||
} catch (Exception ex) {
|
|
||||||
Log("Instance", "Warning: Client threw an exception when stopping: " + ex.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
var clientDispose = Task.Run(DiscordClient.Dispose);
|
|
||||||
if (!clientDispose.Wait(10000)) Log("Instance", "Warning: Client is hanging on dispose. Will continue.");
|
|
||||||
else Log("Instance", "Shard instance disposed.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Log(string source, string message) => Program.Log($"Shard {ShardId:00}] [{source}", message);
|
public void Log(string source, string message) => Program.Log($"Shard {ShardId:00}] [{source}", message);
|
||||||
|
|
||||||
#region Event handling
|
#region Event handling
|
||||||
private Task Client_Log(LogMessage arg) {
|
private Task Client_Log(LogMessage arg) {
|
||||||
// TODO revise this some time, filters might need to be modified by now
|
|
||||||
// Suppress certain messages
|
// Suppress certain messages
|
||||||
if (arg.Message != null) {
|
if (arg.Message != null) {
|
||||||
|
// TODO remove below line ideally when D.Net bug is fixed
|
||||||
if (arg.Message.StartsWith("Unknown Dispatch ") || arg.Message.StartsWith("Unknown Channel")) return Task.CompletedTask;
|
if (arg.Message.StartsWith("Unknown Dispatch ") || arg.Message.StartsWith("Unknown Channel")) return Task.CompletedTask;
|
||||||
switch (arg.Message) // Connection status messages replaced by ShardManager's output
|
switch (arg.Message) // Connection status messages replaced by ShardManager's output
|
||||||
{
|
{
|
||||||
|
@ -92,23 +78,14 @@ class ShardInstance : IDisposable {
|
||||||
case "Connected":
|
case "Connected":
|
||||||
case "Ready":
|
case "Ready":
|
||||||
case "Failed to resume previous session":
|
case "Failed to resume previous session":
|
||||||
case "Resumed previous session":
|
case "Discord.WebSocket.GatewayReconnectException: Server requested a reconnect":
|
||||||
case "Disconnecting":
|
|
||||||
case "Disconnected":
|
|
||||||
case "WebSocket connection was closed":
|
|
||||||
case "Server requested a reconnect":
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
//if (arg.Message == "Heartbeat Errored") {
|
|
||||||
// // Replace this with a custom message; do not show stack trace
|
|
||||||
// Log("Discord.Net", $"{arg.Severity}: {arg.Message} - {arg.Exception.Message}");
|
|
||||||
// return Task.CompletedTask;
|
|
||||||
//}
|
|
||||||
|
|
||||||
Log("Discord.Net", $"{arg.Severity}: {arg.Message}");
|
Log("Discord.Net", $"{arg.Severity}: {arg.Message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg.Exception != null) Log("Discord.Net", arg.Exception.ToString());
|
if (arg.Exception != null) Log("Discord.Net exception", arg.Exception.ToString());
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
@ -152,8 +129,7 @@ class ShardInstance : IDisposable {
|
||||||
if (ex is HttpException) return;
|
if (ex is HttpException) return;
|
||||||
Log("Command", ex.ToString());
|
Log("Command", ex.ToString());
|
||||||
try {
|
try {
|
||||||
channel.SendMessageAsync(":x: An unknown error occurred. It has been reported to the bot owner.").Wait();
|
channel.SendMessageAsync(UserInterface.CommandsCommon.InternalError).Wait();
|
||||||
// TODO webhook report
|
|
||||||
} catch (HttpException) { } // Fail silently
|
} catch (HttpException) { } // Fail silently
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ internal abstract class CommandsCommon {
|
||||||
public const string BadUserError = ":x: Unable to find user. Specify their `@` mention or their ID.";
|
public const string BadUserError = ":x: Unable to find user. Specify their `@` mention or their ID.";
|
||||||
public const string ParameterError = ":x: Invalid usage. Refer to how to use the command and try again.";
|
public const string ParameterError = ":x: Invalid usage. Refer to how to use the command and try again.";
|
||||||
public const string NoParameterError = ":x: This command does not accept any parameters.";
|
public const string NoParameterError = ":x: This command does not accept any parameters.";
|
||||||
public const string InternalError = ":x: An internal bot error occurred. The bot maintainer has been notified of the issue.";
|
public const string InternalError = ":x: An unknown error occurred. If it persists, please notify the bot owner.";
|
||||||
public const string MemberCacheEmptyError = ":warning: Please try the command again.";
|
public const string MemberCacheEmptyError = ":warning: Please try the command again.";
|
||||||
|
|
||||||
public delegate Task CommandHandler(ShardInstance instance, GuildConfiguration gconf,
|
public delegate Task CommandHandler(ShardInstance instance, GuildConfiguration gconf,
|
||||||
|
|
|
@ -1,19 +1,13 @@
|
||||||
using BirthdayBot.Data;
|
using BirthdayBot.Data;
|
||||||
using Discord;
|
|
||||||
using Discord.WebSocket;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace BirthdayBot.UserInterface
|
namespace BirthdayBot.UserInterface;
|
||||||
{
|
|
||||||
internal class HelpInfoCommands : CommandsCommon
|
internal class HelpInfoCommands : CommandsCommon {
|
||||||
{
|
|
||||||
private readonly Embed _helpEmbed;
|
private readonly Embed _helpEmbed;
|
||||||
private readonly Embed _helpConfigEmbed;
|
private readonly Embed _helpConfigEmbed;
|
||||||
|
|
||||||
public HelpInfoCommands(Configuration cfg) : base(cfg)
|
public HelpInfoCommands(Configuration cfg) : base(cfg) {
|
||||||
{
|
|
||||||
var embeds = BuildHelpEmbeds();
|
var embeds = BuildHelpEmbeds();
|
||||||
_helpEmbed = embeds.Item1;
|
_helpEmbed = embeds.Item1;
|
||||||
_helpConfigEmbed = embeds.Item2;
|
_helpConfigEmbed = embeds.Item2;
|
||||||
|
@ -33,13 +27,11 @@ namespace BirthdayBot.UserInterface
|
||||||
("invite", CmdInfo)
|
("invite", CmdInfo)
|
||||||
};
|
};
|
||||||
|
|
||||||
private static (Embed, Embed) BuildHelpEmbeds()
|
private static (Embed, Embed) BuildHelpEmbeds() {
|
||||||
{
|
|
||||||
var cpfx = $"●`{CommandPrefix}";
|
var cpfx = $"●`{CommandPrefix}";
|
||||||
|
|
||||||
// Normal section
|
// Normal section
|
||||||
var cmdField = new EmbedFieldBuilder()
|
var cmdField = new EmbedFieldBuilder() {
|
||||||
{
|
|
||||||
Name = "Commands",
|
Name = "Commands",
|
||||||
Value = $"{cpfx}help`, `{CommandPrefix}info`, `{CommandPrefix}help-tzdata`\n"
|
Value = $"{cpfx}help`, `{CommandPrefix}info`, `{CommandPrefix}help-tzdata`\n"
|
||||||
+ $" » Help and informational messages.\n"
|
+ $" » Help and informational messages.\n"
|
||||||
|
@ -49,8 +41,7 @@ namespace BirthdayBot.UserInterface
|
||||||
+ UserCommands.DocRemove.Export() + "\n"
|
+ UserCommands.DocRemove.Export() + "\n"
|
||||||
+ ListingCommands.DocWhen.Export()
|
+ ListingCommands.DocWhen.Export()
|
||||||
};
|
};
|
||||||
var cmdModField = new EmbedFieldBuilder()
|
var cmdModField = new EmbedFieldBuilder() {
|
||||||
{
|
|
||||||
Name = "Moderator actions",
|
Name = "Moderator actions",
|
||||||
Value = $"{cpfx}config`\n"
|
Value = $"{cpfx}config`\n"
|
||||||
+ $" » Edit bot configuration. See `{CommandPrefix}help-config`.\n"
|
+ $" » Edit bot configuration. See `{CommandPrefix}help-config`.\n"
|
||||||
|
@ -61,8 +52,7 @@ namespace BirthdayBot.UserInterface
|
||||||
|
|
||||||
// Manager section
|
// Manager section
|
||||||
var mpfx = cpfx + "config ";
|
var mpfx = cpfx + "config ";
|
||||||
var configField1 = new EmbedFieldBuilder()
|
var configField1 = new EmbedFieldBuilder() {
|
||||||
{
|
|
||||||
Name = "Basic settings",
|
Name = "Basic settings",
|
||||||
Value = $"{mpfx}role (role name or ID)`\n"
|
Value = $"{mpfx}role (role name or ID)`\n"
|
||||||
+ " » Sets the role to apply to users having birthdays.\n"
|
+ " » Sets the role to apply to users having birthdays.\n"
|
||||||
|
@ -75,8 +65,7 @@ namespace BirthdayBot.UserInterface
|
||||||
+ $"{mpfx}zone (time zone name)`\n"
|
+ $"{mpfx}zone (time zone name)`\n"
|
||||||
+ $" » Sets the default server time zone. See `{CommandPrefix}help-tzdata`."
|
+ $" » Sets the default server time zone. See `{CommandPrefix}help-tzdata`."
|
||||||
};
|
};
|
||||||
var configField2 = new EmbedFieldBuilder()
|
var configField2 = new EmbedFieldBuilder() {
|
||||||
{
|
|
||||||
Name = "Access management",
|
Name = "Access management",
|
||||||
Value = $"{mpfx}modrole (role name, role ping, or ID)`\n"
|
Value = $"{mpfx}modrole (role name, role ping, or ID)`\n"
|
||||||
+ " » Establishes a role for bot moderators. Grants access to `bb.config` and `bb.override`.\n"
|
+ " » Establishes a role for bot moderators. Grants access to `bb.config` and `bb.override`.\n"
|
||||||
|
@ -86,8 +75,7 @@ namespace BirthdayBot.UserInterface
|
||||||
+ " » Prevents or allows using commands for all members excluding moderators."
|
+ " » Prevents or allows using commands for all members excluding moderators."
|
||||||
};
|
};
|
||||||
|
|
||||||
var helpConfig = new EmbedBuilder()
|
var helpConfig = new EmbedBuilder() {
|
||||||
{
|
|
||||||
Author = new EmbedAuthorBuilder() { Name = $"{CommandPrefix} config subcommands" },
|
Author = new EmbedAuthorBuilder() { Name = $"{CommandPrefix} config subcommands" },
|
||||||
Description = "All the following subcommands are only usable by moderators and server managers."
|
Description = "All the following subcommands are only usable by moderators and server managers."
|
||||||
}.AddField(configField1).AddField(configField2);
|
}.AddField(configField1).AddField(configField2);
|
||||||
|
@ -104,16 +92,14 @@ namespace BirthdayBot.UserInterface
|
||||||
=> await reqChannel.SendMessageAsync(embed: _helpConfigEmbed).ConfigureAwait(false);
|
=> await reqChannel.SendMessageAsync(embed: _helpConfigEmbed).ConfigureAwait(false);
|
||||||
|
|
||||||
private async Task CmdHelpTzdata(ShardInstance instance, GuildConfiguration gconf,
|
private async Task CmdHelpTzdata(ShardInstance instance, GuildConfiguration gconf,
|
||||||
string[] param, SocketTextChannel reqChannel, SocketGuildUser reqUser)
|
string[] param, SocketTextChannel reqChannel, SocketGuildUser reqUser) {
|
||||||
{
|
|
||||||
const string tzhelp = "You may specify a time zone in order to have your birthday recognized with respect to your local time. "
|
const string tzhelp = "You may specify a time zone in order to have your birthday recognized with respect to your local time. "
|
||||||
+ "This bot only accepts zone names from the IANA Time Zone Database (a.k.a. Olson Database).\n\n"
|
+ "This bot only accepts zone names from the IANA Time Zone Database (a.k.a. Olson Database).\n\n"
|
||||||
+ "To find your zone: https://xske.github.io/tz/" + "\n"
|
+ "To find your zone: https://xske.github.io/tz/" + "\n"
|
||||||
+ "Interactive map: https://kevinnovak.github.io/Time-Zone-Picker/" + "\n"
|
+ "Interactive map: https://kevinnovak.github.io/Time-Zone-Picker/" + "\n"
|
||||||
+ "Complete list: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones";
|
+ "Complete list: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones";
|
||||||
var embed = new EmbedBuilder();
|
var embed = new EmbedBuilder();
|
||||||
embed.AddField(new EmbedFieldBuilder()
|
embed.AddField(new EmbedFieldBuilder() {
|
||||||
{
|
|
||||||
Name = "Time Zone Support",
|
Name = "Time Zone Support",
|
||||||
Value = tzhelp
|
Value = tzhelp
|
||||||
});
|
});
|
||||||
|
@ -121,8 +107,7 @@ namespace BirthdayBot.UserInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task CmdHelpMessage(ShardInstance instance, GuildConfiguration gconf,
|
private async Task CmdHelpMessage(ShardInstance instance, GuildConfiguration gconf,
|
||||||
string[] param, SocketTextChannel reqChannel, SocketGuildUser reqUser)
|
string[] param, SocketTextChannel reqChannel, SocketGuildUser reqUser) {
|
||||||
{
|
|
||||||
const string msghelp = "The `message` and `messagepl` subcommands allow for editing the message sent into the announcement "
|
const string msghelp = "The `message` and `messagepl` subcommands allow for editing the message sent into the announcement "
|
||||||
+ "channel (defined with `{0}config channel`). This feature is separated across two commands:\n"
|
+ "channel (defined with `{0}config channel`). This feature is separated across two commands:\n"
|
||||||
+ "●`{0}config message`\n"
|
+ "●`{0}config message`\n"
|
||||||
|
@ -134,12 +119,10 @@ namespace BirthdayBot.UserInterface
|
||||||
+ "Leave the parameter blank to clear or reset the message to its default value.";
|
+ "Leave the parameter blank to clear or reset the message to its default value.";
|
||||||
const string msghelp2 = "As examples, these are the default announcement messages used by this bot:\n"
|
const string msghelp2 = "As examples, these are the default announcement messages used by this bot:\n"
|
||||||
+ "`message`: {0}\n" + "`messagepl`: {1}";
|
+ "`message`: {0}\n" + "`messagepl`: {1}";
|
||||||
var embed = new EmbedBuilder().AddField(new EmbedFieldBuilder()
|
var embed = new EmbedBuilder().AddField(new EmbedFieldBuilder() {
|
||||||
{
|
|
||||||
Name = "Custom announcement message",
|
Name = "Custom announcement message",
|
||||||
Value = string.Format(msghelp, CommandPrefix)
|
Value = string.Format(msghelp, CommandPrefix)
|
||||||
}).AddField(new EmbedFieldBuilder()
|
}).AddField(new EmbedFieldBuilder() {
|
||||||
{
|
|
||||||
Name = "Examples",
|
Name = "Examples",
|
||||||
Value = string.Format(msghelp2,
|
Value = string.Format(msghelp2,
|
||||||
BackgroundServices.BirthdayRoleUpdate.DefaultAnnounce, BackgroundServices.BirthdayRoleUpdate.DefaultAnnouncePl)
|
BackgroundServices.BirthdayRoleUpdate.DefaultAnnounce, BackgroundServices.BirthdayRoleUpdate.DefaultAnnouncePl)
|
||||||
|
@ -148,38 +131,31 @@ namespace BirthdayBot.UserInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task CmdInfo(ShardInstance instance, GuildConfiguration gconf,
|
private async Task CmdInfo(ShardInstance instance, GuildConfiguration gconf,
|
||||||
string[] param, SocketTextChannel reqChannel, SocketGuildUser reqUser)
|
string[] param, SocketTextChannel reqChannel, SocketGuildUser reqUser) {
|
||||||
{
|
|
||||||
var strStats = new StringBuilder();
|
var strStats = new StringBuilder();
|
||||||
var asmnm = System.Reflection.Assembly.GetExecutingAssembly().GetName();
|
var asmnm = System.Reflection.Assembly.GetExecutingAssembly().GetName();
|
||||||
strStats.AppendLine("BirthdayBot v" + asmnm.Version.ToString(3));
|
strStats.AppendLine("BirthdayBot v" + asmnm.Version!.ToString(3));
|
||||||
//strStats.AppendLine("Server count: " + Discord.Guilds.Count.ToString());
|
//strStats.AppendLine("Server count: " + Discord.Guilds.Count.ToString()); // TODO restore this statistic
|
||||||
// TODO restore this statistic
|
|
||||||
strStats.AppendLine("Shard #" + instance.ShardId.ToString("00"));
|
strStats.AppendLine("Shard #" + instance.ShardId.ToString("00"));
|
||||||
strStats.AppendLine("Uptime: " + Program.BotUptime);
|
strStats.AppendLine("Uptime: " + Program.BotUptime);
|
||||||
|
|
||||||
// TODO fun stats
|
// TODO fun stats
|
||||||
// current birthdays, total names registered, unique time zones
|
// current birthdays, total names registered, unique time zones
|
||||||
|
|
||||||
var embed = new EmbedBuilder()
|
var embed = new EmbedBuilder() {
|
||||||
{
|
Author = new EmbedAuthorBuilder() {
|
||||||
Author = new EmbedAuthorBuilder()
|
|
||||||
{
|
|
||||||
Name = "Thank you for using Birthday Bot!",
|
Name = "Thank you for using Birthday Bot!",
|
||||||
IconUrl = instance.DiscordClient.CurrentUser.GetAvatarUrl()
|
IconUrl = instance.DiscordClient.CurrentUser.GetAvatarUrl()
|
||||||
},
|
},
|
||||||
// TODO this message needs an overhaul
|
|
||||||
Description = "For more information regarding support, data retention, privacy, and other details, please refer to: "
|
Description = "For more information regarding support, data retention, privacy, and other details, please refer to: "
|
||||||
+ "https://github.com/NoiTheCat/BirthdayBot/blob/master/Readme.md" + "\n\n"
|
+ "https://github.com/NoiTheCat/BirthdayBot/blob/master/Readme.md" + "\n\n"
|
||||||
+ "This bot is provided for free, without any paywalled 'premium' features. "
|
+ "This bot is provided for free, without any paywalled 'premium' features. "
|
||||||
+ "If you've found this bot useful, please consider contributing via the "
|
+ "If you've found this bot useful, please consider contributing via the "
|
||||||
+ "bot author's page on Ko-fi: https://ko-fi.com/noithecat."
|
+ "bot author's page on Ko-fi: https://ko-fi.com/noithecat."
|
||||||
}.AddField(new EmbedFieldBuilder()
|
}.AddField(new EmbedFieldBuilder() {
|
||||||
{
|
|
||||||
Name = "Statistics",
|
Name = "Statistics",
|
||||||
Value = strStats.ToString()
|
Value = strStats.ToString()
|
||||||
});
|
});
|
||||||
await reqChannel.SendMessageAsync(embed: embed.Build()).ConfigureAwait(false);
|
await reqChannel.SendMessageAsync(embed: embed.Build()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -129,7 +129,6 @@ internal class ListingCommands : CommandsCommon {
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Program.Log("Listing", ex.ToString());
|
Program.Log("Listing", ex.ToString());
|
||||||
reqChannel.SendMessageAsync(InternalError).Wait();
|
reqChannel.SendMessageAsync(InternalError).Wait();
|
||||||
// TODO webhook report
|
|
||||||
} finally {
|
} finally {
|
||||||
File.Delete(filepath);
|
File.Delete(filepath);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,9 @@
|
||||||
using BirthdayBot.Data;
|
using BirthdayBot.Data;
|
||||||
using Discord.WebSocket;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace BirthdayBot.UserInterface
|
namespace BirthdayBot.UserInterface;
|
||||||
{
|
|
||||||
internal class UserCommands : CommandsCommon
|
internal class UserCommands : CommandsCommon {
|
||||||
{
|
|
||||||
public UserCommands(Configuration db) : base(db) { }
|
public UserCommands(Configuration db) : base(db) { }
|
||||||
|
|
||||||
public override IEnumerable<(string, CommandHandler)> Commands
|
public override IEnumerable<(string, CommandHandler)> Commands
|
||||||
|
@ -33,11 +28,9 @@ namespace BirthdayBot.UserInterface
|
||||||
/// <exception cref="FormatException">
|
/// <exception cref="FormatException">
|
||||||
/// Thrown for any parsing issue. Reason is expected to be sent to Discord as-is.
|
/// Thrown for any parsing issue. Reason is expected to be sent to Discord as-is.
|
||||||
/// </exception>
|
/// </exception>
|
||||||
private static (int, int) ParseDate(string dateInput)
|
private static (int, int) ParseDate(string dateInput) {
|
||||||
{
|
|
||||||
var m = DateParse1.Match(dateInput);
|
var m = DateParse1.Match(dateInput);
|
||||||
if (!m.Success)
|
if (!m.Success) {
|
||||||
{
|
|
||||||
// Flip the fields around, try again
|
// Flip the fields around, try again
|
||||||
m = DateParse2.Match(dateInput);
|
m = DateParse2.Match(dateInput);
|
||||||
if (!m.Success) throw new FormatException(FormatError);
|
if (!m.Success) throw new FormatException(FormatError);
|
||||||
|
@ -45,12 +38,9 @@ namespace BirthdayBot.UserInterface
|
||||||
|
|
||||||
int day, month;
|
int day, month;
|
||||||
string monthVal;
|
string monthVal;
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
day = int.Parse(m.Groups["day"].Value);
|
day = int.Parse(m.Groups["day"].Value);
|
||||||
}
|
} catch (FormatException) {
|
||||||
catch (FormatException)
|
|
||||||
{
|
|
||||||
throw new Exception(FormatError);
|
throw new Exception(FormatError);
|
||||||
}
|
}
|
||||||
monthVal = m.Groups["month"].Value;
|
monthVal = m.Groups["month"].Value;
|
||||||
|
@ -71,8 +61,7 @@ namespace BirthdayBot.UserInterface
|
||||||
/// <exception cref="FormatException">
|
/// <exception cref="FormatException">
|
||||||
/// Thrown on error. Send out to Discord as-is.
|
/// Thrown on error. Send out to Discord as-is.
|
||||||
/// </exception>
|
/// </exception>
|
||||||
private static (int, int) GetMonth(string input)
|
private static (int, int) GetMonth(string input) {
|
||||||
{
|
|
||||||
return input.ToLower() switch {
|
return input.ToLower() switch {
|
||||||
"jan" or "january" => (1, 31),
|
"jan" or "january" => (1, 31),
|
||||||
"feb" or "february" => (2, 29),
|
"feb" or "february" => (2, 29),
|
||||||
|
@ -103,10 +92,8 @@ namespace BirthdayBot.UserInterface
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private async Task CmdSet(ShardInstance instance, GuildConfiguration gconf,
|
private async Task CmdSet(ShardInstance instance, GuildConfiguration gconf,
|
||||||
string[] param, SocketTextChannel reqChannel, SocketGuildUser reqUser)
|
string[] param, SocketTextChannel reqChannel, SocketGuildUser reqUser) {
|
||||||
{
|
if (param.Length < 2) {
|
||||||
if (param.Length < 2)
|
|
||||||
{
|
|
||||||
await reqChannel.SendMessageAsync(ParameterError, embed: DocSet.UsageEmbed).ConfigureAwait(false);
|
await reqChannel.SendMessageAsync(ParameterError, embed: DocSet.UsageEmbed).ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -117,12 +104,9 @@ namespace BirthdayBot.UserInterface
|
||||||
fullinput = fullinput[1..]; // trim leading space
|
fullinput = fullinput[1..]; // trim leading space
|
||||||
|
|
||||||
int bmonth, bday;
|
int bmonth, bday;
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
(bmonth, bday) = ParseDate(fullinput);
|
(bmonth, bday) = ParseDate(fullinput);
|
||||||
}
|
} catch (FormatException ex) {
|
||||||
catch (FormatException ex)
|
|
||||||
{
|
|
||||||
// Our parse method's FormatException has its message to send out to Discord.
|
// Our parse method's FormatException has its message to send out to Discord.
|
||||||
reqChannel.SendMessageAsync(ex.Message, embed: DocSet.UsageEmbed).Wait();
|
reqChannel.SendMessageAsync(ex.Message, embed: DocSet.UsageEmbed).Wait();
|
||||||
return;
|
return;
|
||||||
|
@ -130,16 +114,12 @@ namespace BirthdayBot.UserInterface
|
||||||
|
|
||||||
// Parsing successful. Update user information.
|
// Parsing successful. Update user information.
|
||||||
bool known; // Extra detail: Bot's response changes if the user was previously unknown.
|
bool known; // Extra detail: Bot's response changes if the user was previously unknown.
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
var user = await GuildUserConfiguration.LoadAsync(gconf.GuildId, reqUser.Id).ConfigureAwait(false);
|
var user = await GuildUserConfiguration.LoadAsync(gconf.GuildId, reqUser.Id).ConfigureAwait(false);
|
||||||
known = user.IsKnown;
|
known = user.IsKnown;
|
||||||
await user.UpdateAsync(bmonth, bday, user.TimeZone).ConfigureAwait(false);
|
await user.UpdateAsync(bmonth, bday, user.TimeZone).ConfigureAwait(false);
|
||||||
}
|
} catch (Exception ex) {
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Program.Log("Error", ex.ToString());
|
Program.Log("Error", ex.ToString());
|
||||||
// TODO webhook report
|
|
||||||
reqChannel.SendMessageAsync(InternalError).Wait();
|
reqChannel.SendMessageAsync(InternalError).Wait();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -148,17 +128,14 @@ namespace BirthdayBot.UserInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task CmdZone(ShardInstance instance, GuildConfiguration gconf,
|
private async Task CmdZone(ShardInstance instance, GuildConfiguration gconf,
|
||||||
string[] param, SocketTextChannel reqChannel, SocketGuildUser reqUser)
|
string[] param, SocketTextChannel reqChannel, SocketGuildUser reqUser) {
|
||||||
{
|
if (param.Length != 2) {
|
||||||
if (param.Length != 2)
|
|
||||||
{
|
|
||||||
await reqChannel.SendMessageAsync(ParameterError, embed: DocZone.UsageEmbed).ConfigureAwait(false);
|
await reqChannel.SendMessageAsync(ParameterError, embed: DocZone.UsageEmbed).ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var user = await GuildUserConfiguration.LoadAsync(gconf.GuildId, reqUser.Id).ConfigureAwait(false);
|
var user = await GuildUserConfiguration.LoadAsync(gconf.GuildId, reqUser.Id).ConfigureAwait(false);
|
||||||
if (!user.IsKnown)
|
if (!user.IsKnown) {
|
||||||
{
|
|
||||||
await reqChannel.SendMessageAsync(":x: You may only update your time zone when you have a birthday registered."
|
await reqChannel.SendMessageAsync(":x: You may only update your time zone when you have a birthday registered."
|
||||||
+ $" Refer to the `{CommandPrefix}set` command.", embed: DocZone.UsageEmbed)
|
+ $" Refer to the `{CommandPrefix}set` command.", embed: DocZone.UsageEmbed)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
@ -166,12 +143,9 @@ namespace BirthdayBot.UserInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
string btz;
|
string btz;
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
btz = ParseTimeZone(param[1]);
|
btz = ParseTimeZone(param[1]);
|
||||||
}
|
} catch (Exception ex) {
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
reqChannel.SendMessageAsync(ex.Message, embed: DocZone.UsageEmbed).Wait();
|
reqChannel.SendMessageAsync(ex.Message, embed: DocZone.UsageEmbed).Wait();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -182,11 +156,9 @@ namespace BirthdayBot.UserInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task CmdRemove(ShardInstance instance, GuildConfiguration gconf,
|
private async Task CmdRemove(ShardInstance instance, GuildConfiguration gconf,
|
||||||
string[] param, SocketTextChannel reqChannel, SocketGuildUser reqUser)
|
string[] param, SocketTextChannel reqChannel, SocketGuildUser reqUser) {
|
||||||
{
|
|
||||||
// Parameter count check
|
// Parameter count check
|
||||||
if (param.Length != 1)
|
if (param.Length != 1) {
|
||||||
{
|
|
||||||
await reqChannel.SendMessageAsync(NoParameterError, embed: DocRemove.UsageEmbed).ConfigureAwait(false);
|
await reqChannel.SendMessageAsync(NoParameterError, embed: DocRemove.UsageEmbed).ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -196,16 +168,12 @@ namespace BirthdayBot.UserInterface
|
||||||
var u = await GuildUserConfiguration.LoadAsync(gconf.GuildId, reqUser.Id).ConfigureAwait(false);
|
var u = await GuildUserConfiguration.LoadAsync(gconf.GuildId, reqUser.Id).ConfigureAwait(false);
|
||||||
known = u.IsKnown;
|
known = u.IsKnown;
|
||||||
await u.DeleteAsync().ConfigureAwait(false);
|
await u.DeleteAsync().ConfigureAwait(false);
|
||||||
if (!known)
|
if (!known) {
|
||||||
{
|
|
||||||
await reqChannel.SendMessageAsync(":white_check_mark: This bot already does not contain your information.")
|
await reqChannel.SendMessageAsync(":white_check_mark: This bot already does not contain your information.")
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
await reqChannel.SendMessageAsync(":white_check_mark: Your information has been removed.")
|
await reqChannel.SendMessageAsync(":white_check_mark: Your information has been removed.")
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue