public async Task GiveKarma(CommandContext context, [Description("The discord user you'd like to give karma.")] DiscordUser member) { if (member.Equals(context.Member)) { await context.RespondAsync($"{context.Member.Mention}, you can't give yourself Karma. That would be cheating. You have to earn it from others."); return; } await context.Message.DeleteAsync(); using IBotAccessProvider provider = this.providerBuilder.Build(); ulong karmaToAdd = 0; for (int i = 0; i < 180; i++) { karmaToAdd += (ulong)this._rng.Next(1, 4); } provider.AddKarma(member.Id, context.Guild.Id, karmaToAdd); DiscordEmbed response = new DiscordEmbedBuilder() .WithDescription($"{member.Mention}, you have been bestowed {karmaToAdd} karma."); await context.RespondAsync(embed : response); }
public async Task WarnMemberAsync(CommandContext context, [Description("Guild Member to Warn")] DiscordMember member, [Description("Reason for warning")] [RemainingText] string reason) { DiscordEmbedBuilder successEmbed = new DiscordEmbedBuilder() .WithTitle($"You have received a warning!") .AddField("Guild:", context.Guild.Name) .AddField("Reason:", reason); using IBotAccessProvider provider = this.providerBuilder.Build(); DiscordChannel logChannel = await SendModerationEmbedAndGetLogChannel(successEmbed, member, context.Member, context.Guild, provider); provider.AddModerationAuditRecord(context.Guild.Id, context.User.Id, member.Id, ModerationActionType.WARN, reason); if (logChannel == null) { return; } successEmbed = new DiscordEmbedBuilder() .WithTitle($"{member.Username} has received a warning!") .AddField("Moderator:", context.User.Username) .AddField("Reason:", reason) .WithFooter($"{this.clock.GetCurrentInstant():g}"); await logChannel.SendMessageAsync(embed : successEmbed); await context.Message.CreateReactionAsync(DiscordEmoji.FromName(context.Client, ":white_check_mark:")); }
public async Task ShowLeaderBoard(CommandContext context) { using IBotAccessProvider provider = this.providerBuilder.Build(); List <GuildKarmaRecord> leaderboardRecords = provider.GetGuildKarmaRecords(context.Guild.Id) .OrderByDescending(record => record.CurrentKarma).ToList(); int requestorRanking = leaderboardRecords.FindIndex(record => record.UserId == context.User.Id) + 1; StringBuilder leaderboardBuilder = new StringBuilder() .AppendLine("```") .AppendLine($"Your rank: {requestorRanking}") .AppendLine(new string('-', 20)); int index = 1; foreach (GuildKarmaRecord record in leaderboardRecords) { try { DiscordMember member = await context.Guild.GetMemberAsync(record.UserId); leaderboardBuilder.AppendLine($"{index}. {member.DisplayName} - {record.CurrentKarma} karma"); index++; if (index > 10) { break; } } catch (NotFoundException) { } } leaderboardBuilder.Append("```"); await context.RespondAsync(leaderboardBuilder.ToString()); }
public async Task ExecuteGroupAsync(CommandContext context) { using IBotAccessProvider dataAccessProvider = this.botAccessProvider.Build(); string prefixString; List <GuildPrefix> guildPrefixes = dataAccessProvider .GetAllAssociatedGuildPrefixes(context.Guild.Id).ToList(); if (!guildPrefixes.Any()) { prefixString = "^"; } else if (guildPrefixes.Count == 1) { prefixString = guildPrefixes.First().Prefix; } else { prefixString = guildPrefixes .Select( prefix => prefix.Prefix) .Aggregate( (partial, next) => $"{partial} {next}"); } await context.RespondAsync($"{context.User.Mention}, the prefixes are: {prefixString}"); }
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 ScheduleGuildEvent( CommandContext context, [Description("The channel to announce the event in")] DiscordChannel announcementChannel, [Description("The role to announce the event to")] DiscordRole role, [Description("The date to schedule the event for")] [RemainingText] string datetimeString ) { using IBotAccessProvider provider = this.accessBuilder.Build(); if (!context.User.TryGetDateTimeZone(provider, this.timeZoneProvider, out DateTimeZone schedulerTimeZone)) { await context.RespondAsync(StringConstants.NoTimeZoneErrorMessage); return; } DiscordMember botMember = await context.Guild.GetMemberAsync(context.Client.CurrentUser.Id); if (!announcementChannel.PermissionsFor(botMember).HasPermission(Permissions.SendMessages | Permissions.MentionEveryone)) { await context.RespondAsync($"{context.Member.Mention}, I don't have permission to send messages and mention `@everyone` in that channel."); return; } LocalDateTime datetime = Recognizers.RecognizeDateTime(datetimeString, DateTimeV2Type.DateTime) .First().Values.Select(value => (LocalDateTime)value.Value).OrderBy(key => key).First(); DiscordMessage msg = await context.RespondAsync($":wave: Hi, {context.User.Mention}! You want to schedule an event for {datetime:g} in your timezone?"); InteractivityExtension interactivity = context.Client.GetInteractivity(); Reaction reaction = await interactivity.AddAndWaitForYesNoReaction(msg, context.User); if (reaction != Reaction.Yes) { return; } DiscordEmbedBuilder scheduleEmbedBase = new DiscordEmbedBuilder() .WithTitle("Select an event by typing: <event number>") .WithColor(context.Member.Color); GuildEvent selectedEvent = await SelectPredefinedEvent(context, provider, msg, interactivity, scheduleEmbedBase); Instant eventDateTime = datetime.InZoneStrictly(schedulerTimeZone).ToInstant(); DiscordEmbed embed = new DiscordEmbedBuilder() .WithAuthor(context.Member.DisplayName, iconUrl: context.Member.AvatarUrl) .WithDescription(selectedEvent.EventDesc) .WithTitle(selectedEvent.EventName) .Build(); await msg.ModifyAsync($"You have scheduled the following event for {datetime:g} in your time zone to be output in the {announcementChannel.Mention} channel.", embed : embed); this.ScheduleEventsForRole(context, announcementChannel, provider, selectedEvent, eventDateTime, role); }
public async Task SetLogChannel(CommandContext context, [Description("The channel to set as the log channel for moderation purposes")] DiscordChannel channel) { using IBotAccessProvider provider = this._providerBuilder.Build(); provider.AddOrUpdateGuildLogChannel(context.Guild.Id, channel.Id); await channel.SendMessageAsync($"{context.User.Mention}, I have set this channel as the logging channel for this guild."); }
public async Task ShowKarmaOfOtherAsync(CommandContext context, [Description("The member whose karma you'd like to view.")] DiscordMember member) { using IBotAccessProvider provider = this.providerBuilder.Build(); GuildKarmaRecord userKarmaRecord = provider.GetUsersGuildKarmaRecord(member.Id, context.Guild.Id); DiscordEmbed response = new DiscordEmbedBuilder() .AddField("Karma:", $"{userKarmaRecord.CurrentKarma}", true) .WithAuthor(member.DisplayName, iconUrl: member.AvatarUrl) .WithColor(member.Color); await context.RespondAsync(embed : response); }
private static DiscordChannel GetGuildLogChannel(DiscordGuild guild, IBotAccessProvider provider) { GuildLogsChannel guildLogsChannel = provider.GetGuildLogChannel(guild.Id); DiscordChannel logChannel = null; if (guildLogsChannel != null) { logChannel = guild.GetChannel(guildLogsChannel.ChannelId); } return(logChannel); }
public async Task RandomEventForRole(CommandContext context, [Description("Role to mention")] DiscordRole role) { DiscordMessage msg = await context.RespondAsync( $":wave: Hi, {context.User.Mention}! You want to `@everyone` and announce a random event?"); await msg.CreateReactionAsync(DiscordEmoji.FromName(context.Client, ":regional_indicator_y:")); await msg.CreateReactionAsync(DiscordEmoji.FromName(context.Client, ":regional_indicator_n:")); InteractivityExtension interactivity = context.Client.GetInteractivity(); InteractivityResult <MessageReactionAddEventArgs> interactivityResult = await interactivity.WaitForReactionAsync(msg, context.User); if (interactivityResult.TimedOut || !interactivityResult.Result.Emoji.Equals( DiscordEmoji.FromName(context.Client, ":regional_indicator_y:"))) { DiscordMessage snark = await context.RespondAsync($"{context.User.Mention}, well then why did you get my attention! Thanks for wasting my time. Now I have to clean up your mess."); await Task.Delay(5000); await context.Channel.DeleteMessagesAsync(new List <DiscordMessage> { msg, snark, context.Message }); return; } await context.Channel.DeleteMessagesAsync(new List <DiscordMessage> { context.Message, msg }); using IBotAccessProvider provider = this.accessBuilder.Build(); List <GuildEvent> guildEvents = provider.GetAllAssociatedGuildEvents(context.Guild.Id).ToList(); GuildEvent selectedEvent = guildEvents[Random.Next(guildEvents.Count)]; DiscordEmbedBuilder eventEmbedBuilder = new DiscordEmbedBuilder(); eventEmbedBuilder .WithTitle(selectedEvent.EventName) .WithDescription(selectedEvent.EventDesc); await context.RespondAsync(role.Mention, embed : eventEmbedBuilder.Build()); }
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously private async Task <int> PrefixResolver(DiscordMessage msg) { using IBotAccessProvider dataAccessProvider = this.providerBuilder.Build(); List <GuildPrefix> guildPrefixes = dataAccessProvider.GetAllAssociatedGuildPrefixes(msg.Channel.GuildId).ToList(); if (!guildPrefixes.Any()) { return(msg.GetStringPrefixLength("^")); } foreach (int length in guildPrefixes.Select(prefix => msg.GetStringPrefixLength(prefix.Prefix)).Where(length => length != -1)) { return(length); } return(-1); }
public async Task MuteMemberAsync(CommandContext context, [Description("The member to mute")] DiscordMember member, [RemainingText] [Description("The reason for the mute")] string reason = null) { DiscordRole mutedRole = await GetOrCreateMutedRole(context); DiscordEmbedBuilder successEmbed = new DiscordEmbedBuilder() .WithTitle($"You have been muted in {context.Guild.Name}!"); if (reason != null) { successEmbed.AddField("Reason:", reason); } using IBotAccessProvider provider = this.providerBuilder.Build(); DiscordChannel logChannel = await SendModerationEmbedAndGetLogChannel(successEmbed, member, context.Member, context.Guild, provider); await member.GrantRoleAsync(mutedRole, reason); provider.AddModerationAuditRecord(context.Guild.Id, context.User.Id, member.Id, ModerationActionType.MUTE, reason); await context.Message.CreateReactionAsync(DiscordEmoji.FromName(context.Client, ":white_check_mark:")); if (logChannel == null) { return; } successEmbed = new DiscordEmbedBuilder() .WithTitle($"{member.DisplayName} was muted") .AddField("Moderator", context.Member.DisplayName) .WithFooter($"{this.clock.GetCurrentInstant():g}"); if (reason != null) { successEmbed.AddField("Reason", reason); } await logChannel.SendMessageAsync(embed : successEmbed); }
public async Task RemoveRole(ulong guildId, ulong userId, ulong roleId) { try { DiscordClient shardClient = this._bot.Client.GetShard(guildId); DiscordGuild discordGuild = await shardClient.GetGuildAsync(guildId); DiscordMember guildMember = await discordGuild.GetMemberAsync(userId); DiscordRole guildRole = discordGuild.GetRole(roleId); await guildMember.RevokeRoleAsync(guildRole); using IBotAccessProvider provider = this._providerBuilder.Build(); } catch (Exception e) { this._logger.LogError("Error in revoking role", e); } }
public async Task BanMemberAsync(CommandContext context, [Description("Guild Member to Ban")] DiscordMember member, [Description("Number of days worth of their messages to delete")] int numDays = 0, [Description("Reason for ban")] [RemainingText] string reason = null) { DiscordEmbedBuilder messageEmbed = new DiscordEmbedBuilder() .WithTitle($"You have been banned from {context.Guild.Name}!"); if (reason != null) { messageEmbed.AddField("Reason:", reason); } using IBotAccessProvider provider = this.providerBuilder.Build(); DiscordChannel logChannel = await SendModerationEmbedAndGetLogChannel(messageEmbed, member, context.Member, context.Guild, provider); await member.BanAsync(numDays, reason); provider.AddModerationAuditRecord(context.Guild.Id, context.User.Id, member.Id, ModerationActionType.BAN, reason); if (logChannel == null) { return; } DiscordEmbedBuilder successEmbed = new DiscordEmbedBuilder() .WithTitle($"{member.Username} was banned") .AddField("Moderator", context.User.Username) .WithFooter($"{this.clock.GetCurrentInstant():g}"); if (reason != null) { successEmbed.AddField("Reason:", reason); } await logChannel.SendMessageAsync(embed : successEmbed); await context.Message.CreateReactionAsync(DiscordEmoji.FromName(context.Client, ":white_check_mark:")); }
/// <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 RemovePrefix( CommandContext context, [Description("The specific string prefix to remove from the guild's prefixes.")] string prefixToRemove) { using IBotAccessProvider dataAccessProvider = this.botAccessProvider.Build(); GuildPrefix guildPrefix = dataAccessProvider.GetAllAssociatedGuildPrefixes(context.Guild.Id) .FirstOrDefault(e => e.Prefix.Equals(prefixToRemove)); if (guildPrefix is null) { await context.RespondAsync( $"{context.User.Mention}, I'm sorry but the prefix you have given me does not exist for this guild."); return; } dataAccessProvider.DeleteGuildPrefix(guildPrefix); await context.RespondAsync( $"{context.User.Mention}, I have removed the prefix {guildPrefix.Prefix} for this server."); }
public BotService( ILoggerFactory loggerFactory, IOptions <BotConfig> botConfig, IBotAccessProviderBuilder dataAccessProviderBuilder, IDateTimeZoneProvider timeZoneProvider, IServiceProvider services) { DiscordConfiguration ClientConfig = new DiscordConfiguration { Token = botConfig.Value.BotToken, TokenType = TokenType.Bot, MinimumLogLevel = LogLevel.Information, LoggerFactory = loggerFactory, Intents = DiscordIntents.All, }; this.commandsConfig = new CommandsNextConfiguration { PrefixResolver = PrefixResolver, Services = services, EnableDms = true, EnableMentionPrefix = true, }; this.interactivityConfig = new InteractivityConfiguration { PaginationBehaviour = PaginationBehaviour.Ignore, Timeout = TimeSpan.FromMinutes(2), }; this.Client = new DiscordShardedClient(ClientConfig); this._devUserId = botConfig.Value.DevId; this.logger = loggerFactory.CreateLogger("BotService"); this.providerBuilder = dataAccessProviderBuilder; this.timeZoneProvider = timeZoneProvider; using IBotAccessProvider provider = providerBuilder.Build(); provider.Migrate(); }
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`."); } }
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); }
public async Task AddPrefix( CommandContext context, [Description("The new prefix that you want to add to the guild's prefixes. Must be at least one character")] string newPrefix) { if (newPrefix.Length < 1) { await context.RespondAsync("I'm sorry, but any new prefix must be at least one character."); return; } if (newPrefix.Length > 20) { await context.RespondAsync("I'm sorry, but any new prefix must be less than 20 characters."); return; } using IBotAccessProvider dataAccessProvider = this.botAccessProvider.Build(); dataAccessProvider.AddGuildPrefix(context.Guild.Id, newPrefix); await context.RespondAsync( $"Congratulations, you have added the prefix {newPrefix} to your server's prefixes for Handy Hansel.\nJust a reminder, this disables the default prefix for Handy Hansel unless you specifically add that prefix in again later or do not have any prefixes of your own."); }
public async Task ShowAuditLogVersionOne(CommandContext context, [Description("The moderator who took action to filter on.")] DiscordUser moderator = null, [Description("The member who had action taken against them to filter on.")] DiscordUser member = null, [Description("The kind of action taken to filter on")] ModerationActionType action = ModerationActionType.NONE) { using IBotAccessProvider provider = this.providerBuilder.Build(); ulong?modUserId = moderator?.Id; ulong?userUserId = member?.Id; List <GuildModerationAuditRecord> auditRecords = provider.GetGuildModerationAuditRecords(context.Guild.Id, modUserId, userUserId, action).ToList(); IReadOnlyCollection <DiscordMember> memberList = await context.Guild.GetAllMembersAsync(); IDictionary <ulong, DiscordMember> memberDict = memberList.ToDictionary(member => member.Id); List <Page> auditPages = GenerateAuditPages(auditRecords, memberDict, context.Client.CurrentUser); InteractivityExtension interactivity = context.Client.GetInteractivity(); await interactivity.SendPaginatedMessageAsync(context.Channel, context.User, auditPages, emojis : null, behaviour : PaginationBehaviour.Ignore, PaginationDeletion.DeleteMessage, timeoutoverride : TimeSpan.FromMinutes(5)); }
private static async Task <GuildEvent> SelectPredefinedEvent(CommandContext context, IBotAccessProvider provider, DiscordMessage msg, InteractivityExtension interactivity, DiscordEmbedBuilder scheduleEmbedBase) { List <GuildEvent> guildEvents = provider.GetAllAssociatedGuildEvents(context.Guild.Id).ToList(); IEnumerable <Page> pages = GetGuildEventsPages(guildEvents, interactivity, scheduleEmbedBase); CustomResult <int> result = await context.WaitForMessageAndPaginateOnMsg(pages, PaginationMessageFunction.CreateWaitForMessageWithIntInRange(context.User, context.Channel, 1, guildEvents.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(null); } return(guildEvents[result.Result - 1]); }
public async Task InteractiveRemovePrefix(CommandContext context) { using IBotAccessProvider provider = this.botAccessProvider.Build(); List <GuildPrefix> guildPrefixes = provider.GetAllAssociatedGuildPrefixes(context.Guild.Id).ToList(); if (!guildPrefixes.Any()) { await context.RespondAsync("You don't have any custom prefixes to remove"); return; } DiscordMessage msg = await context.RespondAsync( $":wave: Hi, {context.User.Mention}! You want to remove a prefix from your guild list?"); await msg.CreateReactionAsync(DiscordEmoji.FromName(context.Client, ":regional_indicator_y:")); await msg.CreateReactionAsync(DiscordEmoji.FromName(context.Client, ":regional_indicator_n:")); InteractivityExtension interactivity = context.Client.GetInteractivity(); InteractivityResult <MessageReactionAddEventArgs> interactivityResult = await interactivity.WaitForReactionAsync(msg, context.User); if (interactivityResult.TimedOut || !interactivityResult.Result.Emoji.Equals( DiscordEmoji.FromName(context.Client, ":regional_indicator_y:"))) { DiscordMessage snark = await context.RespondAsync("Well then why did you get my attention! Thanks for wasting my time."); await Task.Delay(5000); await context.Channel.DeleteMessagesAsync(new List <DiscordMessage> { msg, snark }); return; } DiscordEmbedBuilder removeEventEmbed = new DiscordEmbedBuilder() .WithTitle("Select a prefix to remove by typing: <prefix number>") .WithColor(context.Member.Color); Task <(bool, int)> messageValidationAndReturn(MessageCreateEventArgs messageE) { if (messageE.Author.Equals(context.User) && int.TryParse(messageE.Message.Content, out int eventToChoose)) { return(Task.FromResult((true, eventToChoose))); } else { return(Task.FromResult((false, -1))); } } await msg.DeleteAllReactionsAsync(); CustomResult <int> result = await context.WaitForMessageAndPaginateOnMsg( GetGuildPrefixPages(guildPrefixes, interactivity, removeEventEmbed), messageValidationAndReturn, 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; } GuildPrefix selectedPrefix = guildPrefixes[result.Result - 1]; provider.DeleteGuildPrefix(selectedPrefix); await msg.ModifyAsync( $"You have deleted the prefix \"{selectedPrefix.Prefix}\" from this guild's prefixes.", embed : null); }
private async Task AddGuildEventInteractive(CommandContext context, InteractivityExtension interactivity, DiscordMessage msg) { using IBotAccessProvider provider = this.accessBuilder.Build(); if (msg == null) { await context.RespondAsync(content : "Ok, what do you want the event name to be?"); } else { await msg.ModifyAsync(content : "Ok, what do you want the event name to be?"); } InteractivityResult <DiscordMessage> result = await interactivity.WaitForMessageAsync(xm => xm.Author.Equals(context.User) && xm.Channel.Equals(context.Channel)); if (result.TimedOut) { DiscordMessage snark = await context.RespondAsync( content : "You failed to provide a valid event title within the time limit, so thanks for wasting a minute of myyyy time. :triumph:"); await Task.Delay(5000); await context.Channel.DeleteMessagesAsync(new List <DiscordMessage> { msg, result.Result, snark }); return; } string eventName = result.Result.Content; await result.Result.DeleteAsync(); await msg.ModifyAsync("What do you want the event description to be?"); result = await interactivity.WaitForMessageAsync(xm => xm.Author.Equals(context.User) && xm.Channel.Equals(context.Channel), timeoutoverride : TimeSpan.FromMinutes(3)); if (result.TimedOut) { DiscordMessage snark = await context.RespondAsync( content : "You failed to provide a valid event description within the time limit, so thanks for wasting a minute of myyyy time. :triumph:"); await Task.Delay(5000); await context.Channel.DeleteMessagesAsync(new List <DiscordMessage> { msg, result.Result, snark }); return; } string eventDesc = result.Result.Content; await result.Result.DeleteAsync(); provider.AddGuildEvent(context.Guild.Id, eventName, eventDesc); DiscordEmbed embed = new DiscordEmbedBuilder() .WithAuthor(context.Client.CurrentUser.Username, iconUrl: context.Client.CurrentUser.AvatarUrl) .WithDescription(eventDesc) .WithTitle(eventName) .Build(); await msg.ModifyAsync("You have added the following event to your guild:", embed : embed); }
public async Task UnsetLogChannelAsync(CommandContext context) { using IBotAccessProvider provider = this._providerBuilder.Build(); provider.RemoveGuildLogChannel(context.Guild.Id); await context.RespondAsync($"{context.User.Mention}, I have unset the log channel for this guild."); }
private static async Task <DiscordChannel> SendModerationEmbedAndGetLogChannel(DiscordEmbed embed, DiscordMember member, DiscordMember moderator, DiscordGuild guild, IBotAccessProvider provider) { DiscordChannel logChannel = GetGuildLogChannel(guild, provider); try { await member.SendMessageAsync(embed : embed); } catch (UnauthorizedException) { if (logChannel != null) { await logChannel.SendMessageAsync("This user has closed their DMs and so I was not able to message the user."); } else { try { await moderator.SendMessageAsync("This user has closed their DMs and so I was not able to message the user."); } catch (UnauthorizedException) { } } } return(logChannel); }
public async Task TempMuteMemberAsync(CommandContext context, [Description("The member to mute")] DiscordMember member, [Description("Duration to mute the member for (must be quoted if there are any spaces, however it should work with colloquial language)")] string durationOfMute, [RemainingText] [Description("The reason for the mute")] string reason = null) { DateTimeV2ModelResult durationResult = DateTimeRecognizer .RecognizeDateTime(durationOfMute, culture: Culture.English) .Select(model => model.ToDateTimeV2ModelResult()) .Where(result => result.TypeName is DateTimeV2Type.Duration) .FirstOrDefault(); if (durationResult == null) { await context.RespondAsync("There was an error parsing the duration"); return; } Duration duration = (Duration)durationResult.Values.FirstOrDefault().Value; string durationString = Period.FromSeconds((long)duration.TotalSeconds).AsHumanReadableString(); DiscordRole mutedRole = await GetOrCreateMutedRole(context); DiscordEmbedBuilder successEmbed = new DiscordEmbedBuilder() .WithTitle($"You have been temporarily muted in {context.Guild.Name}!") .AddField("Duration", durationString); if (reason != null) { successEmbed.AddField("Reason:", reason); } using IBotAccessProvider provider = this.providerBuilder.Build(); DiscordChannel logChannel = await SendModerationEmbedAndGetLogChannel(successEmbed, member, context.Member, context.Guild, provider); await member.GrantRoleAsync(mutedRole, reason); provider.AddModerationAuditRecord(context.Guild.Id, context.User.Id, member.Id, ModerationActionType.MUTE, reason); await context.Message.CreateReactionAsync(DiscordEmoji.FromName(context.Client, ":white_check_mark:")); if (logChannel == null) { return; } successEmbed = new DiscordEmbedBuilder() .WithTitle($"{member.DisplayName} was muted") .AddField("Moderator", context.Member.DisplayName) .AddField("Duration", durationString) .WithFooter($"{this.clock.GetCurrentInstant():g}"); if (reason != null) { successEmbed.AddField("Reason", reason); } await logChannel.SendMessageAsync(embed : successEmbed); string jobId = BackgroundJob.Schedule <ModerationService>(service => service.RemoveRole(context.Guild.Id, member.Id, mutedRole.Id), duration.ToTimeSpan()); provider.AddGuildBackgroundJob(jobId, context.Guild.Id, $"Unmute - {member.DisplayName}", this.clock.GetCurrentInstant() + duration, GuildJobType.TEMP_MUTE); }
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"); } } }); }
private void ScheduleEventsForRole(CommandContext context, DiscordChannel announcementChannel, IBotAccessProvider provider, GuildEvent selectedEvent, Instant eventDateTime, DiscordRole role) { Duration eventScheduleDuration = eventDateTime - this.clock.GetCurrentInstant(); string scheduledJobId = BackgroundJob.Schedule <EventService>( eventService => eventService.SendEmbedWithMessageToChannelAsUser( context.Guild.Id, context.Member.Id, announcementChannel.Id, $"{(role == null ? "@everyone" : role.Mention)}, this event is starting now!", selectedEvent.EventName, selectedEvent.EventDesc), eventScheduleDuration.ToTimeSpan()); provider.AddGuildBackgroundJob(scheduledJobId, context.Guild.Id, $"{selectedEvent.EventName} - Announcement", eventDateTime, GuildJobType.SCHEDULED_EVENT); scheduledJobId = BackgroundJob.Schedule <EventService>( eventService => eventService.SendEmbedWithMessageToChannelAsUser( context.Guild.Id, context.Member.Id, announcementChannel.Id, $"{(role == null ? "@everyone" : role.Mention)}, this event is starting in 10 minutes!", selectedEvent.EventName, selectedEvent.EventDesc ), (eventScheduleDuration - Duration.FromMinutes(10)).ToTimeSpan()); provider.AddGuildBackgroundJob(scheduledJobId, context.Guild.Id, $"{selectedEvent.EventName} - 10 Min Announcement", eventDateTime - Duration.FromMinutes(10), GuildJobType.SCHEDULED_EVENT); }