using Google.Protobuf; using Microsoft.Extensions.Options; using WebmrAPI.Configuration; using WebmrAPI.Utils; using WebmrAPI.Utils.Sequences; using WinIPC.Models; using WinIPC.Services; using WinIPC.Utils; namespace WebmrAPI.Services { public sealed class IPCClientService : IPCBaseClientService { public IPCClientService(ILogger logger, IOptions appConfigOptions) : base(logger, appConfigOptions?.Value?.IPCServiceOptions.BasePipeName ?? throw new ArgumentNullException(nameof(appConfigOptions))) { } public async Task> GetWindowInfos(int sessionId, IEnumerable? hwnds = null) { var req = new WindowsRequest(); if (hwnds != null) { foreach (var hwnd in hwnds) { req.Hwnds.Add((int)hwnd); } } var resp = await SendRequest(sessionId, CommandType.GetWindowsInfo, req).GetResponseAsync(); if (resp != null && resp.Success) { return PayloadHandler.ExtractPayload(resp).Data; } // TODO log Error return new List(); } public async Task GetScreenshot(int sessionId, IntPtr hwnd = 0, int x = 0, int y = 0, int width = 0, int height = 0) { var req = new ScreenshotRequest() { Hwnd = (int)hwnd, CropPosition = new() { X = x, Y = y }, CropSize = new() { Width = width, Height = height } }; var resp = await SendRequest(sessionId, CommandType.GetScreenshot, req).GetResponseAsync(); if (resp != null && resp.Success) { return PayloadHandler.ExtractPayload(resp).Data.ToByteArray(); } // TODO log Error return Array.Empty(); } public async Task GetPixelColor(int sessionId, IntPtr hwnd = 0, int x = 0, int y = 0) { var req = new PixelRequest() { Hwnd = (int)hwnd, PixelPosition = new() { X = x, Y = y } }; var resp = await SendRequest(sessionId, CommandType.GetPixelColor, req).GetResponseAsync(); if (resp != null && resp.Success) { return (int)PayloadHandler.ExtractPayload(resp).RgbColor; } // TODO log Error return -1; } private IEnumerable GetMouseMovingPath(ISequenceGenerator pGen, DelayGenerator dGen, ref int nActions) { List actions = new(); foreach (var p in pGen) { var input = new MouseMoveInput() { Position = new() { X = p.X, Y = p.Y } }; actions.Add(new InputAction() { Type = InputType.MouseMoveTo, DelayMs = (uint)dGen.Next().Value, Payload = ByteString.CopyFrom(PayloadHandler.Serialize(input)) }); ++nActions; } return actions; } private IEnumerable GetMouseScrollSequence(ScrollAmountGenerator sGen, DelayGenerator dGen, ref int nActions) { List actions = new(); foreach (var s in sGen) { var input = new ScrollInput() { Offset = s }; actions.Add(new InputAction() { Type = InputType.MouseScroll, DelayMs = (uint)dGen.Next().Value, Payload = ByteString.CopyFrom(PayloadHandler.Serialize(input)) }); ++nActions; } return actions; } private async Task SendInputActions(int sessionId, IntPtr hwnd, IEnumerable actions, int nActions) { var resp = await SendRequest(sessionId, CommandType.InputAction, new InputRequest() { Hwnd = (int)hwnd, Actions = { actions } }).GetResponseAsync(); if (resp != null && resp.Success) { return nActions - PayloadHandler.ExtractPayload(resp).Count; } // TODO log Error return -nActions; } public Task MouseMove(int sessionId, ISequenceGenerator pGen, DelayGenerator dGen, IntPtr hwnd = 0) { int nActions = 0; return SendInputActions(sessionId, hwnd, GetMouseMovingPath(pGen, dGen, ref nActions), nActions); } public Task HoldDownAndMouseMove(int sessionId, ISequenceGenerator pGen, DelayGenerator dGen, Key key, IntPtr hwnd = 0) { return HoldDownAndMouseMove(sessionId, pGen, dGen, new KeyShortcut(key), hwnd); } public Task HoldDownAndMouseMove(int sessionId, ISequenceGenerator pGen, DelayGenerator dGen, KeyShortcut sc, IntPtr hwnd = 0) { IEnumerable holdDown = sc.GetHoldDownActions(), holdUp = sc.GetHoldUpActions(); int nActions = holdDown.Count() + holdUp.Count(); return SendInputActions(sessionId, hwnd, holdDown.Concat(GetMouseMovingPath(pGen, dGen, ref nActions)).Concat(holdUp), nActions); } public Task MouseMoveAndPress(int sessionId, ISequenceGenerator pGen, DelayGenerator dGen, Key key, IntPtr hwnd = 0) { return MouseMoveAndPress(sessionId, pGen, dGen, new KeyShortcut(key), hwnd); } public Task MouseMoveAndPress(int sessionId, ISequenceGenerator pGen, DelayGenerator dGen, KeyShortcut sc, IntPtr hwnd = 0) { return MouseMoveAndPress(sessionId, pGen, dGen, new KeyShortcutSequence(sc), hwnd); } public Task MouseMoveAndPress(int sessionId, ISequenceGenerator pGen, DelayGenerator dGen, KeyShortcutSequence seq, IntPtr hwnd = 0) { IEnumerable press = seq.GetInputActions(); int nActions = press.Count(); return SendInputActions(sessionId, hwnd, GetMouseMovingPath(pGen, dGen, ref nActions).Concat(press), nActions); } public Task MouseScroll(int sessionId, ScrollAmountGenerator sGen, DelayGenerator dGen, IntPtr hwnd = 0) { int nActions = 0; return SendInputActions(sessionId, hwnd, GetMouseScrollSequence(sGen, dGen, ref nActions), nActions); } public Task HoldDownAndMouseScroll(int sessionId, ScrollAmountGenerator sGen, DelayGenerator dGen, Key key, IntPtr hwnd = 0) { return HoldDownAndMouseScroll(sessionId, sGen, dGen, new KeyShortcut(key), hwnd); } public Task HoldDownAndMouseScroll(int sessionId, ScrollAmountGenerator sGen, DelayGenerator dGen, KeyShortcut sc, IntPtr hwnd = 0) { IEnumerable holdDown = sc.GetHoldDownActions(), holdUp = sc.GetHoldUpActions(); int nActions = holdDown.Count() + holdUp.Count(); return SendInputActions(sessionId, hwnd, holdDown.Concat(GetMouseScrollSequence(sGen, dGen, ref nActions)).Concat(holdUp), nActions); } public Task HoldDown(int sessionId, Key key, IntPtr hwnd = 0) { return HoldDown(sessionId, new KeyShortcut(key), hwnd); } public Task HoldUp(int sessionId, Key key, IntPtr hwnd = 0) { return HoldUp(sessionId, new KeyShortcut(key), hwnd); } public Task HoldDown(int sessionId, KeyShortcut sc, IntPtr hwnd = 0) { IEnumerable holdDown = sc.GetHoldDownActions(); return SendInputActions(sessionId, hwnd, holdDown, holdDown.Count()); } public Task HoldUp(int sessionId, KeyShortcut sc, IntPtr hwnd = 0) { IEnumerable holdUp = sc.GetHoldUpActions(); return SendInputActions(sessionId, hwnd, holdUp, holdUp.Count()); } public Task Press(int sessionId, Key key, IntPtr hwnd = 0) { return Press(sessionId, new KeyShortcut(key), hwnd); } public Task Press(int sessionId, KeyShortcut sc, IntPtr hwnd = 0) { return Press(sessionId, new KeyShortcutSequence(sc), hwnd); } public Task Press(int sessionId, KeyShortcutSequence seq, IntPtr hwnd = 0) { IEnumerable press = seq.GetInputActions(); return SendInputActions(sessionId, hwnd, press, press.Count()); } } }