continued work on music
This commit is contained in:
@ -369,7 +369,7 @@ namespace NadekoBot.Modules {
|
||||
.Description("Shows some basic stats for Nadeko.")
|
||||
.Do(async e => {
|
||||
var t = Task.Run(() => {
|
||||
return NadekoStats.Instance.GetStats() + "`" + Music.GetMusicStats() + "`";
|
||||
return NadekoStats.Instance.GetStats(); //+ "`" + Music.GetMusicStats() + "`";
|
||||
});
|
||||
|
||||
await e.Channel.SendMessage(await t);
|
||||
|
@ -16,13 +16,7 @@ namespace NadekoBot.Modules {
|
||||
class Music : DiscordModule {
|
||||
|
||||
public static ConcurrentDictionary<Server, MusicPlayer> musicPlayers = new ConcurrentDictionary<Server, MusicPlayer>();
|
||||
public static ConcurrentDictionary<ulong, float> musicVolumes = new ConcurrentDictionary<ulong, float>();
|
||||
|
||||
internal static string GetMusicStats() {
|
||||
var stats = musicPlayers.Where(kvp => kvp.Value?.SongQueue.Count > 0 || kvp.Value?.CurrentSong != null);
|
||||
int cnt;
|
||||
return $"Playing {cnt = stats.Count()} songs".SnPl(cnt) + $", {stats.Sum(kvp => kvp.Value?.SongQueue?.Count ?? 0)} queued.";
|
||||
}
|
||||
public static ConcurrentDictionary<ulong, float> defaultMusicVolumes = new ConcurrentDictionary<ulong, float>();
|
||||
|
||||
Timer setgameTimer => new Timer();
|
||||
|
||||
@ -34,7 +28,7 @@ namespace NadekoBot.Modules {
|
||||
setgameTimer.Elapsed += (s, e) => {
|
||||
try {
|
||||
int num = musicPlayers.Where(kvp => kvp.Value.CurrentSong != null).Count();
|
||||
NadekoBot.client.SetGame($"{num} songs".SnPl(num) + $", {musicPlayers.Sum(kvp => kvp.Value.SongQueue.Count())} queued");
|
||||
NadekoBot.client.SetGame($"{num} songs".SnPl(num) + $", {musicPlayers.Sum(kvp => kvp.Value.Playlist.Count())} queued");
|
||||
}
|
||||
catch { }
|
||||
};
|
||||
@ -53,28 +47,32 @@ namespace NadekoBot.Modules {
|
||||
cgb.CreateCommand("n")
|
||||
.Alias("next")
|
||||
.Description("Goes to the next song in the queue.")
|
||||
.Do(async e => {
|
||||
if (!musicPlayers.ContainsKey(e.Server)) return;
|
||||
await musicPlayers[e.Server].LoadNextSong();
|
||||
.Do(e => {
|
||||
MusicPlayer musicPlayer;
|
||||
if (!musicPlayers.TryGetValue(e.Server, out musicPlayer)) return;
|
||||
musicPlayer.Next();
|
||||
});
|
||||
|
||||
cgb.CreateCommand("s")
|
||||
.Alias("stop")
|
||||
.Description("Completely stops the music, unbinds the bot from the channel, and cleans up files.")
|
||||
.Do(e => {
|
||||
if (!musicPlayers.ContainsKey(e.Server)) return;
|
||||
musicPlayers[e.Server].Stop(true);
|
||||
.Do(async e => {
|
||||
MusicPlayer musicPlayer;
|
||||
if (!musicPlayers.TryRemove(e.Server, out musicPlayer)) return;
|
||||
await musicPlayer.Stop();
|
||||
});
|
||||
|
||||
cgb.CreateCommand("p")
|
||||
.Alias("pause")
|
||||
.Description("Pauses or Unpauses the song.")
|
||||
.Do(async e => {
|
||||
if (!musicPlayers.ContainsKey(e.Server)) return;
|
||||
if (musicPlayers[e.Server].TogglePause())
|
||||
await e.Channel.SendMessage("🎵`Music player paused.`");
|
||||
MusicPlayer musicPlayer;
|
||||
if (!musicPlayers.TryGetValue(e.Server, out musicPlayer)) return;
|
||||
musicPlayer.TogglePause();
|
||||
if (musicPlayer.Paused)
|
||||
await e.Channel.SendMessage("🎵`Music musicPlayer paused.`");
|
||||
else
|
||||
await e.Channel.SendMessage("🎵`Music player unpaused.`");
|
||||
await e.Channel.SendMessage("🎵`Music musicPlayer unpaused.`");
|
||||
});
|
||||
|
||||
cgb.CreateCommand("q")
|
||||
@ -82,49 +80,51 @@ namespace NadekoBot.Modules {
|
||||
.Description("Queue a song using keywords or a link. Bot will join your voice channel. **You must be in a voice channel**.\n**Usage**: `!m q Dream Of Venice`")
|
||||
.Parameter("query", ParameterType.Unparsed)
|
||||
.Do(async e => {
|
||||
await QueueSong(e, e.GetArg("query"));
|
||||
await QueueSong(e.Channel, e.User.VoiceChannel, e.GetArg("query"));
|
||||
});
|
||||
|
||||
cgb.CreateCommand("lq")
|
||||
.Alias("ls").Alias("lp")
|
||||
.Description("Lists up to 15 currently queued songs.")
|
||||
.Do(async e => {
|
||||
if (musicPlayers.ContainsKey(e.Server) == false) {
|
||||
await e.Channel.SendMessage("🎵 No active music player.");
|
||||
MusicPlayer musicPlayer;
|
||||
if (!musicPlayers.TryGetValue(e.Server, out musicPlayer)) {
|
||||
await e.Channel.SendMessage("🎵 No active music musicPlayer.");
|
||||
return;
|
||||
}
|
||||
var player = musicPlayers[e.Server];
|
||||
string toSend = "🎵 **" + player.SongQueue.Count + "** `videos currently queued.` ";
|
||||
if (player.SongQueue.Count >= 50)
|
||||
string toSend = "🎵 **" + musicPlayer.Playlist.Count + "** `videos currently queued.` ";
|
||||
if (musicPlayer.Playlist.Count >= MusicPlayer.MaximumPlaylistSize)
|
||||
toSend += "**Song queue is full!**\n";
|
||||
int number = 1;
|
||||
await e.Channel.SendMessage(toSend + string.Join("\n", player.SongQueue.Take(15).Select(v => $"`{number++}.` {v.FullPrettyName}")));
|
||||
await e.Channel.SendMessage(toSend + string.Join("\n", musicPlayer.Playlist.Take(15).Select(v => $"`{number++}.` {v.PrettyName}")));
|
||||
});
|
||||
|
||||
cgb.CreateCommand("np")
|
||||
.Alias("playing")
|
||||
.Description("Shows the song currently playing.")
|
||||
.Do(async e => {
|
||||
if (musicPlayers.ContainsKey(e.Server) == false) return;
|
||||
var player = musicPlayers[e.Server];
|
||||
await e.Channel.SendMessage($"🎵`Now Playing` {player.CurrentSong.FullPrettyName}");
|
||||
});
|
||||
.Alias("playing")
|
||||
.Description("Shows the song currently playing.")
|
||||
.Do(async e => {
|
||||
MusicPlayer musicPlayer;
|
||||
if (!musicPlayers.TryGetValue(e.Server, out musicPlayer))
|
||||
return;
|
||||
await e.Channel.SendMessage($"🎵`Now Playing` {musicPlayer.CurrentSong.PrettyName}");
|
||||
});
|
||||
|
||||
cgb.CreateCommand("vol")
|
||||
.Description("Sets the music volume 0-150%")
|
||||
.Parameter("val", ParameterType.Required)
|
||||
.Do(async e => {
|
||||
if (musicPlayers.ContainsKey(e.Server) == false) return;
|
||||
var player = musicPlayers[e.Server];
|
||||
var arg = e.GetArg("val");
|
||||
int volume;
|
||||
if (!int.TryParse(arg, out volume)) {
|
||||
await e.Channel.SendMessage("Volume number invalid.");
|
||||
return;
|
||||
}
|
||||
volume = player.SetVolume(volume);
|
||||
await e.Channel.SendMessage($"🎵 `Volume set to {volume}%`");
|
||||
});
|
||||
.Description("Sets the music volume 0-150%")
|
||||
.Parameter("val", ParameterType.Required)
|
||||
.Do(async e => {
|
||||
MusicPlayer musicPlayer;
|
||||
if (!musicPlayers.TryGetValue(e.Server, out musicPlayer))
|
||||
return;
|
||||
var arg = e.GetArg("val");
|
||||
int volume;
|
||||
if (!int.TryParse(arg, out volume)) {
|
||||
await e.Channel.SendMessage("Volume number invalid.");
|
||||
return;
|
||||
}
|
||||
volume = musicPlayer.SetVolume(volume);
|
||||
await e.Channel.SendMessage($"🎵 `Volume set to {volume}%`");
|
||||
});
|
||||
|
||||
cgb.CreateCommand("dv")
|
||||
.Alias("defvol")
|
||||
@ -137,52 +137,56 @@ namespace NadekoBot.Modules {
|
||||
await e.Channel.SendMessage("Volume number invalid.");
|
||||
return;
|
||||
}
|
||||
musicVolumes.AddOrUpdate(e.Server.Id, volume / 100, (key, newval) => volume / 100);
|
||||
defaultMusicVolumes.AddOrUpdate(e.Server.Id, volume / 100, (key, newval) => volume / 100);
|
||||
await e.Channel.SendMessage($"🎵 `Default volume set to {volume}%`");
|
||||
});
|
||||
|
||||
cgb.CreateCommand("min").Alias("mute")
|
||||
.Description("Sets the music volume to 0%")
|
||||
.Do(e => {
|
||||
if (musicPlayers.ContainsKey(e.Server) == false) return;
|
||||
var player = musicPlayers[e.Server];
|
||||
player.SetVolume(0);
|
||||
MusicPlayer musicPlayer;
|
||||
if (!musicPlayers.TryGetValue(e.Server, out musicPlayer))
|
||||
return;
|
||||
musicPlayer.SetVolume(0);
|
||||
});
|
||||
|
||||
cgb.CreateCommand("max")
|
||||
.Description("Sets the music volume to 100% (real max is actually 150%).")
|
||||
.Do(e => {
|
||||
if (musicPlayers.ContainsKey(e.Server) == false) return;
|
||||
var player = musicPlayers[e.Server];
|
||||
player.SetVolume(100);
|
||||
});
|
||||
.Description("Sets the music volume to 100% (real max is actually 150%).")
|
||||
.Do(e => {
|
||||
MusicPlayer musicPlayer;
|
||||
if (!musicPlayers.TryGetValue(e.Server, out musicPlayer))
|
||||
return;
|
||||
musicPlayer.SetVolume(100);
|
||||
});
|
||||
|
||||
cgb.CreateCommand("half")
|
||||
.Description("Sets the music volume to 50%.")
|
||||
.Do(e => {
|
||||
if (musicPlayers.ContainsKey(e.Server) == false) return;
|
||||
var player = musicPlayers[e.Server];
|
||||
player.SetVolume(50);
|
||||
});
|
||||
.Description("Sets the music volume to 50%.")
|
||||
.Do(e => {
|
||||
MusicPlayer musicPlayer;
|
||||
if (!musicPlayers.TryGetValue(e.Server, out musicPlayer))
|
||||
return;
|
||||
musicPlayer.SetVolume(50);
|
||||
});
|
||||
|
||||
cgb.CreateCommand("sh")
|
||||
.Description("Shuffles the current playlist.")
|
||||
.Do(async e => {
|
||||
if (musicPlayers.ContainsKey(e.Server) == false) return;
|
||||
var player = musicPlayers[e.Server];
|
||||
if (player.SongQueue.Count < 2) {
|
||||
await e.Channel.SendMessage("Not enough songs in order to perform the shuffle.");
|
||||
MusicPlayer musicPlayer;
|
||||
if (!musicPlayers.TryGetValue(e.Server, out musicPlayer))
|
||||
return;
|
||||
if (musicPlayer.Playlist.Count < 2) {
|
||||
await e.Channel.SendMessage("💢 Not enough songs in order to perform the shuffle.");
|
||||
return;
|
||||
}
|
||||
|
||||
player.SongQueue.Shuffle();
|
||||
musicPlayer.Shuffle();
|
||||
await e.Channel.SendMessage("🎵 `Songs shuffled.`");
|
||||
});
|
||||
|
||||
cgb.CreateCommand("setgame")
|
||||
.Description("Sets the game of the bot to the number of songs playing.**Owner only**")
|
||||
.AddCheck(Classes.Permissions.SimpleCheckers.OwnerOnly())
|
||||
.Do(async e => {
|
||||
if (NadekoBot.OwnerID != e.User.Id)
|
||||
return;
|
||||
setgameEnabled = !setgameEnabled;
|
||||
if (setgameEnabled)
|
||||
setgameTimer.Start();
|
||||
@ -204,29 +208,28 @@ namespace NadekoBot.Modules {
|
||||
//todo TEMPORARY SOLUTION, USE RESOLVE QUEUE IN THE FUTURE
|
||||
var msg = await e.Channel.SendMessage($"🎵 `Attempting to queue {ids.Count} songs".SnPl(ids.Count) + "...`");
|
||||
foreach (var id in ids) {
|
||||
Task.Run(async () => await QueueSong(e, id, true));
|
||||
await Task.Delay(150);
|
||||
await QueueSong(e.Channel, e.User.VoiceChannel, id, true);
|
||||
}
|
||||
msg?.Edit("🎵 `Playlist queue complete.`");
|
||||
await msg.Edit("🎵 `Playlist queue complete.`");
|
||||
});
|
||||
|
||||
cgb.CreateCommand("lopl")
|
||||
.Description("Queues up to 50 songs from a directory.")
|
||||
.Parameter("directory", ParameterType.Unparsed)
|
||||
.AddCheck(Classes.Permissions.SimpleCheckers.OwnerOnly())
|
||||
.Do(async e => {
|
||||
var arg = e.GetArg("directory");
|
||||
if (string.IsNullOrWhiteSpace(e.GetArg("directory")))
|
||||
return;
|
||||
try {
|
||||
var fileEnum = System.IO.Directory.EnumerateFiles(e.GetArg("directory")).Take(50);
|
||||
foreach (var file in fileEnum) {
|
||||
await Task.Run(async () => await QueueSong(e, file, true, MusicType.Local)).ConfigureAwait(false);
|
||||
}
|
||||
await e.Channel.SendMessage("🎵 `Directory queue complete.`");
|
||||
}
|
||||
catch { }
|
||||
});
|
||||
.Description("Queues up to 50 songs from a directory.")
|
||||
.Parameter("directory", ParameterType.Unparsed)
|
||||
.AddCheck(Classes.Permissions.SimpleCheckers.OwnerOnly())
|
||||
.Do(async e => {
|
||||
var arg = e.GetArg("directory");
|
||||
if (string.IsNullOrWhiteSpace(e.GetArg("directory")))
|
||||
return;
|
||||
try {
|
||||
var fileEnum = System.IO.Directory.EnumerateFiles(e.GetArg("directory")).Take(50);
|
||||
foreach (var file in fileEnum) {
|
||||
await QueueSong(e.Channel, e.User.VoiceChannel, file, true, MusicType.Local);
|
||||
}
|
||||
await e.Channel.SendMessage("🎵 `Directory queue complete.`");
|
||||
}
|
||||
catch { }
|
||||
});
|
||||
|
||||
cgb.CreateCommand("radio").Alias("ra")
|
||||
.Description("Queues a direct radio stream from a link.")
|
||||
@ -236,41 +239,41 @@ namespace NadekoBot.Modules {
|
||||
await e.Channel.SendMessage("💢 You need to be in a voice channel on this server.\n If you are already in a voice channel, try rejoining it.");
|
||||
return;
|
||||
}
|
||||
await QueueSong(e, e.GetArg("radio_link"), musicType: MusicType.Radio);
|
||||
await QueueSong(e.Channel, e.User.VoiceChannel, e.GetArg("radio_link"), musicType: MusicType.Radio);
|
||||
});
|
||||
|
||||
cgb.CreateCommand("lo")
|
||||
.Description("Queues a local file by specifying a full path. BOT OWNER ONLY.")
|
||||
.Parameter("path", ParameterType.Unparsed)
|
||||
.AddCheck(Classes.Permissions.SimpleCheckers.OwnerOnly())
|
||||
.Do(async e => {
|
||||
var arg = e.GetArg("path");
|
||||
if (string.IsNullOrWhiteSpace(arg))
|
||||
return;
|
||||
await QueueSong(e, e.GetArg("path"), musicType: MusicType.Local);
|
||||
});
|
||||
.Description("Queues a local file by specifying a full path. BOT OWNER ONLY.")
|
||||
.Parameter("path", ParameterType.Unparsed)
|
||||
.AddCheck(Classes.Permissions.SimpleCheckers.OwnerOnly())
|
||||
.Do(async e => {
|
||||
var arg = e.GetArg("path");
|
||||
if (string.IsNullOrWhiteSpace(arg))
|
||||
return;
|
||||
await QueueSong(e.Channel, e.User.VoiceChannel, e.GetArg("path"), musicType: MusicType.Local);
|
||||
});
|
||||
|
||||
cgb.CreateCommand("mv")
|
||||
.Description("Moves the bot to your voice channel. (works only if music is already playing)")
|
||||
.Do(async e => {
|
||||
MusicPlayer mc;
|
||||
if (e.User.VoiceChannel == null || e.User.VoiceChannel.Server != e.Server || !musicPlayers.TryGetValue(e.Server, out mc))
|
||||
return;
|
||||
mc.VoiceChannel = e.User.VoiceChannel;
|
||||
mc.VoiceClient = await mc.VoiceChannel.JoinAudio();
|
||||
});
|
||||
.Description("Moves the bot to your voice channel. (works only if music is already playing)")
|
||||
.Do(e => {
|
||||
MusicPlayer musicPlayer;
|
||||
var voiceChannel = e.User.VoiceChannel;
|
||||
if (voiceChannel == null || voiceChannel.Server != e.Server || !musicPlayers.TryGetValue(e.Server, out musicPlayer))
|
||||
return;
|
||||
musicPlayer.MoveToVoiceChannel(voiceChannel);
|
||||
});
|
||||
|
||||
cgb.CreateCommand("rm")
|
||||
.Description("Remove a song by its # in the queue, or 'all' to remove whole queue.")
|
||||
.Parameter("num", ParameterType.Required)
|
||||
.Do(async e => {
|
||||
var arg = e.GetArg("num");
|
||||
MusicPlayer mc;
|
||||
if (!musicPlayers.TryGetValue(e.Server, out mc)) {
|
||||
MusicPlayer musicPlayer;
|
||||
if (!musicPlayers.TryGetValue(e.Server, out musicPlayer)) {
|
||||
return;
|
||||
}
|
||||
if (arg?.ToLower() == "all") {
|
||||
mc.SongQueue?.Clear();
|
||||
musicPlayer.ClearQueue();
|
||||
await e.Channel.SendMessage($"🎵`Queue cleared!`");
|
||||
return;
|
||||
}
|
||||
@ -278,193 +281,60 @@ namespace NadekoBot.Modules {
|
||||
if (!int.TryParse(arg, out num)) {
|
||||
return;
|
||||
}
|
||||
if (num <= 0 || num > mc.SongQueue.Count)
|
||||
if (num <= 0 || num > musicPlayer.Playlist.Count)
|
||||
return;
|
||||
|
||||
mc.SongQueue.RemoveAt(num - 1);
|
||||
musicPlayer.RemoveSongAt(num - 1);
|
||||
await e.Channel.SendMessage($"🎵**Track at position `#{num}` has been removed.**");
|
||||
});
|
||||
|
||||
cgb.CreateCommand("debug")
|
||||
.Description("Writes some music data to console. **BOT OWNER ONLY**")
|
||||
.AddCheck(Classes.Permissions.SimpleCheckers.OwnerOnly())
|
||||
.Do(e => {
|
||||
if (NadekoBot.OwnerID != e.User.Id)
|
||||
return;
|
||||
var output = "SERVER_NAME---SERVER_ID-----USERCOUNT----QUEUED\n" +
|
||||
string.Join("\n", musicPlayers.Select(kvp => kvp.Key.Name + "--" + kvp.Key.Id + " --" + kvp.Key.Users.Count() + "--" + kvp.Value.SongQueue.Count));
|
||||
string.Join("\n", musicPlayers.Select(kvp => kvp.Key.Name + "--" + kvp.Key.Id + " --" + kvp.Key.Users.Count() + "--" + kvp.Value.Playlist.Count));
|
||||
Console.WriteLine(output);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private async Task QueueSong(CommandEventArgs e, string query, bool silent = false, MusicType musicType = MusicType.Normal) {
|
||||
if (e.User.VoiceChannel?.Server != e.Server) {
|
||||
if (!silent)
|
||||
await e.Channel.SendMessage("💢 You need to be in a voice channel on this server.\n If you are already in a voice channel, try rejoining.");
|
||||
return;
|
||||
private async Task QueueSong(Channel TextCh, Channel VoiceCh, string query, bool silent = false, MusicType musicType = MusicType.Normal) {
|
||||
if (VoiceCh == null || VoiceCh.Server != TextCh.Server) {
|
||||
if(!silent)
|
||||
await TextCh.SendMessage("💢 You need to be in a voice channel on this server.\n If you are already in a voice channel, try rejoining.");
|
||||
throw new ArgumentNullException(nameof(VoiceCh));
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(query) || query.Length < 3)
|
||||
return;
|
||||
|
||||
query = query.Trim();
|
||||
if (musicType != MusicType.Local && IsRadioLink(query)) {
|
||||
musicType = MusicType.Radio;
|
||||
query = await HandleStreamContainers(query) ?? query;
|
||||
}
|
||||
|
||||
if (musicPlayers.ContainsKey(e.Server) == false) {
|
||||
throw new ArgumentException("💢 Invalid query for queue song.", nameof(query));
|
||||
MusicPlayer musicPlayer = null;
|
||||
if (!musicPlayers.TryGetValue(TextCh.Server, out musicPlayer)) {
|
||||
float? vol = null;
|
||||
float throwAway;
|
||||
if (musicVolumes.TryGetValue(e.Server.Id, out throwAway))
|
||||
if (defaultMusicVolumes.TryGetValue(TextCh.Server.Id, out throwAway))
|
||||
vol = throwAway;
|
||||
|
||||
if (!musicPlayers.TryAdd(e.Server, new MusicPlayer(e.User.VoiceChannel, e, vol))) {
|
||||
await e.Channel.SendMessage("Failed to create a music player for this server.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var player = musicPlayers[e.Server];
|
||||
|
||||
if (player.SongQueue.Count >= 50) return;
|
||||
|
||||
try {
|
||||
var sr = new StreamRequest(e, query, player, musicType);
|
||||
|
||||
if (sr == null)
|
||||
throw new NullReferenceException("StreamRequest is null.");
|
||||
|
||||
Message qmsg = null;
|
||||
Message msg = null;
|
||||
if (!silent) {
|
||||
try {
|
||||
qmsg = await e.Channel.SendMessage("🎵 `Searching / Resolving...`");
|
||||
sr.OnResolvingFailed += async (err) => {
|
||||
try {
|
||||
await qmsg.Delete();
|
||||
await e.Channel.Send($"💢 🎵 `Resolving failed` for **{query}**");
|
||||
}
|
||||
catch { }
|
||||
};
|
||||
sr.OnQueued += async () => {
|
||||
try {
|
||||
await qmsg.Delete();
|
||||
await e.Channel.Send($"🎵`Queued`{sr.FullPrettyName}");
|
||||
}
|
||||
catch { }
|
||||
};
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
sr.OnCompleted += async () => {
|
||||
try {
|
||||
MusicPlayer mc;
|
||||
if (musicPlayers.TryGetValue(e.Server, out mc)) {
|
||||
if (mc.SongQueue.Count == 0)
|
||||
mc.Stop();
|
||||
musicPlayer = new MusicPlayer(VoiceCh) {
|
||||
OnCompleted = async (song) => {
|
||||
try {
|
||||
await TextCh.SendMessage($"🎵`Finished`{song.PrettyName}");
|
||||
}
|
||||
await e.Channel.SendMessage($"🎵`Finished`{sr.FullPrettyName}");
|
||||
}
|
||||
catch { }
|
||||
catch { }
|
||||
},
|
||||
OnStarted = async (song) => {
|
||||
try {
|
||||
var msgTxt = $"🎵`Playing`{song.PrettyName} `Vol: {(int)(musicPlayer.Volume * 100)}%`";
|
||||
await TextCh.SendMessage(msgTxt);
|
||||
}
|
||||
catch { }
|
||||
},
|
||||
};
|
||||
musicPlayers.TryAdd(TextCh.Server, musicPlayer);
|
||||
}
|
||||
var resolvedSong = await Song.ResolveSong(query, musicType);
|
||||
|
||||
sr.OnStarted += async () => {
|
||||
try {
|
||||
var msgTxt = $"🎵`Playing`{sr.FullPrettyName} `Vol: {(int)(player.Volume * 100)}%`";
|
||||
if (qmsg != null)
|
||||
await qmsg.Delete();
|
||||
await e.Channel.SendMessage(msgTxt);
|
||||
}
|
||||
catch { }
|
||||
};
|
||||
|
||||
await sr.Resolve();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
await e.Channel.SendMessage($"💢 {ex.Message}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsRadioLink(string query) =>
|
||||
(query.StartsWith("http") ||
|
||||
query.StartsWith("ww"))
|
||||
&&
|
||||
(query.Contains(".pls") ||
|
||||
query.Contains(".m3u") ||
|
||||
query.Contains(".asx") ||
|
||||
query.Contains(".xspf"));
|
||||
|
||||
private async Task<string> HandleStreamContainers(string query) {
|
||||
string file = null;
|
||||
try {
|
||||
file = await SearchHelper.GetResponseAsync(query);
|
||||
}
|
||||
catch {
|
||||
return query;
|
||||
}
|
||||
if (query.Contains(".pls")) {
|
||||
//File1=http://armitunes.com:8000/
|
||||
//Regex.Match(query)
|
||||
try {
|
||||
var m = Regex.Match(file, "File1=(?<url>.*?)\\n");
|
||||
var res = m.Groups["url"]?.ToString();
|
||||
return res?.Trim();
|
||||
}
|
||||
catch {
|
||||
Console.WriteLine($"Failed reading .pls:\n{file}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else if (query.Contains(".m3u")) {
|
||||
/*
|
||||
# This is a comment
|
||||
C:\xxx4xx\xxxxxx3x\xx2xxxx\xx.mp3
|
||||
C:\xxx5xx\x6xxxxxx\x7xxxxx\xx.mp3
|
||||
*/
|
||||
try {
|
||||
var m = Regex.Match(file, "(?<url>^[^#].*)", RegexOptions.Multiline);
|
||||
var res = m.Groups["url"]?.ToString();
|
||||
return res?.Trim();
|
||||
}
|
||||
catch {
|
||||
Console.WriteLine($"Failed reading .m3u:\n{file}");
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
else if (query.Contains(".asx")) {
|
||||
//<ref href="http://armitunes.com:8000"/>
|
||||
try {
|
||||
var m = Regex.Match(file, "<ref href=\"(?<url>.*?)\"");
|
||||
var res = m.Groups["url"]?.ToString();
|
||||
return res?.Trim();
|
||||
}
|
||||
catch {
|
||||
Console.WriteLine($"Failed reading .asx:\n{file}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else if (query.Contains(".xspf")) {
|
||||
/*
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<playlist version="1" xmlns="http://xspf.org/ns/0/">
|
||||
<trackList>
|
||||
<track><location>file:///mp3s/song_1.mp3</location></track>
|
||||
*/
|
||||
try {
|
||||
var m = Regex.Match(file, "<location>(?<url>.*?)</location>");
|
||||
var res = m.Groups["url"]?.ToString();
|
||||
return res?.Trim();
|
||||
}
|
||||
catch {
|
||||
Console.WriteLine($"Failed reading .xspf:\n{file}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return query;
|
||||
if(!silent)
|
||||
await TextCh.Send($"🎵`Queued`{resolvedSong.PrettyName}");
|
||||
musicPlayer.AddSong(resolvedSong);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user