请指导我开发一个定时领券脚本,需求如下:
领券规则:只有在每小时的整点或每小时的30分才可以领取,其他时间领取按钮处于无法点击状态
领券资格:领券按钮默认状态为"待解锁",点击"待解锁"后会有一个弹窗询问是否解锁,点击弹窗的"确认"按钮后,"待解锁"按钮变为“立即抢”
页面初始状态:页面初始状态为已经弹出了待解锁弹窗,弹窗内有取消和确认按钮
关键流程:本脚本需要在整点或30分前提前200毫秒(比如在17点59分800毫秒这个时间点)帮我自动点击弹窗内的确认按钮,弹窗关闭后页面上的待解锁会变为立即抢,并立即寻找页面上的"立即抢"按钮,找到立即抢后触发点击事件。

gutony_ykhu · 3 小时前

回答

Hamibot AI
1
· 3 小时前

开发定时领券脚本需要精确的时间控制和快速的 UI 交互。以下是基于 Hamibot 脚本环境的实现方案和代码示例。

核心逻辑

  1. 时间校准:获取当前设备时间,计算距离下一个整点或半点还差多少毫秒。
  2. 精准等待:使用循环检测时间,确保在目标时间点前 200 毫秒执行操作。
  3. UI 交互:依次点击“确认”按钮解锁,随后立即点击“立即抢”按钮。

脚本代码

请在 Hamibot 编辑器中创建新脚本,复制以下代码。注意代码已适配 Rhino 1.7.15 引擎,避免使用箭头函数和默认参数。

// 文档地址 https://docs.hamibot.com/

// 配置目标分钟数
var targetMinutes = [0, 30];
// 提前量(毫秒)
var advanceMs = 200;

// 获取下一个目标时间点
function getNextTargetTime() {
    var now = new Date();
    var year = now.getFullYear();
    var month = now.getMonth();
    var date = now.getDate();
    var hour = now.getHours();
    var minute = now.getMinutes();
    
    var nextHour = hour;
    var nextMinute = 0;
    
    // 寻找最近的 0 分或 30 分
    var found = false;
    for (var i = 0; i < targetMinutes.length; i++) {
        var m = targetMinutes[i];
        if (m > minute) {
            nextMinute = m;
            found = true;
            break;
        }
    }
    
    if (!found) {
        // 如果当前分钟已超过 30 分,目标为下一个小时的 0 分
        nextHour = hour + 1;
        nextMinute = 0;
    }
    
    var targetDate = new Date(year, month, date, nextHour, nextMinute, 0, 0);
    return targetDate.getTime();
}

// 主流程
function main() {
    var targetTime = getNextTargetTime();
    var nowTime = new Date().getTime();
    var waitTime = targetTime - nowTime - advanceMs;
    
    log("目标时间:" + new Date(targetTime).toLocaleTimeString());
    log("等待毫秒数:" + waitTime);
    
    if (waitTime > 0) {
        // 先睡眠大部分时间,减少 CPU 占用
        sleep(waitTime - 100);
        
        // 最后阶段高精度等待
        while (new Date().getTime() < targetTime - advanceMs) {
            // 空循环等待
        }
    }
    
    log("开始执行点击");
    
    // 1. 点击弹窗确认按钮
    var confirmBtn = text("确认").findOne(1000);
    if (confirmBtn) {
        confirmBtn.click();
        log("已点击确认");
    } else {
        log("未找到确认按钮,尝试直接寻找立即抢");
    }
    
    // 2. 点击立即抢按钮
    // 使用循环确保按钮出现,防止因动画延迟导致点击失败
    var grabBtn = null;
    for (var i = 0; i < 10; i++) {
        grabBtn = text("立即抢").findOne(100);
        if (grabBtn) {
            grabBtn.click();
            log("已点击立即抢");
            break;
        }
    }
    
    if (!grabBtn) {
        log("未找到立即抢按钮");
    }
}

main();

关键实现说明

  1. 时间计算策略
    脚本通过 getNextTargetTime 函数计算下一个 0 分或 30 分的时间戳。采用分段等待策略:先使用 sleep 等待大部分时间,最后 100 毫秒使用 while 循环检测 new Date().getTime(),以减少系统调度带来的误差。

  2. UI 元素定位
    使用 text("按钮文字") 选择器定位元素。findOne(1000) 表示最多等待 1 秒,避免脚本无限卡住。针对“立即抢”按钮,增加了重试循环,防止因弹窗关闭动画导致按钮尚未渲染完成。

  3. 引擎兼容性
    代码遵循 Rhino 1.7.15 规范,全部使用 var 声明变量,函数使用 function 关键字定义,确保在 Hamibot 环境中稳定运行。

注意事项

  • 时间同步:设备系统时间必须准确。建议开启“自动确定日期和时间”,否则本地时间与服务器时间偏差会导致领券失败。
  • 性能影响:最后阶段的高精度循环会占用 CPU,请确保手机性能充足,后台无过多应用干扰。
  • 网络延迟:脚本仅控制点击动作。点击后的请求发送速度受网络和服务器响应影响,200 毫秒提前量旨在抵消部分设备响应延迟,但无法消除网络延迟。
  • 界面适配:如果按钮文字发生变化(如“确认”变为“确定”),请修改代码中的 text("...") 内容。也可使用 desc()id() 选择器提高稳定性。

调试建议

在正式运行前,建议将 advanceMs 调整为较大数值(如 5000),测试脚本能否正确识别时间并执行点击流程。确认逻辑无误后,再调整为 200 毫秒进行实战。

ℹ️ 本回答由 AI 生成,内容仅供参考