diff --git a/X10D.DSharpPlus/src/DiscordClientExtensions.cs b/X10D.DSharpPlus/src/DiscordClientExtensions.cs
index c9f21f4..f3d8964 100644
--- a/X10D.DSharpPlus/src/DiscordClientExtensions.cs
+++ b/X10D.DSharpPlus/src/DiscordClientExtensions.cs
@@ -1,4 +1,6 @@
using DSharpPlus;
+using DSharpPlus.Entities;
+using DSharpPlus.Exceptions;
namespace X10D.DSharpPlus;
@@ -41,4 +43,37 @@ public static class DiscordClientExtensions
};
}
}
+
+ ///
+ /// Gets a user by their ID. If the user is not found, is returned instead of
+ /// being thrown.
+ ///
+ /// The Discord client.
+ /// The ID of the user to retrieve.
+ /// is .
+ public static async Task GetUserOrNullAsync(this DiscordClient client, ulong userId)
+ {
+#if NET6_0_OR_GREATER
+ ArgumentNullException.ThrowIfNull(client);
+#else
+ if (client is null)
+ {
+ throw new ArgumentNullException(nameof(client));
+ }
+#endif
+
+ try
+ {
+ // we should never use exceptions for flow control but this is D#+ we're talking about.
+ // NotFoundException isn't even documented, and yet it gets thrown when a user doesn't exist.
+ // so this method should hopefully clearly express that - and at least using exceptions for flow control *here*,
+ // removes the need to do the same in consumer code.
+ // god I hate this.
+ return await client.GetUserAsync(userId).ConfigureAwait(false);
+ }
+ catch (NotFoundException)
+ {
+ return null;
+ }
+ }
}