Files

300 lines
7.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Threading;
using AxCopilot.Models;
using AxCopilot.SDK;
using AxCopilot.Services;
namespace AxCopilot.Handlers;
public class ClipboardHandler : IActionHandler
{
private readonly SettingsService _settings;
public string? Prefix => "$";
public PluginMetadata Metadata => new PluginMetadata("clipboard", "클립보드 변환", "1.0", "AX");
public ClipboardHandler(SettingsService settings)
{
_settings = settings;
}
public Task<IEnumerable<LauncherItem>> GetItemsAsync(string query, CancellationToken ct)
{
List<LauncherItem> list = new List<LauncherItem>();
IEnumerable<ClipboardTransformer> enumerable = from t in GetBuiltinTransformers()
where string.IsNullOrEmpty(query) || t.Key.Contains(query, StringComparison.OrdinalIgnoreCase)
select t;
foreach (ClipboardTransformer item in enumerable)
{
list.Add(new LauncherItem(item.Key, item.Description ?? "", null, item, null, "\ue77f"));
}
IEnumerable<LauncherItem> collection = from t in _settings.Settings.ClipboardTransformers
where string.IsNullOrEmpty(query) || t.Key.Contains(query, StringComparison.OrdinalIgnoreCase)
select new LauncherItem(t.Key, t.Description ?? t.Type, null, t, null, "\ue77f");
list.AddRange(collection);
return Task.FromResult((IEnumerable<LauncherItem>)list);
}
public async Task ExecuteAsync(LauncherItem item, CancellationToken ct)
{
object data = item.Data;
if (!(data is ClipboardTransformer transformer))
{
return;
}
string input = null;
((DispatcherObject)System.Windows.Application.Current).Dispatcher.Invoke((Action)delegate
{
input = (System.Windows.Clipboard.ContainsText() ? System.Windows.Clipboard.GetText() : null);
});
if (input == null)
{
return;
}
string result = await TransformAsync(transformer, input, ct);
if (result != null)
{
((DispatcherObject)System.Windows.Application.Current).Dispatcher.Invoke((Action)delegate
{
System.Windows.Clipboard.SetText(result);
});
nint prevHwnd = WindowTracker.PreviousWindow;
if (prevHwnd != IntPtr.Zero)
{
SetForegroundWindow(prevHwnd);
}
await Task.Delay(120, ct);
SendKeys.SendWait("^v");
LogService.Info("클립보드 변환: '" + transformer.Key + "' 적용");
}
}
private static async Task<string?> TransformAsync(ClipboardTransformer t, string input, CancellationToken ct)
{
try
{
string type = t.Type;
if (1 == 0)
{
}
string text = type;
string result;
if (!(text == "regex"))
{
if (!(text == "script") || t.Command == null)
{
goto IL_016f;
}
result = await RunScriptAsync(t.Command, input, t.Timeout, ct);
}
else
{
if (t.Pattern == null || t.Replace == null)
{
goto IL_016f;
}
result = Regex.Replace(input, t.Pattern, t.Replace, RegexOptions.None, TimeSpan.FromMilliseconds((t.Timeout > 0) ? t.Timeout : 5000));
}
goto IL_0188;
IL_016f:
result = ExecuteBuiltin(t.Key, input);
goto IL_0188;
IL_0188:
if (1 == 0)
{
}
return result;
}
catch (Exception ex)
{
Exception ex2 = ex;
LogService.Error("변환 실패 (" + t.Key + "): " + ex2.Message);
return null;
}
}
private static async Task<string> RunScriptAsync(string command, string input, int timeoutMs, CancellationToken ct)
{
using CancellationTokenSource cts = CancellationTokenSource.CreateLinkedTokenSource(ct);
cts.CancelAfter(timeoutMs);
string[] parts = command.Split(' ', 2);
ProcessStartInfo psi = new ProcessStartInfo(parts[0])
{
Arguments = ((parts.Length > 1) ? parts[1] : ""),
RedirectStandardInput = true,
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true,
StandardInputEncoding = Encoding.UTF8,
StandardOutputEncoding = Encoding.UTF8
};
using Process proc = Process.Start(psi);
await proc.StandardInput.WriteAsync(input);
proc.StandardInput.Close();
return await proc.StandardOutput.ReadToEndAsync(cts.Token);
}
internal static string? ExecuteBuiltin(string key, string input)
{
if (1 == 0)
{
}
string result = key switch
{
"$json" => FormatJson(input),
"$upper" => input.ToUpperInvariant(),
"$lower" => input.ToLowerInvariant(),
"$ts" => TryParseTimestamp(input),
"$epoch" => TryParseDate(input),
"$urle" => Uri.EscapeDataString(input),
"$urld" => Uri.UnescapeDataString(input),
"$b64e" => Convert.ToBase64String(Encoding.UTF8.GetBytes(input)),
"$b64d" => Encoding.UTF8.GetString(Convert.FromBase64String(input)),
"$md" => StripMarkdown(input),
"$trim" => input.Trim(),
"$lines" => string.Join(Environment.NewLine, from l in input.Split('\n')
select l.Trim() into l
where l.Length > 0
select l),
_ => null,
};
if (1 == 0)
{
}
return result;
}
private static string FormatJson(string input)
{
try
{
JsonDocument value = JsonDocument.Parse(input);
return JsonSerializer.Serialize(value, new JsonSerializerOptions
{
WriteIndented = true
});
}
catch
{
return input;
}
}
private static string? TryParseTimestamp(string input)
{
if (long.TryParse(input.Trim(), out var result))
{
return DateTimeOffset.FromUnixTimeSeconds(result).LocalDateTime.ToString("yyyy-MM-dd HH:mm:ss");
}
return null;
}
private static string? TryParseDate(string input)
{
if (DateTime.TryParse(input.Trim(), out var result))
{
return new DateTimeOffset(result).ToUnixTimeSeconds().ToString();
}
return null;
}
private static string StripMarkdown(string input)
{
return Regex.Replace(input, "(\\*\\*|__)(.*?)\\1|(\\*|_)(.*?)\\3|`(.+?)`|#{1,6}\\s*", "$2$4$5");
}
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(nint hWnd);
private static IEnumerable<ClipboardTransformer> GetBuiltinTransformers()
{
return new _003C_003Ez__ReadOnlyArray<ClipboardTransformer>(new ClipboardTransformer[12]
{
new ClipboardTransformer
{
Key = "$json",
Type = "builtin",
Description = "JSON 포맷팅 (들여쓰기 적용)"
},
new ClipboardTransformer
{
Key = "$upper",
Type = "builtin",
Description = "대문자 변환"
},
new ClipboardTransformer
{
Key = "$lower",
Type = "builtin",
Description = "소문자 변환"
},
new ClipboardTransformer
{
Key = "$ts",
Type = "builtin",
Description = "유닉스 타임스탬프 → 날짜 문자열"
},
new ClipboardTransformer
{
Key = "$epoch",
Type = "builtin",
Description = "날짜 문자열 → 유닉스 타임스탬프"
},
new ClipboardTransformer
{
Key = "$urle",
Type = "builtin",
Description = "URL 인코딩"
},
new ClipboardTransformer
{
Key = "$urld",
Type = "builtin",
Description = "URL 디코딩"
},
new ClipboardTransformer
{
Key = "$b64e",
Type = "builtin",
Description = "Base64 인코딩"
},
new ClipboardTransformer
{
Key = "$b64d",
Type = "builtin",
Description = "Base64 디코딩"
},
new ClipboardTransformer
{
Key = "$md",
Type = "builtin",
Description = "마크다운 문법 제거"
},
new ClipboardTransformer
{
Key = "$trim",
Type = "builtin",
Description = "앞뒤 공백 제거"
},
new ClipboardTransformer
{
Key = "$lines",
Type = "builtin",
Description = "빈 줄 제거 및 각 줄 공백 정리"
}
});
}
}