<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Discord;
using Discord.Commands;
using NadekoBot.Common.Attributes;
using NadekoBot.Extensions;
using NadekoBot.Services;
using NCalc;

namespace NadekoBot.Modules.Utility
{
    public partial class Utility
    {
        [Group]
        public class CalcCommands : NadekoSubmodule
        {
            private readonly DbService _db;

            public CalcCommands(DbService db)
            {
                _db = db;
            }

            [NadekoCommand, Usage, Description, Aliases]
            public async Task Calculate([Remainder] string expression)
            {
                var expr = new Expression(expression, EvaluateOptions.IgnoreCase);
                expr.EvaluateParameter += Expr_EvaluateParameter;
                expr.EvaluateFunction += Expr_EvaluateFunction;
                var result = expr.Evaluate();
                if (expr.Error == null)
                    await Context.Channel.SendConfirmAsync("⚙ " + GetText("result"), expression.Trim() + "\n" + result);
                else
                    await Context.Channel.SendErrorAsync("⚙ " + GetText("error"), expr.Error);
            }

            private static void Expr_EvaluateParameter(string name, ParameterArgs args)
            {
                switch (name.ToLowerInvariant())
                {
                    case "pi":
                        args.Result = Math.PI;
                        break;
                    case "e":
                        args.Result = Math.E;
                        break;
                }
            }

            private void Expr_EvaluateFunction(string name, FunctionArgs args)
            {
                name = name.ToLowerInvariant();
                // All methods have to in CustomNCalcEvaluations and be like:
                // public static object calcfunctionname(ICommandContext context, DbService db, FunctionArgs args){ ... }
                var functions = from m in typeof(CustomNCalcEvaluations).GetTypeInfo().GetMethods()
                    where m.IsStatic && m.IsPublic && m.ReturnType == typeof(object) && 
                          m.GetParameters().Length == 3 &&
                          m.GetParameters()[0].ParameterType == typeof(ICommandContext) &&
                          m.GetParameters()[1].ParameterType == typeof(DbService) &&
                          m.GetParameters()[2].ParameterType == typeof(FunctionArgs)
                    select m;
                var method = functions.FirstOrDefault(m => m.Name.ToLowerInvariant().Equals(name));
                var result = method?.Invoke(null, new object[]{Context, _db, args});
                if (result != null) args.Result = result;
            }

            [NadekoCommand, Usage, Description, Aliases]
            public async Task CalcOps()
            {
                var selection = typeof(Math).GetTypeInfo()
                    .GetMethods()
                    .Distinct(new MethodInfoEqualityComparer())
                    .Select(x => x.Name)
                    .Except(new[]
                    {
                        "ToString",
                        "Equals",
                        "GetHashCode",
                        "GetType"
                    });
                var functions = from m in typeof(CustomNCalcEvaluations).GetTypeInfo().GetMethods()
                    where m.IsStatic && m.IsPublic && m.ReturnType == typeof(object) &&
                          m.GetParameters().Length == 3 &&
                          m.GetParameters()[0].ParameterType == typeof(ICommandContext) &&
                          m.GetParameters()[1].ParameterType == typeof(DbService) &&
                          m.GetParameters()[2].ParameterType == typeof(FunctionArgs)
                    select m.Name;
                await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
                    .WithTitle(GetText("calcops", Prefix))
                    .AddField("Math", string.Join(", ", selection))
                    .AddField("Custom", string.Join(", ", functions)));
            }
        }

        private class CustomNCalcEvaluations
        {
            private static object Level(ICommandContext context, DbService db, FunctionArgs args)
            {
                if (args.Parameters.Length > 0) context.Channel
                     .SendMessageAsync($"args: {args.Parameters.Aggregate("", (s, p) => $"{s}{p.ParsedExpression.ToString()}, ", s => s.Substring(0, s.Length - 2))}")
                     .GetAwaiter().GetResult();
                if (args.Parameters.Length > 1) return null;
                var user = context.User as IGuildUser;
                if (args.Parameters.Length == 1)
                {
                    var parameter = args.Parameters[0];
                    if (parameter.ParsedExpression == null)
                        parameter.Evaluate();
                    var expr = parameter.ParsedExpression.ToString().Trim('[', ']');
                    context.Channel.SendMessageAsync($"expr: \"{expr}\"").GetAwaiter().GetResult();
                    if (ulong.TryParse(expr, out ulong id)) {
                        user = context.Guild.GetUserAsync(id).GetAwaiter().GetResult();
                    }
                    else {
                        context.Channel.SendMessageAsync($"usernames: {context.Guild.GetUsersAsync().GetAwaiter().GetResult().Aggregate("", (s, u) => $"{s}{u.Username}+{u.Mention.Substring(1)}+{u.Nickname} | ", s => s.Substring(0, s.Length - 3))}").GetAwaiter().GetResult();
                        user = context.Guild.GetUsersAsync().GetAwaiter().GetResult()
                            .FirstOrDefault(u => u.Username == expr || u.Mention == expr);
                    }
                }
                context.Channel.SendMessageAsync($"user: {(user == null ? "null" : "notnull")}, {user?.Username}")
                    .GetAwaiter().GetResult();<commit_msg>Fixed an ArgumentException in calcops command<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Discord;
using Discord.Commands;
using NadekoBot.Common.Attributes;
using NadekoBot.Extensions;
using NadekoBot.Services;
using NCalc;

namespace NadekoBot.Modules.Utility
{
    public partial class Utility
    {
        [Group]
        public class CalcCommands : NadekoSubmodule
        {
            private readonly DbService _db;

            public CalcCommands(DbService db)
            {
                _db = db;
            }

            [NadekoCommand, Usage, Description, Aliases]
            public async Task Calculate([Remainder] string expression)
            {
                var expr = new Expression(expression, EvaluateOptions.IgnoreCase);
                expr.EvaluateParameter += Expr_EvaluateParameter;
                expr.EvaluateFunction += Expr_EvaluateFunction;
                var result = expr.Evaluate();
                if (expr.Error == null)
                    await Context.Channel.SendConfirmAsync("⚙ " + GetText("result"), expression.Trim() + "\n" + result);
                else
                    await Context.Channel.SendErrorAsync("⚙ " + GetText("error"), expr.Error);
            }

            private static void Expr_EvaluateParameter(string name, ParameterArgs args)
            {
                switch (name.ToLowerInvariant())
                {
                    case "pi":
                        args.Result = Math.PI;
                        break;
                    case "e":
                        args.Result = Math.E;
                        break;
                }
            }

            private void Expr_EvaluateFunction(string name, FunctionArgs args)
            {
                name = name.ToLowerInvariant();
                // All methods have to in CustomNCalcEvaluations and be like:
                // public static object calcfunctionname(ICommandContext context, DbService db, FunctionArgs args){ ... }
                var functions = from m in typeof(CustomNCalcEvaluations).GetTypeInfo().GetMethods()
                    where m.IsStatic && m.IsPublic && m.ReturnType == typeof(object) && 
                          m.GetParameters().Length == 3 &&
                          m.GetParameters()[0].ParameterType == typeof(ICommandContext) &&
                          m.GetParameters()[1].ParameterType == typeof(DbService) &&
                          m.GetParameters()[2].ParameterType == typeof(FunctionArgs)
                    select m;
                var method = functions.FirstOrDefault(m => m.Name.ToLowerInvariant().Equals(name));
                var result = method?.Invoke(null, new object[]{Context, _db, args});
                if (result != null) args.Result = result;
            }

            [NadekoCommand, Usage, Description, Aliases]
            public async Task CalcOps()
            {
                var selection = typeof(Math).GetTypeInfo()
                    .GetMethods()
                    .Distinct(new MethodInfoEqualityComparer())
                    .Select(x => x.Name)
                    .Except(new[]
                    {
                        "ToString",
                        "Equals",
                        "GetHashCode",
                        "GetType"
                    }).ToArray();
                var functions = (from m in typeof(CustomNCalcEvaluations).GetTypeInfo().GetMethods()
                    where m.IsStatic && m.IsPublic && m.ReturnType == typeof(object) &&
                          m.GetParameters().Length == 3 &&
                          m.GetParameters()[0].ParameterType == typeof(ICommandContext) &&
                          m.GetParameters()[1].ParameterType == typeof(DbService) &&
                          m.GetParameters()[2].ParameterType == typeof(FunctionArgs)
                    select m.Name).ToArray();
                var eb = new EmbedBuilder().WithOkColor()
                    .WithTitle(GetText("calcops", Prefix));
                if (selection.Any()) eb.AddField("Math", string.Join(", ", selection));
                if (functions.Any()) eb.AddField("Custom", string.Join(", ", functions));
                await Context.Channel.EmbedAsync(eb);
            }
        }

        private class CustomNCalcEvaluations
        {
            private static object Level(ICommandContext context, DbService db, FunctionArgs args)
            {
                if (args.Parameters.Length > 0) context.Channel
                     .SendMessageAsync($"args: {args.Parameters.Aggregate("", (s, p) => $"{s}{p.ParsedExpression.ToString()}, ", s => s.Substring(0, s.Length - 2))}")
                     .GetAwaiter().GetResult();
                if (args.Parameters.Length > 1) return null;
                var user = context.User as IGuildUser;
                if (args.Parameters.Length == 1)
                {
                    var parameter = args.Parameters[0];
                    if (parameter.ParsedExpression == null)
                        parameter.Evaluate();
                    var expr = parameter.ParsedExpression.ToString().Trim('[', ']');
                    context.Channel.SendMessageAsync($"expr: \"{expr}\"").GetAwaiter().GetResult();
                    if (ulong.TryParse(expr, out ulong id)) {
                        user = context.Guild.GetUserAsync(id).GetAwaiter().GetResult();
                    }
                    else {
                        context.Channel.SendMessageAsync($"usernames: {context.Guild.GetUsersAsync().GetAwaiter().GetResult().Aggregate("", (s, u) => $"{s}{u.Username}+{u.Mention.Substring(1)}+{u.Nickname} | ", s => s.Substring(0, s.Length - 3))}").GetAwaiter().GetResult();
                        user = context.Guild.GetUsersAsync().GetAwaiter().GetResult()
                            .FirstOrDefault(u => u.Username == expr || u.Mention == expr);
                    }
                }
                context.Channel.SendMessageAsync($"user: {(user == null ? "null" : "notnull")}, {user?.Username}")
                    .GetAwaiter().GetResult();
{'fraction_non_alphanumeric': 0.11599182004089979, 'fraction_numerical': 0.0027811860940695297, 'mean_word_length': 1.5663308144416457, 'pattern_counts': {'":': 4, '<': 3, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '816163', 'n_tokens_mistral': 3107, 'n_tokens_neox': 2943, 'n_words': 602}