118 lines
3.6 KiB
C#
118 lines
3.6 KiB
C#
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();
|
||
}
|
||
}
|