client: Windows 客户端(WinUI3 壳 + agent-core;调试用 Electron 壳存档);localserver token 改为常数时间比较

This commit is contained in:
Qiufeng
2026-08-20 20:38:21 +08:00
parent 33b7d57498
commit 9abf7f8213
60 changed files with 10025 additions and 0 deletions
+117
View File
@@ -0,0 +1,117 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
using System.Threading.Tasks;
using EveryPublish.Client.Models;
namespace EveryPublish.Client.Services;
/// <summary>agent-core 本机控制客户端(读 local.json → 127.0.0.1 + token 鉴权)</summary>
public class CoreClient : IDisposable
{
private readonly HttpClient _http;
private readonly string _dataDir;
private string _base = "";
private string _token = "";
public CoreClient(string dataDir)
{
_dataDir = dataDir;
_http = new HttpClient { Timeout = TimeSpan.FromSeconds(5) };
ReloadLocalJson();
}
/// <summary>重新读取 data/local.json(端口/token,core 每次启动随机)</summary>
public void ReloadLocalJson()
{
try
{
var path = Path.Combine(_dataDir, "local.json");
if (!File.Exists(path)) return;
var info = JsonSerializer.Deserialize<LocalInfo>(File.ReadAllText(path));
if (info == null || info.Port <= 0 || string.IsNullOrEmpty(info.Token)) return;
_base = "http://127.0.0.1:" + info.Port;
_token = info.Token;
}
catch
{
// core 尚未写入 local.json,稍后重试
}
}
private HttpRequestMessage NewRequest(HttpMethod method, string path)
{
var req = new HttpRequestMessage(method, _base + path);
req.Headers.Add("X-Agent-Token", _token);
return req;
}
public async Task<CoreStatus?> GetStatusAsync()
{
try
{
using var resp = await _http.SendAsync(NewRequest(HttpMethod.Get, "/status"));
if (!resp.IsSuccessStatusCode) return null;
return await resp.Content.ReadFromJsonAsync<CoreStatus>();
}
catch
{
return null;
}
}
public async Task<List<ChallengeItem>> GetChallengesAsync()
{
try
{
using var resp = await _http.SendAsync(NewRequest(HttpMethod.Get, "/challenges"));
if (!resp.IsSuccessStatusCode) return new List<ChallengeItem>();
var doc = await resp.Content.ReadFromJsonAsync<JsonElement>();
if (doc.TryGetProperty("list", out var list))
{
return list.Deserialize<List<ChallengeItem>>() ?? new List<ChallengeItem>();
}
return new List<ChallengeItem>();
}
catch
{
return new List<ChallengeItem>();
}
}
public Task<(bool Ok, string Message)> PairAsync(string code, string name)
{
return PostAsync("/pair", new { code, name });
}
public Task<(bool Ok, string Message)> SolveAsync(string challengeId, string value)
{
return PostAsync("/challenges/" + challengeId, new { value });
}
private async Task<(bool Ok, string Message)> PostAsync(string path, object body)
{
try
{
using var req = NewRequest(HttpMethod.Post, path);
req.Content = JsonContent.Create(body);
using var resp = await _http.SendAsync(req);
var doc = await resp.Content.ReadFromJsonAsync<JsonElement>();
var ok = doc.TryGetProperty("code", out var c) && c.GetInt32() == 0;
var msg = doc.TryGetProperty("message", out var m) ? m.GetString() ?? "" : "";
return (ok, msg);
}
catch (Exception ex)
{
return (false, "无法连接客户端核心:" + ex.Message);
}
}
public void Dispose()
{
_http.Dispose();
}
}