diff --git a/Catalogger.Backend/Bot/Commands/InviteCommands.cs b/Catalogger.Backend/Bot/Commands/InviteCommands.cs index 77757f6..7ffa031 100644 --- a/Catalogger.Backend/Bot/Commands/InviteCommands.cs +++ b/Catalogger.Backend/Bot/Commands/InviteCommands.cs @@ -43,6 +43,7 @@ public class InviteCommands( InviteRepository inviteRepository, GuildCache guildCache, IInviteCache inviteCache, + UserCache userCache, IDiscordRestChannelAPI channelApi, IDiscordRestGuildAPI guildApi, FeedbackService feedbackService, @@ -113,21 +114,22 @@ public class InviteCommands( ); [Command("create")] - [Description("Create a new invite.`")] + [Description("Create a new invite.")] public async Task CreateInviteAsync( [Description("The channel to create the invite in")] [ChannelTypes(ChannelType.GuildText, ChannelType.GuildAnnouncement)] IChannel channel, - [Description("What to name the new invite")] string? name = null + [Description("What to name the new invite")] string? name = null, + [Description("How long the invite should be valid for")] InviteDuration? duration = null ) { var (userId, guildId) = contextInjection.GetUserAndGuild(); var inviteResult = await channelApi.CreateChannelInviteAsync( channel.ID, - maxAge: TimeSpan.Zero, + maxAge: duration?.ToTimespan() ?? TimeSpan.Zero, isUnique: true, - reason: $"Create invite command by {userId}" + reason: $"Create invite command by {await userCache.TryFormatUserAsync(userId, addMention: false)}" ); if (inviteResult.Error != null) { @@ -144,17 +146,20 @@ public class InviteCommands( ); } + var durationText = + duration != null ? $"\nThis invite {duration.ToHumanString()}." : string.Empty; + if (name == null) return await feedbackService.ReplyAsync( $"Created a new invite in <#{channel.ID}>!" - + $"\nLink: https://discord.gg/{inviteResult.Entity.Code}" + + $"\nLink: https://discord.gg/{inviteResult.Entity.Code}{durationText}" ); await inviteRepository.SetInviteNameAsync(guildId, inviteResult.Entity.Code, name); return await feedbackService.ReplyAsync( $"Created a new invite in <#{channel.ID}> with the name **{name}**!" - + $"\nLink: https://discord.gg/{inviteResult.Entity.Code}" + + $"\nLink: https://discord.gg/{inviteResult.Entity.Code}{durationText}" ); } @@ -253,3 +258,51 @@ public class InviteAutocompleteProvider( .ToList(); } } + +public enum InviteDuration +{ + [Description("30 minutes")] + ThirtyMinutes, + + [Description("1 hour")] + OneHour, + + [Description("6 hours")] + SixHours, + + [Description("12 hours")] + TwelveHours, + + [Description("1 day")] + OneDay, + + [Description("1 week")] + OneWeek, +} + +internal static class InviteEnumExtensions +{ + internal static TimeSpan ToTimespan(this InviteDuration dur) => + dur switch + { + InviteDuration.ThirtyMinutes => TimeSpan.FromMinutes(30), + InviteDuration.OneHour => TimeSpan.FromHours(1), + InviteDuration.SixHours => TimeSpan.FromHours(6), + InviteDuration.TwelveHours => TimeSpan.FromHours(12), + InviteDuration.OneDay => TimeSpan.FromDays(1), + InviteDuration.OneWeek => TimeSpan.FromDays(7), + _ => TimeSpan.Zero, + }; + + internal static string ToHumanString(this InviteDuration? dur) => + dur switch + { + InviteDuration.ThirtyMinutes => "expires after 30 minutes", + InviteDuration.OneHour => "expires after 1 hour", + InviteDuration.SixHours => "expires after 6 hours", + InviteDuration.TwelveHours => "expires after 12 hours", + InviteDuration.OneDay => "expires after 1 day", + InviteDuration.OneWeek => "expires after 1 week", + _ => "does not expire", + }; +}