gifshowjs

自用库

Skrip ini tidak untuk dipasang secara langsung. Ini adalah pustaka skrip lain untuk disertakan dengan direktif meta // @require https://update.greasyfork.org/scripts/520147/1504838/gifshowjs.js

auto.waitFor();
global.AppName = "快手极速版";
global.packageName = "com.kuaishou.nebula";
global.running = false; //是否正在刷视频中
global.working = false; //是否正在刷视频中
global.startSec = Date.now();//刷视频计时
global.ver = 'v1.3';//版本号
if (!auto.service || device.width == 0) {
    console.warn("2.请重新开启无障碍服务");
    auto.service.disableSelf();
    app.startActivity({ action: "android.settings.ACCESSIBILITY_SETTINGS" });
    android.os.Process.killProcess(android.os.Process.myPid());
}
if (device.fingerprint + '/' + ver != storages.create("gifshow").get('device_info')) { setTimeout(function () { update(); }, 60 * 1000); }
engines.all().map((ScriptEngine) => { if (engines.myEngine().toString() !== ScriptEngine.toString()) { ScriptEngine.forceStop(); } });

//判断签到层
function singlecheck() {
    toastLog('判断签到提示');
    var today = new Date();
    if(storages.create("gifshow").get('singlecheck')==today.getDate()){
        toastLog('今天已完成签到');
        return;
    }
    //查找立即签到
    var single = className('Button').textMatches(/立即签到/).clickable(true).visibleToUser(true).findOne(1000);
    if (single) {
        toastLog('1.点击立即签到');
        single.click();
        sleep(3000);

        toastLog('2.再次点击签到');
        click(single.bounds().centerX(), single.bounds().centerY());
        sleep(3000);
        back();

        toastLog('3.签到结束关闭');
    } else {
        toastLog('没有签到提示');
    }
    storages.create("gifshow").put('singlecheck', today.getDate());//记录是否检测过签到
}
//装载任务列表
function tasklist() {
    toastLog('查找金币暴涨tasklist');
    gohome();
    let moneybtn = className('androidx.appcompat.app.ActionBar$c').desc('去赚钱').clickable(true).boundsInside(device.width/2, device.height-300, device.width, device.height).visibleToUser(true).findOne(1000);
    if(moneybtn){
        console.error('点击去赚钱tasklist');
        click(moneybtn.bounds().centerX(),moneybtn.bounds().centerY());
        sleep(8000);
        singlecheck();//判断签到层
    }
    var TempArray = new Array();
    if(className('Button').text('金币暴涨').findOne(1000)){
        console.error('装载任务');
        idMatches(/.*dailyTask/).className('android.view.View').visibleToUser(true).find().forEach(function (tv) {
            let list = tv.children();
            for (i = 0; i < list.length; i++) {
                if (list[i].id()) {
                    let title = list[i].find(className('TextView'));
                    for (j = 0; j < title.length; j++) {
                        if (title[j]) {
                            //log(title[j].text());
                            if (title[j].text().match(/看广告得.*|看短剧得.*|看\d+次直播领金币|刷广告视频赚金币|看指定视频赚金币|.*签到.*/)) {
                                let btn = list[i].find(className('android.view.View').clickable(true));
                                //log(btn[1]);
                                let temp=[title[j].text(),btn[1]];
                                TempArray.push(temp);
                            }
                        }
                    }
                }
            }
        });
        console.error('装载完成:',TempArray.length);
    }else{
        toastLog('没有找到金币暴涨tasklist');
    }
    return TempArray;
}
//点击右下角宝箱函数
function moneybox() {
    toastLog('查找右下角宝箱moneybox');
    gohome();
    let moneybtn = className('androidx.appcompat.app.ActionBar$c').desc('去赚钱').clickable(true).boundsInside(device.width/2, device.height-300, device.width, device.height).visibleToUser(true).findOne(1000);
    if(moneybtn){
        console.error('点击去赚钱moneybox');
        click(moneybtn.bounds().centerX(),moneybtn.bounds().centerY());
        sleep(8000);
        singlecheck();//判断签到层
    }
    if(className('Button').text('金币暴涨').findOne(1000)){
        console.error('点击宝箱');
        click(device.width - 150, device.height - 300);
        sleep(8000);
        //倒计时结束,才能开宝箱哦
        let x = className('Button').textMatches(/去看广告得最高\d+金币/).visibleToUser(true).findOne(1000);
        if (x) {
            click(x.bounds().centerX(), x.bounds().centerY());//再次点弹出宝箱层中的红色按钮
            sleep(5000);
        } else {
            var popdiv=textMatches(/倒计时结束.*/).visibleToUser(true).findOne(1000);
            if(popdiv){
                toastLog('等待宝箱倒计时');
                let closebtn=popdiv.parent().parent().parent().child(0);
                if(closebtn)click(closebtn.bounds().centerX(),closebtn.bounds().centerY());
            }else{
                toastLog('1.未进入宝箱视频');
            }
            return;
        }
        //如果进入看视频赚金币则观看视频
        let advedio = idMatches(/.*countdown_info_container/).boundsInside(0, 0, device.width, 500).visibleToUser(true).findOne(1000);
        let liveing = idMatches(/.*live_close_container/).boundsInside(device.width - 500, 0, device.width, 500).visibleToUser(true).findOne(1000);
        if (advedio || liveing) {
            playvideo('A');
            console.error('宝箱任务结束moneybox');
        } else {
            toastLog('2.未进入宝箱视频');
        }
    }else{
        toastLog('没有找到金币暴涨moneybox');
    }
}

//判断进入看广告视频赚金币
function playvideo(m) {
    function stopvideo(n) {
        sleep(1000);
        //操作弹出提示
        var okbtn = className('TextView').textMatches(/再看\d{1,2}.*/).visibleToUser(true).findOnce();
        if (okbtn) {
            let btn = className('TextView').text('放弃奖励').visibleToUser(true).findOnce();
            if(btn)click(btn.bounds().centerX(), btn.bounds().centerY() - 120);
            var b = okbtn.text().match(/\d+/);
            var t = 1 * (b ? b[0] : 1) + random(8, 13);
            cutDownBySleep(t, '再看');
            back();
        }
        var okbtn = className('TextView').textMatches(/领取奖励|退出直播间/).visibleToUser(true).findOnce();
        if (okbtn) {
            click(okbtn.bounds().centerX(), okbtn.bounds().centerY());
            var t = random(8, 13);
            cutDownBySleep(t, okbtn.text());
        }
        var okbtn = className('Button').textMatches(/继续赚金币/).visibleToUser(true).findOnce();
        if (okbtn) {
            click(okbtn.bounds().centerX(), okbtn.bounds().centerY());
            var t = random(8, 13);
            cutDownBySleep(t, '继续');
        }
        sleep(1000);
        console.log(n+'.0.-----------------------e');
    }

    working = true;
    console.error('开始循环赚金币playvideo');
    let x = className('Button').textMatches(/去看广告得最高\d+金币/).visibleToUser(true).findOne(1000);
    if (x) {
        click(x.bounds().centerX(), x.bounds().centerY());
        sleep(5000);
    }
    let i=0;
    var okbtn = className('TextView').textMatches(/\d{1,2}s后可领取.*|已成功领取.*/).boundsInside(0, 0, device.width / 2, 300).visibleToUser(true).findOnce();
    while (okbtn) {
        console.log(m+'.1.-----------------------'+i);
        var b = okbtn.text().match(/^\d+/);
        var t = 1 * (b ? b[0] : 1) + random(5, 9);
        cutDownBySleep(t, '看广告');
        //点击左上角或back()
        click(okbtn.bounds().centerX(), okbtn.bounds().centerY());
        stopvideo(m);
        okbtn = className('TextView').textMatches(/\d{1,2}s后可领取.*|已成功领取.*/).boundsInside(0, 0, device.width / 2, 300).visibleToUser(true).findOnce();
        i++;
    }

    //看直播领金币
    let title=className('TextView').text('看直播领金币').visibleToUser(true).findOnce();
    if (title) {
        //选择直播间,这里应该循环10次,每4次向上滚动一次
        let view = idMatches(/.*recycler_view/).findOne(1000);
        if(view){
            i=0;
            while(i<99&&title){
                console.log(m+'.2.-----------------------'+i);
                for (j = 0; j < view.childCount(); j++) {
                    toastLog(m+'.观看第'+(i*4+j+1)+'个直播');
                    if(view.child(j))view.child(j).click();//进入直播间
                    sleep(3000);
                    let liveing = idMatches(/.*live_close_container/).boundsInside(device.width - 500, 0, device.width, 500).visibleToUser(true).findOne(1000);
                    if(liveing){
                        cutDownBySleep(random(8,13), '看直播领金币');
                        //点击退出直播间
                        click(liveing.bounds().centerX(),liveing.bounds().centerY());
                        sleep(1000);
                        var okbtn = className('TextView').textMatches(/继续观看|领取奖励|退出.*/).visibleToUser(true).findOne(1000);
                        if (okbtn) {
                            sleep(1000);
                            click(okbtn.bounds().centerX(),okbtn.bounds().centerY());
                            if(okbtn.text()=='继续观看'){
                                let a = idMatches(/.*close_dialog_title/).className('TextView').visibleToUser(true).findOne(1000);
                                let b = a?a.text().match(/\d+/):3;
                                let t = 1 * (b ? b[0] : 1) + random(8,13);
                                cutDownBySleep(t, okbtn.text());
                            }
                            sleep(1000);
                        }
                    }
                }
                if((i*4+j+1)>random(9,15)){
                    log('=============',(i*4+j+1));
                    break;
                }
                i++;
                view.scrollForward();
                sleep(3000);
                title=className('TextView').text('看直播领金币').visibleToUser(true).findOnce();
            }
        }
    }

    //刷广告视频赚金币
    let back_btn = className('ImageView').desc("返回").clickable(true).boundsInside(0, 0, 500, 500).visibleToUser(true).findOne(1000);
    if (back_btn) {
        console.log('刷广告视频赚金币');
        i=0;
        while(back_btn){
            if(i>50)break;
            console.log(m+'.3.-----------------------'+i);
            var t = random(20, 30);
            cutDownBySleep(t, '刷广告');
            click(back_btn.bounds().centerX(),back_btn.bounds().centerY());
            stopvideo(m);
            back_btn = className('ImageView').desc("返回").clickable(true).boundsInside(0, 0, 500, 500).visibleToUser(true).findOne(1000);
            i++;
        }
        back();
    }

    //返回
    if (!className('Button').text('金币暴涨').findOne(1000)) { back(); sleep(1000); }
    let btn = className('TextView').text('放弃奖励').visibleToUser(true).findOnce();
    if (btn) click(btn.bounds().centerX(), btn.bounds().centerY());

    console.error('循环赚金币结束playvideo');
    working = false;
}

//主程序函数===============================================================
function Main(){
    var loopTimes = random(3,5); //work循环次数
    function work() {
        toastLog("开始工作work");
        var listArray = tasklist();
        if (listArray.length > 0) {
            sleep(3000);
            toastLog('开始做任务');
            for (i = 0; i < listArray.length; i++) {
                if (listArray[i][1]) {
                    toastLog(i+'.'+listArray[i][0]);
                    //点击任务,这里不可以用坐标点击,因为有的条目可能会在屏幕外面
                    listArray[i][1].click();
                    sleep(3000);
                    playvideo(i);
                }
            }
        }
        //开宝箱
        moneybox();
        //回到首页准备刷视频
        console.error("开始刷视频模式+++++++++++++");
        gohome(); startSec = Date.now(); gogogo(50);
        console.error("刷视频模式结束+++++++++++++");
    }
    //打开快手App
    if (getPackageName(AppName)) {
        openApp(AppName);
        //等待进入主界面成功
        toastLog('进入主函数'+ver);
        gohome();
        sleep(3000);
        //先检测签到提示是否自动弹出在【首页】
        //singlecheck();
        //sleep(3000);
        toastLog("刚启动先刷视频提高活跃度");
        gogogo(20);

        while (loopTimes > 0) {
            work();//开始工作
            sleep(5000);
            loopTimes--;
        }

        console.clear();
        console.warn('运行结束关闭应用');
    } else {
        console.warn("未安装:" + AppName);
        work_thread.interrupt();
        device.cancelKeepingAwake();
        engines.myEngine().forceStop();
        return;
    }
    console.show();
    console.warn('执行完成用时' + SecondsToHMS((Date.now() - starttime) / 1000));
    cutDownBySleep(5,'5秒后进入息屏挂机模式');
    console.hide();
    closeApp(AppName);
    sleep(3000);
    oled(random(600,900));//熄屏挂机约10~15分钟左右
}
function getHomeBtn(){
    var homepage = idMatches(/.*left_btn/).desc("侧边栏").clickable(true).boundsInside(0, 0, 500, 500).visibleToUser(true).findOne(1000);
    var topbtn = descMatches(/发现|关注/).selected(true).boundsInside(0, 0, device.width, 500).visibleToUser(true).findOne(1000);
    return (homepage!=null&&topbtn!=null);
}
function gohome() {
    function closediv(){
        //关闭弹出层
        var popdiv=className('Image').text('huge_sign_marketing_popup').findOne(1000);
        if(popdiv){
            let closebtn=popdiv.parent().parent().child(0);
            if(closebtn)click(closebtn.bounds().centerX(),closebtn.bounds().centerY());
        }
    }
    toastLog('回到首页gohome');
    closediv();
    var homepage = idMatches(/.*left_btn/).desc("侧边栏").clickable(true).boundsInside(0, 0, 500, 500).visibleToUser(true).findOne(1000);
    if(!homepage){
        var MaxLoop = 5;
        while (!homepage && MaxLoop > 0) {
            MaxLoop--;
            back(); sleep(3000);
            var okbtn = className('TextView').textMatches(/退出.*/).findOnce();
            if(okbtn){okbtn.click();sleep(3000);}
            homepage = idMatches(/.*left_btn/).desc("侧边栏").clickable(true).boundsInside(0, 0, 500, 500).visibleToUser(true).findOne(1000);
        }
    }
    if(homepage){
        var btn=idMatches(/.*textView/).desc("发现").visibleToUser(true).findOne(1000);
        if(btn)click(btn.bounds().centerX(),btn.bounds().centerY());
        sleep(3000);closediv();
    }else{
        toastLog('需要重启软件【截图】');
        //截图保存界面,以备后续查看
        captureScreen(files.getSdcardPath() + '/脚本/gohome1_' + currentActivity() + '.png');
        sleep(1000);
        device.wakeUp();//唤醒设备
        sleep(1000);
        left2right(1);
        sleep(1000);
        closeApp(AppName);
        sleep(5000);
        openApp(AppName);
        sleep(1000);
    }
}
function randomHeart(num) {
    let randomIndex = num ? num : random(1, 30);
    //随机恢复到首页
    if (randomIndex % 5 == 0) {
        console.log('拟人:随机回首页');
        gohome();
        return;
    }
    //随机点赞
    if (randomIndex % 6 == 0) {
        var like = id('like_element_click_layout').clickable(true).boundsInside(device.width-300, device.height/2, device.width, device.height).visibleToUser(true).findOnce();
        if (like) {
            console.log('拟人:随机点赞');
            click(like.bounds().centerX(),like.bounds().centerY());
            return;
        }
    }
    //随机评论
    if(randomIndex % 7 == 0){
        var plug = id('comment_element_click_layout').longClickable(true).boundsInside(device.width-300, device.height/2, device.width, device.height).visibleToUser(true).findOne(1000);
        if(plug){
            console.log('拟人:随机评论');
            //长按评论按钮
            longClick(plug.bounds().centerX(),plug.bounds().centerY());
            sleep(1000);
            var plugdiv=id('emoji_quick_send_list').className('android.view.ViewGroup').visibleToUser(true).findOne(1000);
            if(plugdiv){
                let icoY=plugdiv.bounds().bottom-90;
                let icoX=[
                    plugdiv.bounds().left+90,
                    plugdiv.bounds().left+220,
                    plugdiv.bounds().left+350,
                    plugdiv.bounds().left+500
                ];
                let index = random(2, icoX.length) - 1;
                //console.log(icoX[index],icoY);
                click(icoX[index],icoY);
                sleep(3000);
            }
        }
    }
    //随机收藏
    if (randomIndex % 8 == 0) {
        var collect = id('click_area_collect').clickable(true).boundsInside(device.width-300, device.height/2, device.width, device.height).visibleToUser(true).findOnce();
        if (collect) {
            console.log('拟人:随机收藏');
            click(collect.bounds().centerX(),collect.bounds().centerY());
            return;
        }
    }
    //随机下滑
    if (randomIndex % 9 == 0) {
        console.log('拟人:随机下滑');
        swipe(device.width / 2, device.height * 0.1 + randomIndex, device.width / 2, device.height * 0.9 - randomIndex, random(500, 1500));
        return;
    }
    //连续上滑
    if (randomIndex % 10 == 0) {
        console.log('拟人:连续上滑');
        var k = random(2, 4);
        for (var i = 0; i < k; i++) {
            var j = random(2, 5);
            if (j == 3) {
                swipe(device.width / j, device.height * 0.1 + j * k, device.width / j, device.height * 0.9 - j * k, j * 50);
            } else {
                swipe(device.width / j, device.height * 0.9 - j * k, device.width / j, device.height * 0.1 + j * k, j * 50);
            }
            sleep(j * 250);
        }
        return;
    }
    //向上滑
    slidingByCurve();
}
function isvideoPage() {
    console.verbose("检测是否视频播放中isvideoPage");
    var isvideo = false;
    var homepage = getHomeBtn();
    if (homepage) {
        //关闭自动弹出的层
        var div1 = idMatches(/.*design_bottom_sheet.*|.*content_nest.*|.*recyclerView.*/).visibleToUser(true).findOnce();
        if (div1) {
            toastLog('0.关闭弹出层');
            //captureScreen(files.getSdcardPath() + '/脚本/isvideoPage_' + currentActivity() + '.png');
            //sleep(1000);
            click(80, 150);
            sleep(3000);
        }
        var living = idMatches(/.*live_close_container/).boundsInside(device.width-300, 0, device.width, 300).visibleToUser(true).findOnce();//直播间
        if (living) {
            toastLog("1.退出直播间");
            click(living.bounds().centerX(), living.bounds().centerY());
            sleep(2000);
            var div0=text('退出直播间').visibleToUser(true).findOnce();
            if(div0)click(div0.bounds().centerX(), div0.bounds().centerY());
            sleep(2000);
        }
        //id=live_slide_view_pager
        if (currentActivity() == 'com.kuaishou.live.core.basic.activity.LiveSlideActivity') {
            toastLog("2.退出直播间");
            back();sleep(2000);
            var div0=text('退出直播间').visibleToUser(true).findOnce();
            if(div0)click(div0.bounds().centerX(), div0.bounds().centerY());
        }
        isvideo=idMatches(/.*nasa_groot_view_pager/).visibleToUser(true).findOne(1000);
        //log(isvideo);
    }
    return isvideo;
}
function gogogo(n) {
    let gotime = random(3,6); //刷视频每n分钟结束一次
    for (var i = 1; i <= n; i++) {
        let flashtime=parseInt((Date.now() - startSec) / 1000);
        console.log('第'+i+'次刷视频,累计用时:',flashtime,'秒');
        if( flashtime > gotime*60){console.warn(gotime+'分种超时,停止刷视频'); running = false; floaty.closeAll(); break;}
        if (isvideoPage()) {
            running = true;

            randomHeart();//拟人化
            cutDownBySleep(random(6, 30),'观看视频:');//每个视频随机时间 6-30s
        } else {
            running = false;
            toastLog('not at the video page');
            var dialog = currentActivity();
            if (!dialog.match(/android\.app\.Dialog|android\.widget\.FrameLayout/)) {
                //截图保存界面,以备后续查看
                console.info('【gogogo截图】',dialog);
                captureScreen(files.getSdcardPath() + '/脚本/gogogo_' + dialog + '.png');
                gohome();
            }
            sleep(3000);
        }
    }
    running = false;
}
function cutDownBySleep(lasterSecend, message) {
    message = message || "";
    floaty.closeAll();
    var fwin = floaty.rawWindow(
        `<frame id="frame" alpha="0" w="{{device.width-500}}px" h="150px" marginTop="{{device.height-550}}px" marginLeft="250px" marginRight="250px">
            <card w="auto" h="auto" layout_gravity="center" cardCornerRadius="5dp" cardBackgroundColor="#eeeeee" >
                <text id="title" text="" textColor="#333333" textSize="13sp" padding="12 8" />
            </card>
        </frame>`
    );
    fwin.setTouchable(false);
    sleep(300);
    for (let i = lasterSecend; i >= 0; i--) {
        if (!running && !working) { break; }
        if (!fwin || !fwin.title) { break; }
        ui.run(() => { fwin.title.setText(message + "剩余" + i + "秒"); fwin.frame.attr("alpha", 0.8); });
        sleep(1000);
    }
    fwin=null;
    floaty.closeAll();
}
function slidingByLine() {
    // top X,Y范围
    tx = randomPointLoc(parseInt(device.width / 3), parseInt(device.width / 2));
    ty = randomPointLoc(parseInt(device.height / 5), parseInt(device.height / 4));
    // bottom X,Y 范围
    bx = randomPointLoc(parseInt(device.width / 3), parseInt(device.width / 2));
    by = randomPointLoc(parseInt(3 * device.height / 4), parseInt(4 * device.height / 5));

    slidingTime = randomRangeTime(0.8, 1.3);
    log("上滑:随机直线");
    //log("X: "+ Math.abs(bx-tx) + " Y: "+ Math.abs(by - ty));
    swipe(bx, by, tx, ty, slidingTime);
}
function left2right(direction) {
    var intX=parseInt(Math.random()*200+400);
    var intY=parseInt(Math.random()*200+200);
    var distance=parseInt(Math.random()*100+device.height/4);
    switch (direction) {
        case 1:
            //向上小距离
            sml_move(intX, intY + distance, intX, intY, 400);
            break;
        case 2:
            //向下小距离
            sml_move(intX, intY, intX, intY + distance, 400);
            break;
        case 3:
            //向左翻屏
            sml_move(
                device.width / 2 + parseInt(Math.random() * 100) + 300,
                device.height / 4 - parseInt(Math.random() * 200) + 100,
                0 + parseInt(Math.random() * 100),
                device.height / 5 + parseInt(Math.random() * 100),
                500
            );
            break;
        case 4:
            //向右翻屏
            sml_move(
                device.width / 2 - parseInt(Math.random() * 100) - 300,
                device.height / 5 - parseInt(Math.random() * 200) + 100,
                device.width - parseInt(Math.random() * 100),
                device.height / 4 + parseInt(Math.random() * 100),
                500
            );
            break;
    }
    sleep(1000);
}
function slidingByCurve() {
    // top X,Y范围
    tx = randomPointLoc(parseInt(device.width / 3), parseInt(device.width / 2));
    ty = randomPointLoc(parseInt(device.height / 5), parseInt(device.height / 4));
    // bottom X,Y 范围
    bx = randomPointLoc(parseInt(device.width / 3), parseInt(device.width / 2));
    by = randomPointLoc(parseInt(2 * device.height / 3), parseInt(3 * device.height / 4));

    slidingTime = randomRangeTime(0.2, 0.6);
    log("上滑:仿真曲线");
    //log("X: "+ Math.abs(bx-tx) + " Y: "+ Math.abs(by - ty));
    sml_move(bx, by, tx, ty, slidingTime);
}
function randomPointLoc(start, end) {
    len = Math.abs(end - start);
    loc = Math.floor(Math.random() * len) + start;
    return loc;
}
function randomRangeTime(start, end) {
    len = Math.abs(end - start) * 1000;
    ms = Math.floor(Math.random() * len) + start * 1000;
    return ms;
}
function sml_move(qx, qy, zx, zy, time) {
    var xxy = [time];
    var point = [];
    var dx0 = {
        "x": qx,
        "y": qy
    };
    var dx1 = {
        "x": random(qx - 100, qx + 100),
        "y": random(qy, qy + 50)
    };
    var dx2 = {
        "x": random(zx - 100, zx + 100),
        "y": random(zy, zy + 50),
    };
    var dx3 = {
        "x": zx,
        "y": zy
    };
    for (var i = 0; i < 4; i++) {
        eval("point.push(dx" + i + ")");
    }
    // log(point[3].x)
    for (let i = 0; i < 1; i += 0.08) {
        let newPoint=bezier_curves(point, i);
        xxyy = [parseInt(newPoint.x), parseInt(newPoint.y)]
        xxy.push(xxyy);
    }
    try {
        gesture.apply(null, xxy);
    } catch (e) {
        log('error:',xxy);
    }
}
function bezier_curves(cp, t) {
    cx = 3.0 * (cp[1].x - cp[0].x);
    bx = 3.0 * (cp[2].x - cp[1].x) - cx;
    ax = cp[3].x - cp[0].x - cx - bx;
    cy = 3.0 * (cp[1].y - cp[0].y);
    by = 3.0 * (cp[2].y - cp[1].y) - cy;
    ay = cp[3].y - cp[0].y - cy - by;

    tSquared = t * t;
    tCubed = tSquared * t;
    result = {
        "x": 0,
        "y": 0
    };
    result.x = (ax * tCubed) + (bx * tSquared) + (cx * t) + cp[0].x;
    result.y = (ay * tCubed) + (by * tSquared) + (cy * t) + cp[0].y;
    return result;
}
function SecondsToHMS(seconds) {
    const hours = Math.floor(seconds / 3600);
    const minutes = Math.floor((seconds % 3600) / 60);
    const remainingSeconds = Math.floor(seconds % 60);
    return (hours > 0 ? hours + "时" : "") + (minutes > 0 ? minutes + "分" : "") + remainingSeconds + "秒";
}
function getindexInParent(child) {
    var parent = child.parent();
    for (var i = 0; i < parent.childCount(); i++) {
        if (parent.child(i).find(className('CheckBox').checked(true).visibleToUser(true)).length > 0) {
            return i;
        }
    }
    return -1; // 如果找不到子元素,则返回-1
}
function isRectInScreen(bounds) {
    var x = bounds.left, y = bounds.top,
        a = bounds.right, b = bounds.bottom;
    return (
      x >= 0 && x <= device.width &&
      y >= 0 && y <= device.height &&
      a > 0 && a <= device.width &&
      b > 0 && b <=device.height
    );
}
function openApp(appname){
    console.warn('启动应用:' + appname);
    var appstate = launchApp(appname);
    sleep(5000);
    if (appstate) {
        toastLog("应用正在运行");
    } else {
        toastLog("无法自启动,需模拟点击");
        home();//要启动的APP必须放在第一页中
        sleep(3000);
        var app = id("item_title").text(appname).visibleToUser(true).findOne(2000);
        if (app) {
            click(app.bounds().centerX(), app.bounds().top - 50);
            sleep(8000);
        }else{
            toastLog('要启动的APP必须放在首页,即按Home能看到的那一页');
            work_thread.interrupt();
            engines.myEngine().forceStop();
            exit();
        }
    }
}
function closeApp(appname) {
    let packageName = getPackageName(appname);
    // 使用ADB命令强行结束进程
    //shell("adb shell am force-stop " + packageName);
    console.warn('关闭应用:' + appname);
    app.openAppSetting(packageName);
    text(app.getAppName(packageName)).waitFor();
    let is_sure = textMatches(/.*强行停止.*/).visibleToUser(true).findOnce();
    if (is_sure&&is_sure.enabled()) {
        try {
            var btn = className("Button").text('强行停止').visibleToUser(true).findOnce();
            if (btn) btn.click();
            sleep(1000);
            btn = className("Button").text('强行停止').visibleToUser(true).findOnce();
            if (btn) btn.click();
            sleep(1000);
            btn = className("Button").text('确定').visibleToUser(true).findOnce();
            if (btn) btn.click();
            back(); back(); back();
            home();
        } catch (e) {
            log(app.getAppName(packageName) + "应用已被关闭");
            sleep(1000);
            back(); back(); back();
            home();
        }
    } else {
        log(app.getAppName(packageName) + "应用不能被正常关闭");
        back(); back(); back();
        home();
    }
}
function update(){
    http.get('https://update.greasyfork.org/scripts/520135/%E5%BF%AB%E6%89%8B%E8%84%9A%E6%9C%AC.js', {}, function(res, err){
        if(res.statusCode == 200){
            var Source = res.body.bytes();
            if(Source){
                files.writeBytes(files.getSdcardPath() + '/脚本/快手脚本.js', Source);
                console.verbose('更新主程序:成功',ver);
            }else{
                console.verbose('更新主程序:错误',ver);
            }
        }else{
            console.verbose('更新主程序:失败',ver);
        }
    });
}

//===================================================================================
requestScreenCapture(false);//请求截图权限
runtime.getImages().initOpenCvIfNeeded();//初始化OpenCv
global.starttime = Date.now();//程序运行开始时间

var oledwin = null, win = null;
function oled(i) {
    let j=i||3;
    floaty.closeAll();
    oledwin = floaty.rawWindow(
        `<frame bg="#000000">
            <card w="auto" h="auto" layout_gravity="center" cardBackgroundColor="#000000" >
            <vertical>
                <text id="texts" text="息屏挂机模式" textColor="#999999" textSize="13sp" />
                <button id="button" text="退出挂机" margin="0 20" />
            </vertical>
            </card>
        </frame>`
    );
    oledwin.button.on("click", function () {
        console.info('手动停止挂机');
        floaty.closeAll();
        oledwin=null;
    });
    oledwin.setSize(-1, -1);
    oledwin.setTouchable(true);
    sleep(300);
    console.info('挂机模式开启……');
    //保持脚本运行
    while (j > 0 && oledwin) {
        if (oledwin.texts) {
            let t = parseInt(j / 60) + "分" + parseInt(j % 60) + "秒";
            ui.run(() => { oledwin.texts.setText("息屏挂机倒计时:" + t + "\n\n倒计时结束后重启主线程gifshow") });
        }
        j--;
        sleep(1000);
    }
    floaty.closeAll();
    oledwin=null;
    console.info('挂机结束用时:',(parseInt((i-j) / 60) + "分" + parseInt((i-j) % 60) + "秒"));
}

function Observer() {
    function unique(arr) {
        let newArr = [arr[0]];
        for (let i = 1; i < arr.length; i++) {
            let flag = false;
            for (var j = 0; j < newArr.length; j++) {
                if (arr[i] == newArr[j]) {
                    flag = true;
                    break;
                }
            }
            if (!flag) {
                newArr.push(arr[i]);
            }
        }
        return newArr;
    }
    var currentActis = new Array();
    for (let c = 0; c < 59; c++) {//连续扫描60秒后返回结果,如果60秒停留在同一活动页面,则就要重启线程了
        //关闭自动弹出的层
        var btn=idMatches(/close/).visibleToUser(true).findOnce();
        if (btn) { 
            console.log('点左上角关闭弹出层Observer');
            click(btn.bounds().centerX(), btn.bounds().centerY());
        }
        var btntxt = textMatches(/同意|满意|关闭|关闭应用|不在提醒|我知道了|以后再说|暂不使用|忽略提醒|仍要退出/).visibleToUser(true).findOnce();
        if (btntxt && btntxt.packageName() == packageName) {
            console.warn('点击:' + btntxt.text());
            //截图保存界面,以备后续查看
            //captureScreen(files.getSdcardPath() + '/脚本/Observer1_' + currentActivity() + '.png');
            click(btntxt.bounds().centerX(),btntxt.bounds().centerY());
        }
        //toastLog(currentActivity());
        currentActis[c] = currentActivity();
        sleep(1000);//这是每秒扫描一次活动页
    }
    //检测oled挂机模式结束,则重启main线程
    if (oledwin) { win = oledwin; return true; } else if (win) { win = null; return false; }
    //toastLog(currentActivity());
    let ac = unique(currentActis);
    let cc = currentActivity().match(/.*HomeActivity|.*PhotoDetailActivity|.*AwardVideoPlayActivity|.*AdKwaiRnActivity|.*app\.Dialog|android\.widget\.FrameLayout/);
    if (ac.length == 1 && !cc) {
        console.info('60秒卡顿:',ac[0]);
        //截图保存界面,以备后续查看
        captureScreen(files.getSdcardPath() + '/脚本/Observer2_' + currentActivity() + '.png');
        return false;
    }
    return true;
}

// 》》》》》》》》》》》》》》》》》》》 START
work_thread = threads.start(function () {
    Main();
});

observer_thread = threads.start(function () {
    setInterval(function () {
        console.verbose('--------多线程安全检测---------');
        if(oledwin){if(oledwin.texts)console.verbose(oledwin.texts.text().split("\n").shift());}
        if (running) {
            let worktime = parseInt((Date.now() - starttime) / 1000);
            console.verbose("脚本连续运行:" + SecondsToHMS(worktime));
            //如果运行时间超过4小时,则关闭应用,停止脚本。
            if (worktime > 60 * 60 * 4) {
                device.cancelKeepingAwake();
                work_thread.interrupt();
                console.show();
                console.clear();
                console.warn("脚本连续运行超4小时,终止运行!");
                sleep(5000);
                console.hide();
                closeApp(AppName);
                sleep(5000);
                //熄屏
                runtime.accessibilityBridge.getService().performGlobalAction(android.accessibilityservice.AccessibilityService.GLOBAL_ACTION_LOCK_SCREEN);
                //停止本脚本
                //engines.myEngine().forceStop();
                //结束所有Autojx进程
                engines.stopAll();
                exit();
            }
        }
        if (!Observer()) {
            work_thread.interrupt();
            work_thread = threads.start(function () {
                toast("Main线程在5秒后重启!");
                console.show();
                console.clear();
                console.warn("Main线程在5秒后重启!");
                running=false;
                sleep(5000);
                console.hide();
                if(currentPackage() == packageName)closeApp(AppName);
                sleep(5000);
                Main();
            });
        }
    }, 3000);//这个时间是线程休息时间
});