using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text.Json; using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; using AxCopilot.SDK; using AxCopilot.Services; namespace AxCopilot.Handlers; public class RoutineHandler : IActionHandler { internal record RoutineDefinition([property: JsonPropertyName("name")] string Name, [property: JsonPropertyName("description")] string Description, [property: JsonPropertyName("steps")] RoutineStep[] Steps); internal record RoutineStep([property: JsonPropertyName("type")] string Type, [property: JsonPropertyName("target")] string Target, [property: JsonPropertyName("label")] string Label); private static readonly string RoutineFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "AxCopilot", "routines.json"); private static readonly JsonSerializerOptions JsonOpts = new JsonSerializerOptions { WriteIndented = true, PropertyNameCaseInsensitive = true }; private static readonly RoutineDefinition[] BuiltInRoutines = new RoutineDefinition[2] { new RoutineDefinition("morning", "출근 루틴", new RoutineStep[2] { new RoutineStep("app", "explorer.exe", "파일 탐색기"), new RoutineStep("info", "info", "시스템 정보 표시") }), new RoutineDefinition("endofday", "퇴근 루틴", new RoutineStep[1] { new RoutineStep("cmd", "journal", "오늘 업무 일지 생성") }) }; public string? Prefix => "routine"; public PluginMetadata Metadata => new PluginMetadata("Routine", "루틴 자동화 — routine", "1.0", "AX"); public Task> GetItemsAsync(string query, CancellationToken ct) { string q = query.Trim(); List list = LoadRoutines(); if (string.IsNullOrWhiteSpace(q)) { List list2 = new List { new LauncherItem("루틴 자동화", $"총 {list.Count}개 루틴 · 이름 입력 시 실행 · routines.json에서 편집", null, null, null, "\ue946") }; foreach (RoutineDefinition item in list) { string value = string.Join(" → ", item.Steps.Select((RoutineStep s) => s.Label)); list2.Add(new LauncherItem("[" + item.Name + "] " + item.Description, $"{item.Steps.Length}단계: {value} · Enter로 실행", null, item, null, "\ue82f")); } return Task.FromResult((IEnumerable)list2); } RoutineDefinition routineDefinition = list.FirstOrDefault((RoutineDefinition r) => r.Name.Equals(q, StringComparison.OrdinalIgnoreCase)); if (routineDefinition != null) { string text = string.Join(" → ", routineDefinition.Steps.Select((RoutineStep s) => s.Label)); return Task.FromResult((IEnumerable)new _003C_003Ez__ReadOnlySingleElementList(new LauncherItem("[" + routineDefinition.Name + "] 루틴 실행", routineDefinition.Description + " · " + text, null, routineDefinition, null, "\ue82f"))); } IEnumerable source = list.Where((RoutineDefinition r) => r.Name.Contains(q, StringComparison.OrdinalIgnoreCase) || r.Description.Contains(q, StringComparison.OrdinalIgnoreCase)); List list3 = source.Select((RoutineDefinition r) => new LauncherItem("[" + r.Name + "] " + r.Description, $"{r.Steps.Length}단계 · Enter로 실행", null, r, null, "\ue82f")).ToList(); if (!list3.Any()) { list3.Add(new LauncherItem("'" + q + "' 루틴 없음", "routines.json에서 직접 추가하거나 routine으로 목록 확인", null, null, null, "\ue7ba")); } return Task.FromResult((IEnumerable)list3); } public async Task ExecuteAsync(LauncherItem item, CancellationToken ct) { object data = item.Data; if (!(data is RoutineDefinition routine)) { return; } int executed = 0; RoutineStep[] steps = routine.Steps; foreach (RoutineStep step in steps) { try { switch (step.Type.ToLowerInvariant()) { case "app": case "url": case "folder": Process.Start(new ProcessStartInfo(step.Target) { UseShellExecute = true }); break; case "cmd": Process.Start(new ProcessStartInfo("powershell.exe", "-Command \"" + step.Target + "\"") { UseShellExecute = false, CreateNoWindow = true }); break; case "info": NotificationService.Notify("루틴", step.Label); break; } executed++; await Task.Delay(300, ct); } catch (Exception ex) { LogService.Warn("루틴 단계 실행 실패: " + step.Label + " — " + ex.Message); } } NotificationService.Notify("루틴 완료", $"[{routine.Name}] {executed}/{routine.Steps.Length}단계 실행 완료"); } private List LoadRoutines() { List list = new List(BuiltInRoutines); try { if (File.Exists(RoutineFile)) { string json = File.ReadAllText(RoutineFile); List list2 = JsonSerializer.Deserialize>(json, JsonOpts); if (list2 != null) { foreach (RoutineDefinition r in list2) { list.RemoveAll((RoutineDefinition x) => x.Name.Equals(r.Name, StringComparison.OrdinalIgnoreCase)); list.Add(r); } } } } catch (Exception ex) { LogService.Warn("루틴 로드 실패: " + ex.Message); } return list; } }