public async Task UnscheduleGuildEvent(CommandContext context)
        {
            using IBotAccessProvider provider = this.accessBuilder.Build();
            InteractivityExtension interactivity = context.Client.GetInteractivity();

            DiscordMessage msg = await context.RespondAsync(
                $":wave: Hi, {context.User.Mention}! You want to unschedule an event for your guild?");

            Reaction reaction = await interactivity.AddAndWaitForYesNoReaction(msg, context.User);

            if (reaction != Reaction.Yes)
            {
                return;
            }

            await context.Message.DeleteAsync();

            DateTimeZone memberTimeZone = this.timeZoneProvider[provider.GetUsersTimeZone(context.User.Id).TimeZoneId];

            List <GuildBackgroundJob> guildEventJobs = provider.GetAllAssociatedGuildBackgroundJobs(context.Guild.Id)
                                                       .Where(x => x.GuildJobType == GuildJobType.SCHEDULED_EVENT)
                                                       .OrderBy(x => x.ScheduledTime)
                                                       .ToList();

            DiscordEmbedBuilder removeEventEmbed = new DiscordEmbedBuilder()
                                                   .WithTitle("Select an event to unschedule by typing: <event number>")
                                                   .WithColor(context.Member.Color);

            CustomResult <int> result = await context.WaitForMessageAndPaginateOnMsg(
                GetScheduledEventsPages(guildEventJobs.Select(x => x.WithTimeZoneConvertedTo(memberTimeZone)), interactivity, removeEventEmbed),
                PaginationMessageFunction.CreateWaitForMessageWithIntInRange(context.User, context.Channel, 1, guildEventJobs.Count + 1),
                msg : msg);

            if (result.TimedOut || result.Cancelled)
            {
                DiscordMessage snark = await context.RespondAsync("You never gave me a valid input. Thanks for wasting my time. :triumph:");

                await Task.Delay(5000);

                await context.Channel.DeleteMessagesAsync(new List <DiscordMessage> {
                    msg, snark
                });

                return;
            }

            GuildBackgroundJob job = guildEventJobs[result.Result - 1];

            msg = await msg.ModifyAsync($"{context.User.Mention}, are you sure you want to unschedule this event?", embed : null);

            reaction = await interactivity.AddAndWaitForYesNoReaction(msg, context.User);

            BackgroundJob.Delete(job.HangfireJobId);
            provider.DeleteGuildBackgroundJob(job);
            await msg.DeleteAllReactionsAsync();

            await msg.ModifyAsync("Ok, I've unscheduled that event!", embed : null);
        }
        public async Task UpdateTimeZone(CommandContext context)
        {
            using IBotAccessProvider accessProvider = this.providerBuilder.Build();

            if (accessProvider.GetUsersTimeZone(context.User.Id) == null)
            {
                await context.RespondAsync(
                    $"{context.User.Mention}, you don't have a timezone set up. To initialize your timezone please type `time init`.");

                return;
            }
            await context.RespondAsync(
                "Please navigate to https://kevinnovak.github.io/Time-Zone-Picker/ and select your timezone. After you do please hit the copy button and paste the contents into the chat.");

            InteractivityExtension interactivity        = context.Client.GetInteractivity();
            InteractivityResult <DiscordMessage> result = await interactivity.WaitForMessageAsync(msg => msg.Author.Equals(context.Message.Author));

            if (!result.TimedOut)
            {
                DateTimeZone test = this.timeZoneProvider.GetZoneOrNull(result.Result.Content);
                if (test != null)
                {
                    UserTimeZone updatedUserTimeZone = accessProvider.GetUsersTimeZone(context.Message.Author.Id);
                    updatedUserTimeZone.TimeZoneId = result.Result.Content;
                    accessProvider.UpdateUserTimeZone(updatedUserTimeZone);
                    await context.RespondAsync(
                        $"I updated your timezone to {result.Result.Content} in all guilds I am a member of.");
                }
                else
                {
                    await context.RespondAsync("You provided me with an invalid timezone. Try again by typing `time update`.");
                }
            }
            else
            {
                await context.RespondAsync(
                    "You either waited too long to respond. Try again by typing `time update`.");
            }
        }
        /// <summary>
        /// Verifies that this DiscordUser has a timezone registered in our database and throws a PreExecutionException if they don't
        /// </summary>
        /// <param name="user">The user who should have a timezone</param>
        /// <param name="provider">The database access provider</param>
        /// <param name="timeZoneProvider"></param>
        /// <returns></returns>
        public static bool TryGetDateTimeZone(this DiscordUser user, IBotAccessProvider provider, IDateTimeZoneProvider timeZoneProvider, out DateTimeZone timeZone)
        {
            UserTimeZone userTimeZone = provider.GetUsersTimeZone(user.Id);

            try
            {
                if (userTimeZone != null)
                {
                    timeZone = timeZoneProvider[userTimeZone.TimeZoneId];
                    return(true);
                }
            }
            catch (DateTimeZoneNotFoundException)
            {
            }

            timeZone = default;
            return(false);
        }
        public async Task ExecuteGroupAsync(CommandContext context, [Description("User to request current time for")] DiscordUser member)
        {
            using IBotAccessProvider provider = this.providerBuilder.Build();
            UserTimeZone memberTimeZone = provider.GetUsersTimeZone(member.Id);

            if (memberTimeZone == null)
            {
                await context.RespondAsync("This user doesn't have a timezone set up. Please try again after the mentioned user has set up their timezone using `time init`");

                return;
            }

            DateTimeZone memberDateTimeZone = this.timeZoneProvider[memberTimeZone.TimeZoneId];

            this.clock.GetCurrentInstant().InZone(memberDateTimeZone).Deconstruct(out LocalDateTime localDateTime, out _, out _);
            localDateTime.Deconstruct(out _, out LocalTime localTime);
            DiscordEmbed outputEmbed = new DiscordEmbedBuilder()
                                       .WithAuthor(iconUrl: member.AvatarUrl)
                                       .WithTitle($"{localTime.ToString("t", null)}");

            await context.RespondAsync(embed : outputEmbed);
        }
        public async Task CurrentTimeAsync(CommandContext context)
        {
            using IBotAccessProvider provider = this.providerBuilder.Build();
            UserTimeZone memberTimeZone = provider.GetUsersTimeZone(context.User.Id);

            if (memberTimeZone == null)
            {
                await context.RespondAsync("You don't have a timezone set up. Please try again after using `time init`");

                return;
            }

            DateTimeZone memberDateTimeZone = this.timeZoneProvider[memberTimeZone.TimeZoneId];

            this.clock.GetCurrentInstant().InZone(memberDateTimeZone).Deconstruct(out LocalDateTime localDateTime, out _, out _);
            localDateTime.Deconstruct(out _, out LocalTime localTime);
            DiscordEmbed outputEmbed = new DiscordEmbedBuilder()
                                       .WithAuthor(iconUrl: context.User.AvatarUrl)
                                       .WithTitle($"{localTime.ToString("t", null)}");

            await context.RespondAsync(embed : outputEmbed);
        }
        private async Task SendAdjustedDate(DiscordClient c, MessageReactionAddEventArgs e)
        {
            if (e.User.IsBot)
            {
                return;
            }

            DiscordChannel channel = await c.GetChannelAsync(e.Channel.Id);

            _ = Task.Run(async() =>
            {
                if (e.Emoji.Equals(this.clockEmoji))
                {
                    try
                    {
                        using IBotAccessProvider database = this.providerBuilder.Build();
                        DiscordMember reactor             = (DiscordMember)e.User;
                        DiscordMessage msg = await channel.GetMessageAsync(e.Message.Id);
                        IEnumerable <DateTimeV2ModelResult> parserList = DateTimeRecognizer.RecognizeDateTime(msg.Content, culture: Culture.English)
                                                                         .Select(x => x.ToDateTimeV2ModelResult()).Where(x => x.TypeName is DateTimeV2Type.Time or DateTimeV2Type.DateTime);

                        if (!parserList.Any())
                        {
                            await reactor.SendMessageAsync("Hey, you're stupid, stop trying to react to messages that don't have times in them.");
                            return;
                        }

                        DiscordEmbedBuilder reactorTimeEmbed = new DiscordEmbedBuilder().WithTitle("You requested a timezone conversion");

                        string opTimeZoneId      = database.GetUsersTimeZone(msg.Author.Id)?.TimeZoneId;
                        string reactorTimeZoneId = database.GetUsersTimeZone(e.User.Id)?.TimeZoneId;

                        if (opTimeZoneId is null)
                        {
                            await reactor.SendMessageAsync("The original poster has not set up a time zone yet.");
                            return;
                        }

                        if (reactorTimeZoneId is null)
                        {
                            await channel.SendMessageAsync("You have not set up a time zone yet. Use `time init` to set up your time zone.");
                            return;
                        }

                        DateTimeZone opTimeZone      = this.timeZoneProvider.GetZoneOrNull(opTimeZoneId);
                        DateTimeZone reactorTimeZone = this.timeZoneProvider.GetZoneOrNull(reactorTimeZoneId);
                        if (opTimeZone == null || reactorTimeZone == null)
                        {
                            await reactor.SendMessageAsync("There was a problem, please reach out to your bot developer.");
                            return;
                        }

                        IEnumerable <(string, DateTimeV2Value)> results = parserList.SelectMany(x => x.Values.Select(y => (x.Text, y)));
                        foreach ((string parsedText, DateTimeV2Value result) in results)
                        {
                            string outputString;
                            if (result.Type is DateTimeV2Type.Time)
                            {
                                DateTimeOffset messageDateTime     = msg.Timestamp;
                                ZonedDateTime zonedMessageDateTime = ZonedDateTime.FromDateTimeOffset(messageDateTime);
                                LocalTime localParsedTime          = (LocalTime)result.Value;
                                LocalDateTime localParsedDateTime  = localParsedTime.On(zonedMessageDateTime.LocalDateTime.Date);
                                ZonedDateTime zonedOpDateTime      = localParsedDateTime.InZoneStrictly(opTimeZone);
                                ZonedDateTime zonedReactorDateTime = zonedOpDateTime.WithZone(reactorTimeZone);
                                outputString = zonedReactorDateTime.LocalDateTime.TimeOfDay.ToString("t", null);
                            }
                            else
                            {
                                LocalDateTime localParsedDateTime  = (LocalDateTime)result.Value;
                                ZonedDateTime zonedOpDateTime      = localParsedDateTime.InZoneStrictly(opTimeZone);
                                ZonedDateTime zonedReactorDateTime = zonedOpDateTime.WithZone(reactorTimeZone);
                                outputString = zonedReactorDateTime.LocalDateTime.ToString("g", null);
                            }

                            reactorTimeEmbed
                            .AddField("Poster's Time", $"\"{parsedText}\"")
                            .AddField("Your time", $"{outputString}");
                        }
                        await reactor.SendMessageAsync(embed: reactorTimeEmbed);
                    }
                    catch (Exception exception)
                    {
                        this.logger.Log(LogLevel.Error, exception, "Error in sending reactor the DM");
                    }
                }
            });
        }