public static async Task<TrackData> Parse(string input) { if (File.Exists(input)) return new TrackData(input, Utils.GetFilename(input)); IStreamResolver resolver = await FindValidResovler(input); if (resolver == null) return null; TrackData retval = new TrackData(input, resolver); if (resolver.SupportsTrackNames) retval.Name = await resolver.GetTrackName(input); else retval.Name = input; return retval; }
void IModule.Install(ModuleManager manager) { _client = manager.Client; manager.CreateDynCommands("stream", PermissionLevel.User, group => { // commands which can only be called when there is a track currently playing. group.CreateGroup("", playingGroup => { playingGroup.AddCheck((cmd, usr, chnl) => GetAudio(chnl).IsPlaying); playingGroup.CreateCommand("goto") .Description("Skips to the given point in the track.") .Parameter("time") .Do(e => GetAudio(e.Channel).SkipToTimeInTrack(TimeSpan.Parse(e.GetArg("time")))); playingGroup.CreateCommand("stop") .Description("Stops playback of the playlist.") .Do(e => GetAudio(e.Channel).StopPlaylist()); playingGroup.CreateCommand("forcestop") .Description("Forcefully stops playback of the playlist, track and leaves the voice channel.") .MinPermissions((int)PermissionLevel.ChannelAdmin) .Do(e => GetAudio(e.Channel).ForceStop()); playingGroup.CreateCommand("next") .Description("Skips the current track and plays the next track in the playlist.") .Do(e => GetAudio(e.Channel).StopPlayback()); playingGroup.CreateCommand("prev") .Description("Skips the current track and plays the previus track in the playlist.") .Do(e => GetAudio(e.Channel).Previous()); playingGroup.CreateCommand("current") .Description("Displays information about the currently played track.") .Do(async e => await GetAudio(e.Channel).PrintCurrentTrack()); playingGroup.CreateCommand("pause") .Description("Pauses/unpauses playback of the current track.") .Do(e => GetAudio(e.Channel).Pause()); }); // commands which can only be called when there is no track playing. group.CreateGroup("", idleGroup => { idleGroup.AddCheck((cmd, usr, chnl) => !GetAudio(chnl).IsPlaying); idleGroup.CreateCommand("start") .Alias("play") .Description("Starts the playback of the playlist.") .Parameter("channel", ParameterType.Unparsed) .Do(async e => { AudioState audio = GetAudio(e.Channel); string channelQuery = e.GetArg("channel"); if (string.IsNullOrEmpty(channelQuery)) { if (e.User.VoiceChannel != null) { audio.PlaybackChannel = e.User.VoiceChannel; } } else { channelQuery = channelQuery.ToLowerInvariant(); Channel voiceChannel = e.Server.VoiceChannels.FirstOrDefault( c => c.Name.ToLowerInvariant().StartsWith(channelQuery)); if (voiceChannel == null) { await e.Channel.SafeSendMessage( $"Voice channel with the name of {channelQuery} was not found."); return; } audio.PlaybackChannel = voiceChannel; } if (audio.PlaybackChannel == null) { await e.Channel.SafeSendMessage("Playback channel not set."); return; } await audio.StartPlaylist(); }); idleGroup.CreateCommand("startat") .Alias("playat") .Description("Starts playback at at given point in the track") .Parameter("time") .Do(async e => { AudioState audio = GetAudio(e.Channel); if (audio.PlaybackChannel == null) { await e.Channel.SafeSendMessage("Playback channel not set."); return; } audio.SkipToTimeInTrack(TimeSpan.Parse(e.GetArg("time"))); await audio.StartPlaylist(); }); }); group.CreateCommand("add") .Description("Adds a track to the music playlist.") .Parameter("location", ParameterType.Unparsed) .Do(async e => { string loc = e.GetArg("location"); TrackData result = await TrackData.Parse(loc); if (result == null) { await e.Channel.SafeSendMessage($"Failed getting the stream url for `{loc}."); return; } GetAudio(e.Channel).Playlist.Add(result); await e.Channel.SafeSendMessage($"Added `{result.Name}` to the playlist."); }); group.CreateCommand("setpos") .Alias("set") .Description("Sets the position of the current played track index to a given number.") .Parameter("index") .Do(e => GetAudio(e.Channel).SkipToTrack(int.Parse(e.GetArg("index")) - 1)); group.CreateCommand("remove") .Alias("rem") .Description("Removes a track at the given position from the playlist.") .Parameter("index") .Do(async e => { AudioState audio = GetAudio(e.Channel); int remIndex = int.Parse(e.GetArg("index")) - 1; TrackData remData = audio.Playlist[remIndex]; audio.Playlist.RemoveAt(remIndex); await e.Channel.SafeSendMessage($"Removed track `{remData.Name}` from the playlist."); }); group.CreateCommand("list") .Description("List the songs in the current playlist.") .Do(async e => { AudioState audio = GetAudio(e.Channel); if (!audio.Playlist.Any()) { await e.Channel.SafeSendMessage("Playlist is empty."); return; } StringBuilder builder = new StringBuilder(); builder.AppendLine("**Playlist:**"); for (int i = 0; i < audio.Playlist.Count; i++) { if (i == audio.TrackIndex && audio.IsPlaying) { builder.Append("Playing: "); } builder.AppendLine($"`{i + 1}: {audio.Playlist[i].Name}`"); } await e.Channel.SafeSendMessage(builder.ToString()); }); group.CreateCommand("clear") .Description("Stops music and clears the playlist.") .MinPermissions((int)PermissionLevel.ServerModerator) .Do(async e => { GetAudio(e.Channel).ClearPlaylist(); await e.Channel.SafeSendMessage("Cleared playlist."); }); group.CreateCommand("channel") .Description( "Sets the channel in which the audio will be played in. Use .c to set it to your current channel.") .Parameter("channel", ParameterType.Unparsed) .Do(async e => { AudioState audio = GetAudio(e.Channel); string channelQuery = e.GetArg("channel"); Channel channel = channelQuery == ".c" ? e.User.VoiceChannel : e.Server.FindChannels(channelQuery, ChannelType.Voice).FirstOrDefault(); if (channel == null) { await e.Channel.SafeSendMessage($"Voice channel `{channelQuery}` not found."); return; } if (audio.IsPlaying) { await audio.SwitchChannel(channel); } else { audio.PlaybackChannel = channel; await e.Channel.SafeSendMessage($"Set playback channel to \"`{audio.PlaybackChannel.Name}`\""); } }); }); }