using System; using System.IO; using System.Net; using System.Security.Cryptography; using System.Text; using Shared.Net; using Shared.SimpleControl.R; using SmartHome.UI.SimpleControl.Phone.Music; namespace Shared.SimpleControl.Phone.Music { [System.Serializable] public class TidalConfig { public readonly static string FileName = "TidalConfig"; /// /// 用户名 /// public string UserName; /// /// 密码 /// public string Passwrod; } [System.Serializable] public class Tidal { public static string fileName = "Tidal"; #region public static readonly System.Collections.Generic.List TempMusicInfoList = new System.Collections.Generic.List (); #endregion //保存当前信息 public void Save () { Shared.IO.FileUtils.WriteFileByBytes (fileName, System.Text.Encoding.UTF8.GetBytes (Newtonsoft.Json.JsonConvert.SerializeObject (CurrentTidal))); } public static string GetResult (string url) { var datetTime = DateTime.Now; var webclient = new MyWebClient (); webclient.Proxy = null; webclient.Headers.Add ("Authorization", "Basic " + Authorization); var resut = webclient.DownloadString (url); System.Console.WriteLine (url + "获取数据时长:" + (DateTime.Now - datetTime).TotalMilliseconds); return resut; //var datetTime = DateTime.Now; //var result = httpRequest.HTTPRequest.HTTPRequestA (url, "Authorization", "Basic " + Authorization, 10); //System.Console.WriteLine (url + "获取数据时长:" + (DateTime.Now - datetTime).TotalMilliseconds); //if (result == null) { // return null; //} else { // return System.Text.Encoding.UTF8.GetString (result.ToArray ()); //} } public static void InitTokenTime () { Shared.IO.FileUtils.DeleteFile (fileName); CurrentTidal = null; //尝试获取多次,有可能有的时候网络有问题获取不成功 int count = 2; while (0 < count) { count--; if (initTokenTime ()) { //如果获取到时间,就马上退出 break; } } } /// /// 获取真实播放地址 /// /// Music info. public static void ReadRealUrl (MusicInfo musicInfo) { try { if (musicInfo.URL.StartsWith ("https://meta.airable.io")) { var result = GetResult (musicInfo.URL); if (!string.IsNullOrEmpty (result)) { var airable = Newtonsoft.Json.JsonConvert.DeserializeObject (result); if (airable != null && airable.url != null) musicInfo.URL = airable.url; } } } catch { } } static Tidal () { new Tidal { IsLogin = false, id = new string [0], time = 0, token = "" }; if (Shared.IO.FileUtils.Exists (fileName)) { CurrentTidal = Newtonsoft.Json.JsonConvert.DeserializeObject (System.Text.Encoding.UTF8.GetString (Shared.IO.FileUtils.ReadFile (fileName))); } } //是否已经登录了 public bool IsLogin; /// /// 当前Token /// public string token; /// /// 服务器记录时间 /// public long time; public string [] id; // "{\"id\":[\"airable\",\"accesstoken\",\"authentication\"],\"token\":\"6ALMArG5kLS6kciUvYuiBhaeXO1JQMGBk8qXEslY9tvSghVIpdwggVRZ1QDsLR3i\",\"time\":1512032632}" public static Tidal CurrentTidal { internal set; get; } //ECJUFDFLAIA static string secret = "PJFKwfIWH7LIoaYGqlEOe5x2QzLCzcVN"; static string @name = "audiocast"; static string version = "1.0"; static string locale = "en-US"; public static string Authorization { get { if (CurrentTidal == null) { return null; } var ts = (DateTime.UtcNow - new DateTime (1970, 1, 1, 0, 0, 0, 0)); var time = Convert.ToInt64 (ts.TotalSeconds).ToString (); var result = Encoding.ASCII.GetBytes (CurrentTidal.token + secret + time); var output = new MD5CryptoServiceProvider ().ComputeHash (result); var password = BitConverter.ToString (output).Replace ("-", "").ToLower (); return Convert.ToBase64String (System.Text.Encoding.ASCII.GetBytes (CurrentTidal.token + ":" + password)); } } static bool initTokenTime () { try { string salt = "345548ab"; var deviceUniqueId = DateTime.Now.Ticks.ToString(); string ss = string.Format ("{0}{1}{2}{3}",deviceUniqueId , locale, salt, secret); var result = Encoding.ASCII.GetBytes (ss); var output = new MD5CryptoServiceProvider ().ComputeHash (result); var password = BitConverter.ToString (output).Replace ("-", "").ToLower (); string url = string.Format ("https://meta.airable.io/authentication?device={0}&name={1}&version={2}&locale={3}&salt={4}&signature={5}", deviceUniqueId, name, version, locale, salt, password ); var dateTime = DateTime.Now; CurrentTidal = Newtonsoft.Json.JsonConvert.DeserializeObject (GetResult (url)); System.Console.WriteLine ("获取Token时间时长:" + (DateTime.Now - dateTime).TotalMilliseconds); //如果获取到时候及Token,马上保存 CurrentTidal.Save (); return true; } catch { return false; } } public static bool Login () { InitTokenTime (); try { //可能网络或者其它原因,时间获取不到,下面代码不能执行 if (CurrentTidal == null) { return false; } var tidal = Newtonsoft.Json.JsonConvert.DeserializeObject (Encoding.UTF8.GetString (Shared.IO.FileUtils.ReadFile (TidalConfig.FileName))); if (tidal != null) { var result = GetResult ("https://meta.airable.io/tidal/login?username=" + tidal.UserName + "&password=" + tidal.Passwrod); var musics = Newtonsoft.Json.JsonConvert.DeserializeObject (result); if (musics.title != "TIDAL") { return false; } CurrentTidal.IsLogin = true; CurrentTidal.Save (); return true; } } catch { } return false; } public static void ReadPlayList (string path, Action gotoLoginActon, Action gotoPageAction) { MainPage.Loading.Start (Language.StringByID (MyInternationalizationString.load)); System.Threading.Tasks.Task.Run (() => { try { var list = TempMusicInfoList.FindAll ((obj) => obj.Tag.ToString() == path); if (list.Count != 0) { return; } var result = GetResult ("https://meta.airable.io/"+path); if (result == null) { result = GetResult ("https://meta.airable.io/"+path); if (result == null) { return; } } var tracks = Newtonsoft.Json.JsonConvert.DeserializeObject (result); //token过期,需要重新登录. if (tracks.id != null) { if (tracks.id [2].ToString () == "authorization") { if (!Login ()) { return; } } } foreach (var v in tracks.content.entries) { var tidalMusicInfo = new MusicInfo () { Tag = path }; if (v.title != null) { tidalMusicInfo.Title = v.title.Replace ("&", ""); } if (v.url != null) { tidalMusicInfo.ID = v.url.Replace ("https://meta.airable.io/", ""); } if (v.id != null) { tidalMusicInfo.IsDirectory = v.id [1].ToString () != "track"; } if (v.album != null) { tidalMusicInfo.Album = v.album.title.Replace ("&", ""); } if (v.artist != null) { tidalMusicInfo.Artist = v.artist.title.Replace ("&", ""); } if (v.streams != null && 0 < v.streams.Length) { tidalMusicInfo.URL = v.streams [0].url; } if (v.images != null) { #region 初始化网络图片路径 string pathIm = ""; if (Shared.Application.IsPad) { pathIm = ""; } else { pathIm = "Phone/" + "MusicImage/"; } pathIm = System.IO.Path.Combine (Shared.IO.FileUtils.RootPath, pathIm + v.images [0].url.Replace ('/', '_').Replace ('\\', '_').Replace (':', '_').Replace ('*', '_').Replace ('?', '_').Replace ('"', '_').Replace ('<', '_').Replace ('>', '_').Replace ('|', '_')); tidalMusicInfo.Image = pathIm; #endregion Shared.IO.FileUtils.DownLoadImage (tidalMusicInfo.Image, v.images [0].url); } if (!tidalMusicInfo.IsDirectory && tidalMusicInfo.URL == null) { } else { TempMusicInfoList.Add (tidalMusicInfo); } } } catch { } finally { if (gotoPageAction != null) { gotoPageAction (path); } } }); } } }