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."); }); } }