Files
AX-Copilot-Codex/.decompiledproj/AxCopilot/Handlers/JsonSkillHandler.cs

181 lines
5.3 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Threading;
using System.Threading.Tasks;
using AxCopilot.SDK;
using AxCopilot.Services;
namespace AxCopilot.Handlers;
public class JsonSkillHandler : IActionHandler
{
private readonly JsonSkillDefinition _def;
private readonly HttpClient _http = new HttpClient();
private List<LauncherItem>? _cache;
private DateTime _cacheExpiry = DateTime.MinValue;
public string? Prefix => _def.Prefix;
public PluginMetadata Metadata => new PluginMetadata(_def.Id, _def.Name, _def.Version, "JSON Skill");
public JsonSkillHandler(JsonSkillDefinition def)
{
_def = def;
_http.Timeout = TimeSpan.FromSeconds(3.0);
if (def.Credential?.Type == "bearer_token")
{
string token = CredentialManager.GetToken(def.Credential.CredentialKey);
if (!string.IsNullOrEmpty(token))
{
_http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
}
}
}
public async Task<IEnumerable<LauncherItem>> GetItemsAsync(string query, CancellationToken ct)
{
if (_cache != null && DateTime.Now < _cacheExpiry)
{
return _cache;
}
if (_def.Request == null || _def.Response == null)
{
return Enumerable.Empty<LauncherItem>();
}
try
{
string url = _def.Request.Url.Replace("{{INPUT}}", Uri.EscapeDataString(query));
if (!Uri.TryCreate(url, UriKind.Absolute, out Uri parsedUrl) || (parsedUrl.Scheme != Uri.UriSchemeHttp && parsedUrl.Scheme != Uri.UriSchemeHttps))
{
LogService.Error("[" + _def.Name + "] 유효하지 않은 URL: " + url);
return new _003C_003Ez__ReadOnlySingleElementList<LauncherItem>(new LauncherItem("설정 오류", "스킬 URL이 유효하지 않습니다 (http/https만 허용)", null, null));
}
string text = _def.Request.Method.ToUpper();
if (1 == 0)
{
}
HttpResponseMessage httpResponseMessage = ((!(text == "POST")) ? (await _http.GetAsync(url, ct)) : (await _http.PostAsync(url, BuildBody(query), ct)));
if (1 == 0)
{
}
HttpResponseMessage response = httpResponseMessage;
response.EnsureSuccessStatusCode();
List<LauncherItem> items = ParseResults(await response.Content.ReadAsStringAsync(ct));
JsonSkillCache? cache = _def.Cache;
if (cache != null && cache.Ttl > 0)
{
_cache = items;
_cacheExpiry = DateTime.Now.AddSeconds(_def.Cache.Ttl);
}
return items;
}
catch (TaskCanceledException)
{
if (_cache != null)
{
LogService.Warn("[" + _def.Name + "] API 타임아웃, 캐시 반환");
return _cache;
}
return new _003C_003Ez__ReadOnlySingleElementList<LauncherItem>(new LauncherItem("네트워크 오류", "연결을 확인하세요", null, null));
}
catch (Exception ex2)
{
LogService.Error("[" + _def.Name + "] API 호출 실패: " + ex2.Message);
return new _003C_003Ez__ReadOnlySingleElementList<LauncherItem>(new LauncherItem("오류: " + ex2.Message, _def.Name, null, null));
}
}
public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
{
if (item.ActionUrl != null && Uri.TryCreate(item.ActionUrl, UriKind.Absolute, out Uri result) && (result.Scheme == Uri.UriSchemeHttp || result.Scheme == Uri.UriSchemeHttps))
{
Process.Start(new ProcessStartInfo(item.ActionUrl)
{
UseShellExecute = true
});
}
return Task.CompletedTask;
}
private HttpContent BuildBody(string query)
{
string content = JsonSerializer.Serialize(_def.Request?.Body).Replace("\"{{INPUT}}\"", "\"" + query + "\"");
return new StringContent(content, Encoding.UTF8, "application/json");
}
private List<LauncherItem> ParseResults(string json)
{
List<LauncherItem> list = new List<LauncherItem>();
try
{
JsonNode jsonNode = JsonNode.Parse(json);
if (jsonNode == null)
{
return list;
}
JsonNode jsonNode2 = NavigatePath(jsonNode, _def.Response.ResultsPath);
if (!(jsonNode2 is JsonArray source))
{
return list;
}
foreach (JsonNode item in source.Take(10))
{
if (item != null)
{
string title = NavigatePath(item, _def.Response.TitleField)?.ToString() ?? "(제목 없음)";
string subtitle = ((_def.Response.SubtitleField == null) ? "" : (NavigatePath(item, _def.Response.SubtitleField)?.ToString() ?? ""));
string actionUrl = ((_def.Response.ActionUrl == null) ? null : NavigatePath(item, _def.Response.ActionUrl)?.ToString());
list.Add(new LauncherItem(title, subtitle, null, item, actionUrl, "\ue82d"));
}
}
}
catch (Exception ex)
{
LogService.Error("[" + _def.Name + "] 응답 파싱 실패: " + ex.Message);
}
return list;
}
private static JsonNode? NavigatePath(JsonNode root, string path)
{
string[] array = path.Split('.');
JsonNode jsonNode = root;
string[] array2 = array;
foreach (string text in array2)
{
if (jsonNode == null)
{
return null;
}
int num = text.IndexOf('[');
if (num >= 0)
{
int num2 = text.IndexOf(']');
if (num2 < 0)
{
return null;
}
string propertyName = text.Substring(0, num);
int num3 = num + 1;
int index = int.Parse(text.Substring(num3, num2 - num3));
jsonNode = jsonNode[propertyName]?[index];
}
else
{
jsonNode = jsonNode[text];
}
}
return jsonNode;
}
}