diff --git a/.github/workflows/hrp-release.yml b/.github/workflows/hrp-release.yml index 1821ccbc..4aa9b662 100644 --- a/.github/workflows/hrp-release.yml +++ b/.github/workflows/hrp-release.yml @@ -21,9 +21,9 @@ jobs: goos: windows steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Release hrp cli binaries - uses: wangyoucao577/go-release-action@v1.23 + uses: wangyoucao577/go-release-action@v1 with: github_token: ${{ secrets.GITHUB_TOKEN }} goos: ${{ matrix.goos }} diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 83b51648..ed37df31 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -5,6 +5,7 @@ **go version** - feat: add `WithSwipeOffset` to set offset for swipe start/end point +- feat: set random offset for tap/swipe points with `WithOffsetRandomRange` - change: set `WithOffset` deprecated, replace with `WithTapOffset` ## v4.3.6 (2023-09-07) diff --git a/examples/uitest/demo_douyin_follow_live_test.go b/examples/uitest/demo_douyin_follow_live_test.go index a749f709..abec51f2 100644 --- a/examples/uitest/demo_douyin_follow_live_test.go +++ b/examples/uitest/demo_douyin_follow_live_test.go @@ -39,8 +39,8 @@ func TestIOSDouyinFollowLive(t *testing.T) { TapByOCR("关注", uixt.WithIndex(1)).Sleep(10), hrp.NewStep("向上滑动 2 次"). IOS().SwipeToTapTexts([]string{"理肤泉", "婉宝"}, uixt.WithCustomDirection(0.6, 0.2, 0.2, 0.2), uixt.WithIdentifier("click_live")).Sleep(10). - Swipe(0.9, 0.7, 0.9, 0.3, uixt.WithIdentifier("slide_in_live")).Sleep(10).ScreenShot(). // 上划 1 次,等待 10s,截图保存 - Swipe(0.9, 0.7, 0.9, 0.3, uixt.WithIdentifier("slide_in_live")).Sleep(10).ScreenShot(), // 再上划 1 次,等待 10s,截图保存 + Swipe(0.9, 0.7, 0.9, 0.3, uixt.WithIdentifier("slide_in_live"), uixt.WithOffsetRandomRange(-10, 10)).Sleep(10).ScreenShot(). // 上划 1 次,等待 10s,截图保存 + Swipe(0.9, 0.7, 0.9, 0.3, uixt.WithIdentifier("slide_in_live"), uixt.WithOffsetRandomRange(-10, 10)).Sleep(10).ScreenShot(), // 再上划 1 次,等待 10s,截图保存 }, } diff --git a/hrp/pkg/uixt/action.go b/hrp/pkg/uixt/action.go index 0433bfbd..d17dd2e9 100644 --- a/hrp/pkg/uixt/action.go +++ b/hrp/pkg/uixt/action.go @@ -106,11 +106,11 @@ type ActionOptions struct { Scope Scope `json:"scope,omitempty" yaml:"scope,omitempty"` AbsScope AbsScope `json:"abs_scope,omitempty" yaml:"abs_scope,omitempty"` - Regex bool `json:"regex,omitempty" yaml:"regex,omitempty"` // use regex to match text - Offset []int `json:"offset,omitempty" yaml:"offset,omitempty"` // used to tap offset of point - OffsetRandomScale float64 `json:"offset_random_scale,omitempty" yaml:"offset_random_scale,omitempty"` // used with Offset, set random scale for point - Index int `json:"index,omitempty" yaml:"index,omitempty"` // index of the target element - MatchOne bool `json:"match_one,omitempty" yaml:"match_one,omitempty"` // match one of the targets if existed + Regex bool `json:"regex,omitempty" yaml:"regex,omitempty"` // use regex to match text + Offset []int `json:"offset,omitempty" yaml:"offset,omitempty"` // used to tap offset of point + OffsetRandomRange []int `json:"offset_random_range,omitempty" yaml:"offset_random_range,omitempty"` // set random range [min, max] for tap/swipe points + Index int `json:"index,omitempty" yaml:"index,omitempty"` // index of the target element + MatchOne bool `json:"match_one,omitempty" yaml:"match_one,omitempty"` // match one of the targets if existed // set custiom options such as textview, id, description Custom map[string]interface{} `json:"custom,omitempty" yaml:"custom,omitempty"` @@ -189,6 +189,11 @@ func (o *ActionOptions) Options() []ActionOption { options = append(options, WithSwipeOffset( o.Offset[0], o.Offset[1], o.Offset[2], o.Offset[3])) } + if len(o.OffsetRandomRange) == 2 { + options = append(options, WithOffsetRandomRange( + o.OffsetRandomRange[0], o.OffsetRandomRange[1])) + } + if o.Regex { options = append(options, WithRegex(true)) } @@ -244,6 +249,17 @@ func (o *ActionOptions) screenshotActions() []string { return actions } +func (o *ActionOptions) getRandomOffset() int { + if len(o.OffsetRandomRange) != 2 { + // invalid offset random range, should be [min, max] + return 0 + } + + minOffset := o.OffsetRandomRange[0] + maxOffset := o.OffsetRandomRange[1] + return builtin.GetRandomNumber(minOffset, maxOffset) +} + func NewActionOptions(options ...ActionOption) *ActionOptions { actionOptions := &ActionOptions{} for _, option := range options { @@ -266,47 +282,47 @@ func mergeDataWithOptions(data map[string]interface{}, options ...ActionOption) if len(actionOptions.Offset) == 2 { if x, ok := data["x"]; ok { xf, _ := builtin.Interface2Float64(x) - data["x"] = xf + float64(actionOptions.Offset[0]) + data["x"] = xf + float64(actionOptions.Offset[0]+actionOptions.getRandomOffset()) } if y, ok := data["y"]; ok { yf, _ := builtin.Interface2Float64(y) - data["y"] = yf + float64(actionOptions.Offset[1]) + data["y"] = yf + float64(actionOptions.Offset[1]+actionOptions.getRandomOffset()) } } else if len(actionOptions.Offset) == 4 { // Android uia2: [startX, startY, endX, endY] if startX, ok := data["startX"]; ok { vf, _ := builtin.Interface2Float64(startX) - data["startX"] = vf + float64(actionOptions.Offset[0]) + data["startX"] = vf + float64(actionOptions.Offset[0]+actionOptions.getRandomOffset()) } if startY, ok := data["startY"]; ok { vf, _ := builtin.Interface2Float64(startY) - data["startY"] = vf + float64(actionOptions.Offset[1]) + data["startY"] = vf + float64(actionOptions.Offset[1]+actionOptions.getRandomOffset()) } if endX, ok := data["endX"]; ok { vf, _ := builtin.Interface2Float64(endX) - data["endX"] = vf + float64(actionOptions.Offset[2]) + data["endX"] = vf + float64(actionOptions.Offset[2]+actionOptions.getRandomOffset()) } if endY, ok := data["endY"]; ok { vf, _ := builtin.Interface2Float64(endY) - data["endY"] = vf + float64(actionOptions.Offset[3]) + data["endY"] = vf + float64(actionOptions.Offset[3]+actionOptions.getRandomOffset()) } // iOS WDA: [fromX, fromY, toX, toY] if fromX, ok := data["fromX"]; ok { vf, _ := builtin.Interface2Float64(fromX) - data["fromX"] = vf + float64(actionOptions.Offset[0]) + data["fromX"] = vf + float64(actionOptions.Offset[0]+actionOptions.getRandomOffset()) } if fromY, ok := data["fromY"]; ok { vf, _ := builtin.Interface2Float64(fromY) - data["fromY"] = vf + float64(actionOptions.Offset[1]) + data["fromY"] = vf + float64(actionOptions.Offset[1]+actionOptions.getRandomOffset()) } if toX, ok := data["toX"]; ok { vf, _ := builtin.Interface2Float64(toX) - data["toX"] = vf + float64(actionOptions.Offset[2]) + data["toX"] = vf + float64(actionOptions.Offset[2]+actionOptions.getRandomOffset()) } if toY, ok := data["toY"]; ok { vf, _ := builtin.Interface2Float64(toY) - data["toY"] = vf + float64(actionOptions.Offset[3]) + data["toY"] = vf + float64(actionOptions.Offset[3]+actionOptions.getRandomOffset()) } } @@ -436,6 +452,12 @@ func WithSwipeOffset(offsetFromX, offsetFromY, offsetToX, offsetToY int) ActionO } } +func WithOffsetRandomRange(min, max int) ActionOption { + return func(o *ActionOptions) { + o.OffsetRandomRange = []int{min, max} + } +} + func WithRegex(regex bool) ActionOption { return func(o *ActionOptions) { o.Regex = regex diff --git a/hrp/pkg/uixt/android_adb_driver.go b/hrp/pkg/uixt/android_adb_driver.go index c0e64cf5..c360a9f4 100644 --- a/hrp/pkg/uixt/android_adb_driver.go +++ b/hrp/pkg/uixt/android_adb_driver.go @@ -225,8 +225,8 @@ func (ad *adbDriver) TapFloat(x, y float64, options ...ActionOption) (err error) actionOptions := NewActionOptions(options...) if len(actionOptions.Offset) == 2 { - x += float64(actionOptions.Offset[0]) - y += float64(actionOptions.Offset[1]) + x += float64(actionOptions.Offset[0] + actionOptions.getRandomOffset()) + y += float64(actionOptions.Offset[1] + actionOptions.getRandomOffset()) } // adb shell input tap x y @@ -275,10 +275,10 @@ func (ad *adbDriver) SwipeFloat(fromX, fromY, toX, toY float64, options ...Actio actionOptions := NewActionOptions(options...) if len(actionOptions.Offset) == 4 { - fromX += float64(actionOptions.Offset[0]) - fromY += float64(actionOptions.Offset[1]) - toX += float64(actionOptions.Offset[2]) - toY += float64(actionOptions.Offset[3]) + fromX += float64(actionOptions.Offset[0] + actionOptions.getRandomOffset()) + fromY += float64(actionOptions.Offset[1] + actionOptions.getRandomOffset()) + toX += float64(actionOptions.Offset[2] + actionOptions.getRandomOffset()) + toY += float64(actionOptions.Offset[3] + actionOptions.getRandomOffset()) } // adb shell input swipe fromX fromY toX toY