using System; using System.Net.Http; using System.Text.RegularExpressions; using System.Threading.Tasks; using NadekoBot.Core.Modules.Music; using NadekoBot.Extensions; using Serilog; namespace NadekoBot.Modules.Music.Resolvers { public class RadioResolver : IRadioResolver { private readonly Regex plsRegex = new Regex("File1=(?.*?)\\n", RegexOptions.Compiled); private readonly Regex m3uRegex = new Regex("(?^[^#].*)", RegexOptions.Compiled | RegexOptions.Multiline); private readonly Regex asxRegex = new Regex(".*?)\"", RegexOptions.Compiled); private readonly Regex xspfRegex = new Regex("(?.*?)", RegexOptions.Compiled); public RadioResolver() { } public async Task ResolveByQueryAsync(string query) { if (IsRadioLink(query)) query = await HandleStreamContainers(query).ConfigureAwait(false); return new SimpleTrackInfo( query.TrimTo(50), query, "https://cdn.discordapp.com/attachments/155726317222887425/261850925063340032/1482522097_radio.png", TimeSpan.MaxValue, MusicPlatform.Radio, query ); } public static bool IsRadioLink(string query) => (query.StartsWith("http", StringComparison.InvariantCulture) || query.StartsWith("ww", StringComparison.InvariantCulture)) && (query.Contains(".pls") || query.Contains(".m3u") || query.Contains(".asx") || query.Contains(".xspf")); private async Task HandleStreamContainers(string query) { string file = null; try { using (var http = new HttpClient()) { file = await http.GetStringAsync(query).ConfigureAwait(false); } } catch { return query; } if (query.Contains(".pls")) { //File1=http://armitunes.com:8000/ //Regex.Match(query) try { var m = plsRegex.Match(file); var res = m.Groups["url"]?.ToString(); return res?.Trim(); } catch { Log.Warning($"Failed reading .pls:\n{file}"); return null; } } if (query.Contains(".m3u")) { /* # This is a comment C:\xxx4xx\xxxxxx3x\xx2xxxx\xx.mp3 C:\xxx5xx\x6xxxxxx\x7xxxxx\xx.mp3 */ try { var m = m3uRegex.Match(file); var res = m.Groups["url"]?.ToString(); return res?.Trim(); } catch { Log.Warning($"Failed reading .m3u:\n{file}"); return null; } } if (query.Contains(".asx")) { // try { var m = asxRegex.Match(file); var res = m.Groups["url"]?.ToString(); return res?.Trim(); } catch { Log.Warning($"Failed reading .asx:\n{file}"); return null; } } if (query.Contains(".xspf")) { /* file:///mp3s/song_1.mp3 */ try { var m = xspfRegex.Match(file); var res = m.Groups["url"]?.ToString(); return res?.Trim(); } catch { Log.Warning($"Failed reading .xspf:\n{file}"); return null; } } return query; } } }