public override ValueTask <CheckResult> CheckAsync(RiasCommandContext context) { var localization = context.Services.GetRequiredService <Localization>(); var currentMember = context.CurrentMember; if (currentMember is null) { return(context.Command.Checks.Any(x => x is ContextAttribute contextAttribute && contextAttribute.Contexts.HasFlag(ContextType.Guild)) ? CheckResult.Successful : CheckResult.Failed(localization.GetText(null, Localization.AttributeBotPermissionNotGuild))); } var guildPermissions = currentMember.GetPermissions(); var hasGuildPermissions = guildPermissions.HasPermission(Permissions); var channelPermissions = currentMember.PermissionsIn(context.Channel); var hasChannelPerm = channelPermissions.HasPermission(Permissions); if (!hasGuildPermissions && !hasChannelPerm) { var guildPermsHumanized = HumanizePermissions(context.Guild !, guildPermissions, localization); return(CheckResult.Failed(localization.GetText(context.Guild !.Id, Localization.AttributeBotGuildPermissions, guildPermsHumanized))); } if (hasGuildPermissions && !hasChannelPerm) { var channelPermsHumanized = HumanizePermissions(context.Guild !, channelPermissions, localization); return(CheckResult.Failed(localization.GetText(context.Guild !.Id, Localization.AttributeBotChannelPermissions, channelPermsHumanized))); } return(CheckResult.Successful); }
private Task SendFailedResultsAsync(RiasCommandContext context, IEnumerable <FailedResult> failedResults) { var guildId = context.Guild?.Id; var embed = new LocalEmbedBuilder { Color = RiasUtilities.ErrorColor, Title = GetText(guildId, Localization.ServiceCommandNotExecuted) }; var reasons = new List <string>(); var parsedPrimitiveType = false; var areTooManyArguments = false; var areTooLessArguments = false; foreach (var failedResult in failedResults) { switch (failedResult) { case ChecksFailedResult checksFailedResult: reasons.AddRange(checksFailedResult.FailedChecks.Select(x => x.Result.Reason)); break; case TypeParseFailedResult typeParseFailedResult: if (_typeParsers.Any(x => x.BaseType !.GetGenericArguments()[0] == typeParseFailedResult.Parameter.Type)) { reasons.Add(typeParseFailedResult.Reason); } else if (!parsedPrimitiveType) { reasons.Add(GetText(guildId, Localization.TypeParserPrimitiveType, context.Prefix, typeParseFailedResult.Parameter.Command.Name)); parsedPrimitiveType = true; } break;
public override ValueTask <CheckResult> CheckAsync(RiasCommandContext context) { if (!GuildPermissions.HasValue) { return(CheckResult.Successful); } var localization = context.ServiceProvider.GetRequiredService <Localization>(); var currentMember = context.CurrentMember; if (currentMember is null) { return(CheckResult.Unsuccessful(localization.GetText(null, Localization.AttributeBotPermissionNotGuild))); } if (currentMember.Permissions.Has(GuildPermissions.Value)) { return(CheckResult.Successful); } var botPerms = currentMember.Permissions.Permissions; var requiredPerms = GuildPermissions ^ (GuildPermissions & botPerms); var requiredPermsList = requiredPerms .GetValueOrDefault() .ToString() .Split(",", StringSplitOptions.RemoveEmptyEntries); var guildId = context.Guild?.Id; var permsHumanized = requiredPermsList.Humanize(x => $"**{x.Titleize()}**", localization.GetText(guildId, Localization.CommonAnd).ToLowerInvariant()); return(CheckResult.Unsuccessful(localization.GetText(guildId, Localization.AttributeBotGuildPermissions, permsHumanized))); }
public override ValueTask <CheckResult> CheckAsync(RiasCommandContext context) { var localization = context.Services.GetRequiredService <Localization>(); var isValid = Contexts switch { ContextType.Guild when context.Guild is not null => true, ContextType.DM when context.Guild is null => true, _ => false }; if (isValid) { return(CheckResult.Successful); } var guildId = context.Guild?.Id; var contexts = Contexts.ToString() .Split(",", StringSplitOptions.RemoveEmptyEntries) .Select(x => localization.GetText(guildId, Localization.CommonContextType(x.ToLower()))); var contextsHumanized = contexts.Humanize(x => $"**{x}**", localization.GetText(guildId, Localization.CommonOr).ToLowerInvariant()); return(CheckResult.Failed(localization.GetText(guildId, Localization.AttributeContext, contextsHumanized))); } }
public override ValueTask <CheckResult> CheckAsync(RiasCommandContext context) { var localization = context.ServiceProvider.GetRequiredService <Localization>(); var isValid = false; if ((_contexts & ContextType.Guild) != 0) { isValid = context.Channel is CachedGuildChannel; } if ((_contexts & ContextType.DM) != 0) { isValid = isValid || context.Channel is CachedDmChannel; } if (isValid) { return(CheckResult.Successful); } var guildId = context.Guild?.Id; var contexts = _contexts.ToString() .Split(",", StringSplitOptions.RemoveEmptyEntries) .Select(x => localization.GetText(guildId, Localization.CommonContextType(x.ToLower()))); var contextsHumanized = contexts.Humanize(x => $"**{x}**", localization.GetText(guildId, Localization.CommonOr).ToLowerInvariant()); return(CheckResult.Unsuccessful(localization.GetText(guildId, Localization.AttributeContext, contextsHumanized))); }
public override async ValueTask <CheckResult> CheckAsync(RiasCommandContext context) { var riasBot = context.ServiceProvider.GetRequiredService <Rias>(); var currentApplication = riasBot.CurrentApplication.IsFetched ? riasBot.CurrentApplication.Value : await riasBot.GetCurrentApplicationAsync(); return(context.User.Id == currentApplication.Owner.Id ? CheckResult.Successful : CheckResult.Unsuccessful(context.ServiceProvider.GetRequiredService <Localization>().GetText(context.Guild?.Id, Localization.AttributeOwnerOnly))); }
public override async ValueTask <CheckResult> CheckAsync(RiasCommandContext context) { if (context.Guild is null) { return(context.Command.Checks.Any(x => x is ContextAttribute contextAttribute && contextAttribute.Contexts.HasFlag(ContextType.Guild)) ? CheckResult.Successful : CheckResult.Failed("Cannot use `CheckDownloadedMembers` outside of a guild.")); } var riasBot = context.Services.GetRequiredService <RiasBot>(); if (!riasBot.ChunkedGuilds.Contains(context.Guild.Id)) { riasBot.ChunkedGuilds.Add(context.Guild.Id); await context.Guild.RequestMembersAsync(); Log.Debug("Members requested for {GuildName} ({GuildId})", context.Guild.Name, context.Guild.Id); } return(CheckResult.Successful); }
public override async ValueTask <TypeParserResult <IUser> > ParseAsync(Parameter parameter, string value, RiasCommandContext context) { var cachedMemberTypeParser = await new CachedMemberTypeParser().ParseAsync(parameter, value, context); if (cachedMemberTypeParser.IsSuccessful) { return(TypeParserResult <IUser> .Successful(cachedMemberTypeParser.Value)); } var localization = context.ServiceProvider.GetRequiredService <Localization>(); IUser?user = null; if (Snowflake.TryParse(value, out var id)) { user = await context.ServiceProvider.GetRequiredService <Rias>().GetUserAsync(id); } if (user != null) { return(TypeParserResult <IUser> .Successful(user)); } if (parameter.IsOptional) { return(TypeParserResult <IUser> .Successful((CachedMember)parameter.DefaultValue)); } return(TypeParserResult <IUser> .Unsuccessful(localization.GetText(context.Guild?.Id, Localization.AdministrationUserNotFound))); }
public override ValueTask <TypeParserResult <CachedVoiceChannel> > ParseAsync(Parameter parameter, string value, RiasCommandContext context) { var localization = context.ServiceProvider.GetRequiredService <Localization>(); if (context.Guild is null) { return(TypeParserResult <CachedVoiceChannel> .Unsuccessful(localization.GetText(context.Guild?.Id, Localization.TypeParserCachedVoiceChannelNotGuild))); } CachedVoiceChannel channel; if (Snowflake.TryParse(value, out var id)) { channel = context.Guild.GetVoiceChannel(id); if (channel != null) { return(TypeParserResult <CachedVoiceChannel> .Successful(channel)); } } channel = context.Guild.VoiceChannels.FirstOrDefault(c => string.Equals(c.Value.Name, value, StringComparison.OrdinalIgnoreCase)).Value; if (channel != null) { return(TypeParserResult <CachedVoiceChannel> .Successful(channel)); } if (parameter.IsOptional) { return(TypeParserResult <CachedVoiceChannel> .Successful((CachedVoiceChannel)parameter.DefaultValue)); } return(TypeParserResult <CachedVoiceChannel> .Unsuccessful(localization.GetText(context.Guild?.Id, Localization.AdministrationVoiceChannelNotFound))); }
public override ValueTask <TypeParserResult <DiscordRole> > ParseAsync(Parameter parameter, string value, RiasCommandContext context) { var localization = context.Services.GetRequiredService <Localization>(); if (context.Guild is null) { return(TypeParserResult <DiscordRole> .Failed(localization.GetText(context.Guild?.Id, Localization.TypeParserRoleNotGuild))); } DiscordRole?role; if (RiasUtilities.TryParseRoleMention(value, out var roleId) || ulong.TryParse(value, out roleId)) { role = context.Guild.GetRole(roleId); if (role != null) { return(TypeParserResult <DiscordRole> .Successful(role)); } return(TypeParserResult <DiscordRole> .Failed(localization.GetText(context.Guild?.Id, Localization.AdministrationRoleNotFound))); } role = context.Guild.Roles.FirstOrDefault(x => string.Equals(x.Value.Name, value, StringComparison.OrdinalIgnoreCase)).Value; if (role != null) { return(TypeParserResult <DiscordRole> .Successful(role)); } return(TypeParserResult <DiscordRole> .Failed(localization.GetText(context.Guild?.Id, Localization.AdministrationRoleNotFound))); }
public abstract ValueTask <CheckResult> CheckAsync(RiasCommandContext context);
public override ValueTask <CheckResult> CheckAsync(RiasCommandContext context) { return(context.Client.CurrentApplication.Owners.Any(x => x.Id == context.User.Id) ? CheckResult.Successful : CheckResult.Failed("This command can be used only by my master.")); }
public override ValueTask <TypeParserResult <TimeSpan> > ParseAsync(Parameter parameter, string value, RiasCommandContext context) { var timespan = RiasUtilities.ConvertToTimeSpan(value); if (timespan.HasValue) { return(TypeParserResult <TimeSpan> .Successful(timespan.Value)); } if (parameter.IsOptional) { return(TypeParserResult <TimeSpan> .Successful((TimeSpan)parameter.DefaultValue)); } var localization = context.ServiceProvider.GetRequiredService <Localization>(); return(TypeParserResult <TimeSpan> .Unsuccessful(localization.GetText(context.Guild?.Id, Localization.TypeParserTimeSpanUnsuccessful))); }
public override ValueTask <TypeParserResult <CachedRole> > ParseAsync(Parameter parameter, string value, RiasCommandContext context) { var localization = context.ServiceProvider.GetRequiredService <Localization>(); if (context.Guild is null) { return(TypeParserResult <CachedRole> .Unsuccessful(localization.GetText(context.Guild?.Id, Localization.TypeParserCachedRoleNotGuild))); } CachedRole role; if (Discord.TryParseRoleMention(value, out var roleId)) { role = context.Guild.GetRole(roleId); if (role != null) { return(TypeParserResult <CachedRole> .Successful(role)); } } if (Snowflake.TryParse(value, out var id)) { role = context.Guild.GetRole(id); if (role != null) { return(TypeParserResult <CachedRole> .Successful(role)); } } role = context.Guild.Roles.FirstOrDefault(x => string.Equals(x.Value.Name, value, StringComparison.OrdinalIgnoreCase)).Value; if (role != null) { return(TypeParserResult <CachedRole> .Successful(role)); } if (parameter.IsOptional) { return(TypeParserResult <CachedRole> .Successful((CachedRole)parameter.DefaultValue)); } return(TypeParserResult <CachedRole> .Unsuccessful(localization.GetText(context.Guild?.Id, Localization.AdministrationRoleNotFound))); }
public override ValueTask <TypeParserResult <DiscordChannel> > ParseAsync(Parameter parameter, string value, RiasCommandContext context) { var localization = context.Services.GetRequiredService <Localization>(); if (context.Guild is null) { return(TypeParserResult <DiscordChannel> .Failed(localization.GetText(context.Guild?.Id, Localization.TypeParserChannelNotGuild))); } var channelType = ChannelType.Unknown; HashSet <ChannelType>?ignoreChannelTypes = null; foreach (var attribute in parameter.Attributes) { switch (attribute) { case CategoryChannelAttribute: channelType = ChannelType.Category; break; case TextChannelAttribute: channelType = ChannelType.Text; break; case VoiceChannelAttribute: channelType = ChannelType.Voice; break; case IgnoreChannelTypesAttribute ignoreChannelTypeAttribute: ignoreChannelTypes = ignoreChannelTypeAttribute.ChannelTypes; break; } } if (channelType is not ChannelType.Unknown && ignoreChannelTypes is not null && ignoreChannelTypes.Contains(channelType)) { throw new ArgumentException("The required channel type and the ignored channel type cannot be the same"); } DiscordChannel?channel; if (RiasUtilities.TryParseChannelMention(value, out var channelId) || ulong.TryParse(value, out channelId)) { channel = context.Guild.GetChannel(channelId); if (channel is not null) { var allowChannel = channelType switch { ChannelType.Text => channel.Type is ChannelType.Text or ChannelType.News or ChannelType.Store, ChannelType.Voice => channel.Type is ChannelType.Voice or ChannelType.Stage, _ => channel.Type == channelType || channelType is ChannelType.Unknown }; if (allowChannel) { return(ignoreChannelTypes is not null && ignoreChannelTypes.Contains(channel.Type) ? TypeParserResult <DiscordChannel> .Failed(localization.GetText(context.Guild.Id, Localization.TypeParserChannelNotAllowed(channel.Type.ToString().ToLower()))) : TypeParserResult <DiscordChannel> .Successful(channel)); } } } else { channel = channelType switch { ChannelType.Category => context.Guild.GetCategoryChannel(value), ChannelType.Text => context.Guild.GetTextChannel(value), ChannelType.Voice => context.Guild.GetVoiceChannel(value), ChannelType.Unknown => ignoreChannelTypes is null ? context.Guild.Channels .OrderBy(c => c.Value.Position) .FirstOrDefault(x => string.Equals(x.Value.Name, value, StringComparison.OrdinalIgnoreCase)) .Value : context.Guild.Channels .Where(c => !ignoreChannelTypes.Contains(c.Value.Type)) .OrderBy(c => c.Value.Position) .FirstOrDefault(x => string.Equals(x.Value.Name, value, StringComparison.OrdinalIgnoreCase)) .Value }; if (channel != null) { return(TypeParserResult <DiscordChannel> .Successful(channel)); } } return(channelType switch { ChannelType.Category => TypeParserResult <DiscordChannel> .Failed(localization.GetText(context.Guild.Id, Localization.AdministrationCategoryChannelNotFound)), ChannelType.Text => TypeParserResult <DiscordChannel> .Failed(localization.GetText(context.Guild.Id, Localization.AdministrationTextChannelNotFound)), ChannelType.Voice => TypeParserResult <DiscordChannel> .Failed(localization.GetText(context.Guild.Id, Localization.AdministrationVoiceChannelNotFound)), ChannelType.Unknown => TypeParserResult <DiscordChannel> .Failed(localization.GetText(context.Guild.Id, Localization.AdministrationChannelNotFound)) });
public abstract ValueTask <TypeParserResult <T> > ParseAsync(Parameter parameter, string value, RiasCommandContext context);
public override async ValueTask <TypeParserResult <DiscordMember> > ParseAsync(Parameter parameter, string value, RiasCommandContext context) { var localization = context.Services.GetRequiredService <Localization>(); if (context.Guild is null) { return(TypeParserResult <DiscordMember> .Failed(localization.GetText(context.Guild?.Id, Localization.TypeParserMemberNotGuild))); } var riasBot = context.Services.GetRequiredService <RiasBot>(); if (!riasBot.ChunkedGuilds.Contains(context.Guild.Id)) { var botService = context.Services.GetRequiredService <BotService>(); var tcs = new TaskCompletionSource(); botService.GuildsTcs[context.Guild.Id] = tcs; riasBot.ChunkedGuilds.Add(context.Guild.Id); await context.Guild.RequestMembersAsync(); Log.Debug("Members requested for {GuildName} ({GuildId})", context.Guild.Name, context.Guild.Id); var delayTimeout = context.Guild.MemberCount switch {
public async Task <EvaluationDetails?> EvaluateAsync(RiasCommandContext context, string code) { var globals = new RoslynGlobals { Rias = RiasBot, Context = context }; var imports = new[] { "System", "System.Collections.Generic", "System.Linq", "Disqord", "Disqord.WebSocket", "System.Threading.Tasks", "System.Text", "Microsoft.Extensions.DependencyInjection", "System.Net.Http", "Rias.Core.Extensions", "Rias.Core.Database", "Qmmands" }; var scriptOptions = ScriptOptions.Default.WithReferences(typeof(Rias).Assembly).AddImports(imports); code = SanitizeCode(code); using var loader = new InteractiveAssemblyLoader(); var sw = Stopwatch.StartNew(); var script = CSharpScript.Create(code, scriptOptions, typeof(RoslynGlobals), loader); var diagnostics = script.Compile(); sw.Stop(); var compilationTime = sw.Elapsed; if (diagnostics.Any(x => x.Severity == DiagnosticSeverity.Error)) { return(new EvaluationDetails { CompilationTime = compilationTime, Code = code, IsCompiled = false, Exception = string.Join("\n", diagnostics.Select(x => x.ToString())) }); } sw.Restart(); try { var result = await script.RunAsync(globals); sw.Stop(); if (result.ReturnValue is null) { return(null); } var evaluationDetails = new EvaluationDetails { CompilationTime = compilationTime, ExecutionTime = sw.Elapsed, Code = code, IsCompiled = true, Success = true }; var returnValue = result.ReturnValue; var type = result.ReturnValue.GetType(); switch (returnValue) { case string str: evaluationDetails.Result = str; evaluationDetails.ReturnType = type.Name; break; case IEnumerable enumerable: var list = enumerable.Cast <object>().ToList(); var enumType = enumerable.GetType(); evaluationDetails.Result = list.Count != 0 ? $"[{string.Join(", ", list)}]" : "empty"; evaluationDetails.ReturnType = $"{enumType.Name}<{string.Join(", ", enumType.GenericTypeArguments.Select(t => t.Name))}>"; break; case Enum @enum: evaluationDetails.Result = @enum.ToString(); evaluationDetails.ReturnType = @enum.GetType().Name; break; default: evaluationDetails.Result = returnValue.ToString(); evaluationDetails.ReturnType = type.Name; break; } return(evaluationDetails); } catch (Exception ex) { sw.Stop(); return(new EvaluationDetails { CompilationTime = compilationTime, ExecutionTime = sw.Elapsed, Code = code, ReturnType = ex.GetType().Name, IsCompiled = true, Success = false, Exception = ex.Message }); } }
private async Task ExecuteCommandAsync(CachedUserMessage userMessage, ICachedMessageChannel?channel, string prefix, string output) { if (await CheckUserBan(userMessage.Author) && userMessage.Author.Id != Credentials.MasterId) { return; } var guildChannel = channel as CachedTextChannel; if (guildChannel != null) { var channelPermissions = guildChannel.Guild.CurrentMember.GetPermissionsFor(guildChannel); if (!channelPermissions.SendMessages) { return; } if (!guildChannel.Guild.CurrentMember.Permissions.EmbedLinks) { await guildChannel.SendMessageAsync(GetText(guildChannel.Guild.Id, Localization.ServiceNoEmbedLinksPermission)); return; } if (!channelPermissions.EmbedLinks) { await guildChannel.SendMessageAsync(GetText(guildChannel.Guild.Id, Localization.ServiceNoEmbedLinksChannelPermission)); return; } } var context = new RiasCommandContext(userMessage, RiasBot, prefix); var result = await _commandService.ExecuteAsync(output, context); if (result.IsSuccessful) { if (guildChannel != null && guildChannel.Guild.CurrentMember.Permissions.ManageMessages && await CheckGuildCommandMessageDeletion(guildChannel.Guild) && !string.Equals(context.Command.Name, "prune")) { await userMessage.DeleteAsync(); } CommandsExecuted++; return; } CommandsAttempted++; switch (result) { case OverloadsFailedResult overloadsFailedResult: await RunTaskAsync(SendFailedResultsAsync(context, overloadsFailedResult.FailedOverloads.Values)); break; case ChecksFailedResult _: case TypeParseFailedResult _: case ArgumentParseFailedResult _: await RunTaskAsync(SendFailedResultsAsync(context, new [] { (FailedResult)result })); break; case CommandOnCooldownResult commandOnCooldownResult: await RunTaskAsync(SendCommandOnCooldownMessageAsync(context, commandOnCooldownResult)); break; } }
public override ValueTask <TypeParserResult <CachedMember> > ParseAsync(Parameter parameter, string value, RiasCommandContext context) { var localization = context.ServiceProvider.GetRequiredService <Localization>(); if (context.Guild is null) { return(TypeParserResult <CachedMember> .Unsuccessful(localization.GetText(context.Guild?.Id, Localization.TypeParserCachedMemberNotGuild))); } CachedMember member; if (Discord.TryParseUserMention(value, out var userId)) { member = context.Guild.GetMember(userId); if (member != null) { return(TypeParserResult <CachedMember> .Successful(member)); } } if (Snowflake.TryParse(value, out var id)) { member = context.Guild.GetMember(id); if (member != null) { return(TypeParserResult <CachedMember> .Successful(member)); } } var members = context.Guild.Members; var index = value.LastIndexOf("#", StringComparison.Ordinal); if (index > 0) { var username = value[..index];
public override ValueTask <TypeParserResult <DiscordColor> > ParseAsync(Parameter parameter, string value, RiasCommandContext context) { var hex = RiasUtilities.HexToInt(value); if (hex.HasValue) { return(TypeParserResult <DiscordColor> .Successful(new DiscordColor(hex.Value))); } var color = default(System.Drawing.Color); if (Enum.TryParse <System.Drawing.KnownColor>(value.Replace(" ", string.Empty), true, out var knownColor)) { color = System.Drawing.Color.FromKnownColor(knownColor); } if (!color.IsEmpty) { return(TypeParserResult <DiscordColor> .Successful(new DiscordColor(color.R, color.G, color.B))); } var localization = context.Services.GetRequiredService <Localization>(); return(TypeParserResult <DiscordColor> .Failed(localization.GetText(context.Guild?.Id, Localization.TypeParserInvalidColor))); }
public override async ValueTask <TypeParserResult <DiscordUser> > ParseAsync(Parameter parameter, string value, RiasCommandContext context) { var cachedMemberTypeParser = await new MemberTypeParser().ParseAsync(parameter, value, context); if (cachedMemberTypeParser.IsSuccessful) { return(TypeParserResult <DiscordUser> .Successful(cachedMemberTypeParser.Value)); } var localization = context.Services.GetRequiredService <Localization>(); if (ulong.TryParse(value, out var id)) { try { var user = await context.Client.GetUserAsync(id); return(TypeParserResult <DiscordUser> .Successful(user)); } catch { return(TypeParserResult <DiscordUser> .Failed(localization.GetText(context.Guild?.Id, Localization.AdministrationUserNotFound))); } } return(TypeParserResult <DiscordUser> .Failed(localization.GetText(context.Guild?.Id, Localization.AdministrationUserNotFound))); }