using DualScreenDemo; using System; using System.IO; using System.Net; using System.Windows.Markup; namespace DBObj { public class SongData { private Song basic; private Artist A; private Artist B; public bool isPublicSong { get; set; } public PlayState state; public SongData() { basic = new("", "", "", "", 0, 1, ""); A = new("", ""); // B = new(null, null); isPublicSong = false; } public SongData(string songNumber, string song, string filename, int humanVoice, bool isPublic) { basic = new(songNumber, song, "", filename, humanVoice, 0, ""); isPublicSong = isPublic; } public SongData(string songNumber, string song, string artistA, string artistB, string filename, string artistASimplified, string artistBSimplified, string songSimplified, int humanVoice, int dbChange, string situation) { basic = new(songNumber, song, songSimplified, filename, humanVoice, dbChange, situation); A = new Artist(artistA, artistASimplified); B = !artistB.Equals("") ? new Artist(artistB, artistBSimplified) : null; isPublicSong = false; } public SongData(SongData value, PlayState s) { basic = value.getBasic(); A = value.getA(); B = value.getB(); state = s; } public Song getBasic() => basic; public Artist getA() => A; public Artist getB() => B; public string getNumber() => basic.getNumber(); public string getName(bool IsSimplified = false) => basic.getName(IsSimplified); public string getName() => basic.getName(); public string getArtist_A(bool IsSimplified) => A.getName(IsSimplified); public string getArtist_A() => A.getName(); public string getArtist_B(bool IsSimplified) => B.getName(IsSimplified); public string getArtist_B() => B.getName(); public int getNameLength() => basic.getName().Length; public string getFileName() => basic.getFileName(); public string next_song_text() { var str = (state == PlayState.InsertPlayback) ? GetStateTxt(false) : ""; return String.Format("下一首:{0} {1}", basic.getName(false), str); } public string artist_text() { return B != null ? $"{A.getName(false)} - {B.getName(false)}" : A.getName(false); } public string name_text() { return B != null ? String.Format("{0} - {1} - {2}", A.getName(false), B.getName(false), basic.getName(false)) : String.Format("{0} - {1}", A.getName(false), basic.getName(false)); } public bool FileExistsInServers() { foreach (var server in Utils.Env.GetSongServers()) { try { // string fullPath = Path.Combine(server, basic.getFileName()); Uri fullUri = new Uri(new Uri(server), basic.getFileName()); // if (File.Exists(fullPath)) // { // Console.WriteLine($"找到檔案: {fullPath}"); return true; // } } catch (Exception ex) { Console.WriteLine($"檢查檔案時發生錯誤: {ex.Message}"); } } Console.WriteLine($"全部 server 都找不到檔案: {basic.getFileName()}"); return false; } public string getFile() { return FindExistingPath(basic.getFileName()); } private string FindExistingPath(string filename) { foreach (var server in Utils.Env.GetSongServers()) { string fullPath = Path.Combine(server, filename); if (File.Exists(fullPath)) return fullPath; } return null; // 找不到就回原本的 filename,不加路徑 } public Uri getFileUrl() { if (!isPublicSong) { return GetUri(basic.getFileName()); } return null; } private Uri GetUri(string filename) { foreach (var server in Utils.Env.GetSongServers()) { var check = IsFtpUriReachable(new Uri(server).ToString()); if (!string.IsNullOrWhiteSpace(server) && check != false) { // Console.WriteLine(new Uri(new Uri(server), filename)); if (IsFtpUriReachable(new Uri(new Uri(server), filename).ToString())) return new Uri(new Uri(server), filename); } } // throw new InvalidOperationException("No valid server found."); if (!isPublicSong) Console.WriteLine("No valid server found."); return null; } public Color GetStateColor() => state switch { PlayState.Played => Color.Gray, PlayState.Skipped => Color.Gray, PlayState.NoFile => Color.Gray, PlayState.Playing => Color.LimeGreen, PlayState.InsertPlayback => Color.Gold, _ => Color.White }; public string GetStateTxt(bool IsSimplified) => (state == PlayState.NotPlayed) ? "" : $"({state.GetDescription(IsSimplified)})"; public void SetState(PlayState s) => state = s; public PlayState GetState() => state; public int getHumanVoice() => basic.getHumanVoice(); public override string ToString() { return String.Format("{0} {1}", basic.getName(), state.GetDescription()); } public bool IsFtpUriReachable(string ftpUri) { try { #pragma warning disable SYSLIB0014 // 類型或成員已經過時 var request = (FtpWebRequest)WebRequest.Create(ftpUri); #pragma warning restore SYSLIB0014 // 類型或成員已經過時 request.Method = WebRequestMethods.Ftp.ListDirectory; // Lightweight check // request.Credentials = new NetworkCredential("svr", "svr"); // Replace with actual username/password request.Timeout = 5000; using var response = (FtpWebResponse)request.GetResponse(); return response.StatusCode == FtpStatusCode.OpeningData || response.StatusCode == FtpStatusCode.DataAlreadyOpen; } catch (WebException ex) { if (ex.Response is FtpWebResponse ftpResponse) { Console.WriteLine($"FTP error: {ftpResponse.StatusDescription}"); return false; } Console.WriteLine($"Connection error: {ex.Message}"); return false; } catch (Exception ex) { Console.WriteLine($"Unexpected error: {ex.Message}"); return false; } } public static bool IsFtpUri(Uri uri) { return uri != null && uri.Scheme == Uri.UriSchemeFtp; } } }