superstar_v2/HttpServer.cs

1251 lines
55 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using Newtonsoft.Json; // For JsonConvert and JsonException
using System.Drawing.Imaging; // For ImageFormat
using ZXing; // For BarcodeWriter and BarcodeFormat
using ZXing.QrCode; // For QrCodeEncodingOptions
using ActionString = System.Action<string>; // 现在可以在代码中使用 ActionString
using System.Collections.Concurrent;
using DBObj;
using OverlayFormObj;
namespace DualScreenDemo
{
public class HttpServer
{
private static string _localIP = GetLocalIPAddress();
private static int _port = 9090; // 或其他方式設置
// 服务器类变量
private static SongListManager songListManager;
// 使用完整命名空间来避免歧义
public static event ActionString OnDisplayBarrage;
private static DateTime lastClickTime = DateTime.MinValue;
public static string randomFolderPath; // 声明全局变量
//private static OverlayForm form;
private static readonly ConcurrentDictionary<string, byte[]> _fileCache = new ConcurrentDictionary<string, byte[]>();
private static readonly SemaphoreSlim _requestThrottle = new SemaphoreSlim(20); // 限制并发请求数
private static readonly CancellationTokenSource _serverCts = new CancellationTokenSource();
private static HttpListener _listener;
private static CancellationTokenSource _cts;
private static Task _serverTask;
private static string _baseDirectory = @"themes\superstar\_www"; // 根據實際情況設定
private static TaskCompletionSource<string> _qrReadyTcs;
public static async Task StartServer(string baseDirectory, int port, SongListManager manager, CancellationToken token)
{
songListManager = manager;
string randomFolderName = CreateRandomFolderAndRedirectHTML(baseDirectory);
randomFolderPath = randomFolderName;
// 安裝包更新
string localAddress = GetLocalIPAddress();
string externalAddress = Utils.Env.Get("PhoneIP", "").Trim();
_listener = new HttpListener();
_listener.Prefixes.Add($"http://{localAddress}:{port}/");
string hostName = System.Net.Dns.GetHostName();
string externalPort = '1' + hostName.Substring(Math.Max(2, hostName.Length - 20));
if (!string.IsNullOrEmpty(externalAddress))
{
string host = externalAddress.Split(':')[0];
externalPort = '1' + System.Net.Dns.GetHostName().Substring(Math.Max(2, System.Net.Dns.GetHostName().Length - 20));
_listener.Prefixes.Add($"http://{host}:{externalPort}/");
}
string localQrContent = String.Format("http://{0}:{1}/{2}/windows.html", localAddress, port, randomFolderName);
// 修改外网二维码内容生成
string externalQrContent = !string.IsNullOrEmpty(externalAddress) ?
String.Format("http://{0}:{1}/{2}/windows.html", externalAddress, externalPort, randomFolderName) :
localQrContent;
GenerateQRCode(externalQrContent, Path.Combine(baseDirectory, randomFolderName, "qrcode.png"));
_qrReadyTcs?.TrySetResult(randomFolderName); // safe callnull-safe
try
{
_listener.Start();
Console.WriteLine("Server started : " + externalQrContent);
}
catch (HttpListenerException ex)
{
Console.WriteLine("Error starting server: " + ex.Message);
return;
}
while (!token.IsCancellationRequested)
{
try
{
HttpListenerContext context = await _listener.GetContextAsync();
await ProcessRequestAsync(context, baseDirectory, randomFolderName);
}
catch (HttpListenerException)
{
// 可能是 Stop() 引起,不處理
break;
}
}
_listener.Close();
Console.WriteLine("Server stopped.");
}
public static async Task RestartServer()
{
Console.WriteLine("Restarting server...");
_cts?.Cancel();
_listener?.Stop();
if (_serverTask != null)
{
try { await _serverTask; }
catch (OperationCanceledException) { }
}
DeleteRandomFolder(_baseDirectory);
_cts = new CancellationTokenSource();
// ✅ 等 QR code 跑完
_qrReadyTcs = new TaskCompletionSource<string>();
_serverTask = StartServer(_baseDirectory, _port, songListManager, _cts.Token);
string readyFolder = await _qrReadyTcs.Task;
// ✅ 等 QR Code 圖片準備好之後再處理 UI 更新
Console.WriteLine("restart : " + readyFolder);
PrimaryForm.Instance.OverlayQRCodeOnImage(readyFolder);
OverlayForm.Instance.DisplayQRCodeOnOverlay(readyFolder);
}
private static async Task ProcessRequestWithTimeout(HttpListenerContext context, string baseDirectory, string randomFolderName)
{
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
try
{
await _requestThrottle.WaitAsync(cts.Token);
try
{
await ProcessRequestAsync(context, baseDirectory, randomFolderName);
}
finally
{
_requestThrottle.Release();
}
}
catch (OperationCanceledException)
{
context.Response.StatusCode = 408; // Request Timeout
context.Response.Close();
}
catch (Exception ex)
{
Console.WriteLine($"Error processing request: {ex.Message}");
try
{
context.Response.StatusCode = 500;
context.Response.Close();
}
catch { }
}
}
public static void DeleteRandomFolder(string baseDirectory)
{
string fullPath = Path.Combine(baseDirectory, randomFolderPath);
if (Directory.Exists(fullPath))
{
try
{
Directory.Delete(fullPath, true);
Console.WriteLine("刪除 random folder: " + fullPath);
}
catch (Exception ex)
{
Console.WriteLine("錯誤 deleting random folder: " + ex.Message);
}
}
}
public static string GetServerAddress()
{
return String.Format("http://{0}:{1}/", _localIP, _port);
}
/// <summary>
/// 生成隨機路徑
/// </summary>
/// <param name="baseDirectory"></param>
/// <returns></returns>
private static string CreateRandomFolderAndRedirectHTML(string baseDirectory)
{
string randomFolderName = Path.GetRandomFileName().Replace(".", "");
string randomFolderPath = Path.Combine(baseDirectory, randomFolderName);
Directory.CreateDirectory(randomFolderPath);
Console.WriteLine(String.Format("Created random folder: {0}", randomFolderPath));
string sourceHTMLPath = Path.Combine(baseDirectory, "windows.html");
string targetHTMLPath = Path.Combine(randomFolderPath, "windows.html");
File.Copy(sourceHTMLPath, targetHTMLPath, true);
Console.WriteLine(String.Format("Copied windows.html to {0}", targetHTMLPath));
// 在生成的 HTML 中注入随机路径
string htmlContent = File.ReadAllText(sourceHTMLPath);
htmlContent = htmlContent.Replace("var randomFolder = '';", String.Format("var randomFolder = '{0}';", randomFolderName));
File.WriteAllText(targetHTMLPath, htmlContent);
return randomFolderName;
}
// 生成 QR 码并返回图像路径
public static string GenerateQRCode(string content, string savePath)
{
var writer = new BarcodeWriter
{
Format = BarcodeFormat.QR_CODE,
Options = new QrCodeEncodingOptions
{
Height = 165,
Width = 165,
Margin = 0
}
};
using (var bitmap = writer.Write(content))
{
bitmap.Save(savePath, ImageFormat.Png);
return savePath;
}
}
private static async Task ProcessRequestAsync(HttpListenerContext context, string baseDirectory, string randomFolderName)
{
try
{
// 添加CORS头
context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
context.Response.Headers.Add("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
context.Response.Headers.Add("Access-Control-Allow-Headers", "Content-Type");
// 处理OPTIONS请求
if (context.Request.HttpMethod == "OPTIONS")
{
context.Response.StatusCode = 200;
context.Response.Close();
return;
}
// 添加基本的缓存控制
context.Response.Headers.Add("Cache-Control", "public, max-age=3600");
if (context.Request.HttpMethod == "POST")
{
string relativePath = context.Request.Url.AbsolutePath.Replace($"/{randomFolderName}", "");
Console.WriteLine("Received request for path: " + relativePath);
switch (relativePath)
{
case "/search":
await HandleSearchRequest(context);
break;
case "/signal":
await HandleSignalRequest(context);
break;
case "/sound-control":
await HandleSoundControlRequest(context);
break;
case "/send-sticker":
await HandleStickerRequest(context);
break;
case "/order-song":
await HandleOrderSongRequest(context);
break;
case "/insert-song":
await HandleInsertSongRequest(context);
break;
case "/ordered-song":
await HandleOrderSongListRequest(context);
break;
case "/message":
await HandlemessageRequest(context);
break;
case "/favorite":
await HandleFavoriteRequest(context);
break;
default:
context.Response.StatusCode = 404;
break;
}
}
else if (context.Request.HttpMethod == "GET")
{
// 获取请求的完整URL路径
string requestPath = context.Request.Url.AbsolutePath;
// 如果是根路径访问直接返回404
if (requestPath == "/" || requestPath == "/windows.html")
{
context.Response.StatusCode = (int)HttpStatusCode.NotFound;
return;
}
string requestedFile = context.Request.Url.LocalPath.Replace($"/{randomFolderName}/", "");
if (string.IsNullOrEmpty(requestedFile.Trim('/')))
{
requestedFile = "windows.html";
}
await HandleGetRequest(context, baseDirectory, requestedFile);
}
}
catch (Exception ex)
{
Console.WriteLine($"Error processing request: {ex.Message}");
try
{
context.Response.StatusCode = 500;
context.Response.Close();
}
catch { }
}
finally
{
try
{
context.Response.Close();
}
catch { }
}
}
private static async Task SendJsonResponseAsync(HttpListenerContext context, object data, int statusCode = 200)
{
try
{
string jsonResponse = JsonConvert.SerializeObject(data);
byte[] buffer = Encoding.UTF8.GetBytes(jsonResponse);
context.Response.StatusCode = statusCode;
context.Response.ContentType = "application/json; charset=utf-8";
context.Response.ContentLength64 = buffer.Length;
await context.Response.OutputStream.WriteAsync(buffer, 0, buffer.Length);
}
catch (Exception ex)
{
Console.WriteLine($"Error sending JSON response: {ex.Message}");
context.Response.StatusCode = 500;
}
}
// 點歌問題
private static async Task HandleSearchRequest(HttpListenerContext context)
{
try
{
string requestBody = await ReadRequestBodyAsync(context.Request);
var searchRequest = JsonConvert.DeserializeObject<SearchRequest>(requestBody);
List<SongData> searchResults;
switch (searchRequest.Type)
{
case "new-songs":
searchResults = songListManager.SearchNewSongs();
break;
case "top-ranking":
searchResults = songListManager.SearchHotSongs();
break;
case "singer":
Console.WriteLine("Query : " + searchRequest.Query);
searchResults = songListManager.SearchSongsBySinger(searchRequest.Query);
break;
case "song":
searchResults = songListManager.SearchSongsByName(searchRequest.Query);
break;
default:
searchResults = new List<SongData>();
break;
}
await SendJsonResponseAsync(context, searchResults);
}
catch (Exception ex)
{
Console.WriteLine($"Error handling search request: {ex.Message}");
await SendJsonResponseAsync(context, new { error = "Search failed" }, 500);
}
}
private static async Task<string> ReadRequestBodyAsync(HttpListenerRequest request)
{
using var reader = new StreamReader(request.InputStream, request.ContentEncoding);
return await reader.ReadToEndAsync();
}
private static async Task HandleSignalRequest(HttpListenerContext context)
{
Console.WriteLine("Handling signal request...");
string requestBody;
using (var reader = new StreamReader(context.Request.InputStream, context.Request.ContentEncoding))
{
requestBody = await reader.ReadToEndAsync();
}
Console.WriteLine("Received POST body: " + requestBody);
var responseMessage = new { status = "Signal received" };
string jsonResponse = JsonConvert.SerializeObject(responseMessage);
byte[] buffer = Encoding.UTF8.GetBytes(jsonResponse);
context.Response.ContentType = "application/json";
context.Response.ContentLength64 = buffer.Length;
context.Response.StatusCode = (int)HttpStatusCode.OK;
await context.Response.OutputStream.WriteAsync(buffer, 0, buffer.Length);
}
private static async Task HandleSoundControlRequest(HttpListenerContext context)
{
string requestBody;
using (var reader = new StreamReader(context.Request.InputStream, context.Request.ContentEncoding))
{
requestBody = await reader.ReadToEndAsync();
}
Console.WriteLine("Received sound control command: " + requestBody);
try
{
var data = JsonConvert.DeserializeObject<SoundControlRequest>(requestBody);
switch (data.Command)
{
case "pause":
// 执行暂停操作
if (VideoPlayerForm.Instance.isPaused)
{
PrimaryForm.Instance.Invoke(new System.Action(() =>
{
PrimaryForm.Instance.videoPlayerForm.Play();
PrimaryForm.Instance.pauseButton.Visible = true;
PrimaryForm.Instance.playButton.Visible = false;
PrimaryForm.Instance.syncPauseButton.Visible = true;
PrimaryForm.Instance.syncPlayButton.Visible = false;
}));
}
else
{
PrimaryForm.Instance.Invoke(new System.Action(() =>
{
PrimaryForm.Instance.videoPlayerForm.Pause();
PrimaryForm.Instance.pauseButton.Visible = false;
PrimaryForm.Instance.playButton.Visible = true;
PrimaryForm.Instance.syncPauseButton.Visible = false;
PrimaryForm.Instance.syncPlayButton.Visible = true;
}));
}
break;
case "volume_up":
// 执行音量增大操作
PrimaryForm.SendCommandThroughSerialPort("a2 b3 a4");
OverlayForm.MainForm.Invoke(new System.Action(() =>
{
OverlayForm.MainForm.ShowVolumeUpLabel();
PrimaryForm.Instance.volumeUpTimer.Start();
OverlayForm.MainForm.HideAllLabels();
PrimaryForm.Instance.volumeUpTimer.Stop();
}));
break;
case "mic_up":
// 执行麦克风增大操作
PrimaryForm.SendCommandThroughSerialPort("a2 b5 a4");
OverlayForm.MainForm.Invoke(new System.Action(() =>
{
OverlayForm.MainForm.ShowMicUpLabel();
PrimaryForm.Instance.micControlTimer.Start();
OverlayForm.MainForm.HideAllLabels();
PrimaryForm.Instance.micControlTimer.Stop();
}));
break;
case "mute":
// 执行静音操作
PrimaryForm.Instance.Invoke(new System.Action(() =>
{
if (PrimaryForm.Instance.videoPlayerForm.isMuted)
{
// 取消静音,恢复之前的音量
PrimaryForm.Instance.videoPlayerForm.SetVolume(PrimaryForm.Instance.videoPlayerForm.previousVolume);
// muteButton.Text = "Mute";
PrimaryForm.Instance.videoPlayerForm.isMuted = false;
OverlayForm.MainForm.HideMuteLabel();
}
else
{
// 静音,将音量设置为-10000
PrimaryForm.Instance.videoPlayerForm.previousVolume = PrimaryForm.Instance.videoPlayerForm.GetVolume();
PrimaryForm.Instance.videoPlayerForm.SetVolume(-10000);
// muteButton.Text = "Unmute";
PrimaryForm.Instance.videoPlayerForm.isMuted = true;
OverlayForm.MainForm.ShowMuteLabel();
}
}));
break;
case "volume_down":
// 执行音量减小操作
PrimaryForm.SendCommandThroughSerialPort("a2 b4 a4");
OverlayForm.MainForm.Invoke(new System.Action(() =>
{
OverlayForm.MainForm.ShowVolumeDownLabel();
PrimaryForm.Instance.volumeDownTimer.Start();
OverlayForm.MainForm.HideAllLabels();
PrimaryForm.Instance.volumeDownTimer.Stop();
}));
break;
case "mic_down":
// 执行麦克风减小操作
PrimaryForm.SendCommandThroughSerialPort("a2 b6 a4");
OverlayForm.MainForm.Invoke(new System.Action(() =>
{
OverlayForm.MainForm.ShowMicDownLabel();
PrimaryForm.Instance.micControlTimer.Start();
OverlayForm.MainForm.HideAllLabels();
PrimaryForm.Instance.micControlTimer.Stop();
}));
break;
case "original_song":
if (PrimaryForm.Instance.InvokeRequired)
{
PrimaryForm.Instance.Invoke(new System.Action(() =>
{
PrimaryForm.Instance.videoPlayerForm.ToggleVocalRemoval();
}));
}
else
{
PrimaryForm.Instance.videoPlayerForm.ToggleVocalRemoval();
}
// 执行原唱操作
break;
case "service":
// 执行服务操作
PrimaryForm.SendCommandThroughSerialPort("a2 53 a4");
OverlayForm.MainForm.Invoke(new System.Action(() => {
OverlayForm.MainForm.ShowServiceBell();
}));
// 异步处理等待和隐藏标签
await HttpServer.HandleServiceBellAsync();
break;
case "replay":
// 执行重唱操作
PrimaryForm.Instance.Invoke(new System.Action(() =>
{
// 在这里执行按钮点击后的操作
// 比如切歌操作
PrimaryForm.Instance.videoPlayerForm.ReplayCurrentSong();
}));
break;
case "male_key":
// 执行男调操作
OverlayForm.MainForm.Invoke(new System.Action(() => {
OverlayForm.MainForm.ShowMaleKeyLabel();
}));
if (SerialPortManager.mySerialPort != null && SerialPortManager.mySerialPort.IsOpen)
{
// 假設 0xA2, 0xC1, 0xA4 是升調的指令
byte[] commandBytesIncreasePitch1 = new byte[] { 0xA2, 0x7F, 0xA4 };
SerialPortManager.mySerialPort.Write(commandBytesIncreasePitch1, 0, commandBytesIncreasePitch1.Length);
byte[] commandBytesDecreasePitch = new byte[] { 0xA2, 0xB2, 0xA4 };
SerialPortManager.mySerialPort.Write(commandBytesDecreasePitch, 0, commandBytesDecreasePitch.Length);
SerialPortManager.mySerialPort.Write(commandBytesDecreasePitch, 0, commandBytesDecreasePitch.Length);
// MessageBox.Show("升調指令已發送。");
}
else
{
MessageBox.Show("串口未開啟,無法發送升調指令。");
}
break;
case "female_key":
// 执行女调操作
OverlayForm.MainForm.Invoke(new System.Action(() => {
OverlayForm.MainForm.ShowFemaleKeyLabel();
}));
if (SerialPortManager.mySerialPort != null && SerialPortManager.mySerialPort.IsOpen)
{
// 假設 0xA2, 0xC1, 0xA4 是升調的指令
byte[] commandBytesIncreasePitch1 = new byte[] { 0xA2, 0x7F, 0xA4 };
SerialPortManager.mySerialPort.Write(commandBytesIncreasePitch1, 0, commandBytesIncreasePitch1.Length);
byte[] commandBytesIncreasePitch = new byte[] { 0xA2, 0xB1, 0xA4 };
SerialPortManager.mySerialPort.Write(commandBytesIncreasePitch, 0, commandBytesIncreasePitch.Length);
SerialPortManager.mySerialPort.Write(commandBytesIncreasePitch, 0, commandBytesIncreasePitch.Length);
// MessageBox.Show("升調指令已發送。");
}
else
{
MessageBox.Show("串口未開啟,無法發送升調指令。");
}
break;
case "cut":
// 执行切歌操作
if (PrimaryForm.Instance.InvokeRequired)
{
PrimaryForm.Instance.Invoke(new System.Action(() =>
{
PrimaryForm.Instance.videoPlayerForm.SkipToNextSong();
}));
}
else
{
PrimaryForm.Instance.videoPlayerForm.SkipToNextSong();
}
break;
case "lower_key":
// 执行降调操作
OverlayForm.MainForm.Invoke(new System.Action(() => {
OverlayForm.MainForm.ShowKeyDownLabel();
}));
// MessageBox.Show("降調功能啟動");
if (SerialPortManager.mySerialPort != null && SerialPortManager.mySerialPort.IsOpen)
{
// 假設 0xA2, 0xC2, 0xA4 是降調的指令
byte[] commandBytesDecreasePitch = new byte[] { 0xA2, 0xB2, 0xA4 };
SerialPortManager.mySerialPort.Write(commandBytesDecreasePitch, 0, commandBytesDecreasePitch.Length);
// MessageBox.Show("降調指令已發送。");
}
else
{
// MessageBox.Show("串口未開啟,無法發送降調指令。");
}
break;
case "standard_key":
// 执行标准调操作
OverlayForm.MainForm.Invoke(new System.Action(() => {
OverlayForm.MainForm.ShowStandardKeyLabel();
}));
if (SerialPortManager.mySerialPort != null && SerialPortManager.mySerialPort.IsOpen)
{
// 假設 0xA2, 0xC1, 0xA4 是升調的指令
byte[] commandBytesIncreasePitch = new byte[] { 0xA2, 0x7F, 0xA4 };
SerialPortManager.mySerialPort.Write(commandBytesIncreasePitch, 0, commandBytesIncreasePitch.Length);
// MessageBox.Show("升調指令已發送。");
}
else
{
MessageBox.Show("串口未開啟,無法發送升調指令。");
}
break;
case "raise_key":
// 执行升调操作
OverlayForm.MainForm.Invoke(new System.Action(() => {
OverlayForm.MainForm.ShowKeyUpLabel();
}));
// MessageBox.Show("升調功能啟動");
if (SerialPortManager.mySerialPort != null && SerialPortManager.mySerialPort.IsOpen)
{
// 假設 0xA2, 0xC1, 0xA4 是升調的指令
byte[] commandBytesIncreasePitch = new byte[] { 0xA2, 0xB1, 0xA4 };
SerialPortManager.mySerialPort.Write(commandBytesIncreasePitch, 0, commandBytesIncreasePitch.Length);
// MessageBox.Show("升調指令已發送。");
}
else
{
MessageBox.Show("串口未開啟,無法發送升調指令。");
}
break;
default:
Console.WriteLine("Unknown command: " + data.Command);
break;
}
var response = new { status = "success" };
string jsonResponse = JsonConvert.SerializeObject(response);
context.Response.ContentType = "application/json";
context.Response.ContentLength64 = Encoding.UTF8.GetByteCount(jsonResponse);
context.Response.StatusCode = (int)HttpStatusCode.OK;
using (var streamWriter = new StreamWriter(context.Response.OutputStream))
{
await streamWriter.WriteAsync(jsonResponse);
await streamWriter.FlushAsync();
}
}
catch (JsonException ex)
{
Console.WriteLine("JSON parsing error: " + ex.Message);
context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
await context.Response.OutputStream.WriteAsync(new byte[0], 0, 0);
}
}
private static async Task HandleServiceBellAsync()
{
await Task.Delay(3000); // 等待 3 秒
OverlayForm.MainForm.Invoke(new System.Action(() => {
OverlayForm.MainForm.HideServiceBellLabel();
}));
}
private static async Task HandleOrderSongListRequest(HttpListenerContext context)
{
try
{
// 读取请求的内容
string requestBody;
using (var reader = new StreamReader(context.Request.InputStream, context.Request.ContentEncoding))
{
requestBody = await reader.ReadToEndAsync();
}
Console.WriteLine("Received order song request: " + requestBody);
// 检查 playedSongsHistory 是否存在且不为空
if (PrimaryForm.playedSongsHistory != null && PrimaryForm.playedSongsHistory.Count > 0)
{
Console.WriteLine("Played Songs History Count: " + PrimaryForm.playedSongsHistory.Count);
foreach (var song in PrimaryForm.playedSongsHistory)
{
Console.WriteLine($"Song: {song.Name}, ArtistA: {song.Artist_A}");
}
// 根据播放历史确定每首歌的播放状态
var playStates = DeterminePlayStates(PrimaryForm.playedSongsHistory);
// 创建响应数据
var response = new
{
playingSongList = PrimaryForm.playedSongsHistory
.Select((song, index) => CreateSongResponse(song, playStates[index])) // 使用新的播放状态
.ToList(),
// 生成播放历史
currentSongIndexInHistory = PrimaryForm.currentSongIndexInHistory
};
string jsonResponse = JsonConvert.SerializeObject(response);
Console.WriteLine("Serialized JSON Response: " + jsonResponse);
context.Response.ContentType = "application/json";
context.Response.StatusCode = (int)HttpStatusCode.OK;
await SendResponseAsync(context, jsonResponse);
}
else
{
// 如果播放历史为空,回传一条消息
var response = new { status = "info", message = "No songs in the played history" };
string jsonResponse = JsonConvert.SerializeObject(response);
Console.WriteLine("Sending empty response: " + jsonResponse);
context.Response.ContentType = "application/json";
context.Response.StatusCode = (int)HttpStatusCode.OK;
await SendResponseAsync(context, jsonResponse);
}
}
catch (Exception ex)
{
Console.WriteLine("Error handling order song request: " + ex.Message);
context.Response.ContentType = "application/json";
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
await SendResponseAsync(context, "{\"status\": \"error\", \"message\": \"An error occurred\"}");
}
}
// 确定每首歌的播放状态
private static List<PlayState?> DeterminePlayStates(List<SongData> playedSongsHistory)
{
var playStates = new List<PlayState?>();
bool foundPlaying = false; // 标记是否已找到正在播放的歌曲
for (int i = 0; i < playedSongsHistory.Count; i++)
{
// 这里可以根据您的业务逻辑来确定每首歌的播放状态
if (i == PrimaryForm.currentSongIndexInHistory)
{
playStates.Add(PlayState.Playing);
foundPlaying = true; // 找到正在播放的歌曲
}
else if (foundPlaying)
{
playStates.Add(null); // 找到播放中的歌曲后,后面的状态设置为 null
}
else
{
playStates.Add(PlayState.NotPlayed); // 未播放状态
}
}
return playStates;
}
// 用于创建歌曲响应对象,包括播放状态
private static object CreateSongResponse(SongData song, PlayState? playState)
{
return new
{
song.Name,
song.Artist_A,
song.FileName,
PlayState = playState.HasValue ? (playState.Value == PlayState.Playing ? "播放中" : "播放完畢") : null // 如果状态为 null不返回状态信息
};
}
// 生成播放状态
private static async Task HandleOrderSongRequest(HttpListenerContext context)
{
try
{
string requestBody;
using (var reader = new StreamReader(context.Request.InputStream, context.Request.ContentEncoding))
{
requestBody = await reader.ReadToEndAsync();
}
Console.WriteLine("Received order song request: " + requestBody);
// 解析 JSON 为 Song 对象
var song = JsonConvert.DeserializeObject<SongData>(requestBody);
if (song != null)
{
Console.WriteLine($"Ordering Song: {song.Name} by {song.Artist_A}");
// 这里可以添加处理逻辑,例如将歌曲加入到播放列表或数据库中
OverlayForm.MainForm.AddSongToPlaylist(song);
var response = new { status = "success", message = "Song ordered successfully" };
string jsonResponse = JsonConvert.SerializeObject(response);
await SendResponseAsync(context, jsonResponse);
}
else
{
context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
await SendResponseAsync(context, "{\"status\": \"error\", \"message\": \"Invalid song data\"}");
}
}
catch (JsonException ex)
{
Console.WriteLine("JSON parsing error: " + ex.Message);
context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
await SendResponseAsync(context, "{\"status\": \"error\", \"message\": \"Invalid JSON format\"}");
}
}
private static async Task HandleInsertSongRequest(HttpListenerContext context)
{
try
{
string requestBody;
using (var reader = new StreamReader(context.Request.InputStream, context.Request.ContentEncoding))
{
requestBody = await reader.ReadToEndAsync();
}
Console.WriteLine("Received insert song request: " + requestBody);
// 解析 JSON 为 Song 对象
var song = JsonConvert.DeserializeObject<SongData>(requestBody);
if (song != null)
{
Console.WriteLine($"Inserting Song: {song.Name} by {song.Artist_A}");
// 这里可以添加插播歌曲的处理逻辑
OverlayForm.MainForm.InsertSongToPlaylist(song);
var response = new { status = "success", message = "Song inserted successfully" };
string jsonResponse = JsonConvert.SerializeObject(response);
await SendResponseAsync(context, jsonResponse);
}
else
{
context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
await SendResponseAsync(context, "{\"status\": \"error\", \"message\": \"Invalid song data\"}");
}
}
catch (JsonException ex)
{
Console.WriteLine("JSON parsing error: " + ex.Message);
context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
await SendResponseAsync(context, "{\"status\": \"error\", \"message\": \"Invalid JSON format\"}");
}
}
public class SoundControlRequest
{
public string Command { get; set; }
}
private static async Task HandleStickerRequest(HttpListenerContext context)
{
string requestBody;
using (var reader = new StreamReader(context.Request.InputStream, context.Request.ContentEncoding))
{
requestBody = await reader.ReadToEndAsync();
}
Console.WriteLine("Received sticker ID: " + requestBody);
try
{
var data = JsonConvert.DeserializeObject<StickerRequest>(requestBody);
string stickerId = data.StickerId;
// 处理 stickerId 的逻辑,例如显示贴图
if (OverlayForm.MainForm != null)
{
OverlayForm.MainForm.DisplaySticker(stickerId);
}
else
{
Console.WriteLine("MainForm is null.");
}
var response = new { status = "success" };
string jsonResponse = JsonConvert.SerializeObject(response);
context.Response.ContentType = "application/json";
context.Response.ContentLength64 = Encoding.UTF8.GetByteCount(jsonResponse);
context.Response.StatusCode = (int)HttpStatusCode.OK;
using (var streamWriter = new StreamWriter(context.Response.OutputStream))
{
await streamWriter.WriteAsync(jsonResponse);
await streamWriter.FlushAsync();
}
}
catch (JsonException ex)
{
Console.WriteLine("JSON parsing error: " + ex.Message);
context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
await context.Response.OutputStream.WriteAsync(new byte[0], 0, 0);
}
}
public class StickerRequest
{
public string StickerId { get; set; }
}
// 封装响应代码以避免重复
async static Task SendResponseAsync(HttpListenerContext context, string jsonResponse) {
context.Response.ContentType = "application/json";
context.Response.ContentLength64 = Encoding.UTF8.GetByteCount(jsonResponse);
context.Response.StatusCode = (int)HttpStatusCode.OK;
using (var streamWriter = new StreamWriter(context.Response.OutputStream)) {
await streamWriter.WriteAsync(jsonResponse);
await streamWriter.FlushAsync();
}
}
static void InvokeAction(System.Action action)
{
if (OverlayForm.MainForm.InvokeRequired)
{
OverlayForm.MainForm.Invoke(action);
}
else
{
action();
}
}
private static async Task HandlemessageRequest(HttpListenerContext context)
{
try
{
// 初始化 form如果未初始化
// 读取请求体中的消息
using (var reader = new StreamReader(context.Request.InputStream, context.Request.ContentEncoding))
{
// 异步读取整个请求体内容
string json = await reader.ReadToEndAsync();
// 确保 JSON 内容不为空
if (!string.IsNullOrEmpty(json))
{
// 返回成功响应
context.Response.StatusCode = 200;
context.Response.ContentType = "application/json"; // 确保返回 JSON 格式
int startIndex = json.IndexOf("\"message\":\"") + 11; // 11 是 "message\":\"" 的长度
int endIndex = json.IndexOf("\"", startIndex);
string Messagefist ="藏鏡人:";
// 如果找到了 "message" 字段
if (startIndex >= 0 && endIndex >= 0)
{
// 提取 "message" 字段的值
string message = json.Substring(startIndex, endIndex - startIndex);
for(int i=0;i<3;i++)
{
string Messagelast="";
for(int j=0;j < message.Length;j++){
Messagelast += message[j];
await Task.Delay(10);
// 将读取到的 "message" 字段传递给 UI 控件显示
if (OverlayForm.MainForm.InvokeRequired)
{
OverlayForm.MainForm.Invoke(new System.Action(() =>
{
OverlayForm.MainForm.ShowmessageLabel(Messagefist + Messagelast + '_');
}));
}
else
{
OverlayForm.MainForm.ShowmessageLabel(Messagefist + Messagelast + '_');
}
}
// 真情告白顯示秒數
await Task.Delay(3000);
}
}
}
else
{
// 如果没有有效的 JSON 数据,返回错误响应
context.Response.StatusCode = 400; // Bad Request
context.Response.StatusDescription = "Invalid JSON data.";
}
}
}
//catch (JsonException ex)
//{
// context.Response.StatusCode = 400;
// Console.WriteLine("解析留言数据时出错");
//}
//catch (Exception ex)
//{
// context.Response.StatusCode = 500;
// Console.WriteLine("服务器内部错误");
//}
finally
{
context.Response.Close();
}
}
private static async Task OutputMessageAsync(string message, Label messageLabel)
{
messageLabel.Text = ""; // 清空现有的文本
foreach (char c in message)
{
messageLabel.Text += c; // 逐字显示消息
await Task.Delay(500); // 每个字符间隔 0.5 秒
}
// 模拟等待 5 秒后继续其他操作
await Task.Delay(5000);
}
private static string GetMimeType(string filePath)
{
// 获取MIME类型的逻辑
string mimeType = "application/octet-stream"; // Default MIME type
string extension = Path.GetExtension(filePath).ToLowerInvariant();
// MIME type lookup based on file extension
switch (extension)
{
case ".html":
case ".htm":
mimeType = "text/html";
break;
case ".css":
mimeType = "text/css";
break;
case ".js":
mimeType = "application/javascript";
break;
case ".png":
mimeType = "image/png";
break;
case ".jpg":
case ".jpeg":
mimeType = "image/jpeg";
break;
case ".gif":
mimeType = "image/gif";
break;
case ".svg":
mimeType = "image/svg+xml";
break;
case ".json":
mimeType = "application/json";
break;
// Add more cases for other file types as needed
}
return mimeType;
}
private static string GetLocalIPAddress()
{
var host = Dns.GetHostEntry(Dns.GetHostName());
foreach (var ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
return ip.ToString(); // 返回找到的 IPv4 地址
}
}
throw new Exception("No network adapters with an IPv4 address in the system!");
}
// 启动服务器的公共方法
private static async Task HandleFavoriteRequest(HttpListenerContext context)
{
try
{
if (PrimaryForm.isPhoneNumberValid && !string.IsNullOrEmpty(PrimaryForm.Instance.userPhone))
{
//string phone = PrimaryForm.phonenumber; // 直接通过类名访问
// 登录用户
//SongListManager.Instance.UserLogin(phone);
// 获取用户的收藏歌曲
var favoriteSongs=new List<SongData>(); //= SongListManager.Instance.GetFavoriteSongsByPhoneNumber();
string query =PrimaryForm.Instance.SearchFavoriteSongs_Mysql();
var searchResults = PrimaryForm.Instance.SearchSongs_Mysql(query);
// 创建响应数据
var response = new
{
isLoggedIn = true,
favoriteSongList = searchResults
.Select(song => new
{
song.Name,
song.Artist_A,
song.Number,
song.Artist_A_Simplified,
song.Artist_B_Simplified,
song.Name_Simplified,
song.HumanVoice,
song.FileName
})
.ToList(),
status = "success",
message = "Favorites retrieved successfully"
};
string jsonResponse = JsonConvert.SerializeObject(response);
Console.WriteLine("Serialized JSON Response: " + jsonResponse);
// 返回响应
context.Response.ContentType = "application/json";
context.Response.StatusCode = (int)HttpStatusCode.OK;
await SendResponseAsyncs(context, jsonResponse);
}
else
{
// 如果手机号无效,返回未登录的状态
var response = new
{
isLoggedIn = false,
status = "error",
message = "Invalid mobile number or user not logged in"
};
string jsonResponse = JsonConvert.SerializeObject(response);
Console.WriteLine("Sending not logged in response: " + jsonResponse);
// 返回错误响应
context.Response.ContentType = "application/json";
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
await SendResponseAsyncs(context, jsonResponse);
}
}
catch (Exception ex)
{
Console.WriteLine($"Error handling favorite song request: {ex.Message}");
// 增强异常信息,返回详细的错误
var errorResponse = new
{
status = "error",
message = "An error occurred while processing your request",
errorDetails = ex.Message // 可以把错误信息传递给前端,帮助调试
};
string jsonResponse = JsonConvert.SerializeObject(errorResponse);
context.Response.ContentType = "application/json";
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
await SendResponseAsyncs(context, jsonResponse);
}
}
// 异步响应发送方法
private static async Task SendResponseAsyncs(HttpListenerContext context, string responseContent)
{
try
{
using (var writer = new StreamWriter(context.Response.OutputStream))
{
await writer.WriteAsync(responseContent);
}
}
catch (Exception ex)
{
Console.WriteLine("Error sending response: " + ex.Message);
}
}
private static async Task HandleGetRequest(HttpListenerContext context, string baseDirectory, string requestedFile)
{
try
{
// 获取请求的完整URL路径
string requestPath = context.Request.Url.AbsolutePath;
// 检查URL是否包含随机文件夹名
if (!requestPath.Contains("/" + randomFolderPath + "/"))
{
Console.WriteLine($"Access denied: Request path {requestPath} does not contain valid random folder");
context.Response.StatusCode = (int)HttpStatusCode.NotFound;
return;
}
string filePath = Path.Combine(baseDirectory, requestedFile.TrimStart('/'));
if (!File.Exists(filePath))
{
context.Response.StatusCode = (int)HttpStatusCode.NotFound;
return;
}
string contentType = GetMimeType(filePath);
context.Response.ContentType = contentType;
// 对于静态文件使用缓存
if (_fileCache.TryGetValue(filePath, out byte[] cachedContent))
{
context.Response.ContentLength64 = cachedContent.Length;
await context.Response.OutputStream.WriteAsync(cachedContent, 0, cachedContent.Length);
return;
}
// 读取文件内容
byte[] buffer;
using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
buffer = new byte[fileStream.Length];
await fileStream.ReadAsync(buffer, 0, buffer.Length);
}
// 缓存静态文件
if (contentType.StartsWith("text/") || contentType.Contains("javascript") || contentType.Contains("json"))
{
_fileCache.TryAdd(filePath, buffer);
}
context.Response.ContentLength64 = buffer.Length;
await context.Response.OutputStream.WriteAsync(buffer, 0, buffer.Length);
}
catch (Exception ex)
{
Console.WriteLine($"Error serving file: {ex.Message}");
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
}
}
}
}