Exemplo n.º 1
0
 public void CreatePermalinkCmd(Commands.CommandGroupBuilder group, string name, string[] aliases, bool is_playlist)
 {
     CreatePLCmd(group, name, $"SoundCloud {(!is_playlist ? "Track" : "Playlist")} Permalink(s)", $"I'll add SoundCloud {(is_playlist ? "playlist " : "")}songs to the playlist!", aliases)
     .Do(e =>
     {
         // TODO: Find out if snd.sc links for playlists exist, it's doubtful since it's not exposed in their ui.
         MatchCollection m = Regex.Matches(e.Args[0].Replace(' ', '\n'), $@"^https?:\/\/(?:soundcloud\.com({(is_playlist ? "?:" : "?!")}\/.+\/sets){(is_playlist ? "" : @"|snd\.sc")})\/.+$", RegexOptions.IgnoreCase | RegexOptions.Multiline);
         if (m.Count == 0)
         {
             e.Channel.SendMessage($"{e.User.Mention} No SoundCloud {(is_playlist ? "playlist" : "track")} permalink matches.");
         }
         else
         {
             foreach (var link in from Match match in m select match.Groups[0].ToString())
             {
                 if (is_playlist)
                 {
                     Triad(e, GetPlaylist(link), false);
                 }
                 else
                 {
                     Triad(e, GetTrack(link), true);
                 }
             }
         }
     });
 }
Exemplo n.º 2
0
 static void CreateLewdCommand(Commands.CommandGroupBuilder group, string chan)
 {
     group.CreateCommand(chan)
     .FlagNsfw(true)
     .Description($"I'll give you a random image from https://lewdchan.com/{chan}/")
     .Do(async e => await LewdSX(chan, e.Channel));
 }
Exemplo n.º 3
0
        static void AddResponseCommands(Commands.CommandGroupBuilder group, string file)
        {
            var json = Helpers.GetJsonFileIfExists(file);

            if (json == null)
            {
                return;
            }
            foreach (var cmdjson in json)
            {
                Helpers.CreateJsonCommand(group, cmdjson, (cmd, val) =>
                {
                    cmd.FlagNsfw(val["nsfw"].ToObject <bool>());
                    var responses = val["responses"].ToObject <string[]>();
                    if (responses.Length == 1)
                    {
                        cmd.Do(async e => await e.Channel.SendMessageAsync(responses[0]));
                    }
                    else
                    {
                        cmd.Do(async e => await e.Channel.SendMessageAsync(Helpers.Pick(responses)));
                    }
                });
            }
        }
Exemplo n.º 4
0
 public CommandService(CommandServiceConfig config, Func<Channel, bool> getNsfwFlag = null, Func<User, bool> getMusicFlag = null, Func<Channel, User, bool> getIgnoredChannelFlag = null)
 {
     _config = config;
     _getNsfwFlag = getNsfwFlag;
     _getMusicFlag = getMusicFlag;
     _getIgnoredChannelFlag = getIgnoredChannelFlag;
     _allCommands = new List<Command>();
     _map = new CommandMap(null, "", "");
     _categories = new Dictionary<string, CommandMap>();
     _root = new CommandGroupBuilder(this, "", null);
 }
Exemplo n.º 5
0
        public CommandService(CommandServiceConfig config, Func <IMessageChannel, bool> getNsfwFlag = null, Func <IVoiceState, bool> getMusicFlag = null, Func <IMessageChannel, IUser, bool> getIgnoredChannelFlag = null)
        {
            Config = config;

            _getNsfwFlag           = getNsfwFlag;
            _getMusicFlag          = getMusicFlag;
            _getIgnoredChannelFlag = getIgnoredChannelFlag;
            _allCommands           = new List <Command>();
            _map        = new CommandMap();
            _categories = new Dictionary <string, CommandMap>();
            Root        = new CommandGroupBuilder(this);
        }
Exemplo n.º 6
0
 internal static void AddCommands(CommandGroupBuilder group)
 {
     var secret_file = "calendar_client_secret.json";
     if (File.Exists(secret_file))
     {
         UserCredential credential;
         using (var stream = new FileStream(secret_file, FileMode.Open, FileAccess.Read))
         {
             credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
                 GoogleClientSecrets.Load(stream).Secrets, new[]{CalendarService.Scope.CalendarReadonly}, Program.Config.AppName, CancellationToken.None).Result;
         }
         Func<string> timezone = () =>
         {
             var offset = TimeZoneInfo.Local.BaseUtcOffset.ToString();
             return $"(UTC{offset.Substring(0, offset.LastIndexOf(':'))})";
         };
         foreach (var calendar_cmd in (JObject)Program.config["GoogleCalendar"])
         {
             Helpers.CreateJsonCommand(group, calendar_cmd, (cmd, val) =>
             {
                 var include_desc = Helpers.FieldExistsSafe<bool>(val, "includeDescription");
                 cmd.Parameter("count or event id", ParameterType.Optional)
                 .Do(async e =>
                 {
                     var service = new CalendarService(new BaseClientService.Initializer()
                     {
                         HttpClientInitializer = credential,
                         ApplicationName = Program.Config.AppName
                     });
                     Func<Event, string> header = item =>
                       $"**{item.Summary}:**\n{(item.Start.DateTime == null ? $"All day {(item.Start.Date.Equals(DateTime.Now.ToString("yyyy-MM-dd")) ? "today" : $"on {item.Start.Date}")}" : $"{(DateTime.Now > item.Start.DateTime ? $"Happening until" : $"Will happen {item.Start.DateTime} and end at")} {item.End.DateTime} {timezone()}")}.\n";
                     Func<Event, string> header_desc = item => $"{header(item)}{item.Description}";
                     int results = 1;
                     if (Helpers.HasArg(e.Args))
                         if (!int.TryParse(e.Args[0], out results)) // Must be an event ID
                         {
                             var r = await service.Events.Get(val["calendarId"].ToString(), e.Args[0]).ExecuteAsync();
                             await e.Channel.SendMessage(header_desc(r));
                             return;
                         }
                     var request = service.Events.List(val["calendarId"].ToString());
                     request.TimeMin = DateTime.Now;
                     request.SingleEvents = true;
                     request.OrderBy = EventsResource.ListRequest.OrderByEnum.StartTime;
                     request.MaxResults = results;
                     var events = await request.ExecuteAsync();
                     if (events.Items?.Count > 0)
                         foreach (var item in events.Items)
                             await e.Channel.SendMessage(include_desc ? header_desc(item) : $"{header(item)}ID: {item.Id}");
                     else await e.Channel.SendMessage("Apparently, there's nothing coming up nor taking place right now...");
                 });
             });
Exemplo n.º 7
0
        internal static void AddDelayedCommands(Commands.CommandGroupBuilder group)
        {
            var creds = Program.config["CleverBot"];

            if (!Helpers.FieldExists(creds, "user")) // no credentials
            {
                return;
            }

            // Create the handler
            var handler = new Handler(Program.Self.Id, creds["user"].ToString(), creds["key"].ToString());

            group.CreateCommand("bot")
            .Alias("chatbot")
            .Parameter("on or off", Commands.ParameterType.Optional)
            .MinPermissions(3)
            .Description("I'll turn on/off the chatbot for this channel.\nIf no args, I'll tell you if there's a bot on for this channel.")
            .Do(e =>
            {
                bool botstatus = handler.HasBot(e.Channel.Id);
                if (e.Args.Any())
                {
                    Helpers.OnOffCmd(e, on =>
                    {
                        if (botstatus == on)
                        {
                            e.Channel.SendMessageAsync("The bot is already " + (botstatus ? "on" : "off") + $" for {e.Channel}");
                        }
                        else
                        {
                            if (botstatus)
                            {
                                handler.RemoveBot(e.Channel.Id);
                            }
                            else
                            {
                                handler.CreateBot(group.Service.Client.CurrentUser.Id.ToString(), e.Channel.Id.ToString());
                            }
                            e.Channel.SendMessageAsync("The bot is now " + (!botstatus ? "on" : "off") + $" for {e.Channel}");
                            SQL.AddOrUpdateFlag(e.Channel.Id, "chatbot", botstatus ? "-1" : "0");
                        }
                    });
                }
                else
                {
                    e.Channel.SendMessageAsync("The bot is currently " + (botstatus ? "on" : "off") + $" for {e.Channel}.");
                }
            });
        }
Exemplo n.º 8
0
        //static IEnumerable<string> PlaylistFiles(string folder) => Directory.EnumerateFiles(folder, "*.*", UseSubdirs ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly).Where(s => new[]{".pls"}.Contains(Path.GetExtension(s)));

        static Commands.CommandBuilder CreatePLCmd(Commands.CommandGroupBuilder group, string name, string description, string[] aliases = null)
        {
            var cmd = group.CreateCommand(name)
                      .Description(description)
                      .FlagMusic(true);

            if (aliases != null)
            {
                foreach (var alias in aliases)
                {
                    cmd.Alias(alias);
                }
            }
            return(cmd);
        }
Exemplo n.º 9
0
            public static void CreateCommand(Commands.CommandGroupBuilder group, string name, bool all /*, bool is_playlist*/)
            {
                CreatePLCmd(group, name, $"{(/*is_playlist ? "playlist" :*/ "song")}{(all ? "s" : "")} to find", $"I'll try to add {(all ? "all songs matching " : "")}your request to the playlist!")
                .Do(e =>
                {
                    var args = string.Join(" ", e.Args);
                    if (args.Length == 0)
                    {
                        e.Channel.SendMessage("You need to provide at least a character to search for.");
                        return;
                    }
                    args = args.ToLower();
                    Func <string, bool> search = f => Path.GetFileNameWithoutExtension(f).ToLower().Contains(args);
                    long filecount             = 0;
                    var pl = playlist[e.User.VoiceChannel.Id];

                    /*var insert_file = is_playlist ? (Action<string>)(file =>
                     *  {
                     *      for ()
                     *  }) :
                     *  file => pl.InsertFile(file, e);*/
                    Action <string> insert_file = file => pl.InsertFile(file, e);
                    var songs = /*is_playlist ? PlaylistFiles(Folder) :*/ Files(Folder);
                    if (all)
                    {
                        var files = songs.Where(search);
                        foreach (var file in files)
                        {
                            insert_file(file);
                        }
                        filecount = files.Count();
                    }
                    else
                    {
                        var file = songs.FirstOrDefault(search);
                        if (file != null)
                        {
                            insert_file(file);
                            filecount = 1;
                        }
                    }

                    e.Channel.SendMessage($"{e.User.Mention} {(filecount > 1 ? filecount.ToString() : "Your")} request{(filecount != 0 ? $"{(filecount == 1 ? " has" : "s have")} been added to the list" : " was not found")}.");
                });
            }
Exemplo n.º 10
0
        static void CreateBooruCommand(Commands.CommandGroupBuilder group, string booru, string[] aliases = null)
        {
            var cmd = group.CreateCommand(booru);

            cmd.Parameter("[-]tag1", Commands.ParameterType.Optional)
            .Parameter("[-]tag2", Commands.ParameterType.Optional)
            .Parameter("[-]tagn", Commands.ParameterType.Multiple)
            .FlagNsfw(true)
            .Description($"I'll give you a random image from {booru} (optionally with tags)");
            if (aliases != null)
            {
                foreach (var alias in aliases)
                {
                    cmd.Alias(alias);
                }
            }
            cmd.Do(e => Task.Run(() => Board.Execute(booru, e)));
        }
Exemplo n.º 11
0
 static public void CreateCommand(Commands.CommandGroupBuilder group, string name, string[] aliases = null)
 {
     CreatePLCmd(group, name, $"youtube video link(s)", $"I'll add youtube videos to the playlist", aliases)
     .Do(e =>
     {
         MatchCollection m = regex.Matches(e.Args[0]);
         if (m.Count == 0)
         {
             e.Channel.SendMessage($"None of {e.Args[0]} could be added to playlist because no valid youtube links were found within.");
         }
         else
         {
             foreach (var link in from Match match in m select $"youtube.com/watch?v={match.Groups[1]}")
             {
                 Triad(e, VideoData.Get(link));
             }
         }
     });
 }
Exemplo n.º 12
0
        internal static void AddCommands(Commands.CommandGroupBuilder group)
        {
            group.CreateCommand("nsfw status")
            .Alias("canlewd status")
            .Description("I'll tell you if this channel allows nsfw commands.")
            .Do(async e => await e.Channel.SendMessageAsync($"This channel {(GetNsfw(e.Channel) ? "allows" : "doesn't allow")} nsfw commands."));

            // Moderator Commands
            group.CreateCommand("nsfw")
            .Alias("canlewd")
            .Parameter("on/off", Commands.ParameterType.Required)
            .MinPermissions(1)
            .Description("I'll set a channel's nsfw flag to on or off.")
            .Do(e =>
            {
                Helpers.OnOffCmd(e, on =>
                {
                    string status = on ? "allow" : "disallow";
                    if (GetNsfw(e.Channel) == on)
                    {
                        e.Channel.SendMessageAsync($"{e.User.Mention}, this channel is already {status}ing nsfw commands.");
                    }
                    else
                    {
                        SQL.AddOrUpdateFlag(e.Channel.Id, "nsfw", on ? "1" : "0");
                        e.Channel.SendMessageAsync($"I've set this channel to {status} nsfw commands.");
                    }
                });
            });

            // TODO: clean up welcome and sayleft to be the same function via strings and lambdas.
            group.CreateCommand("welcome")
            .Parameter("on/off", Commands.ParameterType.Required)
            .Parameter("channel", Commands.ParameterType.Optional)
            .MinPermissions(2)
            .Description("I'll turn welcomes on this server off or on (in a given channel).")
            .Do(e => Helpers.OnOffCmd(e, on =>
            {
                string status  = on ? "en" : "dis";
                ITextChannel c = (ITextChannel)e.Server.GetChannelAsync(e.Message.MentionedChannelIds.FirstOrDefault()) ?? e.TextChannel;
                if (GetWelcome(e.Server, c) == on)
                {
                    e.Channel.SendMessageAsync($"{e.User.Mention}, Welcoming is already {status}abled, here.");
                }
                else
                {
                    SQL.AddOrUpdateServer(e.Server.Id, "welcome", on ? "1" : "0");
                    e.Channel.SendMessageAsync($"I will no{(on ? "w" : " longer")} welcome people to this server{(on ? $" in {c.Mention}" : "")}.");
                }
            }));

            group.CreateCommand("sayleft")
            .Parameter("on/off", Commands.ParameterType.Required)
            .Parameter("channel", Commands.ParameterType.Optional)
            .MinPermissions(2)
            .Description("I'll turn leave announcements on this server off or on (in a given channel).")
            .Do(e => Helpers.OnOffCmd(e, on =>
            {
                string status  = on ? "en" : "dis";
                ITextChannel c = e.Message.Tags.FirstOrDefault(t => t.Type == TagType.ChannelMention)?.Value as ITextChannel ?? e.TextChannel;
                if (GetLeft(e.Server, c) == on)
                {
                    e.Channel.SendMessageAsync($"{e.User.Mention}, Announcing people who leave is already {status}abled, here.");
                }
                else
                {
                    SQL.AddOrUpdateServer(e.Server.Id, "sayleft", on ? "1" : "0");
                    SQL.AddOrUpdateServer(e.Server.Id, "leftchannel", on ? c.Id.ToString() : "");
                    e.Channel.SendMessageAsync($"I will no{(on ? "w" : " longer")} announce when people leave this server{(on ? $" in {c.Mention}" : "")}.");
                }
            }));

            Func <IRole, EMentionType> mention_type = r => r.IsMentionable ? EMentionType.role : EMentionType.unmentionableRole;

            // Administrator Commands
            group.CreateCommand("ignore")
            .Parameter("channel", Commands.ParameterType.Optional)
            .Parameter("user", Commands.ParameterType.Optional)
            .Parameter("role", Commands.ParameterType.Optional)
            .Parameter("...", Commands.ParameterType.Multiple)
            .MinPermissions(1)
            .Description("I'll ignore a particular channel, user or role")
            .Do(async e =>
            {
                if (e.Message.MentionedChannelIds.Any() || e.Message.MentionedUserIds.Any() || e.Message.MentionedRoleIds.Any())
                {
                    int perms    = Helpers.GetPermissions(e.User, e.Channel);
                    string reply = "";
                    foreach (var c in e.Message.MentionedChannelIds)
                    {
                        reply += (reply != "" ? "\n" : "") + await SetIgnored("channel", "flags", c, EMentionType.channel, perms);
                    }
                    foreach (var u in e.Message.MentionedUserIds)
                    {
                        reply += (reply != "" ? "\n" : "") + await SetIgnored("user", "users", u, EMentionType.user, perms, Helpers.GetPermissions(u, e.Channel));
                    }
                    var senpai = (SocketGuildUser)await e.Server.GetUserAsync(Program.masterId);
                    foreach (var r in e.Message.MentionedRoleIds)
                    {
                        var role = e.Server.GetRole(r);
                        reply   += (reply != "" ? "\n" : "") + await SetIgnored("role", "roles", r, mention_type(role), perms, (senpai != null && senpai.Roles.Contains(role)) ? -2 : (e.User as SocketGuildUser).Roles.Contains(role) ? -1 : perms);
                    }
                    await e.Channel.SendMessageAsync(reply);
                }
                else
                {
                    await e.Channel.SendMessageAsync("You need to mention at least one user, channel or role!");
                }
            });

            Action <IEnumerable <ulong>, IGuild> add_roles = (roles, server) => SetDefaultRoles(server, roles.Union(GetDefaultRoles(server)));

            group.CreateCommand("adddefaultroles")
            .Parameter("role(s)", Commands.ParameterType.Unparsed)
            .MinPermissions(3)
            .Description("I'll automatically add anyone who joins the server to the roles you tell me with this command.")
            .Do(async e =>
            {
                var roles = e.Message.MentionedRoleIds;
                if (roles.Any())
                {
                    add_roles(roles, e.Server);
                    await e.Channel.SendMessageAsync("Roles added.");
                }
                else
                {
                    await e.Channel.SendMessageAsync("You need to mention at least one role.");
                }
            });

            Action <IEnumerable <ulong>, IGuild> rem_roles = (roles, server) => SetDefaultRoles(server, roles.Except(GetDefaultRoles(server)));

            group.CreateCommand("remdefaultroles")
            .Parameter("role(s)", Commands.ParameterType.Unparsed)
            .MinPermissions(3)
            .Description("I'll remove roles from those automatically assigned to anyone who joins the server.")
            .Do(async e =>
            {
                var roles = e.Message.MentionedRoleIds;
                if (roles.Any())
                {
                    rem_roles(roles, e.Server);
                    await e.Channel.SendMessageAsync("Roles removed.");
                }
                else
                {
                    await e.Channel.SendMessageAsync("You need to mention at least one role.");
                }
            });

            Func <Commands.CommandEventArgs, Func <IRole, Task <string> >, Task> rolenames_command = async(e, func) =>
            {
                string reply = "";
                if (e.Args[0].Length == 0)
                {
                    reply = "You need to provide at least one role name!";
                }
                else
                {
                    Helpers.CommaSeparateRoleNames(e, async(roles, str) =>
                    {
                        var count = roles.Count();
                        if (reply != "")
                        {
                            reply += '\n';
                        }
                        reply += count == 1 ? await func(roles.Single()) : $"{(count == 0 ? "No" : count.ToString())} roles found for {str}";
                    });
                }
                await e.Channel.SendMessageAsync(reply);
            };

            group.CreateCommand("ignore role")
            .Parameter("role(s)", Commands.ParameterType.Unparsed)
            .MinPermissions(3)
            .Description("I'll ignore particular roles by name (comma separated)")
            .Do(async e =>
            {
                int perms  = Helpers.GetPermissions(e.User, e.Channel);
                var senpai = (SocketGuildUser)await e.Server.GetUserAsync(Program.masterId);
                await rolenames_command(e, (r) => SetIgnored("role", "roles", r.Id, mention_type(r), perms, (senpai != null && senpai.Roles.Contains(r)) ? -2 : (e.User as SocketGuildUser).Roles.Contains(r) ? -1 : perms));
            });

            group.CreateCommand("adddefaultrolesbyname")
            .Parameter("role(s)", Commands.ParameterType.Unparsed)
            .MinPermissions(3)
            .Description("I'll automatically add anyone who joins the server to these roles (names must be comma separated).")
            .Do(async e =>
            {
                var roles = new List <IRole>();
                await rolenames_command(e, (r) =>
                {
                    roles.Add(r);
                    return(Task.FromResult(roles.Count == 1 ? "Adding default role(s)." : string.Empty));
                });
                add_roles(roles.Select(r => r.Id), e.Server);
            });

            group.CreateCommand("remdefaultrolesbyname")
            .Parameter("role(s)", Commands.ParameterType.Unparsed)
            .MinPermissions(3)
            .Description("I'll remove roles from those automatically assigned to anyone who joins the server. (names must be comma separated).")
            .Do(async e =>
            {
                var roles = new List <IRole>();
                await rolenames_command(e, (r) =>
                {
                    roles.Add(r);
                    return(Task.FromResult(roles.Count == 1 ? "Removing default role(s)." : string.Empty));
                });
                rem_roles(roles.Select(r => r.Id), e.Server);
            });
        }
Exemplo n.º 13
0
 static void CreateBooruCommand(Commands.CommandGroupBuilder group, string booru, string alias) => CreateBooruCommand(group, booru, new[] { alias });
Exemplo n.º 14
0
 static Commands.CommandBuilder CreatePLCmd(Commands.CommandGroupBuilder group, string name, string parameter, string description, string alias) => CreatePLCmd(group, name, parameter, description, new[] { alias });
Exemplo n.º 15
0
        internal static void AddCommands(Commands.CommandGroupBuilder group)
        {
            group.CreateCommand("ping")
            .Description("I'll reply with 'Pong!'")
            .Do(e => e.Channel.SendMessage($"{e.User.Mention}, Pong!{DoPing(e.Message)}"));

            group.CreateCommand("pong")
            .Hide()     // More of an easter egg, don't show in help.
            .Description("I'll reply with 'Ping?'")
            .Do(e => e.Channel.SendMessage($"{e.User.Mention}, Ping?{DoPing(e.Message)}"));

            group.CreateCommand("uptime")
            .Description("I'll tell you how long I've been awake~")
            .Do(e => e.Channel.SendMessage(Format.Code(Helpers.Uptime().ToString())));

            Func <Role, string> role_info = r =>
            {
                string ret = $"{r.Name} is id {r.Id}, has {r.Members.Count()} members, color is {r.Color}, perms are {r.Permissions.RawValue}, and position is {r.Position}";
                if (r.IsManaged)
                {
                    ret += "; it is managed by the server";
                }
                return($"{ret}.\n");
            };

            group.CreateCommand("whois")
            .Alias("getinfo")
            .Parameter("[@User1] [@User2] [...]", Commands.ParameterType.Unparsed)
            .Description("I'll give you information about the mentioned user(s).")
            .Do(async e =>
            {
                if (e.Args[0].Length == 0 || (!e.Message.MentionedUsers.Any() && !e.Message.MentionedRoles.Any()))
                {
                    return;
                }
                string reply   = "";
                bool oniicheck = e.User.Id == 63299786798796800;
                foreach (User u in e.Message.MentionedUsers)
                {
                    bool onii         = oniicheck && u.Id == 63296013791666176;
                    string possessive = onii ? "his" : "their";
                    reply            += u.Name;
                    if (!string.IsNullOrEmpty(u.Nickname))
                    {
                        reply += $" (Nick: {u.Nickname})";
                    }
                    reply += $"{(onii ? " is your onii-chan <3 and his" : "'s")} id is {u.Id}, {possessive} discriminator is {u.Discriminator} and {possessive} permission level is {Helpers.GetPermissions(u, e.Channel)}.";
                    if (u.IsBot)
                    {
                        reply += " Also, they are a bot!";
                    }
                    reply += '\n';
                }
                foreach (Role r in e.Message.MentionedRoles)
                {
                    reply += role_info(r);
                }
                await e.Channel.SendMessage('\n' + reply);
            });

            group.CreateCommand("whois role")
            .Alias("getinfo role")
            .Parameter("role(s)", Commands.ParameterType.Unparsed)
            .Description("I'll give you info on particular roles by name (comma separated)")
            .Do(e =>
            {
                string reply = "";
                if (e.Args[0].Length == 0)
                {
                    reply = "You need to provide at least one role name!";
                }
                else
                {
                    Helpers.CommaSeparateRoleNames(e, (roles, str) =>
                    {
                        foreach (var r in roles)
                        {
                            reply += role_info(r);
                        }
                    });
                }
                e.Channel.SendMessage(reply);
            });

            Music.AddCommands(group);

            Image.AddCommands(group);

            Action <Commands.CommandEventArgs, Func <string, string> > lookup_cmd = (e, f) =>
            {
                var args = e.Args[0];
                e.Channel.SendMessage(args.Length == 0 ? "I cannot lookup nothing, silly!" : f(args));
            };

            group.CreateCommand("urban")
            .Alias("urbandictionary")
            .Alias("ud")
            .Parameter("phrase", Commands.ParameterType.Unparsed)
            .Description("I'll give you the urban dictionary definition of a phrase.")
            .Do(e => lookup_cmd(e, args =>
            {
                var req = new RestRequest("define", Method.GET);
                req.AddQueryParameter("term", args);
                var resp = JObject.Parse(Helpers.GetRestClient("http://api.urbandictionary.com/v0").Execute(req).Content)["list"][0];
                return($"{resp["word"]}: {resp["definition"]}\n⬆{resp["thumbs_up"]} ⬇{resp["thumbs_down"]} <{resp["permalink"]}>```{resp["example"]}```");
            }));

            if (Helpers.FieldExists("WolframAlpha", "appid"))
            {
                group.CreateCommand("wolfram")
                .Parameter("input", Commands.ParameterType.Unparsed)
                .Description("I'll look something up for you on ")
                .Do(e => lookup_cmd(e, args =>
                {
                    var rc = Helpers.GetRestClient("http://api.wolframalpha.com/v2/");     // TODO: Do we want this static?
                    rc.AddDefaultParameter("appid", Program.config["WolframAlpha"]["appid"]);
                    var req = new RestRequest("query", Method.GET);
                    req.AddQueryParameter("input", args);
                    string ret = "";
                    var json   = Helpers.XmlToJson(rc.Execute(req).Content)["queryresult"];
                    if (!json["@success"].ToObject <bool>())
                    {
                        const string didyoumeans = "didyoumeans";
                        if (Helpers.FieldExists(json, didyoumeans))
                        {
                            ret      += "Perhaps you meant";
                            json      = json[didyoumeans];
                            int count = json["@count"].ToObject <int>();
                            Func <JToken, string> format_suggestion = suggestion => $" `{suggestion["#text"]}`";
                            json = json["didyoumean"];
                            if (count == 1)
                            {
                                ret += format_suggestion(json);
                            }
                            else
                            {
                                for (int i = 0; i < count; ++i)
                                {
                                    ret += (i == 0 ? "" : i == count - 1 ? ", or " : ",") + format_suggestion(json[i]);
                                }
                            }
                            ret += '?';
                        }
                        else
                        {
                            ret = "Sorry, I couldn't find anything for your input.";
                        }
                    }
                    else
                    {
                        json = json["pod"];
                        for (int i = 0; i != 4 && i < json.Count(); ++i)     // Show the first four results
                        {
                            ret += $"{json[i]["subpod"]["img"]["@src"]}\n";
                        }
                    }
                    return(ret);
                }));
            }

            group.CreateCommand("quote")
            .Description("I'll give you a random quote from https://inspiration.julxzs.website/quotes")
            .Do(async e =>
            {
                var result = JObject.Parse(Helpers.GetRestClient("https://inspiration.julxzs.website").Execute <JObject>(new RestRequest("api/quote", Method.GET)).Content)["quote"];
                await e.Channel.SendMessage($"\"{result["quote"]}\" - {result["author"]} {result["date"]}");
            });

            group.CreateCommand("8ball")
            .Parameter("question", Commands.ParameterType.Optional)
            .Parameter("?", Commands.ParameterType.Multiple)
            .Description("The magic eightball can answer any question!")
            .Do(async e =>
            {
                // TODO: Decide if we want to load this will all the other response commands, if so this check could be bypassed
                // Note: We'd also need to put all responses in asterisks.
                if (!string.Join(" ", e.Args).EndsWith("?"))
                {
                    await e.Channel.SendMessage("You must ask a proper question!");
                    return;
                }
                string[] eightball =
                {
                    "It is certain.",             "It is decidedly so.",   "Without a doubt.",
                    "Yes, definitely.",           "You may rely on it.",   "As I see it, yes.",           "Most likely.",          "Outlook good.",
                    "Yes.",                       "Signs point to yes.",   "Reply hazy try again...",     "Ask again later...",
                    "Better not tell you now...", "Cannot predict now...", "Concentrate and ask again...",
                    "Don't count on it.",         "My reply is no.",       "My sources say no.",          "Outlook not so good.",
                    "Very doubtful.",             "Nyas.",                 "Why not?",                    "zzzzz...",              "No."
                };
                await e.Channel.SendMessage($"*{Helpers.Pick(eightball)}*");
            });

            AddResponseCommands(group, "response_commands.json");
            AddResponseCommands(group, "custom_response_commands.json");

            group.CreateCommand("say")
            .Alias("forward")
            .Alias("echo")
            .Parameter("[#channel or @User (or user/channel id in PMs)] text...", Commands.ParameterType.Unparsed)
            .Description("I'll repeat what you said. (To a given user or channel)")
            .Do(async e =>
            {
                Channel channel = e.Channel;
                string message  = e.Args[0];
                if (message.Length == 0)
                {
                    return;                          // Unparsed can be empty
                }
                message = e.Message.MentionedChannels.Aggregate(
                    e.Message.MentionedUsers.Aggregate(message, (m, u) => m.Replace($"@{u.Name}", u.Mention)),
                    (m, c) => m.Replace($"#{c.Name}", c.Mention));

                bool usermention = e.Message.MentionedUsers.Count() > (e.Message.IsMentioningMe() ? 1 : 0) && message.StartsWith("<@");
                if (usermention || (e.Message.MentionedChannels.Any() && message.StartsWith("<#")))
                {
                    int index = message.IndexOf(">");
                    if (index + 2 < message.Length)
                    {
                        ulong mentionid = Convert.ToUInt64(message.Substring(2, index - 2));
                        if (mentionid != e.Server.CurrentUser.Id)
                        {
                            channel = usermention ? await e.Message.MentionedUsers.First(u => u.Id == mentionid).CreatePMChannel()
                                    : e.Message.MentionedChannels.First(c => c.Id == mentionid);
                            if (Helpers.CanSay(ref channel, e.User, e.Channel))
                            {
                                message = message.Substring(index + 2);
                            }
                        }
                    }
                }
                else if (channel.IsPrivate)
                {
                    try
                    {
                        var index = message.IndexOf(' ');
                        if (index != -1 && index + 2 < message.Length)
                        {
                            channel = await Program.GetChannel(Convert.ToUInt64(message.Substring(0, index)));
                            if (Helpers.CanSay(ref channel, e.User, e.Channel))
                            {
                                message = message.Substring(index + 1);
                            }
                        }
                    } catch { }
                }
                if (message.TrimEnd() != "")
                {
                    await channel.SendMessage(message);
                }
            });

            group.CreateCommand("reverse")
            .Alias("backward")
            .Alias("flip")
            .Parameter("text...", Commands.ParameterType.Unparsed)
            .Description("I'll repeat what you said, in reverse!")
            .Do(async e =>
            {
                var text = e.Args[0];
                if (text.Length != 0)
                {
                    await e.Channel.SendMessage(string.Join("", Helpers.GraphemeClusters(text).Reverse().ToArray()));
                }
            });

            group.CreateCommand("whereami")
            .Alias("channelinfo")
            .Alias("channel")
            .Alias("location")
            .Alias("where")
            .Description("I'll tell you information about the channel and server you're asking me this from.")
            .Do(async e =>
            {
                if (e.Channel.IsPrivate)
                {
                    await e.Channel.SendMessage("You're in a private message with me, baka.");
                }
                else
                {
                    string message = $@"You are currently in {e.Channel.Name} (id: {e.Channel.Id})
on server **{e.Server.Name}** (id: {e.Server.Id}) (region: {e.Server.Region.Name} (id: {e.Server.Region.Id}))
owned by {e.Server.Owner.Name} (id: {e.Server.Owner.Id}).";
                    if (e.Channel.Topic != "" || e.Channel.Topic != null)
                    {
                        message = message + $@"
The current topic is: {e.Channel.Topic}";
                    }
                    await e.Channel.SendMessage(message);
                }
            });

            group.CreateCommand("avatar")
            .Parameter("[@User1] [@User2] [...]", Commands.ParameterType.Unparsed)
            .Description("I'll give you the avatars of every mentioned users.")
            .Do(async e =>
            {
                if (e.Args[0].Length == 0)
                {
                    return;
                }
                foreach (User u in e.Message.MentionedUsers)
                {
                    await e.Channel.SendMessage(u.Mention + (u.AvatarUrl == null ? " has no avatar." : $"'s avatar is: {u.AvatarUrl}"));
                }
            });

            group.CreateCommand("lastlog")
            .Parameter("few (default 4)", Commands.ParameterType.Optional)
            .Parameter("string to search for (case-sensitive)", Commands.ParameterType.Unparsed)
            .Description("I'll search for and return the last `few` messages in this channel with your search string in them (This may take a while, depending on history size and `few`)")
            .Do(async e =>
            {
                var args = e.Args;
                if (!Helpers.HasArg(args))
                {
                    await e.Channel.SendMessage("Just read the last messages yourself, baka!");
                }
                else
                {
                    int few = 4;
                    if (Helpers.HasArg(args, 1))
                    {
                        if (int.TryParse(args[0], out few))
                        {
                            if (few <= 0)
                            {
                                await e.Channel.SendMessage("You're silly!");
                                return;
                            }
                            args = args.Skip(1).ToArray();
                        }
                        else
                        {
                            few = 4;
                        }
                    }

                    var search = string.Join(" ", args).TrimEnd();
                    var found  = new List <Message>();
                    await Helpers.DoToMessages(e.Channel, few, (msgs, has_cmd_msg) =>
                    {
                        found.AddRange(has_cmd_msg ? msgs.Where(s => s.Id != e.Message.Id && s.Text.Contains(search)) : msgs.Where(s => s.Text.Contains(search)));
                        return(found.Count());
                    });

                    if ((few = Math.Min(found.Count(), few)) == 0)
                    {
                        await e.Channel.SendMessage("None found...");
                    }
                    else
                    {
                        foreach (var msg in found.Take(few))
                        {
                            var extradata = $"[{msg.Timestamp}]{msg.User.Name}:";
                            // If the message would reach the max if we add extra data, send that separate.
                            if (msg.RawText.Length + extradata.Length >= 1999)
                            {
                                await e.Channel.SendMessage(extradata);
                                await e.Channel.SendMessage(msg.RawText);
                            }
                            else
                            {
                                await e.Channel.SendMessage($"{extradata} {msg.RawText}");
                            }
                        }
                    }
                }
            });

            RPG.AddCommands(group);

            group.CreateCommand("lotto")
            .Description("I'll give you a set of 6 lucky numbers!")
            .Do(async e =>
            {
                List <int> lotto = new List <int>();
                Random rnd       = new Random();
                for (var i = 0; i != 6; ++i)
                {
                    var number = rnd.Next(1, 60);
                    if (!lotto.Contains(number))
                    {
                        lotto.Add(number);
                    }
                }
                await e.Channel.SendMessage($"Your lucky numbers are **{lotto[0]}, {lotto[1]}, {lotto[2]}, {lotto[3]}, {lotto[4]}, {lotto[5]}**.");
            });

            // TODO: Decide if PerformAction commands should be moved to their own json file like response_commands.json
            group.CreateCommand("pet")
            .Alias("pets")
            .Parameter("[@User1] [@User2] [...]", Commands.ParameterType.Unparsed)
            .Description("Everyone loves being pet, right!?! Pets each *@user*. Leave empty (or mention me too) to pet me!")
            .Do(e => Helpers.PerformAction(e, "pet", "*purrs*", false));

            group.CreateCommand("hug")
            .Alias("hugs")
            .Parameter("[@User1] [@User2] [...]", Commands.ParameterType.Unparsed)
            .Description("Hug someone! Hugs each *@user*. Leave empty to get a hug!")
            .Do(e => Helpers.PerformAction(e, "hug", "<3", true));
        }
Exemplo n.º 16
0
        // Commands first to help with adding new commands
        static void GenerateCommands(CommandGroupBuilder group)
        {
            // User commands
            group.CreateCommand("servers")
                .Description("I'll send you statistics about the servers, channels and users (can be spammy, goes to private).")
                .MinPermissions(4)
                .Do(async e =>
                {
                    var output = "";
                    foreach (var server in client.Servers)
                    {
                        output += $"{server.Name}: {server.TextChannels.Count()} text & {server.VoiceChannels.Count()} voice channels, {server.Users.Count()} users. ID: {server.Id}";
                        if (output.Length >= 2000)
                        {
                            var index = output.Length == 2000 ? 0 : output.LastIndexOf('\n');
                            await e.User.SendMessage(Format.Code(index == 0 ? output : output.Substring(0, index)));
                            output = index == 0 ? "" : output.Substring(index+1);
                        }
                        else output += '\n';
                    }
                    if (output.Any()) await e.User.SendMessage(Format.Code(output));
                });

            group.CreateCommand("status")
                .Description("I'll tell you some useful stats about myself.")
                .Do(async e => await e.Channel.SendMessage($"I'm connected to {client.Servers.Count()} servers, which have a total of {client.Servers.SelectMany(x => x.TextChannels).Count()} text and {client.Servers.SelectMany(x => x.VoiceChannels).Count()} voice channels, and see a total of {client.Servers.SelectMany(x => x.Users).Distinct().Count()} different users.\n{Format.Code($"Uptime: {Helpers.Uptime()}\n{Console.Title}")}"));

            group.CreateCommand("version")
                .Description("I'll tell you the current version and check if a newer version is available.")
                .Do(async e =>
                {
                    var version = Config.AppVersion;
                    string[] versions = version.Split('.');
                    string remoteversion = JObject.Parse(Helpers.GetRestClient("https://raw.githubusercontent.com").Execute<JObject>(new RestRequest("Kusoneko/Nekobot/master/version.json", Method.GET)).Content)["version"].ToString();
                    string[] remoteversions = remoteversion.Split('.');
                    int diff;
                    string section =
                        (diff = int.Parse(versions[0]) - int.Parse(remoteversions[0])) != 0 ? $"major version{(Math.Abs(diff) == 1 ? "" : "s")}" :
                        (diff = int.Parse(versions[1]) - int.Parse(remoteversions[1])) != 0 ? $"minor version{(Math.Abs(diff) == 1 ? "" : "s")}" :
                        (diff = int.Parse(versions[2]) - int.Parse(remoteversions[2])) != 0 ? $"patch{(Math.Abs(diff) == 1 ? "" : "es")}" : null;
                    await e.Channel.SendMessage($"I'm {(section == null ? $"up to date! (Current version: {version})" : $"currently {Math.Abs(diff)} {section} {(diff > 0 ? "ahead" : "behind")}. (Current version: {version}, latest {("released ")}version: {remoteversion})")}");
                });

            Common.AddCommands(group);

            group.CreateCommand("playeravatar")
                .Parameter("username1", Commands.ParameterType.Required)
                .Parameter("username2", Commands.ParameterType.Optional)
                .Parameter("username3", Commands.ParameterType.Multiple)
                .Description("I'll get you the avatar of each Player.me username provided.")
                .Do(async e =>
                {
                    var rclient = Helpers.GetRestClient("https://player.me/api/v1/auth");
                    var request = new RestRequest("pre-login", Method.POST);
                    foreach (string s in e.Args)
                    {
                        request.AddQueryParameter("login", s);
                        JObject result = JObject.Parse(rclient.Execute(request).Content);
                        await e.Channel.SendMessage(s + (result["success"].ToObject<bool>() == false
                            ? " was not found." : $"'s avatar: https:{result["results"]["avatar"]["original"]}"));
                    }
                });

            if (config["LastFM"].HasValues)
            {
                lfclient = new LastFM.LastfmClient(config["LastFM"]["apikey"].ToString(), config["LastFM"]["apisecret"].ToString());
                group.CreateCommand("lastfm")
                    .Parameter("username(s)", Commands.ParameterType.Unparsed)
                    .Description("I'll tell you the last thing you, a lastfm user, or users on this server (if I know their lastfm) listened to.")
                    .Do(async e =>
                    {
                        var api = new LastFM.UserApi(lfclient.Auth, lfclient.HttpClient);
                        var users = e.Args[0].Any() ? e.Message.MentionedUsers.Any() ? e.Message.MentionedUsers : null : new[]{e.User};
                        var response = "";
                        if (users == null)
                            response = await GetLastScrobble(api, Tuple.Create(e.Args[0], e.Args[0], false));
                        else foreach (var user in (from u in users select Tuple.Create(SQL.ReadUser(u.Id, "lastfm"), u.Name, u == e.User)))
                            response += (user.Item1 != null ? await GetLastScrobble(api, user)
                                    : $"I don't know {(user.Item3 ? "your" : $"{user.Item2}'s")} lastfm yet{(user.Item3 ? ", please use the `setlastfm <username>` command" : "")}"
                                ) + ".\n";
                        await e.Channel.SendMessage(response);
                    });

                group.CreateCommand("setlastfm")
                    .Parameter("username", Commands.ParameterType.Unparsed)
                    .Description("I'll remember your lastfm username.")
                    .Do(async e =>
                    {
                        var lastfm = e.Args[0];
                        if (lastfm.Any() && lastfm.Length < 16)
                        {
                            lastfm = $"'{lastfm}'";
                            await SQL.AddOrUpdateUserAsync(e.User.Id, "lastfm", lastfm);
                            await e.Channel.SendMessage($"I'll remember your lastfm is {lastfm} now, {e.User.Name}.");
                        }
                        else await e.Channel.SendMessage($"'{lastfm}' is not a valid lastfm username.");
                    });
            }
Exemplo n.º 17
0
 internal static void AddCommands(Commands.CommandGroupBuilder group)
 {
 }
Exemplo n.º 18
0
        internal static void AddCommands(Commands.CommandGroupBuilder group)
        {
            group.CreateCommand("rand")
            .Parameter("min", Commands.ParameterType.Optional)
            .Parameter("max", Commands.ParameterType.Optional)
            .Description("I'll give you a random number between *min* and *max*. Both are optional. If only one is given, it's *max*. (defaults: 1-100)")
            .Do(async e =>
            {
                foreach (string s in e.Args)
                {
                    if (!int.TryParse(s, out int dummy))
                    {
                        await e.Channel.SendMessageAsync($"{s} is not a number!");
                        return;
                    }
                }
                int min = e.Args.Length > 1 ? int.Parse(e.Args[0]) : 1;
                int max = e.Args.Length > 0 ? int.Parse(e.Args[e.Args.Length == 1 ? 0 : 1]) : 100;
                if (min == max)
                {
                    await e.Channel.SendMessageAsync($"You're joking right? It's {min}.");
                    return;
                }
                if (min > max)
                {
                    int z = min;
                    min   = max;
                    max   = z;
                }
                await e.Channel.SendMessageAsync($"Your number is **{new Random().Next(min,max+1)}**.");
            });

            var dk = new DiceKernel().Init();
            var dd = dk.Get <Dice>();

            group.CreateCommand("roll")
            .Parameter("[times]t [dice expressions]", Commands.ParameterType.Unparsed)
            .Description("I'll roll a dice expression([count]d[sides]k[kept][mods...]...) as many `times` as you ask(default 1). (If empty or just `times`, will roll default: 1d6.)")
            .Do(async e =>
            {
                var chan = e.Channel;
                if (e.Args[0].ToLower() == "rick")
                {
                    await chan.SendMessageAsync("https://youtu.be/dQw4w9WgXcQ");
                    return;
                }
                var args = string.Join(" ", e.Args);
                int times;
                if ((times = args.IndexOf("t")) != -1)
                {
                    int t = times;
                    if (int.TryParse(args.Substring(0, t), out times))
                    {
                        if (times <= 0)
                        {
                            await chan.SendMessageAsync($"0, baka!");
                            return;
                        }
                        args = args.Substring(t + 1);
                    }
                    else
                    {
                        times = 1;
                    }
                }
                else
                {
                    times = 1;
                }

                string response = "";
                double?total    = times > 1 ? (int?)0 : null;
                bool do_default = args.Length == 0;     // Default roll.
                for (; times != 0; --times)
                {
                    double val;
                    if (do_default)
                    {
                        val       = dd.Roll().d6().AsSum();
                        response += $"{val} {(total == null ? "" : times == 1 ? "=" : "+")} ";
                    }
                    else
                    {
                        try
                        {
                            var roll = dd.ReplaceRollsWithSumExpression(args);
                            var eval = dk.Get <IParser>().Compile(roll).EvalValue(null);
                            val      = Utils.ChangeType <double>(eval);
                            if (response != "")
                            {
                                response += '\n';
                            }
                            var str = Utils.BooleanOrType <double>(eval);
                            if (roll != str)
                            {
                                response += $"{Discord.Format.Code(roll)} = ";
                            }
                            response += $"**{str}**.";
                        }
                        catch (Exception ex)
                        {
                            await chan.SendMessageAsync($"Invalid Arguments: {ex.Message}");
                            return;
                        }
                    }
                    if (total != null)
                    {
                        total += val;
                    }
                }
                if (total != null)
                {
                    if (!do_default)
                    {
                        response += "\nTotal Result = ";
                    }
                    response += $"**{total}**.";
                }
                await chan.SendMessageAsync(response);
            });

            group.CreateCommand("rollsentence")
            .Parameter("[sentence]", Commands.ParameterType.Unparsed)
            .Description("I'll replace all instances of dice expressions wrapped like {1d4} with their resolutions. (see ` help roll` for info on dice expressions)")
            .Do(async e => await e.Channel.SendMessageAsync(e.Args[0].Length == 0 ? "" : dd.ReplaceWrappedExpressions <double>(e.Args[0])));
        }
Exemplo n.º 19
0
 static Commands.CommandBuilder CreatePLCmd(Commands.CommandGroupBuilder group, string name, string parameter, string description, string[] aliases = null) => CreatePLCmd(group, name, description, aliases).Parameter(parameter, Commands.ParameterType.Unparsed);
Exemplo n.º 20
0
 public void CreatePermalinkCmd(Commands.CommandGroupBuilder group, string name, string alias, bool is_playlist) => CreatePermalinkCmd(group, name, new[] { alias }, is_playlist);
Exemplo n.º 21
0
        internal static void AddCommands(Commands.CommandGroupBuilder group)
        {
            group.CreateCommand("ping")
            .Description("I'll reply with 'Pong!'")
            .Do(e => e.Channel.SendMessageAsync($"{e.User.Mention}, Pong!{DoPing(e.Message)}"));

            group.CreateCommand("pong")
            .Hide()     // More of an easter egg, don't show in help.
            .Description("I'll reply with 'Ping?'")
            .Do(e => e.Channel.SendMessageAsync($"{e.User.Mention}, Ping?{DoPing(e.Message)}"));

            group.CreateCommand("uptime")
            .Description("I'll tell you how long I've been awake~")
            .Do(e => e.Channel.SendMessageAsync(Format.Code(Helpers.Uptime().ToString())));

            EmbedFieldBuilder role_info(SocketRole r)
            {
                string ret = $"ID is {r.Id}, has {r.Members.Count()} members, color is {r.Color}, perms are {r.Permissions.RawValue}, and position is {r.Position}";

                if (r.IsManaged)
                {
                    ret += "; it is managed by the server";
                }
                ret += $"\nIt was created on {r.CreatedAt}";
                return(new EmbedFieldBuilder().WithName(r.Name).WithValue(ret));
            }

            group.CreateCommand("whois")
            .Alias("getinfo")
            .Parameter("[@User1] [@User2] [...]", Commands.ParameterType.Unparsed)
            .Description("I'll give you information about the mentioned user(s).")
            .Do(async e =>
            {
                if (e.Args[0].Length == 0 || (!e.Message.MentionedUserIds.Any() && !e.Message.MentionedRoleIds.Any()))
                {
                    return;
                }
                bool oniicheck = e.User.Id == 63299786798796800;
                var embed      = Helpers.EmbedDesc("WhoIs Response");
                async Task <IUserMessage> send() => await e.Channel.SendMessageAsync(embed: embed.Build());
                foreach (var t in e.Message.Tags)
                {
                    if (embed.Fields.Count == EmbedBuilder.MaxFieldCount)
                    {
                        await send();
                        embed.Fields.Clear();
                    }
                    switch (t.Type)
                    {
                    case TagType.RoleMention:
                        embed.AddField(role_info(t.Value as SocketRole));
                        break;

                    case TagType.UserMention:
                        var u             = t.Value as IGuildUser;
                        bool onii         = oniicheck && u.Id == 63296013791666176;
                        string possessive = onii ? "His" : "Their";
                        string pronoun    = onii ? "He" : "They";
                        var field         = new EmbedFieldBuilder();
                        string reply      = string.Empty;
                        if (onii)
                        {
                            reply += "is your onii-chan <3\n";
                        }
                        if (!string.IsNullOrEmpty(u.Nickname))
                        {
                            reply += $"Nick: {u.Nickname}\n";
                        }
                        reply += $"ID: {u.Id}\n{possessive} discriminator is {u.Discriminator}. {possessive} permission level is {Helpers.GetPermissions(u, e.Channel)}.";
                        reply += $"\n{pronoun} joined Discord on {u.CreatedAt}.\n{pronoun} joined this server on {u.JoinedAt}.\n";
                        if (u.IsBot)
                        {
                            reply += $" {pronoun} are also a bot!";
                        }
                        reply += $" {possessive} status is {u.Status}.\n";
                        if (u.Activity != null)
                        {
                            reply += $"\n{pronoun} {(onii ? "is" : "are")} {u.Activity.Type} {u.Activity.Name}.";
                        }
                        if (u.VoiceChannel != null)
                        {
                            reply += $"Current voice channel: {u.VoiceChannel.Name}";
                        }
                        embed.AddField(u.Username, reply);
                        break;
                    }
                }
                if (embed.Fields.Count != 0)
                {
                    await send();
                }
            });

            group.CreateCommand("whois role")
            .Alias("getinfo role")
            .Parameter("role(s)", Commands.ParameterType.Unparsed)
            .Description("I'll give you info on particular roles by name (comma separated)")
            .Do(e =>
            {
                string reply = "";
                if (e.Args[0].Length == 0)
                {
                    reply = "You need to provide at least one role name!";
                }
                else
                {
                    Helpers.CommaSeparateRoleNames(e, (roles, str) =>
                    {
                        foreach (var r in roles)
                        {
                            reply += role_info(r);
                        }
                    });
                }
                e.Channel.SendMessageAsync(reply);
            });

            Music.AddCommands(group);

            Image.AddCommands(group);

            Func <Commands.CommandEventArgs, Task <bool> > lookup_nothing = async e =>
            {
                var args = e.Args[0];
                if (args.Length == 0)
                {
                    await Helpers.SendEmbed(e, Helpers.EmbedDesc("I cannot lookup nothing, silly!"));

                    return(true);
                }
                return(false);
            };

            group.CreateCommand("urban")
            .Alias("urbandictionary")
            .Alias("ud")
            .Parameter("phrase", Commands.ParameterType.Unparsed)
            .Description("I'll give you the urban dictionary definition of a phrase.")
            .Do(async e =>
            {
                if (await lookup_nothing(e))
                {
                    return;
                }
                var req = new RestRequest("define", Method.GET);
                req.AddQueryParameter("term", e.Args[0]);
                var json = JObject.Parse(Helpers.GetRestClient("http://api.urbandictionary.com/v0").Execute(req).Content);
                var list = json["list"];
                if (!list.HasValues)
                {
                    await Helpers.SendEmbed(e, Helpers.EmbedDesc("No results found."));
                    return;
                }
                var resp  = list[0];
                var embed = Helpers.EmbedDesc(resp["definition"].ToString())
                            .WithTitle(resp["word"].ToString())
                            .WithUrl(resp["permalink"].ToString())
                            .WithFooter($"⬆{resp["thumbs_up"]} ⬇{resp["thumbs_down"]}")
                            .WithTimestamp(DateTime.Parse(resp["written_on"].ToString(), null, System.Globalization.DateTimeStyles.RoundtripKind))
                            .AddField("Example", resp["example"]);
                var sounds = resp["sound_urls"];
                if (sounds.HasValues)
                {
                    embed.AddField(sounds.Count() > 1 ? "Sounds" : "Sound", string.Join("\n", sounds));     // I wish we could embed just one of these and have an audio player, but this works too.
                }
                await Helpers.SendEmbed(e, embed);
            });

            if (Helpers.FieldExists("WolframAlpha", "appid"))
            {
                group.CreateCommand("wolfram")
                .Parameter("input", Commands.ParameterType.Unparsed)
                .Description("I'll look something up for you on WolframAlpha")
                .Do(async e =>
                {
                    if (await lookup_nothing(e))
                    {
                        return;
                    }
                    var rc = Helpers.GetRestClient("http://api.wolframalpha.com/v2/");     // TODO: Do we want this static?
                    rc.AddDefaultParameter("appid", Program.config["WolframAlpha"]["appid"]);
                    var req = new RestRequest("query", Method.GET);
                    req.AddQueryParameter("input", e.Args[0]);
                    var json = Helpers.XmlToJson(rc.Execute(req).Content)["queryresult"];
                    if (!json["@success"].ToObject <bool>())
                    {
                        const string didyoumeans = "didyoumeans";
                        if (Helpers.FieldExists(json, didyoumeans))
                        {
                            var embed  = Helpers.EmbedBuilder.WithTitle("Perhaps you meant");
                            json       = json[didyoumeans];
                            int count  = json["@count"].ToObject <int>();
                            string ret = "";
                            Func <JToken, string> format_suggestion = suggestion => $" `{suggestion["#text"]}`";
                            json = json["didyoumean"];
                            if (count == 1)
                            {
                                ret += format_suggestion(json);
                            }
                            else
                            {
                                for (int i = 0; i < count; ++i)
                                {
                                    ret += (i == 0 ? "" : i == count - 1 ? ", or " : ",") + format_suggestion(json[i]);
                                }
                            }
                            ret += '?';
                            await Helpers.SendEmbed(e, embed.WithDescription(ret.TrimStart()));
                        }
                        await Helpers.SendEmbed(e, Helpers.EmbedDesc("Sorry, I couldn't find anything for your input."));
                    }
                    else
                    {
                        int show   = 4;   // Show the first four results
                        json       = json["pod"];
                        string ret = "";
                        //var embed = Helpers.EmbedBuilder.WithTitle($"Results for {e.Args}");
                        for (int i = 0, count = json.Count(); show != 0 && i < count; ++i)
                        {
                            var pod        = json[i];
                            int numsubpods = pod["@numsubpods"].ToObject <int>();
                            if (numsubpods == 1)
                            {
                                ret += $"{pod["subpod"]["img"]["@src"]}\n";
                                --show;
                            }
                            else
                            {
                                for (int j = 0; show != 0 && j < numsubpods; ++j, --show)
                                {
                                    ret += $"{pod["subpod"][j]["img"]["@src"]}\n";
                                }
                            }
                        }
                        await e.Channel.SendMessageAsync(ret);
                        //await Helpers.SendEmbed(e, embed.WithDescription(ret)); // I don't know how this would look good, at this point.
                    }
                });
            }

            var quote_site = "http://bacon.mlgdoor.uk/";

            group.CreateCommand("quote")
            .Description($"I'll give you a random quote from {quote_site}quotes")
            .Do(async e =>
            {
                var result = JObject.Parse(Helpers.GetRestClient(quote_site).Execute <JObject>(new RestRequest("api/v1/quotes/random", Method.GET)).Content)["quotes"][0];
                await e.Channel.SendMessageAsync($"\"{result["quote"]}\" - {result["author"]} {result["year"]}");
            });

            Func <string, string, string, string> add_quote = (quote, author, year) =>
            {
                var result = JObject.Parse(Helpers.GetRestClient(quote_site)
                                           .Execute <JObject>(new RestRequest("api/v1/quotes", Method.POST)
                                                              .AddParameter("quote", quote)
                                                              .AddParameter("author", author)
                                                              .AddParameter("year", year))
                                           .Content);
                return(result["success"].ToObject <bool>() ? "Quote added." : $"Adding quote failed: {result["data"]}");
            };

            group.CreateCommand("addquote")
            .Parameter("<quote>|<author>[|year]", Commands.ParameterType.MultipleUnparsed)
            .Description($"I'll add a quote to {quote_site}quotes, mentions will be garbage text in this.")
            .Do(async e =>
            {
                // TODO: Resolve mentions?
                var args = string.Join(" ", e.Args).Split('|');
                if (args.Length < 2)
                {
                    await e.Channel.SendMessageAsync("I need a quote and its author, silly!");
                    return;
                }
                await e.Channel.SendMessageAsync(add_quote(args[0], args[1], args.Length == 2 ? DateTime.Now.Year.ToString() : args[2]));
            });
            group.CreateCommand("quotemessage")
            .Parameter("messageid", Commands.ParameterType.Required)
            .Description($"I'll add a message from this channel as a quote on {quote_site}quotes, mentions will be resolved.")
            .Do(async e =>
            {
                IMessage message = await e.Channel.GetMessageAsync(Convert.ToUInt64(e.Args[0]));
                if (message == null)     // It's missing, report failure.
                {
                    await e.Channel.SendMessageAsync("Sorry, I couldn't find that message!");
                    return;
                }
                await e.Channel.SendMessageAsync(add_quote(Helpers.ResolveTags(message), Helpers.Nickname(message.Author as SocketGuildUser), message.Timestamp.Date.ToShortDateString()));
            });

            Google.AddCommands(group);

            group.CreateCommand("8ball")
            .Parameter("question", Commands.ParameterType.Optional)
            .Parameter("?", Commands.ParameterType.Multiple)
            .Description("The magic eightball can answer any question!")
            .Do(async e =>
            {
                // TODO: Decide if we want to load this will all the other response commands, if so this check could be bypassed
                // Note: We'd also need to put all responses in asterisks.
                if (!string.Join(" ", e.Args).EndsWith("?"))
                {
                    await e.Channel.SendMessageAsync("You must ask a proper question!");
                    return;
                }
                string[] eightball =
                {
                    "It is certain.",             "It is decidedly so.",   "Without a doubt.",
                    "Yes, definitely.",           "You may rely on it.",   "As I see it, yes.",           "Most likely.",          "Outlook good.",
                    "Yes.",                       "Signs point to yes.",   "Reply hazy try again...",     "Ask again later...",
                    "Better not tell you now...", "Cannot predict now...", "Concentrate and ask again...",
                    "Don't count on it.",         "My reply is no.",       "My sources say no.",          "Outlook not so good.",
                    "Very doubtful.",             "Nyas.",                 "Why not?",                    "zzzzz...",              "No."
                };
                await e.Channel.SendMessageAsync($"*{Helpers.Pick(eightball)}*");
            });

            AddResponseCommands(group, "response_commands.json");
            AddResponseCommands(group, "custom_response_commands.json");

            group.CreateCommand("say")
            .Alias("forward")
            .Alias("echo")
            .Parameter("[#channel or @User (or user/channel id in PMs)] text...", Commands.ParameterType.Unparsed)
            .Description("I'll repeat what you said. (To a given user or channel)")
            .Do(async e =>
            {
                IMessageChannel channel = e.Channel;
                string message          = e.Args[0];
                if (message.Length == 0)
                {
                    return;                          // Unparsed can be empty
                }

                /* Liru Note: I don't think we have to do this anymore.
                 * message = e.Message.MentionedChannels.Aggregate(
                 *  e.Message.MentionedUsers.Aggregate(message, (m, u) => m.Replace($"@{u.Name}", u.Mention)),
                 *  (m, c) => m.Replace($"#{c.Name}", c.Mention));
                 */

                if (message.StartsWith("<@") || message.StartsWith("<#"))
                {
                    bool selfmention = e.Message.MentionedUserIds.Contains(Program.Self.Id);
                    var tag          = e.Message.Tags.Skip(selfmention ? 1 : 0).FirstOrDefault();
                    var usermention  = tag.Type == TagType.UserMention;
                    if (tag != null && (usermention || tag.Type == TagType.ChannelMention))
                    {
                        // FIXME: This will fail in some cases, like mentioning a channel way later... we should check the mention is directly after, aside from spacing
                        int index = message.IndexOf('>', selfmention ? message.IndexOf('>') : 0);
                        if (index + 2 < message.Length)
                        {
                            ulong mentionid = tag.Key;
                            if (mentionid != Program.client.CurrentUser.Id)
                            {
                                channel = usermention ? await(tag.Value as IUser).GetOrCreateDMChannelAsync() : tag.Value as IMessageChannel;
                                if (Helpers.CanSay(ref channel, await channel.GetUserAsync(e.User.Id), e.Channel))
                                {
                                    message = message.Substring(index + 2);
                                }
                            }
                        }
                    }
                }
                else if (channel is IPrivateChannel)
                {
                    try
                    {
                        var index = message.IndexOf(' ');
                        if (index != -1 && index + 2 < message.Length)
                        {
                            channel = await Program.GetChannel(Convert.ToUInt64(message.Substring(0, index)));
                            if (Helpers.CanSay(ref channel, (IGuildUser)channel.GetUserAsync(e.User.Id), e.Channel))
                            {
                                message = message.Substring(index + 1);
                            }
                        }
                    } catch { }
                }
                if (message.TrimEnd() != "")
                {
                    await channel.SendMessageAsync(message);
                }
            });

            group.CreateCommand("reverse")
            .Alias("backward")
            .Alias("flip")
            .Parameter("text...", Commands.ParameterType.Unparsed)
            .Description("I'll repeat what you said, in reverse!")
            .Do(async e =>
            {
                var text = e.Args[0];
                if (text.Length != 0)
                {
                    await e.Channel.SendMessageAsync(string.Join("", Helpers.GraphemeClusters(text).Reverse().ToArray()));
                }
            });

            group.CreateCommand("whereami")
            .Alias("channelinfo")
            .Alias("channel")
            .Alias("location")
            .Alias("where")
            .Description("I'll tell you information about the channel and server you're asking me this from.")
            .Do(async e =>
            {
                if (e.Channel is IPrivateChannel)
                {
                    await e.Channel.SendMessageAsync("You're in a private message with me, baka.");
                }
                else
                {
                    var owner      = await e.Server.GetOwnerAsync();
                    var chan       = e.Channel as ITextChannel;
                    string message = $@"You are currently in {e.Channel.Name} (id: {e.Channel.Id})
on server **{e.Server.Name}** (id: {e.Server.Id}) (region: {Program.client.GetVoiceRegion(e.Server.VoiceRegionId).Name} (id: {e.Server.VoiceRegionId}))
owned by {owner.Nickname ?? owner.Username} (id: {e.Server.OwnerId}).";
                    if (!string.IsNullOrEmpty(chan.Topic))
                    {
                        message = message + $@"
The current topic is: {chan.Topic}";
                    }
                    await e.Channel.SendMessageAsync(message);
                }
            });

            group.CreateCommand("avatar")
            .Parameter("[@User1] [@User2] [...]", Commands.ParameterType.Unparsed)
            .Description("I'll give you the avatars of every mentioned users.")
            .Do(async e =>
            {
                if (e.Args[0].Length == 0)
                {
                    return;
                }
                foreach (var t in e.Message.Tags)
                {
                    if (t.Type == TagType.UserMention)
                    {
                        var u   = t.Value as IUser;
                        var url = u.GetAvatarUrl();
                        await e.Channel.SendMessageAsync(u.Mention + (url == null ? " has no avatar." : $"'s avatar is: {url.Substring(0, url.LastIndexOf('?'))}"));
                    }
                }
            });

            group.CreateCommand("lastlog")
            .Parameter("few (default 4)", Commands.ParameterType.Optional)
            .Parameter("string to search for (case-sensitive)", Commands.ParameterType.Unparsed)
            .Description("I'll search for and return the last `few` messages in this channel with your search string in them (This may take a while, depending on history size and `few`)")
            .Do(async e =>
            {
                var args = e.Args;
                if (!Helpers.HasArg(args))
                {
                    await e.Channel.SendMessageAsync("Just read the last messages yourself, baka!");
                }
                else
                {
                    int few = 4;
                    if (Helpers.HasArg(args, 1))
                    {
                        if (int.TryParse(args[0], out few))
                        {
                            if (few <= 0)
                            {
                                await e.Channel.SendMessageAsync("You're silly!");
                                return;
                            }
                            args = args.Skip(1).ToArray();
                        }
                        else
                        {
                            few = 4;
                        }
                    }

                    var search = string.Join(" ", args).TrimEnd();
                    var found  = new List <IMessage>();
                    await Helpers.DoToMessages((e.Channel as SocketTextChannel), few, (msgs, has_cmd_msg) =>
                    {
                        Func <IMessage, bool> find = s => Helpers.ResolveTags(s).Contains(search);
                        found.AddRange(has_cmd_msg ? msgs.Where(s => s.Id != e.Message.Id && find(s)) : msgs.Where(find));
                        return(found.Count());
                    });

                    if ((few = Math.Min(found.Count(), few)) == 0)
                    {
                        await e.Channel.SendMessageAsync("None found...");
                    }
                    else
                    {
                        foreach (var msg in found.Take(few))
                        {
                            var extradata = $"[[{msg.Timestamp}]({msg.GetJumpUrl()})]{msg.Author.Username}:";
                            //if (msg.Content.Length > EmbedBuilder.MaxDescriptionLength) // This should never happen, unless we decide to start searching embeds.
                            {
                                var builder = Helpers.EmbedBuilder;
                                builder.WithTimestamp(msg.Timestamp).WithDescription(msg.Content);
                                builder.WithTitle($"{msg.Author.ToString()}'s message").WithUrl(msg.GetJumpUrl());
                                await e.Channel.SendMessageAsync(embed: builder.Build());
                            }
                            //else await e.Channel.SendMessageAsync($"Content too long to show, message here: <{msg.GetJumpUrl()}>");
                        }
                    }
                }
            });

            RPG.AddCommands(group);

            group.CreateCommand("lotto")
            .Description("I'll give you a set of 6 lucky numbers!")
            .Do(async e =>
            {
                List <int> lotto = new List <int>();
                Random rnd       = new Random();
                for (var i = 0; i != 6; ++i)
                {
                    var number = rnd.Next(1, 60);
                    if (!lotto.Contains(number))
                    {
                        lotto.Add(number);
                    }
                }
                await e.Channel.SendMessageAsync($"Your lucky numbers are **{lotto[0]}, {lotto[1]}, {lotto[2]}, {lotto[3]}, {lotto[4]}, {lotto[5]}**.");
            });

            // TODO: Decide if PerformAction commands should be moved to their own json file like response_commands.json
            group.CreateCommand("pet")
            .Alias("pets")
            .Parameter("[@User1] [@User2] [...]", Commands.ParameterType.Unparsed)
            .Description("Everyone loves being pet, right!?! Pets each *@user*. Leave empty (or mention me too) to pet me!")
            .Do(e => Helpers.PerformAction(e, "pet", "*purrs*", false));

            group.CreateCommand("hug")
            .Alias("hugs")
            .Parameter("[@User1] [@User2] [...]", Commands.ParameterType.Unparsed)
            .Description("Hug someone! Hugs each *@user*. Leave empty to get a hug!")
            .Do(e => Helpers.PerformAction(e, "hug", "<3", true));
        }
Exemplo n.º 22
0
        internal static void AddCommands(Commands.CommandGroupBuilder group)
        {
            group.CreateCommand("playlist")
            .Description("I'll give you the list of songs in the playlist.")
            .FlagMusic(true)
            .Do(e => e.Channel.SendMessage(playlist[e.User.VoiceChannel.Id].SongList()));

            group.CreateCommand("songcount")
            .Alias("playlist size")
            .FlagMusic(true)
            .Do(e => e.Channel.SendMessage(playlist[e.User.VoiceChannel.Id].SongCount()));

            group.CreateCommand("song")
            .Description("I'll tell you the song I'm currently playing.")
            .FlagMusic(true)
            .Do(e => e.Channel.SendMessage(playlist[e.User.VoiceChannel.Id].CurrentSong()));

            YT.CreateCommand(group, "ytrequest");

            if (Program.config["SoundCloud"].HasValues)
            {
                SC sc = new SC(Program.config["SoundCloud"]["client_id"].ToString(), Console.Title);
                sc.CreateSearchCmd(group, "scsearch", "scs", false);
                sc.CreateSearchCmd(group, "scsrandom", "scsr", false, SC.SearchType.Random);
                sc.CreateSearchCmd(group, "scsall", new[] { "scsmultiple", "scsa", "scsmulti" }, false, SC.SearchType.Multiple);
                sc.CreatePermalinkCmd(group, "screquest", new[] { "sctrack", "sctr" }, false);
                sc.CreatePermalinkCmd(group, "scplaylist", "scpl", true);
                sc.CreateSearchCmd(group, "scplsearch", "scpls", true);
                sc.CreateSearchCmd(group, "scplsrandom", "scplsr", true, SC.SearchType.Random);
                sc.CreateSearchCmd(group, "scplsall", new[] { "scplsmultiple", "scplsa", "scplsm" }, true, SC.SearchType.Multiple);
            }

            if (HasFolder())
            {
                Local.CreateCommand(group, "request", false /*, false*/);
                Local.CreateCommand(group, "requestall", true /*, false*/);
                //Local.CreateCommand(group, "requestpl", false, true);
                //Local.CreateCommand(group, "requestplall", true, true);
            }

            group.CreateCommand("skip")
            .Description("Vote to skip the current song. (Will skip at 50% or more)")
            .FlagMusic(true)
            .Do(e => playlist[e.User.VoiceChannel.Id].Skip(e));

            group.CreateCommand("reset")
            .Description("Vote to reset the stream. (Will reset at 50% or more)")
            .FlagMusic(true)
            .Do(e => playlist[e.User.VoiceChannel.Id].Reset(e));

            group.CreateCommand("encore")
            .Alias("replay")
            .Alias("ankoru")
            .Description("Vote to replay the current song. (Will replay at 50% or more)")
            .FlagMusic(true)
            .Do(e => playlist[e.User.VoiceChannel.Id].Encore(e));

            var gestures = Program.config["gestures"].ToString();

            if (gestures != "")
            {
                foreach (var gesture in Files(gestures))
                {
                    var file = Path.GetFileNameWithoutExtension(gesture);
                    group.CreateCommand(file)
                    .FlagMusic(true)
                    .Do(e => streams.Get(e.User.VoiceChannel).QueueGesture(gesture));
                }
                var json = Helpers.GetJsonFileIfExists($"{gestures}/gestures.json");
                if (json != null)
                {
                    foreach (var cmd_data in json)
                    {
                        var val = cmd_data.Value;
                        Helpers.CreateJsonCommand(group, cmd_data.Key, val, cmd =>
                        {
                            var uris = val["uris"].ToObject <string[]>();
                            if (uris.Length == 1)
                            {
                                cmd.Do(e => streams.Get(e.User.VoiceChannel).QueueGesture(GetRealURI(uris[0])));
                            }
                            else
                            {
                                cmd.Do(e => streams.Get(e.User.VoiceChannel).QueueGesture(GetRealURI(Helpers.Pick(uris))));
                            }
                        });
                    }
                }
            }

            // Moderator commands
            group.CreateCommand("setentrancegesture")
            .Alias("setgesture")
            .MinPermissions(1)
            .Parameter("<User mentions>|<entrance gesture>", Commands.ParameterType.Unparsed)
            .Description("I'll set the gesture to play when someone enters my voice channel to whatever's after the `|`.\nHaving nothing after will reset. Gesture can be file uri or youtube link or direct media link.")
            .Do(e =>
            {
                var args = e.Args[0];
                var i    = args.LastIndexOf('|');
                if (i == -1)
                {
                    e.Channel.SendMessage("You need a `|` before the gesture uri");
                    return;
                }
                ++i;
                var entrance_gesture = i == args.Length ? "" : args.Substring(i);
                foreach (var u in e.Message.MentionedUsers)
                {
                    if (entrance_gesture.Length == 0)
                    {
                        EntranceGestures.Remove(u.Id);
                    }
                    else
                    {
                        EntranceGestures[u.Id] = entrance_gesture;
                    }
                    Task.Run(() => SQL.AddOrUpdateUserAsync(u.Id, "entrance_gesture", $"'{entrance_gesture}'"));
                }
            });

            group.CreateCommand("forceskip")
            .MinPermissions(1)
            .Parameter("count", Commands.ParameterType.Optional)
            .FlagMusic(true)
            .Description("I'll skip the currently playing song(s).")
            .Do(e =>
            {
                int count;
                playlist[e.User.VoiceChannel.Id].SkipSongs(e.Args.Any() && int.TryParse(e.Args[0], out count) ? count : 1);
                e.Channel.SendMessage("Forcefully skipping...");
            });

            group.CreateCommand("skiprange")
            .MinPermissions(1)
            .Parameter("index")
            .Parameter("count")
            .FlagMusic(true)
            .Description("I'll forget about `count` upcoming song(s) starting at `index`.")
            .Do(e =>
            {
                int index, count;
                string msg;
                if (int.TryParse(e.Args[0], out index) && int.TryParse(e.Args[1], out count))
                {
                    playlist[e.User.VoiceChannel.Id].SkipRange(index, count);
                    msg = "Forcefully removed songs.";
                }
                else
                {
                    msg = "Invalid input.";
                }
                e.Channel.SendMessage(msg);
            });

            group.CreateCommand("skiplast")
            .MinPermissions(1)
            .Parameter("count", Commands.ParameterType.Optional)
            .FlagMusic(true)
            .Description("I'll forget about the last song(s) currently in the playlist.")
            .Do(e =>
            {
                int count;
                playlist[e.User.VoiceChannel.Id].SkipLastSongs(e.Args.Any() && int.TryParse(e.Args[0], out count) ? count : 1);
                e.Channel.SendMessage("Forcefully removed songs.");
            });

            group.CreateCommand("forcereset")
            .MinPermissions(1)
            .FlagMusic(true)
            .Description("I'll reset the stream in case of bugs, while keeping the playlist intact.")
            .Do(async e =>
            {
                await e.Channel.SendMessage("Reseting stream...");
                await streams.Reset(e.User.VoiceChannel);
            });

            group.CreateCommand("pause")
            .Alias("unpause")
            .MinPermissions(1)
            .FlagMusic(true)
            .Description("I'll toggle pause on the stream")
            .Do(e => playlist[e.User.VoiceChannel.Id].Pause(e));

            group.CreateCommand("repeat")
            .MinPermissions(1)
            .FlagMusic(true)
            .Description("I'll toggle repeat mode on the stream")
            .Do(e => playlist[e.User.VoiceChannel.Id].Repeat(e));

            // Administrator commands
            group.CreateCommand("music")
            .Parameter("on/off", Commands.ParameterType.Required)
            .Description("I'll start or end a stream in a particular voice channel, which you need to be in. (Turning this on will allow you to play gestures as well.)")
            .MinPermissions(2)
            .Do(e =>
            {
                if (e.User.VoiceChannel == null)
                {
                    e.Channel.SendMessage($"{e.User.Mention}, you need to be in a voice channel to use this.");
                }
                else
                {
                    Helpers.OnOffCmd(e, async on =>
                    {
                        var stream    = streams.Get(e.User.VoiceChannel);
                        string status = on ? "start" : "halt";
                        if ((stream != null) == on)
                        {
                            if (on && stream.Request) // The user is switching back to normal streaming mode.
                            {
                                await e.Channel.SendMessage("Switching to normal streaming mode.");
                                await streams.Play(e, false, stream);
                            }
                            else
                            {
                                string blah = on ? "streaming in! Did you mean to !reset or !forcereset the stream?" : "not streaming in!";
                                await e.Channel.SendMessage($"{e.User.Mention}, I can't {status} streaming in a channel that I'm already {blah}");
                            }
                        }
                        else
                        {
                            await e.Channel.SendMessage($"{e.User.Mention}, I'm {status}ing the stream!");
                            if (on)
                            {
                                await streams.Play(e, false);
                            }
                            else
                            {
                                streams.Get(e.User.VoiceChannel).Stop();
                            }
                        }
                    });
                }
            });

            if (HasFolder()) // Request-driven mode is always on when we don't have a folder, therefore we won't need this command.
            {
                group.CreateCommand("music request")
                .Alias("gesture mode activate")
                .Description("I'll turn request-driven streaming on in a particular voice channel, which you need to be in. (This will allow you to play gestures)")
                .MinPermissions(2)
                .Do(e =>
                {
                    var stream = streams.Get(e.User.VoiceChannel);
                    if (stream != null && stream.Request)
                    {
                        e.Channel.SendMessage("The stream is already in request mode.");
                        return;
                    }
                    Task.Run(() => streams.Play(e, true, stream));
                    e.Channel.SendMessage("I am now streaming in request-driven mode.");
                });
            }
        }
Exemplo n.º 23
0
        internal static void AddCommands(Commands.CommandGroupBuilder group)
        {
            group.CreateCommand("nsfw status")
            .Alias("canlewd status")
            .Description("I'll tell you if this channel allows nsfw commands.")
            .Do(async e => await e.Channel.SendMessage($"This channel {(GetNsfw(e.Channel) ? "allows" : "doesn't allow")} nsfw commands."));

            // Moderator Commands
            group.CreateCommand("nsfw")
            .Alias("canlewd")
            .Parameter("on/off", Commands.ParameterType.Required)
            .MinPermissions(1)
            .Description("I'll set a channel's nsfw flag to on or off.")
            .Do(e =>
            {
                Helpers.OnOffCmd(e, on =>
                {
                    string status = on ? "allow" : "disallow";
                    if (GetNsfw(e.Channel) == on)
                    {
                        e.Channel.SendMessage($"{e.User.Mention}, this channel is already {status}ing nsfw commands.");
                    }
                    else
                    {
                        SQL.AddOrUpdateFlag(e.Channel.Id, "nsfw", on ? "1" : "0");
                        e.Channel.SendMessage($"I've set this channel to {status} nsfw commands.");
                    }
                });
            });

            Func <Role, EMentionType> mention_type = r => r.IsEveryone ? EMentionType.everyoneRole : r.IsMentionable ? EMentionType.role : EMentionType.unmentionableRole;

            // Administrator Commands
            group.CreateCommand("ignore")
            .Parameter("channel", Commands.ParameterType.Optional)
            .Parameter("user", Commands.ParameterType.Optional)
            .Parameter("role", Commands.ParameterType.Optional)
            .Parameter("...", Commands.ParameterType.Multiple)
            .MinPermissions(1)
            .Description("I'll ignore a particular channel, user or role")
            .Do(async e =>
            {
                if (e.Message.MentionedChannels.Any() || e.Message.MentionedUsers.Any() || e.Message.MentionedRoles.Any())
                {
                    int perms    = Helpers.GetPermissions(e.User, e.Channel);
                    string reply = "";
                    foreach (Channel c in e.Message.MentionedChannels)
                    {
                        reply += (reply != "" ? "\n" : "") + await SetIgnored("channel", "flags", c.Id, EMentionType.channel, perms);
                    }
                    foreach (User u in e.Message.MentionedUsers)
                    {
                        reply += (reply != "" ? "\n" : "") + await SetIgnored("user", "users", u.Id, EMentionType.user, perms, Helpers.GetPermissions(u, e.Channel));
                    }
                    var senpai = e.Server.GetUser(Program.masterId);
                    foreach (Role r in e.Message.MentionedRoles)
                    {
                        reply += (reply != "" ? "\n" : "") + await SetIgnored("role", "roles", r.Id, mention_type(r), perms, senpai.Roles.Contains(r) ? -2 : e.User.Roles.Contains(r) ? -1 : perms);
                    }
                    await e.Channel.SendMessage(reply);
                }
                else
                {
                    await e.Channel.SendMessage("You need to mention at least one user, channel or role!");
                }
            });

            group.CreateCommand("ignore role")
            .Parameter("role(s)", Commands.ParameterType.Unparsed)
            .MinPermissions(3)
            .Description("I'll ignore particular roles by name (comma separated)")
            .Do(async e =>
            {
                string reply = "";
                if (e.Args[0].Length == 0)
                {
                    reply = "You need to provide at least one role name!";
                }
                else
                {
                    int perms  = Helpers.GetPermissions(e.User, e.Channel);
                    var senpai = e.Server.GetUser(Program.masterId);
                    Helpers.CommaSeparateRoleNames(e, async(roles, str) =>
                    {
                        var count = roles.Count();
                        if (reply != "")
                        {
                            reply += '\n';
                        }
                        if (count != 1)
                        {
                            reply += $"{(count == 0 ? "No" : count.ToString())} roles found for {str}";
                        }
                        else
                        {
                            var r  = roles.Single();
                            reply += await SetIgnored("role", "roles", r.Id, mention_type(r), perms, senpai.Roles.Contains(r) ? -2 : e.User.Roles.Contains(r) ? -1 : perms);
                        }
                    });
                }
                await e.Channel.SendMessage(reply);
            });
        }
Exemplo n.º 24
0
 public void CreateSearchCmd(Commands.CommandGroupBuilder group, string name, string alias, bool is_playlist, SearchType st = SearchType.Simple) => CreateSearchCmd(group, name, new[] { alias }, is_playlist, st);
Exemplo n.º 25
0
 static public void CreateCommand(Commands.CommandGroupBuilder group, string name, string alias) => CreateCommand(group, name, new[] { alias });
Exemplo n.º 26
0
            public void CreateSearchCmd(Commands.CommandGroupBuilder group, string name, string[] aliases, bool is_playlist, SearchType st = SearchType.Simple)
            {
                const int random_tries = 10; // how many times to retry random selection.
                bool      multiple     = st == SearchType.Multiple;
                var       cmd          = CreatePLCmd(group, name,
                                                     $"I'll search for your {(is_playlist ? "playlist " : "")}request on SoundCloud!\nResults will be considered {(st == SearchType.Random ? $"{random_tries} times at random until one is found that isn't already in the playlist." : $"in order until {(!multiple ? "one not in the playlist is found" : "the amount of count or all (that are not already in the playlist) have been added")}")}.", aliases);

                if (multiple)
                {
                    cmd.Parameter("count", Commands.ParameterType.Optional);
                }
                // Until we can figure out how to include Playlist search terms without getting gateway errors, RIP.
                if (!is_playlist)
                {
                    cmd.Parameter("keywords", Commands.ParameterType.Unparsed);
                }
                cmd.Do(e => st == SearchType.Random ? Task.Run(() =>
                {
                    var container = Search(e, is_playlist);
                    if (container == null)
                    {
                        return;
                    }
                    var r = new Random();
                    for (int i = random_tries; i != 0; --i)
                    {
                        var thing = container[r.Next(container.Length)];
                        if (is_playlist ? Triad(e, (SoundCloud.NET.Models.Playlist)thing, true) != 0 : Triad(e, (SoundCloud.NET.Models.Track)thing, false))
                        {
                            return;
                        }
                    }
                    e.Channel.SendMessage($"No new tracks found, tried {random_tries} times.");
                })
                    : Task.Run(() =>
                {
                    int max = 0;
                    if (multiple && Helpers.HasArg(e.Args) && !int.TryParse(e.Args[0], out max))
                    {
                        max = 100;
                    }
                    var container = Search(e, is_playlist, max);
                    if (container == null)
                    {
                        return;
                    }
                    int count      = 0;
                    int trackcount = 0;
                    foreach (var thing in container)
                    {
                        var tc = is_playlist ? Triad(e, (SoundCloud.NET.Models.Playlist)thing, true, multiple) : Triad(e, (SoundCloud.NET.Models.Track)thing, false, multiple) ? 1 : 0;
                        if (tc != 0)
                        {
                            if (!multiple)
                            {
                                return;
                            }
                            if (is_playlist)
                            {
                                trackcount += tc;
                            }
                            if (++count == max)
                            {
                                break;
                            }
                        }
                    }
                    e.Channel.SendMessage(multiple && count != 0 ? $"{count} {(is_playlist ? $"playlists (totaling {trackcount} tracks)" : "tracks")} added." : $"{e.User.Mention} No results for your requested search aren't already in the playlist.");
                }));
            }
Exemplo n.º 27
0
        internal static void AddCommands(Commands.CommandGroupBuilder group)
        {
#if lewdchanexisted
            CreateLewdCommand(group, "neko");
            CreateLewdCommand(group, "qt");
            CreateLewdCommand(group, "kitsune");
            CreateLewdCommand(group, "lewd");
#endif

            var imagedir = Program.config["images"].ToString();
            if (imagedir.Length == 0)
            {
                imagedir = "images";
            }
            if (System.IO.Directory.Exists(imagedir))
            {
                string[] imgexts = { ".jpg", ".jpeg", ".png", ".gif", ".bmp" };
                foreach (var subdir in System.IO.Directory.EnumerateDirectories(imagedir))
                {
                    var data = Helpers.GetJsonFileIfExists($"{subdir}/command.json");
                    Func <Commands.CommandEventArgs, Task> cmd_body = async e =>
                    {
                        var files = from file in System.IO.Directory.EnumerateFiles($@"{subdir}", "*.*").Where(s => imgexts.Contains(System.IO.Path.GetExtension(s.ToLower()))) select new { File = file };
                        await e.Channel.SendFileAsync(files.ElementAt(new Random().Next(0, files.Count() - 1)).File);
                    };
                    if (data == null)
                    {
                        group.CreateCommand(Helpers.FileWithoutPath(subdir)).Do(cmd_body);
                    }
                    else
                    {
                        Helpers.CreateJsonCommand(group, data.ToObject <Dictionary <string, JToken> >().First(), (cmd, cmd_data) =>
                                                  cmd.FlagNsfw(cmd_data["nsfw"].ToObject <bool>()).Do(cmd_body));
                    }
                }
            }

            group.CreateCommand("img")
            .Parameter("search query", Commands.ParameterType.Required)
            .Parameter("extended query", Commands.ParameterType.Multiple)
            .Description("I'll get a random image from Google!")
            .AddCheck((h, i, d) => false).Hide()     // Until we can  update this to work
            .Do(e =>
            {
                Random rnd           = new Random();
                var request          = new RestRequest($"images?v=1.0&q={string.Join(" ", e.Args)}&rsz=8&start={rnd.Next(1, 12)}&safe=active", Method.GET);
                JObject result       = JObject.Parse(Helpers.GetRestClient("https://ajax.googleapis.com/ajax/services/search").Execute(request).Content);
                List <string> images = new List <string>();
                foreach (var element in result["responseData"]["results"])
                {
                    images.Add(element["unescapedUrl"].ToString());
                }
                e.Channel.SendMessageAsync(images[rnd.Next(images.Count())].ToString());
            });

            group.CreateCommand("imgur")
            .Parameter("Reddit Board", Commands.ParameterType.Required)
            .Description("I'll pick out a random image from the day's best on an imgur reddit!")
            .Do(e =>
            {
                try
                {
                    var result = JObject.Parse(Helpers.GetRestClient("http://imgur.com/r/").Execute(new RestRequest($"{e.Args[0]}/top/day.json", Method.GET)).Content)["data"].First;
                    for (var i = new Random().Next(result.Parent.Count - 1); i != 0; --i, result = result.Next)
                    {
                        ;
                    }
                    var part = $"imgur.com/{result["hash"]}";
                    e.Channel.SendMessageAsync($"**http://{part}** http://i.{part}{result["ext"]}");
                }
                catch { e.Channel.SendMessageAsync("Imgur says nope~"); }
            });

            CreateBooruCommand(group, "safebooru");
            CreateBooruCommand(group, "gelbooru"); // Disabled without auth, which can't be done through api. (Resurrected cause API no longer requires login for now.)
            CreateBooruCommand(group, "rule34");
            CreateBooruCommand(group, "konachan", "kona");
            CreateBooruCommand(group, "yandere");
            CreateBooruCommand(group, "lolibooru", "loli");
            if (Helpers.FieldExists("Booru", "sankaku"))
            {
                CreateBooruCommand(group, "sankaku", new[] { "sankakuchan", "schan" });
            }
            //CreateBooruCommand(group, "sankakuidol", "sidol"); // Idol disables their API for some reason.
            CreateBooruCommand(group, "e621", "furry");

            group.CreateCommand("meme")
            .Parameter("Meme type (see memelist)")
            .Parameter("Top][/Bottom", Commands.ParameterType.MultipleUnparsed)
            .Description("http://memegen.link/xy/MakeAllTheMemes.jpg")
            .Do(e => e.Channel.SendMessageAsync($"http://memegen.link/{e.Args[0]}{(e.Args.Length == 1 ? "" : $"/{Uri.EscapeDataString(string.Join("-", e.Args, 1, e.Args.Length - 1))}")}.jpg"));

            group.CreateCommand("meme templates")
            .Alias("memelist")
            .Description("See what memes are on the menu. (I'll tell you in PM)")
            .Do(async e =>
            {
                var json    = JObject.Parse(Helpers.GetRestClient("http://memegen.link").Execute(new RestRequest("templates")).Content);
                var outputs = new List <string>();
                var i       = -1;
                foreach (var pair in json)
                {
                    var s = pair.Value.ToString();
                    s     = $"{pair.Key}: `{s.Substring(s.LastIndexOf('/') + 1)}`\n";
                    if (outputs.Count == 0 || s.Length + outputs[i].Length > 2000)
                    {
                        outputs.Add(s);
                        ++i;
                    }
                    else
                    {
                        outputs[i] += s;
                    }
                }
                var chan = await e.User.GetOrCreateDMChannelAsync();
                foreach (var output in outputs)
                {
                    await chan.SendMessageAsync(output);
                }
            });
        }
Exemplo n.º 28
0
        // Commands first to help with adding new commands
        static void GenerateCommands(CommandGroupBuilder group)
        {
            group.DefaultMusicFlag(false);
            group.DefaultNsfwFlag(false);

            // User commands
            group.CreateCommand("ping")
                .Description("I'll reply with 'Pong!'")
                .Do(async e =>
                {
                    await client.SendMessage(e.Channel, $"<@{e.User.Id}>, Pong!");
                });

            group.CreateCommand("status")
                .Description("I'll give statistics about the servers, channels and users.")
                .Do(async e =>
                {
                    await client.SendMessage(e.Channel, $"I'm connected to {client.AllServers.Count()} servers, which have a total of {client.AllServers.SelectMany(x => x.Channels).Count()} channels, and see a total of {client.AllServers.SelectMany(x => x.Members).Distinct().Count()} different users.");
                });

            group.CreateCommand("whois")
                .Alias("getinfo")
                .Parameter("@User1] [@User2] [...", Commands.ParameterType.Unparsed)
                .Description("I'll give you information about the mentioned user(s).")
                .Do(async e =>
                {
                    if (e.Args[0] == "") return;
                    string reply = "";
                    foreach (User u in e.Message.MentionedUsers)
                    {
                        if (u.Id == 63296013791666176 && e.User.Id == 63299786798796800)
                        {
                            reply += $@"
<@{u.Id}> is your onii-chan <3 and his id is {u.Id} and his permission level is {GetPermissions(u, e.Channel)}.
";
                        }
                        else
                        {
                            reply += $@"
<@{u.Id}>'s id is {u.Id} and their permission level is {GetPermissions(u, e.Channel)}.
";
                        }
                    }
                    await client.SendMessage(e.Channel, reply);
                });

            Music.AddCommands(group);

            group.CreateCommand("quote")
                .Description("I'll give you a random quote from https://inspiration.julxzs.website/quotes")
                .Do(async e =>
                {
                    rclient.BaseUrl = new Uri("https://inspiration.julxzs.website");
                    var request = new RestRequest("api/quote", Method.GET);
                    JObject result = JObject.Parse(rclient.Execute<JObject>(request).Content);
                    string quote = result["quote"]["quote"].ToString();
                    string author = result["quote"]["author"].ToString();
                    string date = result["quote"]["date"].ToString();
                    await client.SendMessage(e.Channel, $"\"{quote}\" - {author} {date}");
                });

            group.CreateCommand("version")
                .Description("I'll tell you the current version and check if a newer version is available.")
                .Do(async e =>
                {
                    string[] versions = version.Split('.');
                    rclient.BaseUrl = new Uri("https://raw.githubusercontent.com");
                    var request = new RestRequest("Kusoneko/Nekobot/master/version.json", Method.GET);
                    JObject result = JObject.Parse(rclient.Execute<JObject>(request).Content);
                    string remoteversion = result["version"].ToString();
                    string[] remoteversions = remoteversion.Split('.');
                    if (int.Parse(versions[0]) < int.Parse(remoteversions[0]))
                        await client.SendMessage(e.Channel, $"I'm currently {(int.Parse(remoteversions[0]) - int.Parse(versions[0]))} major version(s) behind. (Current version: {version}, latest version: {remoteversion})");
                    else if (int.Parse(versions[0]) > int.Parse(remoteversions[0]))
                        await client.SendMessage(e.Channel, $"I'm currently {(int.Parse(versions[0]) - int.Parse(remoteversions[0]))} major version(s) ahead. (Current version: {version}, latest released version: {remoteversion})");
                    else if (int.Parse(versions[1]) < int.Parse(remoteversions[1]))
                        await client.SendMessage(e.Channel, $"I'm currently {(int.Parse(remoteversions[1]) - int.Parse(versions[1]))} minor version(s) behind. (Current version: {version}, latest version: {remoteversion})");
                    else if (int.Parse(versions[1]) > int.Parse(remoteversions[1]))
                        await client.SendMessage(e.Channel, $"I'm currently {(int.Parse(versions[1]) - int.Parse(remoteversions[1]))} minor version(s) ahead. (Current version: {version}, latest released version: {remoteversion})");
                    else if (int.Parse(versions[2]) < int.Parse(remoteversions[2]))
                        await client.SendMessage(e.Channel, $"I'm currently {(int.Parse(remoteversions[2]) - int.Parse(versions[2]))} patch(es) behind. (Current version: {version}, latest version: {remoteversion})");
                    else if (int.Parse(versions[2]) > int.Parse(remoteversions[2]))
                        await client.SendMessage(e.Channel, $"I'm currently {(int.Parse(versions[2]) - int.Parse(remoteversions[2]))} patch(es) ahead. (Current version: {version}, latest released version: {remoteversion})");
                    else
                        await client.SendMessage(e.Channel, $"I'm up to date! (Current version: {version})");
                });

            Image.AddCommands(group);

            group.CreateCommand("fortune")
                .Description("I'll give you a fortune!")
                .Do(async e =>
                {
                    string[] fortunes = new string[] { "Don't sleep for too long, or you'll miss naptime!", "Before crying over spilt milk, remember it can still be delicious without a bowl.", "A bird in the paw is worth nom nom nom...", "Let no surface, no matter how high or cluttered, go unexplored.", "Neko never catches the laser if neko never tries.", "Our greatest glory is not in never falling, but in making sure master doesn't find the mess.", "A mouse shared halves the food but doubles the happiness.", "There exists nary a toy as pertinent as the box from whence that toy came.", "Neko will never be fed if neko does not meow all day!", "Ignore physics, and physics will ignore you.", "Never bite the hand that feeds you!", "Before finding the red dot, you must first find yourself.", "Some see the glass half empty. Some see the glass half full. Neko sees the glass and knocks it over.", "Make purrs not war.", "Give a neko fish and you feed them for a day; Teach a neko to fish and... mmmm fish.", "Wheresoever you go, go with all of master's things.", "Live your dreams every day! Why do you think neko naps so much?", "The hardest thing of all is to find a black cat in a dark room, especially if there is no cat.", "Meow meow meow meow, meow meow. Meow meow meow." };
                    Random rnd = new Random();
                    await client.SendMessage(e.Channel, fortunes[rnd.Next(0, fortunes.Count())]);
                });

            group.CreateCommand("playeravatar")
                .Parameter("username1", Commands.ParameterType.Required)
                .Parameter("username2", Commands.ParameterType.Optional)
                .Parameter("username3", Commands.ParameterType.Multiple)
                .Description("I'll get you the avatar of each Player.me username provided.")
                .Do(async e =>
                {
                    rclient.BaseUrl = new System.Uri("https://player.me/api/v1/auth");
                    var request = new RestRequest("pre-login", Method.POST);
                    foreach (string s in e.Args)
                    {
                        request.AddQueryParameter("login", s);
                        JObject result = JObject.Parse(rclient.Execute(request).Content);
                        if (Convert.ToBoolean(result["success"]) == false)
                            await client.SendMessage(e.Channel, $"{s} was not found.");
                        else
                        {
                            string avatar = result["results"]["avatar"]["original"].ToString();
                            await client.SendMessage(e.Channel, $"{s}'s avatar: https:{avatar}");
                        }
                    }
                });

            group.CreateCommand("nya")
                .Alias("nyaa")
                .Alias("nyan")
                .Description("I'll say 'Nyaa~'")
                .Do(async e =>
                {
                    await client.SendMessage(e.Channel, "Nyaa~");
                });

            group.CreateCommand("poi")
                .Description("I'll say 'Poi!'")
                .Do(async e =>
                {
                    await client.SendMessage(e.Channel, "Poi!");
                });

            group.CreateCommand("aicrai")
                .Alias("aicraievritiem")
                .Alias("aicraievritaim")
                .Alias("sadhorn")
                .Alias("icri")
                .Description("When sad things happen...")
                .Do(async e =>
                {
                    await client.SendMessage(e.Channel, "https://www.youtube.com/watch?v=0JAn8eShOo8");
                });

            group.CreateCommand("notnow")
                .Alias("rinpls")
                .Description("How to Rekt: Rin 101")
                .Do(async e =>
                {
                    await client.SendMessage(e.Channel, "https://www.youtube.com/watch?v=2BZUzJfKFwM");
                });

            group.CreateCommand("uninstall")
                .Description("A great advice in any situation.")
                .Do(async e =>
                {
                    await client.SendMessage(e.Channel, "https://www.youtube.com/watch?v=5sQzi0dn_dA");
                });

            group.CreateCommand("killyourself")
                .Alias("kys")
                .Description("Another great advice.")
                .Do(async e =>
                {
                    await client.SendMessage(e.Channel, "https://www.youtube.com/watch?v=2dbR2JZmlWo");
                });

            group.CreateCommand("congratulations")
                .Alias("congrats")
                .Alias("grats")
                .Alias("gg")
                .Description("Congratulate someone for whatever reason.")
                .Do(async e =>
                {
                    await client.SendMessage(e.Channel, "https://www.youtube.com/watch?v=oyFQVZ2h0V8");
                });

            group.CreateCommand("say")
                .Alias("forward")
                .Alias("echo")
                .Parameter("#channel or @User (or user/channel id in PMs)] [...", Commands.ParameterType.Unparsed)
                .Description("I'll repeat what you said. (To a given user or channel)")
                .Do(async e =>
                {
                    Channel channel = e.Channel;
                    string message = e.Args[0];
                    if (message == "") return; // Unparsed can be empty

                    foreach (User user in e.Message.MentionedUsers)
                        message = message.Replace($"@{user.Name}", $"<@{user.Id}>");
                    foreach (Channel chan in e.Message.MentionedChannels)
                        message = message.Replace($"#{chan.Name}", $"<#{chan.Id}>");

                    bool usermention = e.Message.MentionedUsers.Count() > (e.Message.IsMentioningMe ? 1 : 0) && message.StartsWith("<@");
                    if (usermention || (e.Message.MentionedChannels.Count() > 0 && message.StartsWith("<#")))
                    {
                        int index = message.IndexOf(">");
                        if (index+2 < message.Length)
                        {
                            long mentionid = Convert.ToInt64(message.Substring(2, index-2));
                            if (mentionid != client.CurrentUserId)
                            {
                                channel = usermention ? await client.CreatePMChannel(e.Message.MentionedUsers.Where(u => u.Id == mentionid).Single())
                                    : e.Message.MentionedChannels.Where(c => c.Id == mentionid).Single();
                                if (CanSay(ref channel, e.User, e.Channel))
                                    message = message.Substring(index + 2);
                            }
                        }
                    }
                    else if (channel.IsPrivate)
                    {
                        try
                        {
                            string chanstr = message.Split(' ').First();
                            if (chanstr.Length+1 < message.Length)
                            {
                                long id = Convert.ToInt64(chanstr);
                                channel = client.GetChannel(id) ?? await client.CreatePMChannel(client.AllServers.Select(x => client.GetUser(x, id)).FirstOrDefault());
                                if (CanSay(ref channel, e.User, e.Channel))
                                    message = message.Substring(message.IndexOf(" ")+1);
                            }
                        } catch (Exception) { }
                    }
                    if (message.TrimEnd() != "")
                        await client.SendMessage(channel, message);
                });

            group.CreateCommand("reverse")
                .Alias("backward")
                .Alias("flip")
                .Parameter("text...", Commands.ParameterType.Unparsed)
                .Description("I'll repeat what you said, in reverse!")
                .Do(async e =>
                {
                    var text = e.Args[0];
                    if (text.Length != 0)
                        await client.SendMessage(e.Channel, String.Join("", GraphemeClusters(text).Reverse().ToArray()));
                });

            group.CreateCommand("whereami")
                .Alias("channelinfo")
                .Alias("channel")
                .Alias("location")
                .Alias("where")
                .Description("I'll tell you information about the channel and server you're asking me this from.")
                .Do(async e =>
                {
                    if (e.Channel.IsPrivate)
                        await client.SendMessage(e.Channel, "You're in a private message with me, baka.");
                    else
                    {
                        string message = $@"You are currently in {e.Channel.Name} (id: {e.Channel.Id})
on server **{e.Server.Name}** (id: {e.Server.Id}) (region: {e.Server.Region})
owned by {e.Server.Owner.Name} (id {e.Server.Owner.Id}).";
                        if (e.Channel.Topic != "" || e.Channel.Topic != null)
                            message = message + $@"
The current topic is: {e.Channel.Topic}";
                        await client.SendMessage(e.Channel, message);
                    }
                });

            group.CreateCommand("avatar")
                .Parameter("@User1] [@User2] [...", Commands.ParameterType.Unparsed)
                .Description("I'll give you the avatars of every mentioned users.")
                .Do(async e =>
                {
                    if (e.Args[0] == "") return;
                    foreach (User u in e.Message.MentionedUsers)
                    {
                        if (u.AvatarUrl == null)
                            await client.SendMessage(e.Channel, $"<@{u.Id}> has no avatar.");
                        else
                            await client.SendMessage(e.Channel, $"<@{u.Id}>'s avatar is: https://discordapp.com/api/{u.AvatarUrl}");
                    }
                });

            group.CreateCommand("rand")
                .Parameter("min", Commands.ParameterType.Optional)
                .Parameter("max", Commands.ParameterType.Optional)
                .Description("I'll give you a random number between *min* and *max*. Both are optional. If only one is given, it's *max*. (defaults: 1-100)")
                .Do(async e =>
                {
                    foreach (string s in e.Args)
                    {
                        int dummy = 0;
                        if (!int.TryParse(s, out dummy))
                        {
                            await client.SendMessage(e.Channel, $"{s} is not a number!");
                            return;
                        }
                    }
                    int min = e.Args.Length > 1 ? int.Parse(e.Args[0]) : 1;
                    int max = e.Args.Length > 0 ? int.Parse(e.Args[e.Args.Length == 1 ? 0 : 1]) : 100;
                    if (min == max)
                    {
                        await client.SendMessage(e.Channel, $"You're joking right? It's {min}.");
                        return;
                    }
                    if (min > max)
                    {
                        int z = min;
                        min = max;
                        max = z;
                    }
                    ++max;
                    await client.SendMessage(e.Channel, $"Your number is **{new Random().Next(min,max)}**.");
                });

            group.CreateCommand("roll")
                .Parameter("dice", Commands.ParameterType.Optional)
                .Parameter("sides", Commands.ParameterType.Optional)
                .Parameter("times", Commands.ParameterType.Optional)
                .Description("I'll roll a few sided dice for a given number of times. All params are optional. (defaults: 1 *dice*, 6 *sides*, 1 *times*)")
                .Do(async e =>
                {
                    bool rick = false;
                    bool valid = true;
                    foreach (string s in e.Args)
                    {
                        int dummy = 0;
                        if (!int.TryParse(s, out dummy))
                            valid = false;
                        if (s == "rick")
                            rick = true;
                        if (rick || !valid)
                            break;
                    }
                    if (!rick)
                    {
                        if (valid)
                        {
                            int dice = e.Args.Count() >= 1 ? int.Parse(e.Args[0]): 1;
                            int sides = e.Args.Count() >= 2 ? int.Parse(e.Args[1]): 6;
                            int times = e.Args.Count() >= 3 ? int.Parse(e.Args[2]): 1;

                            int roll = 0;
                            Random rnd = new Random();
                            for (int i = times; i > 0; i--)
                            {
                                for (int j = dice; j > 0; j--)
                                {
                                    roll += rnd.Next(1, sides + 1);
                                }
                            }
                            await client.SendMessage(e.Channel, $"You rolled {dice} different {sides}-sided dice {times} times... Result: **{roll}**");
                        }
                        else
                            await client.SendMessage(e.Channel, $"Arguments are not all numbers!");
                    }
                    else
                        await client.SendMessage(e.Channel, $"https://www.youtube.com/watch?v=dQw4w9WgXcQ");
                });

            group.CreateCommand("lotto")
                .Description("I'll give you a set of 6 lucky numbers!")
                .Do(async e =>
                {
                    List<int> lotto = new List<int>();
                    Random rnd = new Random();
                    while (lotto.Count() < 6)
                    {
                        int number = rnd.Next(1, 60);
                        for (int i = 0; i < lotto.Count(); i++)
                        {
                            if (lotto[i] == number)
                            {
                                lotto.Remove(number);
                                break;
                            }
                        }
                        lotto.Add(number);
                    }
                    await client.SendMessage(e.Channel, $"Your lucky numbers are **{lotto[0]}, {lotto[1]}, {lotto[2]}, {lotto[3]}, {lotto[4]}, {lotto[5]}**.");
                });

            group.CreateCommand("pet")
                .Alias("pets")
                .Parameter("@User1] [@User2] [...", Commands.ParameterType.Unparsed)
                .Description("Everyone loves being pet, right!?! Pets each *@user*. Leave empty (or mention me too) to pet me!")
                .Do(async e =>
                {
                    await PerformAction(e, "pet", "*purrs*", false);
                });

            group.CreateCommand("hug")
                .Alias("hugs")
                .Parameter("@User1] [@User2] [...", Commands.ParameterType.Unparsed)
                .Description("Hug someone! Hugs each *@user*. Leave empty to get a hug!")
                .Do(async e =>
                {
                    await PerformAction(e, "hug", "<3", true);
                });

            group.CreateCommand("8ball")
                .Parameter("question", Commands.ParameterType.Optional)
                .Parameter("?", Commands.ParameterType.Multiple)
                .Description("The magic eightball can answer any question!")
                .Do(async e =>
                {
                    string[] eightball = new string[] { "It is certain.", "It is decidedly so.", "Without a doubt.", "Yes, definitely.", "You may rely on it.", "As I see it, yes.", "Most likely.", "Outlook good.", "Yes.", "Signs point to yes.", "Reply hazy try again...", "Ask again later...", "Better not tell you now...", "Cannot predict now...", "Concentrate and ask again...", "Don't count on it.", "My reply is no.", "My sources say no.", "Outlook not so good.", "Very doubtful.", "Nyas.", "Why not?", "zzzzz...", "No." };
                    Random rnd = new Random();
                    if (String.Join(" ", e.Args)[String.Join(" ", e.Args).Length - 1] != '?')
                        await client.SendMessage(e.Channel, "You must ask a proper question!");
                    else
                        await client.SendMessage(e.Channel, $"*{eightball[rnd.Next(eightball.Length)]}*");
                });

            group.CreateCommand("hbavatar")
                .Parameter("username1", Commands.ParameterType.Required)
                .Parameter("username2", Commands.ParameterType.Optional)
                .Parameter("username3", Commands.ParameterType.Multiple)
                .Description("I'll give you the hummingbird avatar of the usernames provided.")
                .Do(async e =>
                {
                    rclient.BaseUrl = new Uri("http://hummingbird.me/api/v1/users");
                    string message = "";
                    foreach (string s in e.Args)
                    {
                        var request = new RestRequest($"{s}", Method.GET);
                        if (rclient.Execute(request).Content[0] == '<')
                        {
                            message += $@"
{s} doesn't exist.";
                        }
                        else
                        {
                            JObject result = JObject.Parse(rclient.Execute(request).Content);
                            string username = result["name"].ToString();
                            string avatar = result["avatar"].ToString();
                            message += $@"
{username}'s avatar: {avatar}";
                        }
                    }
                    await client.SendMessage(e.Channel, message);
                });

            group.CreateCommand("hb")
                .Parameter("username1", Commands.ParameterType.Required)
                .Parameter("username2", Commands.ParameterType.Optional)
                .Parameter("username3", Commands.ParameterType.Multiple)
                .Description("I'll give you information on the hummingbird accounts of the usernames provided.")
                .Do(async e =>
                {
                    rclient.BaseUrl = new Uri("http://hummingbird.me/api/v1/users");
                    foreach (string s in e.Args)
                    {
                        string message = "";
                        var request = new RestRequest($"{s}", Method.GET);
                        if (rclient.Execute(request).Content[0] == '<')
                        {
                            message += $@"{s} doesn't exist.";
                        }
                        else
                        {
                            JObject result = JObject.Parse(rclient.Execute(request).Content);
                            var username = result["name"].ToString();
                            var avatar = result["avatar"].ToString();
                            var userurl = $"http://hummingbird.me/users/{username}";
                            var waifu = result["waifu"].ToString();
                            var waifu_prefix = result["waifu_or_husbando"].ToString();
                            var bio = result["bio"].ToString();
                            var location = result["location"].ToString();
                            var website = result["website"].ToString();
                            var life_spent_on_anime = int.Parse(result["life_spent_on_anime"].ToString());

                            string lifeAnime = CalculateTime(life_spent_on_anime);

                            message += $@"
**User**: {username}
**Avatar**: {avatar} 
**{waifu_prefix}**: {waifu}
**Bio**: {bio}
**Time wasted on Anime**: {lifeAnime}";
                            if (!String.IsNullOrWhiteSpace(location))
                                message += $@"
**Location**: {location}";
                            if (!String.IsNullOrWhiteSpace(website))
                                message += $@"
**Website**: {website}";
                            message += $@"
**Hummingbird page**: {userurl}";
                        }
                        await client.SendMessage(e.Channel, message);
                    }
                });

            group.CreateCommand("player")
                .Parameter("username1", Commands.ParameterType.Required)
                .Parameter("username2", Commands.ParameterType.Optional)
                .Parameter("username3", Commands.ParameterType.Multiple)
                .Description("I'll give you information on the Player.me of each usernames provided.")
                .Do(async e =>
                {
                    rclient.BaseUrl = new System.Uri("https://player.me/api/v1/auth");
                    var request = new RestRequest("pre-login", Method.POST);
                    foreach (string s in e.Args)
                    {
                        request.AddQueryParameter("login", s);
                        JObject result = JObject.Parse(rclient.Execute(request).Content);
                        if (Convert.ToBoolean(result["success"]) == false)
                            await client.SendMessage(e.Channel, $"{s} was not found.");
                        else
                        {
                            string username = result["results"]["username"].ToString();
                            string avatar = "https:" + result["results"]["avatar"]["original"].ToString();
                            string bio = result["results"]["short_description"].ToString();
                            DateTime date = DateTime.Parse(result["results"]["created_at"].ToString());
                            string joined = date.ToString("yyyy-MM-dd");
                            int followers = Convert.ToInt32(result["results"]["followers_count"]);
                            int following = Convert.ToInt32(result["results"]["following_count"]);
                            await client.SendMessage(e.Channel, $@"
**User**: {username}
**Avatar**: {avatar}
**Bio**: {bio}
**Joined on**: {joined}
**Followers**: {followers}
**Following**: {following}");
                        }
                    }
                });

            // Moderator commands
            group.CreateCommand("invite")
                .Parameter("invite code or link", Commands.ParameterType.Required)
                .MinPermissions(1)
                .Description("I'll join a new server using the provided invite code or link.")
                .Do(async e =>
                {
                    await client.AcceptInvite(client.GetInvite(e.Args[0]).Result);
                });

            // Administrator commands
            group.CreateCommand("setpermissions")
                .Alias("setperms")
                .Alias("setauth")
                .Parameter("newPermissionLevel", Commands.ParameterType.Required)
                .Parameter("@User1] [@User2] [...", Commands.ParameterType.Unparsed)
                .MinPermissions(2)
                .Description("I'll set the permission level of the mentioned people to the level mentioned (cannot be higher than or equal to yours).")
                .Do(async e =>
                {
                    int newPermLevel = 0;
                    int eUserPerm = GetPermissions(e.User, e.Channel);
                    if (e.Args[1] == "" || e.Message.MentionedUsers.Count() < 1)
                        await client.SendMessage(e.Channel, "You need to at least specify a permission level and mention one user.");
                    else if (!int.TryParse(e.Args[0], out newPermLevel))
                        await client.SendMessage(e.Channel, "The first argument needs to be the new permission level.");
                    else if (eUserPerm <= newPermLevel)
                        await client.SendMessage(e.Channel, "You can only set permission level to lower than your own.");
                    else
                    {
                        string reply = "";
                        foreach (User u in e.Message.MentionedUsers)
                        {
                            int oldPerm = GetPermissions(u, e.Channel);
                            if (oldPerm >= eUserPerm)
                            {
                                reply += $"<@{u.Id}>'s permission level is no less than yours, you are not allowed to change it.";
                                continue;
                            }
                            bool change_needed = oldPerm != newPermLevel;
                            if (change_needed)
                            {
                                await SQL.ExecuteNonQueryAsync(SQL.ExecuteScalarPos($"select count(user) from users where user='******'")
                                    ? $"update users set perms={newPermLevel} where user='******'"
                                    : $"insert into users values ('{u.Id}', {newPermLevel}, 0)");
                            }
                            if (reply != "")
                                reply += '\n';
                            reply += $"<@{u.Id}>'s permission level is "+(change_needed ? "now" : "already at")+$" {newPermLevel}.";
                        }
                        await client.SendMessage(e.Channel, reply);
                    }
                });

            // Owner commands

            group.CreateCommand("leave")
                .MinPermissions(3)
                .Description("I'll leave the server this command was used in.")
                .Do(async e =>
                {
                    await client.SendMessage(e.Channel, "Bye bye!");
                    await client.LeaveServer(e.Server);
                });

            group.CreateCommand("color")
                .Parameter("Rolename", Commands.ParameterType.Required)
                .Parameter("hex", Commands.ParameterType.Optional)
                .Parameter("r", Commands.ParameterType.Optional)
                .Parameter("g", Commands.ParameterType.Optional)
                .Parameter("b", Commands.ParameterType.Optional)
                .MinPermissions(3)
                .Description("I'll set a role's color to the hex(000000-FFFFFF) or rgb(0-255 0-255 0-255) color value provided.")
                .Do(async e =>
                {
                    if (e.Args.Count() == 2)
                    {
                        // assume hex code was provided
                        string r = e.Args[1].Substring(0, 2);
                        string g = e.Args[1].Substring(2, 2);
                        string b = e.Args[1].Substring(4, 2);
                        int red = Convert.ToInt32(r, 16);
                        int green = Convert.ToInt32(g, 16);
                        int blue = Convert.ToInt32(b, 16);
                        Role role = client.FindRoles(e.Server, e.Args[0]).FirstOrDefault();
                        Discord.Color color = new Color(0);
                        color.R = Convert.ToByte(red);
                        color.B = Convert.ToByte(blue);
                        color.G = Convert.ToByte(green);
                        await client.EditRole(role, color: color);
                        await client.SendMessage(e.Channel, $"Role {role.Name}'s color has been changed.");
                    }
                    else if (e.Args.Count() == 4)
                    {
                        // assume it's rgb color codes
                        int red = int.Parse(e.Args[1]);
                        int green = int.Parse(e.Args[2]);
                        int blue = int.Parse(e.Args[3]);
                        Role role = client.FindRoles(e.Server, e.Args[0]).FirstOrDefault();
                        Discord.Color color = new Color(0);
                        color.R = Convert.ToByte(red);
                        color.B = Convert.ToByte(blue);
                        color.G = Convert.ToByte(green);
                        await client.EditRole(role, color: color);
                        await client.SendMessage(e.Channel, $"Role {role.Name}'s color has been changed.");
                    }
                    else
                        await client.SendMessage(e.Channel, "The parameters are invalid.");
                });

            Flags.AddCommands(group);

            Chatbot.AddCommands(group);
        }