first commit
This commit is contained in:
commit
761b95080f
404 files changed
+312608
No files matched your search
@@ -0,0 +1,280 @@
|
||||
using MoonSharp.Interpreter;
|
||||
|
||||
namespace anjianjingling.Lua
|
||||
{
|
||||
/// <summary>
|
||||
/// 把自动化能力注册进 Lua 全局环境。
|
||||
/// 两套写法并存:
|
||||
/// 1) 全局简写(按键精灵风格) moveTo(100,200) leftClick() delay(500)
|
||||
/// 2) 命名空间写法 mouse.moveTo(100,200) mouse.click() key.press("ENTER")
|
||||
/// </summary>
|
||||
internal static class ScriptApi
|
||||
{
|
||||
private const double DefaultSim = 0.85;
|
||||
private const int DefaultTolerance = 10;
|
||||
|
||||
public static void Bind(Script script, LuaEngine engine, ILuaHost host)
|
||||
{
|
||||
var g = script.Globals;
|
||||
|
||||
// ===================== 基础 =====================
|
||||
g["log"] = (Action<string>)(m => host.Log(m));
|
||||
g["delay"] = (Action<double>)(ms => engine.Sleep(ms));
|
||||
g["sleep"] = (Action<double>)(ms => engine.Sleep(ms));
|
||||
g["delayRandom"] = (Action<double, double>)((a, b) =>
|
||||
{
|
||||
int lo = (int)Math.Min(a, b), hi = (int)Math.Max(a, b);
|
||||
engine.Sleep(lo >= hi ? lo : Random.Shared.Next(lo, hi + 1));
|
||||
});
|
||||
g["random"] = (Func<double, double, double>)((a, b) =>
|
||||
{
|
||||
int lo = (int)Math.Min(a, b), hi = (int)Math.Max(a, b);
|
||||
return lo >= hi ? lo : Random.Shared.Next(lo, hi + 1);
|
||||
});
|
||||
g["now"] = (Func<double>)(() => DateTimeOffset.Now.ToUnixTimeMilliseconds());
|
||||
g["stop"] = (Action)(() => throw new AbortSignal(false));
|
||||
|
||||
// ===================== 鼠标 =====================
|
||||
var mouse = new Table(script);
|
||||
mouse["moveTo"] = (Action<int, int>)((x, y) => { engine.Tick(); host.MouseMove(x, y); });
|
||||
mouse["moveR"] = (Action<int, int>)((dx, dy) => { engine.Tick(); host.MouseMoveR(dx, dy); });
|
||||
mouse["down"] = (Action<string>)(b => { engine.Tick(); host.MouseDown(NormBtn(b)); });
|
||||
mouse["up"] = (Action<string>)(b => { engine.Tick(); host.MouseUp(NormBtn(b)); });
|
||||
mouse["wheel"] = (Action<int>)(d => { engine.Tick(); host.MouseWheel(d); });
|
||||
mouse["drag"] = (Action<int, int, int, int, int>)((x1, y1, x2, y2, ms) =>
|
||||
{
|
||||
engine.Tick();
|
||||
host.MouseDrag(x1, y1, x2, y2, ms <= 0 ? 400 : ms);
|
||||
});
|
||||
mouse["pos"] = (Func<DynValue>)(() =>
|
||||
{
|
||||
engine.Tick();
|
||||
var p = host.MousePosition();
|
||||
return DynValue.NewTuple(DynValue.NewNumber(p.X), DynValue.NewNumber(p.Y));
|
||||
});
|
||||
|
||||
// click 支持多种参数形态
|
||||
mouse["click"] = DynValue.NewCallback((ctx, a) =>
|
||||
{
|
||||
engine.Tick();
|
||||
string btn = "left";
|
||||
int? x = null, y = null;
|
||||
if (a.Count >= 3 && a[0].Type == DataType.Number)
|
||||
{
|
||||
x = (int)Math.Round(a[0].Number);
|
||||
y = (int)Math.Round(a[1].Number);
|
||||
btn = a[2].Type == DataType.String ? a[2].String : "left";
|
||||
}
|
||||
else if (a.Count >= 2 && a[0].Type == DataType.Number)
|
||||
{
|
||||
x = (int)Math.Round(a[0].Number);
|
||||
y = (int)Math.Round(a[1].Number);
|
||||
}
|
||||
else if (a.Count >= 1 && a[0].Type == DataType.String)
|
||||
{
|
||||
btn = a[0].String;
|
||||
}
|
||||
host.MouseClick(NormBtn(btn), x, y);
|
||||
return DynValue.Nil;
|
||||
});
|
||||
|
||||
mouse["doubleClick"] = DynValue.NewCallback((ctx, a) =>
|
||||
{
|
||||
engine.Tick();
|
||||
int? x = a.Count >= 2 && a[0].Type == DataType.Number ? (int)Math.Round(a[0].Number) : null;
|
||||
int? y = a.Count >= 2 && a[0].Type == DataType.Number ? (int)Math.Round(a[1].Number) : null;
|
||||
host.MouseDoubleClick(x, y);
|
||||
return DynValue.Nil;
|
||||
});
|
||||
g["mouse"] = mouse;
|
||||
|
||||
// ===================== 键盘 =====================
|
||||
var key = new Table(script);
|
||||
key["press"] = (Action<string>)(k => { engine.Tick(); host.KeyPress(k); });
|
||||
key["down"] = (Action<string>)(k => { engine.Tick(); host.KeyDown(k); });
|
||||
key["up"] = (Action<string>)(k => { engine.Tick(); host.KeyUp(k); });
|
||||
key["hotkey"] = (Action<string>)(k => { engine.Tick(); host.HotKey(k); });
|
||||
key["type"] = (Action<string>)(t => { engine.Tick(); host.TypeText(t); });
|
||||
g["key"] = key;
|
||||
|
||||
// ===================== 屏幕 / 视觉 =====================
|
||||
var screen = new Table(script);
|
||||
screen["size"] = (Func<DynValue>)(() =>
|
||||
{
|
||||
engine.Tick();
|
||||
var (w, h) = host.ScreenSize();
|
||||
return DynValue.NewTuple(DynValue.NewNumber(w), DynValue.NewNumber(h));
|
||||
});
|
||||
screen["color"] = (Func<int, int, string>)((x, y) => { engine.Tick(); return host.ColorAt(x, y); });
|
||||
screen["shot"] = (Action<string>)(p => { engine.Tick(); host.ScreenShot(p); });
|
||||
screen["pick"] = (Func<string, string>)(p =>
|
||||
{
|
||||
engine.Tick();
|
||||
return host.PickRegion(string.IsNullOrWhiteSpace(p) ? null : p) ?? "";
|
||||
});
|
||||
|
||||
screen["findColor"] = DynValue.NewCallback((ctx, a) =>
|
||||
{
|
||||
engine.Tick();
|
||||
string hex = a.Count > 0 && a[0].Type == DataType.String ? a[0].String : "FF0000";
|
||||
int tol = a.Count > 1 && a[1].Type == DataType.Number ? (int)Math.Round(a[1].Number) : DefaultTolerance;
|
||||
var (w, h) = host.ScreenSize();
|
||||
int x1 = a.Count > 2 ? (int)Math.Round(a[2].Number) : 0;
|
||||
int y1 = a.Count > 3 ? (int)Math.Round(a[3].Number) : 0;
|
||||
int x2 = a.Count > 4 ? (int)Math.Round(a[4].Number) : w - 1;
|
||||
int y2 = a.Count > 5 ? (int)Math.Round(a[5].Number) : h - 1;
|
||||
var p = host.FindColor(x1, y1, x2, y2, hex, tol);
|
||||
return DynValue.NewTuple(DynValue.NewNumber(p.X), DynValue.NewNumber(p.Y));
|
||||
});
|
||||
|
||||
screen["findImage"] = DynValue.NewCallback((ctx, a) =>
|
||||
{
|
||||
engine.Tick();
|
||||
string path = a.Count > 0 && a[0].Type == DataType.String ? a[0].String : "";
|
||||
double sim = a.Count > 1 && a[1].Type == DataType.Number ? a[1].Number : DefaultSim;
|
||||
var (w, h) = host.ScreenSize();
|
||||
int x1 = a.Count > 2 ? (int)Math.Round(a[2].Number) : 0;
|
||||
int y1 = a.Count > 3 ? (int)Math.Round(a[3].Number) : 0;
|
||||
int x2 = a.Count > 4 ? (int)Math.Round(a[4].Number) : w - 1;
|
||||
int y2 = a.Count > 5 ? (int)Math.Round(a[5].Number) : h - 1;
|
||||
var r = host.FindImage(x1, y1, x2, y2, path, sim);
|
||||
return DynValue.NewTuple(
|
||||
DynValue.NewNumber(r.X), DynValue.NewNumber(r.Y), DynValue.NewNumber(r.Score));
|
||||
});
|
||||
|
||||
screen["waitImage"] = DynValue.NewCallback((ctx, a) =>
|
||||
{
|
||||
string path = a.Count > 0 && a[0].Type == DataType.String ? a[0].String : "";
|
||||
int timeout = a.Count > 1 && a[1].Type == DataType.Number ? (int)Math.Round(a[1].Number) : 10000;
|
||||
double sim = a.Count > 2 && a[2].Type == DataType.Number ? a[2].Number : DefaultSim;
|
||||
|
||||
var (w, h) = host.ScreenSize();
|
||||
var sw = System.Diagnostics.Stopwatch.StartNew();
|
||||
int rx = -1, ry = -1;
|
||||
double best = 0;
|
||||
while (sw.ElapsedMilliseconds < timeout)
|
||||
{
|
||||
engine.Tick();
|
||||
var r = host.FindImage(0, 0, w - 1, h - 1, path, sim);
|
||||
best = r.Score;
|
||||
if (r.X >= 0) { rx = r.X; ry = r.Y; break; }
|
||||
engine.Sleep(300);
|
||||
}
|
||||
host.Log(rx >= 0
|
||||
? $"等待图片出现:找到 ({rx},{ry}) 相似度 {best:0.00}"
|
||||
: $"等待图片超时:{path}(最高 {best:0.00})");
|
||||
return DynValue.NewTuple(
|
||||
DynValue.NewNumber(rx), DynValue.NewNumber(ry), DynValue.NewNumber(best));
|
||||
});
|
||||
|
||||
screen["exists"] = DynValue.NewCallback((ctx, a) =>
|
||||
{
|
||||
engine.Tick();
|
||||
string path = a.Count > 0 && a[0].Type == DataType.String ? a[0].String : "";
|
||||
double sim = a.Count > 1 && a[1].Type == DataType.Number ? a[1].Number : DefaultSim;
|
||||
var (w, h) = host.ScreenSize();
|
||||
var r = host.FindImage(0, 0, w - 1, h - 1, path, sim);
|
||||
return DynValue.NewBoolean(r.X >= 0);
|
||||
});
|
||||
g["screen"] = screen;
|
||||
|
||||
// ===================== 窗口 / 系统 =====================
|
||||
var win = new Table(script);
|
||||
win["launch"] = (Action<string, string>)((p, args) => { engine.Tick(); host.Launch(p, args); });
|
||||
win["activate"] = (Func<string, bool>)(t => { engine.Tick(); return host.ActivateWindow(t); });
|
||||
win["list"] = (Func<DynValue>)(() =>
|
||||
{
|
||||
engine.Tick();
|
||||
var list = new Table(script);
|
||||
var arr = host.ListWindows();
|
||||
for (int i = 0; i < arr.Length; i++) list[i + 1] = arr[i];
|
||||
return DynValue.NewTable(list);
|
||||
});
|
||||
g["win"] = win;
|
||||
|
||||
var sys = new Table(script);
|
||||
sys["time"] = (Func<double>)(() => DateTimeOffset.Now.ToUnixTimeMilliseconds());
|
||||
sys["sleep"] = (Action<double>)(ms => engine.Sleep(ms));
|
||||
sys["speed"] = (Func<double, double>)(s => { engine.Speed = s <= 0 ? 1 : s; return engine.Speed; });
|
||||
g["sys"] = sys;
|
||||
|
||||
// ===================== 剪贴板 =====================
|
||||
var clip = new Table(script);
|
||||
clip["get"] = (Func<string>)(() => host.ClipGet());
|
||||
clip["set"] = (Action<string>)(t => host.ClipSet(t));
|
||||
g["clip"] = clip;
|
||||
|
||||
// ===================== 浏览器 =====================
|
||||
var browser = new Table(script);
|
||||
browser["open"] = (Action<string>)(u => { engine.Tick(); host.BrowserOpen(u); });
|
||||
browser["click"] = (Func<string, bool>)(s => { engine.Tick(); return host.BrowserClick(s); });
|
||||
browser["type"] = (Func<string, string, bool>)((s, t) => { engine.Tick(); return host.BrowserType(s, t); });
|
||||
browser["wait"] = (Func<string, int, bool>)((s, ms) => { engine.Tick(); return host.BrowserWaitFor(s, ms <= 0 ? 10000 : ms); });
|
||||
browser["text"] = (Func<string, string>)(s => { engine.Tick(); return host.BrowserGetText(s); });
|
||||
browser["js"] = (Func<string, string>)(js => { engine.Tick(); return host.BrowserExecJs(js); });
|
||||
browser["shot"] = (Action<string>)(p => { engine.Tick(); host.BrowserShot(p); });
|
||||
browser["back"] = (Action)(() => { engine.Tick(); host.BrowserBack(); });
|
||||
browser["forward"] = (Action)(() => { engine.Tick(); host.BrowserForward(); });
|
||||
browser["reload"] = (Action)(() => { engine.Tick(); host.BrowserReload(); });
|
||||
g["browser"] = browser;
|
||||
|
||||
// ===================== 全局简写 =====================
|
||||
g["moveTo"] = mouse["moveTo"];
|
||||
g["moveR"] = mouse["moveR"];
|
||||
g["click"] = mouse["click"];
|
||||
g["leftClick"] = DynValue.NewCallback((ctx, a) =>
|
||||
{
|
||||
engine.Tick();
|
||||
int? x = a.Count >= 2 ? (int)Math.Round(a[0].Number) : null;
|
||||
int? y = a.Count >= 2 ? (int)Math.Round(a[1].Number) : null;
|
||||
host.MouseClick("left", x, y);
|
||||
return DynValue.Nil;
|
||||
});
|
||||
g["rightClick"] = DynValue.NewCallback((ctx, a) =>
|
||||
{
|
||||
engine.Tick();
|
||||
int? x = a.Count >= 2 ? (int)Math.Round(a[0].Number) : null;
|
||||
int? y = a.Count >= 2 ? (int)Math.Round(a[1].Number) : null;
|
||||
host.MouseClick("right", x, y);
|
||||
return DynValue.Nil;
|
||||
});
|
||||
g["middleClick"] = DynValue.NewCallback((ctx, a) =>
|
||||
{
|
||||
engine.Tick();
|
||||
int? x = a.Count >= 2 ? (int)Math.Round(a[0].Number) : null;
|
||||
int? y = a.Count >= 2 ? (int)Math.Round(a[1].Number) : null;
|
||||
host.MouseClick("middle", x, y);
|
||||
return DynValue.Nil;
|
||||
});
|
||||
g["doubleClick"] = mouse["doubleClick"];
|
||||
g["wheel"] = mouse["wheel"];
|
||||
g["drag"] = mouse["drag"];
|
||||
|
||||
g["keyPress"] = key["press"];
|
||||
g["keyDown"] = key["down"];
|
||||
g["keyUp"] = key["up"];
|
||||
g["hotkey"] = key["hotkey"];
|
||||
g["typeText"] = key["type"];
|
||||
g["sayText"] = key["type"];
|
||||
|
||||
g["findImage"] = screen["findImage"];
|
||||
g["findColor"] = screen["findColor"];
|
||||
g["waitImage"] = screen["waitImage"];
|
||||
g["exists"] = screen["exists"];
|
||||
g["colorAt"] = screen["color"];
|
||||
g["screenshot"] = screen["shot"];
|
||||
|
||||
g["run"] = win["launch"];
|
||||
g["activate"] = win["activate"];
|
||||
g["clipGet"] = clip["get"];
|
||||
g["clipSet"] = clip["set"];
|
||||
}
|
||||
|
||||
private static string NormBtn(string b) => b.Trim().ToLowerInvariant() switch
|
||||
{
|
||||
"右" or "right" or "r" or "rightclick" => "right",
|
||||
"中" or "middle" or "m" => "middle",
|
||||
_ => "left"
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user