Files
AX-Copilot/src/AxCopilot/Handlers/EncodeHandler.cs

209 lines
7.4 KiB
C#

using System.Security.Cryptography;
using System.Text;
using System.Windows;
using AxCopilot.SDK;
using AxCopilot.Themes;
namespace AxCopilot.Handlers;
/// <summary>
/// 인코딩/해싱 변환 핸들러. "encode " 프리픽스로 사용합니다.
/// 예: encode base64 hello → aGVsbG8=
/// encode decode base64 aGVsbG8= → hello
/// encode url https://example.com → URL 인코딩
/// encode hex hello → 68656c6c6f
/// encode md5 hello → 5d41402abc4b2a76b9719d911017c592
/// encode sha256 hello → 2cf24dba...
/// encode sha1 hello → aaf4c61d...
/// encode (빈 쿼리) → 지원 목록
/// </summary>
public class EncodeHandler : IActionHandler
{
public string? Prefix => "encode "; // 뒤에 공백 포함
public PluginMetadata Metadata => new(
"Encoder",
"인코딩/해싱 — encode base64/url/hex/md5/sha256 텍스트",
"1.0",
"AX");
public Task<IEnumerable<LauncherItem>> GetItemsAsync(string query, CancellationToken ct)
{
var q = query.Trim();
if (string.IsNullOrWhiteSpace(q))
return Task.FromResult(HelpItems());
// "decode <타입> <값>" 파턴
if (q.StartsWith("decode ", StringComparison.OrdinalIgnoreCase))
{
var rest = q[7..].Trim();
return Task.FromResult(HandleDecode(rest));
}
// "<타입> <값>" 패턴
var spaceIdx = q.IndexOf(' ');
if (spaceIdx < 0)
return Task.FromResult(HelpItems());
var type = q[..spaceIdx].Trim().ToLowerInvariant();
var input = q[(spaceIdx + 1)..];
return Task.FromResult(HandleEncode(type, input));
}
private static IEnumerable<LauncherItem> HandleEncode(string type, string input)
{
try
{
return type switch
{
"base64" or "b64" => SingleResult("Base64 인코딩",
Convert.ToBase64String(Encoding.UTF8.GetBytes(input))),
"url" => SingleResult("URL 인코딩",
Uri.EscapeDataString(input)),
"hex" => SingleResult("HEX 인코딩",
Convert.ToHexString(Encoding.UTF8.GetBytes(input)).ToLowerInvariant()),
"md5" => SingleResult("MD5 해시",
MD5Hash(input)),
"sha1" => SingleResult("SHA-1 해시",
SHA1Hash(input)),
"sha256" => SingleResult("SHA-256 해시",
SHA256Hash(input)),
"sha512" => SingleResult("SHA-512 해시",
SHA512Hash(input)),
"html" => SingleResult("HTML 엔티티 인코딩",
System.Net.WebUtility.HtmlEncode(input)),
_ =>
[
new LauncherItem(
$"알 수 없는 타입: {type}",
"base64, url, hex, md5, sha1, sha256, sha512, html 중 선택",
null, null, Symbol: Symbols.Warning)
]
};
}
catch (Exception ex)
{
return
[
new LauncherItem("변환 오류", ex.Message, null, null, Symbol: Symbols.Error)
];
}
}
private static IEnumerable<LauncherItem> HandleDecode(string rest)
{
var spaceIdx = rest.IndexOf(' ');
if (spaceIdx < 0)
return [new LauncherItem("사용법: encode decode <타입> <값>", "타입: base64, url, hex, html", null, null, Symbol: Symbols.Info)];
var type = rest[..spaceIdx].Trim().ToLowerInvariant();
var input = rest[(spaceIdx + 1)..];
try
{
return type switch
{
"base64" or "b64" => SingleResult("Base64 디코딩",
Encoding.UTF8.GetString(Convert.FromBase64String(input))),
"url" => SingleResult("URL 디코딩",
Uri.UnescapeDataString(input)),
"hex" => SingleResult("HEX 디코딩",
Encoding.UTF8.GetString(Convert.FromHexString(input))),
"html" => SingleResult("HTML 엔티티 디코딩",
System.Net.WebUtility.HtmlDecode(input)),
_ =>
[
new LauncherItem(
$"디코딩 불가 타입: {type}",
"디코딩 지원: base64, url, hex, html",
null, null, Symbol: Symbols.Warning)
]
};
}
catch (Exception ex)
{
return
[
new LauncherItem("디코딩 오류", ex.Message, null, null, Symbol: Symbols.Error)
];
}
}
private static IEnumerable<LauncherItem> SingleResult(string title, string result)
{
var preview = result.Length > 80 ? result[..77] + "…" : result;
return
[
new LauncherItem(
title,
$"{preview} · Enter로 복사",
null,
result,
Symbol: Symbols.EncodeIcon)
];
}
private static IEnumerable<LauncherItem> HelpItems()
{
return
[
new LauncherItem("encode base64 <텍스트>", "Base64 인코딩/디코딩", null, null, Symbol: Symbols.EncodeIcon),
new LauncherItem("encode url <텍스트>", "URL 퍼센트 인코딩/디코딩", null, null, Symbol: Symbols.EncodeIcon),
new LauncherItem("encode hex <텍스트>", "16진수 인코딩/디코딩", null, null, Symbol: Symbols.EncodeIcon),
new LauncherItem("encode md5 <텍스트>", "MD5 해시 (단방향)", null, null, Symbol: Symbols.EncodeIcon),
new LauncherItem("encode sha256 <텍스트>", "SHA-256 해시 (단방향)", null, null, Symbol: Symbols.EncodeIcon),
new LauncherItem("encode html <텍스트>", "HTML 엔티티 인코딩/디코딩", null, null, Symbol: Symbols.EncodeIcon),
new LauncherItem("encode decode base64 <값>", "Base64 디코딩 예시", null, null, Symbol: Symbols.EncodeIcon),
];
}
// ─── 해시 헬퍼 ─────────────────────────────────────────────────────────────
private static string MD5Hash(string input)
{
var bytes = MD5.HashData(Encoding.UTF8.GetBytes(input));
return Convert.ToHexString(bytes).ToLowerInvariant();
}
private static string SHA1Hash(string input)
{
var bytes = SHA1.HashData(Encoding.UTF8.GetBytes(input));
return Convert.ToHexString(bytes).ToLowerInvariant();
}
private static string SHA256Hash(string input)
{
var bytes = SHA256.HashData(Encoding.UTF8.GetBytes(input));
return Convert.ToHexString(bytes).ToLowerInvariant();
}
private static string SHA512Hash(string input)
{
var bytes = SHA512.HashData(Encoding.UTF8.GetBytes(input));
return Convert.ToHexString(bytes).ToLowerInvariant();
}
public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
{
if (item.Data is string text)
{
try { Clipboard.SetText(text); } catch (Exception) { }
}
return Task.CompletedTask;
}
}