public static bool IsAdmin(this SocketGuildUser user, VolteContext ctx) { var db = ctx.Services.GetRequiredService <DatabaseService>(); return(HasRole(user, ctx.GuildData.Configuration.Moderation.AdminRole) || IsGuildOwner(user)); }
public static async Task PerformAsync(this BlacklistAction action, VolteContext ctx, SocketGuildUser member, string word) { switch (action) { case BlacklistAction.Warn: await member.WarnAsync(ctx, $"Used blacklisted word \"{word}\"."); break; case BlacklistAction.Kick: await member.KickAsync($"Used blacklisted word \"{word}\"."); break; case BlacklistAction.Ban: await member.BanAsync(7, $"Used blacklisted word \"{word}\"."); break; case BlacklistAction.Nothing: break; default: throw new ArgumentOutOfRangeException(nameof(action), action, null); } }
public ModActionEventArgs WithDefaultsFromContext(VolteContext ctx) { return(WithContext(ctx) .WithTime(ctx.Now) .WithGuild(ctx.Guild) .WithModerator(ctx.User)); }
public MessageReceivedEventArgs(SocketMessage s, IServiceProvider provider) { Message = s.Cast <SocketUserMessage>() ?? throw new ArgumentException($"{nameof(s)} is not a SocketUserMessage; aborting event handler call."); provider.Get(out _db); Context = VolteContext.Create(s, provider); Data = _db.GetData(Context.Guild); }
public CommandBadRequestEventArgs(BadRequestResult res, ResultCompletionData data, VolteContext ctx, string args, Stopwatch sw) { Result = res; ResultCompletionData = data; Context = ctx; Arguments = args; Stopwatch = sw; }
public string FormatContent(VolteContext ctx) => SanitizeContent() .Replace("{ServerName}", ctx.Guild.Name) .Replace("{GuildName}", ctx.Guild.Name) .Replace("{UserName}", ctx.User.Username) .Replace("{UserMention}", ctx.User.Mention) .Replace("{OwnerMention}", ctx.Guild.Owner.Mention) .Replace("{UserTag}", ctx.User.Discriminator);
public CommandFailedEventArgs(FailedResult res, VolteContext ctx, string args, Stopwatch sw) { FailedResult = res; Context = ctx; Arguments = args; Stopwatch = sw; }
public CommandBadRequestEventArgs(BadRequestResult res, VolteContext ctx, string args, Stopwatch sw) { BadRequestResult = res; Context = ctx; Arguments = args; Stopwatch = sw; }
public static string GetUsage(this Command c, VolteContext ctx) { var aliases = $"({c.FullAliases.Join('|')})"; return((c.Remarks ?? "No usage provided") .Replace(c.Name.ToLower(), (c.FullAliases.Count > 1 ? aliases : c.Name).ToLower()) .Replace("|prefix|", ctx.GuildData.Configuration.CommandPrefix) .Replace("Usage: ", string.Empty)); }
private static EvalEnvironment CreateEvalEnvironment(VolteContext ctx) => new EvalEnvironment { Context = ctx, Database = ctx.Services.Get <DatabaseService>(), Client = ctx.Client.GetShardFor(ctx.Guild), Data = ctx.Services.Get <DatabaseService>().GetData(ctx.Guild), Commands = ctx.Services.Get <CommandService>() };
public static Reminder CreateFrom(VolteContext ctx, DateTime end, string reminder) => new Reminder { TargetTime = end, CreationTime = ctx.Now, CreatorId = ctx.User.Id, GuildId = ctx.Guild.Id, ChannelId = ctx.Channel.Id, MessageId = ctx.Message.Id, ReminderText = reminder };
public override async ValueTask <ResultCompletionData> ExecuteResultAsync(VolteContext ctx) { if (!ctx.Guild.CurrentUser.GetPermissions(ctx.Channel).SendMessages) { return(new ResultCompletionData()); } if (_separateLogic != null) { if (_runFuncAsync) { await _separateLogic(); } else { _ = _separateLogic(); } return(new ResultCompletionData()); } IUserMessage message; if (_embed is null) { if (_shouldEmbed) { message = await ctx.CreateEmbed(_message).SendToAsync(ctx.Channel); } else { message = await ctx.Channel.SendMessageAsync(_message); } } else { message = await _embed.SendToAsync(ctx.Channel); } if (_callback != null) { if (_runFuncAsync) { await _callback(message); } else { _ = _callback(message); } } return(new ResultCompletionData(message)); }
public async ValueTask <IUserMessage> SendPaginatedMessageAsync(VolteContext context, PaginatedMessage pager, ICriterion <SocketReaction> criterion = null) { var callback = new PaginatedMessageCallback(this, context, pager, criterion); _activePagers.Enqueue(callback); await callback.DisplayAsync(); return(callback.Message); }
private EvalEnvironment CreateEvalEnvironment(VolteContext ctx) => new EvalEnvironment { Context = ctx, Client = ctx.Client.GetShardFor(ctx.Guild), Data = _db.GetData(ctx.Guild), Logger = _logger, CommandService = _commands, DatabaseService = _db, EmojiService = _emoji };
public static async IAsyncEnumerable <Command> WhereAccessibleAsync(this IEnumerable <Command> commands, VolteContext ctx) { foreach (var cmd in commands) { if (await CanShowCommandAsync(ctx, cmd)) { yield return(cmd); } } }
private EvalObjects GetEvalObjects(VolteContext ctx) => new EvalObjects { Context = ctx, Client = ctx.Client.GetShardFor(ctx.Guild), Data = _db.GetData(ctx.Guild), Logger = _logger, CommandService = _commands, DatabaseService = _db, EmojiService = _emoji };
/// <summary> /// Sends a message to the contextual channel and deletes it after <paramref name="timeout"/> has ended. /// </summary> /// <param name="context">The context to use.</param> /// <param name="content">The content of the message to send. Can be empty if you're sending an embed.</param> /// <param name="isTts">Whether or not the message should use TTS. Defaults to false.</param> /// <param name="embed">The embed to send.</param> /// <param name="timeout">The time elapsed after the message is sent for it to be deleted.</param> /// <param name="options">The Discord.Net <see cref="RequestOptions"/> for the SendMessageAsync method.</param> /// <returns>The message that will be deleted.</returns> public async ValueTask <IUserMessage> ReplyAndDeleteAsync(VolteContext context, string content, bool isTts = false, Embed embed = null, TimeSpan?timeout = null, RequestOptions options = null) { timeout ??= _config.DefaultTimeout; var message = await context.Channel.SendMessageAsync(content, isTts, embed, options); _ = Executor.ExecuteAfterDelayAsync(timeout.Value, async() => await message.TryDeleteAsync()); return(message); }
private async Task ExecuteScriptAsync(string code, VolteContext ctx) { ctx.Services.Get <EmojiService>(out var e); var sopts = ScriptOptions.Default.WithImports(_imports).WithReferences( AppDomain.CurrentDomain.GetAssemblies() .Where(x => !x.IsDynamic && !x.Location.IsNullOrWhitespace())); var embed = ctx.CreateEmbedBuilder(); var msg = await embed.WithTitle("Evaluating").WithDescription(Format.Code(code, "cs")) .SendToAsync(ctx.Channel); try { var sw = Stopwatch.StartNew(); var state = await CSharpScript.RunAsync(code, sopts, CreateEvalEnvironment(ctx)); sw.Stop(); if (state.ReturnValue is null) { await msg.DeleteAsync(); await ctx.Message.AddReactionAsync(new Emoji(e.BallotBoxWithCheck)); } else { var res = state.ReturnValue switch { string str => str, IEnumerable enumerable => enumerable.Cast <object>().Select(x => $"{x}").Join(", "), IUser user => $"{user} ({user.Id})", ITextChannel channel => $"#{channel.Name} ({channel.Id})", _ => state.ReturnValue.ToString() }; await msg.ModifyAsync(m => m.Embed = embed.WithTitle("Eval") .AddField("Elapsed Time", $"{sw.Elapsed.Humanize()}", true) .AddField("Return Type", state.ReturnValue.GetType(), true) .WithDescription(Format.Code(res, "ini")).Build()); } } catch (Exception ex) { await msg.ModifyAsync(m => m.Embed = embed .AddField("Exception Type", ex.GetType(), true) .AddField("Message", ex.Message, true) .WithTitle("Error") .Build() ); } }
private static async Task ExecuteScriptAsync(string code, VolteContext ctx) { var embed = ctx.CreateEmbedBuilder(); var msg = await embed.WithTitle("Evaluating").WithDescription(Format.Code(code, "cs")) .SendToAsync(ctx.Channel); try { var env = CreateEvalEnvironment(ctx); var sw = Stopwatch.StartNew(); var state = await CSharpScript.RunAsync(code, Options, env); sw.Stop(); var shouldReply = true; if (state.ReturnValue != null) { switch (state.ReturnValue) { case EmbedBuilder eb: shouldReply = false; await env.ReplyAsync(eb); break; case Embed e: shouldReply = false; await env.ReplyAsync(e); break; } var res = state.ReturnValue switch { bool b => b.ToString().ToLower(), IEnumerable enumerable when !(state.ReturnValue is string) => enumerable.Cast <object>().ToReadableString(), IUser user => $"{user} ({user.Id})", ITextChannel channel => $"#{channel.Name} ({channel.Id})", IMessage message => env.Inspect(message), _ => state.ReturnValue.ToString() }; await(shouldReply switch { true => msg.ModifyAsync(m => m.Embed = embed.WithTitle("Eval") .AddField("Elapsed Time", $"{sw.Elapsed.Humanize()}", true) .AddField("Return Type", state.ReturnValue.GetType().AsPrettyString(), true) .WithDescription(Format.Code(res, res.IsNullOrEmpty() ? string.Empty : "ini")).Build()), false => msg.DeleteAsync().ContinueWith(_ => env.ReactAsync(DiscordHelper.BallotBoxWithCheck)) }); }
/// <summary> /// Starts a poll in the contextual channel using the specified <see cref="PollInfo"/> applied to the embed. /// This method does not start or in any way support reaction tracking. /// This message will have its poll emojis added in the background so it's not a long-running <see cref="Task"/>. /// </summary> /// <param name="context">The context to use</param> /// <param name="pollInfo">The <see cref="PollInfo"/> to apply</param> /// <returns>The sent poll message.</returns> public async ValueTask <IUserMessage> StartPollAsync(VolteContext context, PollInfo pollInfo) { var m = await pollInfo.Apply(context.CreateEmbedBuilder()).SendToAsync(context.Channel); _ = Executor.ExecuteAsync(async() => { _ = await context.Message.TryDeleteAsync("Poll invocation message."); await DiscordHelper.GetPollEmojis().GetRange(0, pollInfo.Fields.Count) .ForEachAsync(async emoji => { await m.AddReactionAsync(emoji); }); }); return(m); }
private async Task ExecuteScriptAsync(string code, VolteContext ctx) { var sopts = ScriptOptions.Default.WithImports(_imports).WithReferences( AppDomain.CurrentDomain.GetAssemblies() .Where(x => !x.IsDynamic && !x.Location.IsNullOrWhitespace())); var embed = ctx.CreateEmbedBuilder(); var msg = await embed.WithTitle("Evaluating").WithDescription(Format.Code(code, "cs")).SendToAsync(ctx.Channel); try { var sw = Stopwatch.StartNew(); var result = await CSharpScript.EvaluateAsync(code, sopts, CreateEvalEnvironment(ctx)); sw.Stop(); if (result is null) { await msg.DeleteAsync(); await ctx.ReactSuccessAsync(); } else { var res = result switch { string str => str, IEnumerable enumerable => enumerable.Cast <object>().Select(x => $"{x}").Join(", "), _ => result.ToString() }; await msg.ModifyAsync(m => m.Embed = embed.WithTitle("Eval") .AddField("Elapsed Time", $"{sw.Elapsed.Humanize()}", true) .AddField("Return Type", result.GetType(), true) .WithDescription(Format.Code(res, "ini")).Build()); } } catch (Exception e) { await msg.ModifyAsync(m => m.Embed = embed .AddField("Exception Type", e.GetType(), true) .AddField("Message", e.Message, true) .WithTitle("Error") .Build() ); } }
public override async ValueTask <ResultCompletionData> ExecuteResultAsync(VolteContext ctx) { if (_after is null) { return(new ResultCompletionData()); } if (_awaitCallback) { await _after(); } else { _ = _after(); } return(new ResultCompletionData()); }
public PaginatedMessageCallback(InteractiveService interactive, VolteContext sourceContext, PaginatedMessage pager, ICriterion <SocketReaction> criterion = null) { Interactive = interactive; Context = sourceContext; Criterion = criterion ?? new EmptyCriterion <SocketReaction>(); _pager = pager; if (_pager.Pages is IEnumerable <EmbedFieldBuilder> ) { _pageCount = ((_pager.Pages.Count() - 1) / _pager.Options.FieldsPerPage) + 1; } else { _pageCount = _pager.Pages.Count(); } }
/// <summary> /// Waits for the next message in the contextual channel. /// This is a long-running <see cref="Task"/>. /// </summary> /// <param name="context">The context to wait on.</param> /// <param name="fromSourceUser">Should the message only be from the source user.</param> /// <param name="inSourceChannel">Should the message only be from the source channel.</param> /// <param name="timeout">The timeout to abort the waiting after.</param> /// <param name="token">The cancellation token to observe.</param> /// <returns>The waited message; or null if no message was received.</returns> public ValueTask <SocketUserMessage> NextMessageAsync(VolteContext context, bool fromSourceUser = true, bool inSourceChannel = true, TimeSpan?timeout = null, CancellationToken token = default) { var criterion = new Criteria <SocketUserMessage>(); if (fromSourceUser) { criterion.AddCriterion(new EnsureSourceUserCriterion()); } if (inSourceChannel) { criterion.AddCriterion(new EnsureSourceChannelCriterion()); } return(NextMessageAsync(context, criterion, timeout, token)); }
public async Task EvaluateAsync(VolteContext ctx, string code) { try { if (code.StartsWithIgnoreCase("```cs") && code.EndsWith("```")) { code = code.Substring(5); code = code.Remove(code.LastIndexOf("```", StringComparison.OrdinalIgnoreCase), 3); } await ExecuteScriptAsync(code, ctx); } catch (Exception e) { _logger.Error(LogSource.Module, string.Empty, e); } finally { GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true); GC.WaitForPendingFinalizers(); } }
/// <summary> /// Waits for the next message in the contextual channel. /// This is a long-running <see cref="Task"/>. /// </summary> /// <param name="context">The context to wait on.</param> /// <param name="criterion">The <see cref="ICriterion{SocketUserMessage}"/> to use.</param> /// <param name="timeout">The timeout to abort the waiting after.</param> /// <param name="token">The cancellation token to observe.</param> /// <returns>The waited message; or null if no message was received.</returns> public async ValueTask <SocketUserMessage> NextMessageAsync(VolteContext context, ICriterion <SocketUserMessage> criterion, TimeSpan?timeout = null, CancellationToken token = default) { timeout ??= _config.DefaultTimeout; var msgTcs = new TaskCompletionSource <SocketUserMessage>(); var cancelTcs = new TaskCompletionSource <bool>(); token.Register(() => cancelTcs.SetResult(true)); async Task Handler(SocketMessage m) { if (m.ShouldHandle(out var msg)) { var result = await criterion.JudgeAsync(context, msg); if (result) { msgTcs.SetResult(msg); } } } context.Client.MessageReceived += Handler; var trigger = msgTcs.Task; var task = await Task.WhenAny(trigger, Task.Delay(timeout.Value, token), cancelTcs.Task); context.Client.MessageReceived -= Handler; if (task == trigger) { return(await trigger); } return(null); }
public Task EvaluateAsync(VolteContext ctx, string code) { try { if (Pattern.IsMatch(code, out var match)) { code = match.Groups[1].Value; } return(ExecuteScriptAsync(code, ctx)); } catch (Exception e) { _logger.Error(LogSource.Module, string.Empty, e); } finally { GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true); GC.WaitForPendingFinalizers(); } return(Task.CompletedTask); }
public async ValueTask <bool> JudgeAsync(VolteContext sourceContext, T parameter) { foreach (var criterion in _critiera) { var result = await criterion.JudgeAsync(sourceContext, parameter); if (!result) { return(false); } } foreach (var criteria in _localCriteria) { var result = await criteria(sourceContext, parameter); if (!result) { return(false); } } return(true); }
public ValueTask <bool> JudgeAsync(VolteContext sourceContext, SocketReaction parameter) => new ValueTask <bool>(parameter.UserId == sourceContext.User.Id);
public MessageReceivedEventArgs(SocketMessage s, IServiceProvider provider) { Message = s.Cast <SocketUserMessage>() ?? throw new ArgumentException($"{nameof(s)} is not a SocketUserMessage; aborting EventArgs construction."); Context = VolteContext.Create(s, provider); Data = provider.Get <DatabaseService>().GetData(Context.Guild); }