tiktok.js

自用程序调用库

Tính đến 26-11-2024. Xem phiên bản mới nhất.

Script này sẽ không được không được cài đặt trực tiếp. Nó là một thư viện cho các script khác để bao gồm các chỉ thị meta // @require https://update.greasyfork.org/scripts/518778/1491427/tiktokjs.js

/**点赚钱图标是否进入了照相机 */
function ifcarmer(btn) {
    if (flashonly) { toastLog('当前账户没有赚钱福袋'); return true; }
    click(device.width / 2, btn.bounds().centerY());//点赚钱图标
    sleep(2000);
    if (currentActivity().match(/.*VideoRecordNewActivity/)) {
        flashonly = true;
        back();
        toastLog('当前账户没有赚钱福袋');
        return true;
    } else {
        return false;
    }
}

/**判断是否在赚钱任务页**/
function istaskpage() {
    var istask = null;
    var taskpage = className("androidx.recyclerview.widget.RecyclerView").scrollable(true).focusable(true).find();
    //toastLog(taskpage);
    if (taskpage) {
        for (var i = 0; i < taskpage.length; i++) {
            var page = taskpage[i];
            //console.log('istaskpage',page.childCount(),page.rowCount(),page.id(),page.bounds())
            if (isRectInScreen(page.bounds()) && page.childCount() > 5 && page.id() == null && page.rowCount() > 20) {
                istask = page;
                break;
            }
            //log('istaskpage===',page);
        }
    }
    return istask;
}

//执行赚钱任务函数
function takelist() {
    console.info('执行任务takelist');
    var homebtn = null;
    var taskpage = istaskpage();
    if (!taskpage) {
        toastLog("不在任务页takelist");
        var homepage = className("android.widget.TextView").descStartsWith("推荐").clickable(true).findOne(1000);
        if (!homepage) {
            gohome();//如果不在任务页面,则返回到首页再重新进入到任务页面
            sleep(3000);
            homepage = className("android.widget.TextView").descStartsWith("推荐").clickable(true).findOne(1000);
        }
        if (homepage) {
            toastLog("进入任务页takelist");
            MaxLoop = 5;
            homebtn = className("android.widget.TextView").desc("首页,按钮").findOne(1000);
            while (!homebtn && MaxLoop > 0) {
                MaxLoop--;
                back(); sleep(1000);
                homebtn = className("android.widget.TextView").desc("首页,按钮").findOne(1000);
            }
            //click(device.width/2,homebtn.bounds().centerY());//点赚钱图标
            if (ifcarmer(homebtn)) { exit; }
            sleep(3000);
        }
        taskpage = istaskpage();
    }
    if (taskpage) {
        toastLog("已在任务页takelist");
        randomHeart(9);//下划
        var itemcount = taskpage.childCount();
        toastLog('找到任务数----------------' + itemcount);
        for (var j = 2; j < itemcount; j++) {
            if (!taskpage) {
                gohome();
                toastLog('返回到任务页----------------');
                //再次点中间赚钱图标进入任务页
                MaxLoop = 5;
                homebtn = className("android.widget.TextView").desc("首页,按钮").findOne(1000);
                while (!homebtn && MaxLoop > 0) {
                    MaxLoop--;
                    back(); sleep(1000);
                    homebtn = className("android.widget.TextView").desc("首页,按钮").findOne(1000);
                }
                //click(device.width / 2 , homebtn.bounds().centerY());//点赚钱图标
                if (ifcarmer(homebtn)) { break; }
                sleep(5000);
                randomHeart(9);//下划
                taskpage = istaskpage();
                if (!taskpage) break;
                if (j > 2) j--;
                if (j >= taskpage.childCount()) break;
                continue;
            }
            if (j >= taskpage.childCount()) break;
            var FrameLayout = taskpage.child(j);
            if (!FrameLayout || FrameLayout.className() != 'android.widget.FrameLayout' || FrameLayout.bounds().height() < 200) {
                //toastLog(FrameLayout);
                continue;
            }
            toastLog('执行赚钱任务目:' + j);
            if (FrameLayout.childCount() > 0) {
                if (FrameLayout.find(descMatches(/.*(\d{2}:\d{2}).*|.*填码得现金/)).length > 0) {
                    toastLog('有倒计时不点击====条目' + j);
                    continue;
                }
            }
            //toastLog('点击条目:' + j);
            //swipe(FrameLayout.bounds().left+100, FrameLayout.bounds().top, FrameLayout.bounds().right-100, FrameLayout.bounds().bottom, 5000);
            click(FrameLayout.bounds().centerX(), FrameLayout.bounds().centerY());
            sleep(3000);

            var videopage = className("com.lynx.tasm.behavior.ui.text.FlattenUIText").desc("反馈").findOne(1000);
            if (videopage) {
                console.error('观看广告视频-------条目' + j);
                //看广告视频赚金币
                playvideo();
                sleep(3000);
                taskpage = istaskpage();
                break;
            }
            var living = id("com.ss.android.ugc.aweme.lite:id/root").desc("关闭").findOne(1000);
            if (living) {
                console.error('直播间领金币-------条目' + j);
                //退出直播间
                toastLog('退出直播间takelist');
                //关闭直播间的自动弹出层

                click(living.bounds().centerX(), living.bounds().centerY());
                sleep(3000);
                taskpage = istaskpage();
                continue;
            }
            var address = textContains("发现你的通讯录朋友").findOne(1000);
            if (address) {
                //通讯录朋友
                console.error('通讯录朋友-------条目' + j);
                click("拒绝");
                toastLog('拒绝发现通讯录朋友');
                sleep(3000);
                continue;
            }
            var book = descMatches(/一键领取|立即预约领取/).findOne(1000);
            if (book) {
                console.error('进入预约-------条目' + j);
                //判断是否进入预约
                click(book.bounds().centerX(), book.bounds().centerY());
                sleep(3000);
                back();
                toastLog('预约已完成takelist');
                taskpage = istaskpage();
                continue;
            }
            var daygold = text('closePopup').findOne(1000);
            if (daygold) {
                console.error('进入天天领金币-------条目' + j);
                var today = text('今日可领').findOnce();
                if (today) {
                    click(device.width - 200, today.bounds().centerY());
                }
                toastLog('金币已领完takelist');
                sleep(1000);
                click(daygold.bounds().centerX(), daygold.bounds().centerY());
                sleep(1000); back(); sleep(1000);
                taskpage = istaskpage();
                continue;
            }
            var friendpage = className("android.widget.TextView").text("朋友日常").clickable(true).findOne(1000);
            if (friendpage) {
                console.error('进入朋友随机刷10次-------条目' + j);
                //进入朋友页面
                gogogo(10);
                toastLog('朋友视频已刷完takelist');
                //再次点中间赚钱图标进入任务页
                MaxLoop = 5;
                homebtn = className("android.widget.TextView").desc("首页,按钮").findOne(1000);
                while (!homebtn && MaxLoop > 0) {
                    MaxLoop--;
                    back(); sleep(1000);
                    homebtn = className("android.widget.TextView").desc("首页,按钮").findOne(1000);
                }
                //click(device.width / 2 , homebtn.bounds().centerY());//点赚钱图标
                if (ifcarmer(homebtn)) { break; }
                sleep(3000);
                taskpage = istaskpage();
                continue;
            }
            if (!istaskpage()) {
                toastLog('不执行该条目任务返回====条目' + j);
                back();
            } else {
                console.error('判断是否为签到-------条目' + j);
                //判断是否进入签到
                singlecheck();
                back();
            }
            sleep(3000);
            taskpage = istaskpage();
        }
        console.info('任务完成takelist');
    } else {
        console.info('无法取得任务列表takelist');
        //截图保存界面,以备后续查看
        captureScreen(files.getSdcardPath() + '/脚本/takelist_' + currentActivity() + '.png');
        back();
    }
}

//判断进入看广告视频赚金币
function playvideo() {
    function stopvideo() {
        let plug = ['很糟糕', '一般般', '太赞了'];
        var s = plug[2];//randomPointLoc(0,3)
        console.error('点击评价:' + s);
        var uc = className("com.lynx.tasm.behavior.ui.text.UIText").desc(s).findOne(1000);
        click(uc.bounds().centerX(), uc.bounds().centerY());
        sleep(2000);
        console.error('点击收下金币playvideo');
        click(uc.bounds().centerX(), uc.bounds().centerY() + 230);
        console.error('完成看广告视频赚金币playvideo');
    }
    var video = className("com.lynx.tasm.behavior.ui.text.FlattenUIText").desc("反馈").findOne(1000);
    if (video) {
        toastLog('进入看广告视频赚金币playvideo');
        for (var i = 1; i < 99; i++) {
            //判断进入了直播间
            var living = id("com.ss.android.ugc.aweme.lite:id/root").desc("关闭").findOne(1000);
            if (living) {
                toastLog('进入直播间playvideo');
                //关闭领金币宝箱自动弹出
                if (currentActivity().match(/.*NoMarginSheetBaseDialog$/gi)) {
                    click(80, 150);
                    sleep(1000);
                }
                toastLog('退出直播间playvideo');
                living.click();
                sleep(3000);
            }
            //判断是否进入了广告页面/^playvideocom.bytedance.*/
            var adpage = className("android.widget.Button").desc("返回").findOne(1000);
            if (adpage) {
                toastLog('退出广告页playvideo' + currentActivity());
                adpage.click();
                sleep(3000);
            }
            video = className("com.lynx.tasm.behavior.ui.text.FlattenUIText").desc("反馈").findOne(1000);

            if (!video) {
                toastLog('未进入广告视频模式' + currentActivity());
                break;
            }
            var okbtn = className("com.lynx.tasm.behavior.ui.view.UIView").descMatches(/领取成功.*|\d{1,2}秒后可领奖励.*/).findOne(1000);
            if (!okbtn) {
                toastLog('无法取得领取成功,点击右上角');
                click(device.width - 200, video.bounds().centerY());
                okbtn = true;
                sleep(5000);
            } else {
                if (okbtn.text() == '领取成功') {
                    var t = 9;
                    toastLog('等待' + t + '秒');
                    sleep(t * 1000);
                    toastLog('0.点击领取成功');
                    click(okbtn.bounds().centerX(), okbtn.bounds().centerY());
                    sleep(5000);
                } else {
                    var b = okbtn.desc().match(/\d+/);
                    var t = 1 * (b ? b[0] : 1) + 9;
                    toastLog('等待' + t + '秒');
                    sleep(t * 1000);
                    toastLog('1.点击领取成功');
                    click(okbtn.bounds().centerX(), okbtn.bounds().centerY());
                    sleep(5000);
                }
            }
            if (okbtn) {
                //随时点击弹出层className("com.lynx.tasm.behavior.ui.text.FlattenUIText")
                var tv = textMatches(/继续观看|领取奖励|评价并收下金币/).findOne(1000);
                if (tv) {
                    try {
                        if (tv.text() == '评价并收下金币') {
                            stopvideo();
                            sleep(1000);
                            return;
                        } else {
                            toastLog('2.点击' + tv.text());
                            click(tv.bounds().centerX(), tv.bounds().centerY());
                            sleep(2000);
                            var a = textMatches(/再看\d{1,2}秒可领奖励|评价并收下金币/).findOne(1000);
                            if (a) {
                                if (a.text() == '评价并收下金币') {
                                    stopvideo();
                                } else {
                                    var b = a.text().match(/\d+/);
                                    var t = 1 * (b ? b[0] : 1) + 9;
                                    toastLog('等待' + t + '秒');
                                    sleep(t * 1000);
                                }
                            }
                        }
                    } catch (e) {
                        toastLog('3.点击' + tv.text() + '=====' + tv.bounds());
                    }
                    sleep(1000);
                }
            } else {
                toastLog('等待观看倒计时结束playvideo');
                sleep(1000);
            }
            toastLog('继续检查playvideo-----' + i);
            sleep(1000);
        }//end for
    }
}

//判断签到层
function singlecheck() {
    console.error('判断签到提示singlecheck');
    var i = 0;
    var single = className("android.view.ViewGroup").depth(4).findOnce();
    //toastLog(single);
    if (single && isRectInScreen(single.bounds())) {
        while (single) {
            i++;
            click(single.bounds().centerX(), single.bounds().bottom + 100);
            sleep(3000);
            single = className("android.view.ViewGroup").depth(4).findOnce();
            if (i > 2 || !single || !isRectInScreen(single.bounds())) break;
        }
    } else {
        //图像识别查找
        single = FindPicture(img_single);
        if (single) {
            //点击签到
            click(single.x, single.y - 100);
            sleep(1000);
            //点击关闭
            click(device.width / 2, single.y + 100);
            i++;
        }
    }
    //如果已经点击了签到按钮
    if (i > 0) {
        var popup = textMatches(/手机充值|确认身份信息/).findOne(1000);
        if (popup) {
            click(80, popup.bounds().centerY());
            sleep(2000);
            var div = textMatches(/领惊喜现金|确认放弃.*/).findOne(1000);
            if (div) {
                if (div.text() != '领惊喜现金') {
                    click(div.bounds().left + 50, div.bounds().top + 50);
                    sleep(1000);
                }
                back();
            }
        }
        console.error('签到结束singlecheck');
        sleep(3000);
        toastLog('判断是否进入看视频singlecheck');
        playvideo();
    } else {
        console.error('没有签到提示singlecheck');
    }
}

//点击右下角宝箱函数
function moneybox() {
    toastLog('执行右下角宝箱任务moneybox');
    var taskpage = istaskpage()
    if (!taskpage) {
        toastLog("不在任务页moneybox");
        var homepage = className("android.widget.TextView").descStartsWith("推荐").clickable(true).findOne(1000);
        if (!homepage) {
            gohome();//如果不在任务页面,则返回到首页再重新进入到任务页面
            sleep(3000);
            homepage = className("android.widget.TextView").descStartsWith("推荐").clickable(true).findOne(1000);
        }
        if (homepage) {
            toastLog("点击首页赚钱moneybox");
            MaxLoop = 5;
            var homebtn = className("android.widget.TextView").desc("首页,按钮").findOne(1000);
            while (!homebtn && MaxLoop > 0) {
                MaxLoop--;
                back(); sleep(1000);
                homebtn = className("android.widget.TextView").desc("首页,按钮").findOne(1000);
            }
            //click(device.width/2,homebtn.bounds().centerY());//点赚钱图标
            if (ifcarmer(homebtn)) { exit; }
            sleep(3000);
        }
        taskpage = istaskpage();
    }
    if (taskpage) {
        console.error('点击右下角宝箱');
        //点击宝箱位置
        click(device.width - 150, device.height - 150);//点右下角
        sleep(3000);
        setScreenMetrics(1220, 2700);
        click(device.width / 2, 1730);//点弹出宝箱层中的红色按钮,有可能没有弹出
        setScreenMetrics(device.width, device.height);
        sleep(5000);
        //如果进入看视频赚金币则观看视频
        //if(currentActivity()=='com.ss.android.excitingvideo.ExcitingVideoActivity')
        if (className("com.lynx.tasm.behavior.ui.text.FlattenUIText").desc("反馈").findOne(1000)) {
            playvideo();
            console.error('右下角宝箱完成');
        } else {
            toastLog('右下角宝箱已开过');
        }
    } else {
        console.info('无法取得任务列表moneybox');
        //截图保存界面,以备后续查看
        captureScreen(files.getSdcardPath() + '/脚本/moneybox_' + currentActivity() + '.png');
    }
}

//主程序函数===============================================================
function Main() {
    function work() {
        toastLog("开始工作work");
        var homebtn = className("android.widget.TextView").desc("首页,按钮").findOne(1000);
        if (!homebtn) {
            toastLog("当前不在首页");
            gohome(); sleep(3000);
            homebtn = className("android.widget.TextView").desc("首页,按钮").findOne(1000);
        }
        if (homebtn) {
            toastLog("点赚钱图标进任务页");
            //click(device.width / 2 , homebtn.bounds().centerY());//点赚钱图标
            if (!ifcarmer(homebtn)) {
                sleep(8000);
                //检测签到提示是否弹出到【任务页】
                singlecheck();
                sleep(5000);
                //挨个点击任务列表里的任务
                takelist();
                sleep(3000);
                //点击右下角宝箱
                moneybox();
                sleep(3000);
            }
        }
        //回到首页准备刷视频
        console.error("准备开始滑动+++++++++");
        gohome(); gogogo(times);
        console.error("滑动" + times + "次已完成+++++++++");
    }
    //打开抖音App
    if (getPackageName(tiktokAppName)) {
        toastLog('启动应用:' + tiktokAppName);
        //launch('com.ss.android.ugc.aweme.lite');
        launchApp(tiktokAppName);
        sleep(5000);
        //跳过开屏广告
        if (desc("跳过").findOnce()) { click("跳过"); }
        //等待进入主界面成功
        MaxLoop = 9;
        var homebtn = className("android.widget.TextView").desc("首页,按钮").findOne(1000);
        while (!homebtn && MaxLoop > 0) {
            MaxLoop--;
            sleep(1000);
            homebtn = className("android.widget.TextView").desc("首页,按钮").findOne(1000);
        }
        toastLog("进入主函数V2.0.1");
        sleep(3000);
        //先检测签到提示是否自动弹出在【首页】
        singlecheck();
        sleep(3000);
        slidingByCurve();

        //开始工作
        work();
        //切换账号
        chengaccound();
        //开始工作
        work();
        endtime = new Date().getTime();
        var worktime = Math.floor((endtime - starttime) / 1000 / 60);
        console.show();
        console.warn('执行完成,用时' + worktime + '分钟');
        sleep(3000);
        console.hide();
        closeApp(tiktokAppName);
    } else {
        toastLog("未安装" + tiktokAppName);
        //launch('com.ss.android.ugc.aweme.lite');
        engines.myEngine().forceStop();
        return;
    }

    console.show();
    console.warn("执行完成,5秒后熄屏");
    sleep(5000);
    console.hide();
    console.clear();
    //熄屏
    runtime.accessibilityBridge.getService().performGlobalAction(android.accessibilityservice.AccessibilityService.GLOBAL_ACTION_LOCK_SCREEN);
    //停止本脚本
    //engines.myEngine().forceStop();
    //结束所有Autojx进程
    engines.stopAll();
}

function toActivePage(page) {
    //if(currentActivity()!=page){
    let intent = new Intent();
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    let package = packageName;
    let className = page;
    let componentName = new android.content.ComponentName(package, className);
    intent.setComponent(componentName);
    context.startActivity(intent);
    //}
}
/**回到首页面**/
function gohome() {
    toastLog('执行回到首页gohome');
    //launch(packageName);
    launchApp(tiktokAppName);
    toActivePage('com.ss.android.ugc.aweme.main.MainActivity');
    sleep(2000);
    MaxLoop = 5;
    var homebtn = className("android.widget.TextView").desc("首页,按钮").findOne(1000);
    while (!homebtn && MaxLoop > 0) {
        MaxLoop--;
        back(); sleep(1000);
        homebtn = className("android.widget.TextView").desc("首页,按钮").findOne(1000);
    }
    if (!homebtn) {
        toastLog('可能需要重启软件');
        //截图保存界面,以备后续查看
        captureScreen(files.getSdcardPath() + '/脚本/gohome1_' + currentActivity() + '.png');
        closeApp(tiktokAppName);
        sleep(5000);
    } else if (className('ImageView').desc('拍摄,按钮').findOnce()) {
        toastLog('当前账户没有赚钱福袋');
        //截图保存界面,以备后续查看
        captureScreen(files.getSdcardPath() + '/脚本/gohome2_' + currentActivity() + '.png');
        flashonly = true;
    }
    //launch(packageName);
    launchApp(tiktokAppName);
    sleep(1000);
}

/**随机拟人化(防止被判定是机器)**/
function randomHeart(num) {
    let randomIndex = num ? num : random(1, 30);
    let delayTime = random(10000, 15000);
    //随机点赞
    if (randomIndex % 10 == 0) {
        var like = className("android.widget.LinearLayout").descStartsWith('未点赞').clickable(true).findOnce();
        if (like) {
            console.log('拟人:随机点赞');
            like.click();
            return;
        }
    }
    //随机下滑
    if (randomIndex % 9 == 0) {
        console.log('拟人:随机下滑');
        swipe(device.width / 2, device.height * 0.1 + randomIndex, device.width / 2, device.height * 0.9 - randomIndex, delayTime / 10);
        return;
    }
    //随机切换频道
    if (randomIndex % 8 == 0) {
        var idList = ["短剧", "热点", "包头", "直播", "关注", "推荐"];
        var index = random(1, idList.length) - 1;
        var tab = className("android.widget.TextView").desc(idList[index] + ',按钮').clickable(true).findOnce();
        if (tab) {
            console.log('拟人:切换频道:' + idList[index]);
            tab.click();
            return;
        }
    }
    //连续上滑
    if (randomIndex % 7 == 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;
    }
    //随机左右划
    if (randomIndex % 6 == 0) {
        left2right();
        return;
    }
    //随机恢复到首页
    if (randomIndex % 5 == 0) {
        console.log('拟人:随机回首页');
        gohome();
        return;
    }
    //向上滑
    slidingByCurve();
}

/**判断是否在视频播放页**/
function isvideoPage() {
    var isvideo = false;
    var taskpage = istaskpage();
    if (!taskpage) {
        console.log("检测是否在视频播放中isvideoPage");
        //console.log(currentActivity());
        var view = descMatches(/播放视频.*|暂停视频.*|.*进入直播间.*/).findOnce();
        if (view) {
            isvideo = true;
            console.log("正在播放视频:" + view.desc());
            if (text('发现通讯录朋友').findOnce()) {
                randomHeart(8);//切换频道
                sleep(1000);
            }
        }
        var living = id("com.ss.android.ugc.aweme.lite:id/root").desc("关闭").clickable(true).findOnce();//直播间
        if (living) {
            isvideo = true;
            console.log("退出直播间isvideoPage");
            //关闭直播间的自动弹出层

            click(living.bounds().centerX(), living.bounds().centerY());
            sleep(2000);
        }
        if (currentActivity() == 'com.ss.android.ugc.aweme.live.LivePlayActivity') {
            back();
        }
        if (text('当前无新视频').findOnce()) {
            click(device.right - 100, device.top - 100);

        }
    }
    return isvideo;
}

/**随机上滑n次**/
function gogogo(n) {
    times = 0;
    for (var i = 1; i <= n; i++) {
        var sleepTime = randomRangeTime(6, 20);  //每个视频随机时间 6-20s
        if (isvideoPage()) {
            var adbutton = className('com.lynx.tasm.behavior.ui.view.UIView').descMatches(/提交,按钮.*/).findOne(1000);
            if (adbutton && isRectInScreen(adbutton.bounds())) {
                sleep(randomRangeTime(5, 9));
                //广告视频则多停留一个周期
                left2right();
                //进入广告看详情
                if (!desc('立即下载').findOnce()) {
                    click(adbutton.bounds().centerX(), adbutton.bounds().centerY());
                    sleep(randomRangeTime(3, 6));
                    back();
                }
                sleep(randomRangeTime(3, 6));
            }
            randomHeart();//拟人化
            toastLog('观看视频:' + (sleepTime / 1000) + '秒');
            sleep(sleepTime);
        } else {
            times = 50;
            toastLog('not at the video page');
            var dialog = currentActivity();
            console.log(dialog);
            if (dialog.match(/.*Dialog.*/gi)) {
                //截图保存界面,以备后续查看
                captureScreen(files.getSdcardPath() + '/脚本/gogogo_' + dialog + '.png');
            }
            gohome();
            sleep(3000);
        }
    }
    times = 50;
}

/**------------------------------------------------------------
 * 从下往上滑动,随机坐标
 */
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 / 2), parseInt(device.width / 3));
    by = randomPointLoc(parseInt(4 * device.height / 5), parseInt(3 * device.height / 4));

    slidingTime = randomRangeTime(0.3, 0.6);
    log("sliding:(" + bx + "," + by + "), (" + tx + "," + ty + ")," + slidingTime);
    //log("X: "+ Math.abs(bx-tx) + " Y: "+ Math.abs(by - ty));
    swipe(bx, by, tx, ty, slidingTime);
}

/**
 * 上部左右滑动
 */
function left2right() {
    var randomP = random(300, 500);
    var points = [randomP];
    var interval = 0.1;
    var x0 = random(device.width / 2 - 500, device.width / 2 + 500);
    var y0 = random(500, 700);
    var a = random(200, 300);
    for (var t = 0; t < Math.PI / 2; t += interval) {
        var x = x0 + a * (1.5 * Math.sin(t * 0.9) - Math.sin(2 * t * 0.6));
        var y = y0 + a * (0.6 * Math.cos(t * 0.9) - Math.cos(2 * t * 0.6));
        points.push([parseInt(x), parseInt(y)]);
    }
    gesture.apply(null, points);
    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 / 2), parseInt(device.width / 3));
    by = randomPointLoc(parseInt(4 * device.height / 5), parseInt(3 * device.height / 4));

    slidingTime = randomRangeTime(0.3, 0.6);
    log("Move:[" + bx + "," + by + "], [" + tx + "," + ty + "], T=" + slidingTime);
    //log("X: "+ Math.abs(bx-tx) + " Y: "+ Math.abs(by - ty));
    sml_move(bx, by, tx, ty, slidingTime);
}
/**
 * 随机位置点
 * @param {起始值} start 
 * @param {结束值} end 
 * @returns 
 */
function randomPointLoc(start, end) {
    len = Math.abs(end - start);
    loc = Math.floor(Math.random() * len) + start;
    return loc;
}

/**
 * 从几秒到几秒
 * @param {开始秒} start 
 * @param {结束秒} end 
 * @returns
 */
function randomRangeTime(start, end) {
    len = Math.abs(end - start) * 1000;
    ms = Math.floor(Math.random() * len) + start * 1000;
    return ms;
}

/**
 * 仿真随机带曲线滑动 
 * @param {起点x} qx 
 * @param {起点y} qy 
 * @param {终点x} zx 
 * @param {终点y} zy 
 * @param {滑动时间,单位毫秒} time 
 */
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) {
        xxyy = [parseInt(bezier_curves(point, i).x), parseInt(bezier_curves(point, i).y)]
        xxy.push(xxyy);
    }
    try {
        gesture.apply(null, xxy);
    } catch (e) {
        log(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;
}

/**
 * 判断一个元素是否在屏幕范围内
 * @param {元素的坐标rect类型} bounds 
 */
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
    );
}
/**
 * 获取当前时间格式yyyyMMdd
 */
function getDate() {
    var date = new Date();
    var year = date.getFullYear();
    var month = date.getMonth() + 1;
    if (month < 10) {
        month = "0" + month;
    }
    var day = date.getDate();
    if (day < 10) {
        day = "0" + day;
    }
    return year + "-" + month + "-" + day;
}

/**获取子元素的索引**/
function getindexInParent(child) {
    var parent = child.parent();
    for (var i = 0; i < parent.childCount(); i++) {
        if (parent.child(i).find(className('CheckBox').checked(true)).length > 0) {
            return i;
        }
    }
    return -1; // 如果找不到子元素,则返回-1
}

/**
*监控脚本是否卡在某界面不动,发现此情况重启脚本
*/
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();
    var PackageName = getPackageName(tiktokAppName);
    for (let c = 0; c < 59; c++) {//连续扫描60秒后返回结果,如果60秒停留在同一活动页面,则就要重启线程了
        var btntxt = textMatches(/同意|取消|关闭|不在提醒|我知道了|以后再说|暂不使用/).findOnce();
        if (btntxt && btntxt.packageName() == PackageName) {
            console.warn('执行:' + btntxt.text());
            click(btntxt.text());
        }
        var div1 = text('请完成下列验证后继续').findOnce();
        if (div1 && div1.packageName() == PackageName) {
            console.warn('请完成下列验证后继续');
            //这里有一个滑动块验证,待开发

            click(div1.bounds().right + 250, div1.bounds().centerY());
        }
        var div2 = textMatches(/确认身份信息/).findOnce();
        if (div2 && div2.packageName() == PackageName) {
            console.warn('确认身份信息');
            click(80, div2.bounds().centerY());
        }
        //关闭签到提示
        var single = text("签到提醒").findOnce();
        if (single && single.packageName() == PackageName) {
            click(single.bounds().centerX(), single.bounds().centerY() - 150);
            sleep(1000);
            click(single.bounds().centerX(), single.bounds().centerY() + 180);
            console.warn('结束签到提醒');
        }
        // 验证账号重新登录
        //com.ss.android.ugc.aweme.account.ui.dialog.AccountStatusViewDialog
        if (textMatches(/账号安全,请重新登录|登录后,体验完整功能/).findOnce()) {
            click("重新登录");
            console.warn('重新登录验证');
            sleep(2000);
            var a = textContains("已阅读并同意").findOnce();
            if (a) {
                click(a.bounds().left, a.bounds().centerY());
                sleep(500);
                click(a.bounds().centerX(), a.bounds().centerY() - 200);
            } else {
                click("一键登录");
                sleep(2000);
                click("同意并登录");
            }
        }
        //toastLog(currentActivity());
        currentActis[c] = currentActivity();
        sleep(1000);//这是每秒扫描一次活动页
    }
    //toastLog(currentActivity());
    ac = unique(currentActis);
    cc = currentActivity().match(/.*ExcitingVideoActivity|.*main\.MainActivity|.*app\.Dialog/gi);
    if (ac.length == 1 && !cc) {
        toastLog(ac[0]);
        return false;
    }
    return true;
}

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

observer_thread = threads.start(function () {
    setInterval(function () {
        console.verbose('--------多线程安全检测---------');
        if (!Observer() && times > 0) {
            work_thread.interrupt();
            work_thread = threads.start(function () {
                //如果运行时间超过3小时,则关闭应用,停止脚本。
                endtime = new Date().getTime();
                if (Math.floor((endtime - starttime) / 1000) > 60 * 180) {
                    console.show();
                    console.warn("本脚本已运行超三小时!");
                    toast("本脚本已运行超三小时!");
                    sleep(5000);
                    console.hide();
                    closeApp(tiktokAppName);
                    //熄屏
                    runtime.accessibilityBridge.getService().performGlobalAction(android.accessibilityservice.AccessibilityService.GLOBAL_ACTION_LOCK_SCREEN);
                    //停止本脚本
                    //engines.myEngine().forceStop();
                    //结束所有Autojx进程
                    engines.stopAll();
                } else {
                    console.warn("Main线程在5秒后重启!");
                    toast("Main线程在5秒后重启!");
                    //toastLog(currentActivity());
                    closeApp(tiktokAppName);
                    sleep(5000);
                    Main();
                }
            });
        }
    }, 3000);//这个时间是线程休息时间
});

//息屏挂机模式,常亮device.keepScreenOn()
function oled() {
    var w = floaty.rawWindow('<frame gravity="center" bg="#000000" />');
    w.setSize(-1, -1);
    w.setTouchable(true);
    //保持脚本运行
    setInterval(() => { }, 1000);
}

//关闭软件
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(/.*强行停止.*/).findOnce();
    if (is_sure.enabled()) {
        try {
            var btn = className("Button").text('强行停止').findOnce();
            if (btn) btn.click();
            sleep(1000);
            btn = className("Button").text('强行停止').findOnce();
            if (btn) btn.click();
            sleep(1000);
            btn = className("Button").text('确定').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 FindPicture(templateImage64) {
    let bounds = null;
    toastLog('开始图像识别FindPicture');

    //安卓系统中,autoJS运行截图操作时,每次都会询问“要开始录制或投射内容吗”,并且没有始终允许的设置,可以用如下adb命令设置为始终允许
    //adb shell appops set org.autojs.autoxjs.v6 PROJECT_MEDIA allow

    //该请求截图权限函数在截图脚本中只需执行一次,而无需每次调用captureScreen()都调用一次;若已有截图权限,则抛出异常。
    //if (!requestScreenCapture(false)) {
    //    console.log("请求截图权限失败");
    //    return bounds;
    //}

    /*
    let iscapture = captureScreen(files.getSdcardPath() + '/脚本/1.png');
    sleep(1000);
    if(iscapture){
        screenPicture = images.read(files.getSdcardPath() + '/脚本/1.png');
    }else{
        console.log("截图保存失败");
        return bounds;
    }
    */

    //这里可以不保存到文件,直接在内存中查找
    //let screenPicture = captureScreen();
    let coinPicture = images.fromBase64(templateImage64);
    if (!coinPicture) {
        console.log("模板:", coinPicture);
        return bounds;
    }
    //找到图会返回坐标 找不到返回null
    try {
        var result = images.findImage(captureScreen(), coinPicture, { region: [0, 2 * device.height / 3], threshold: 0.7 });
        toastLog('图像识别完成FindPicture');
        if (result) {
            console.log("坐标:", result);
            bounds = result;
        }
    } catch (e) {
        toastLog('图像识别失败FindPicture');
    }
    coinPicture.recycle();
    return bounds;
}

//切换用户
function chengaccound() {
    console.show();
    console.warn("【准备切换登录账号】");
    //首先需要进入我的页面中
    if (!className("android.widget.TextView").desc('我,按钮').findOnce()) {
        gohome();
        sleep(1000);
    }
    try {
        var me = className("android.widget.TextView").desc('我,按钮').findOnce();
        if (me) click(me.bounds().centerX(), me.bounds().centerY());
        sleep(2000);
        var more = className("android.view.ViewGroup").desc('更多').findOnce();
        if (more) click(more.bounds().centerX(), more.bounds().centerY());
        sleep(2000);
        var setting = className("android.view.ViewGroup").desc('设置,按钮').findOnce().click();
        //if(setting)click(setting.bounds().centerX(),setting.bounds().centerY());
        sleep(2000);
        var account = className("android.widget.RelativeLayout").desc('切换账号').findOnce().click();
        //if(account)click(account.bounds().centerX(),account.bounds().centerY());
        sleep(2000);

        var checkbox = className("android.widget.CheckBox").checked(true).findOnce().parent();
        //找到当前为选择状态的下一个兄弟节点并点击选择,如果没有下一个兄弟,则选择第一个兄弟
        var checknext = checkbox.parent().child(getindexInParent(checkbox) + 1);
        if (checknext && checknext.className() == checkbox.className()) {
            toastLog("选择下一个账号");
            checknext.click();
        } else {
            toastLog("选择第一个账号");
            checkbox.parent().child(0).click();
        }
        sleep(1000);

        var j = 0;
        var backbtn = id("com.ss.android.ugc.aweme.lite:id/back_btn").desc('返回').findOnce();
        while (backbtn) {
            backbtn.click();
            sleep(1000);
            backbtn = id("com.ss.android.ugc.aweme.lite:id/back_btn").desc('返回').findOnce();
            if (text('更多功能').findOnce()) {
                back();
                break;
            }
            if (j > 5) break;
        }
        back();
    } catch (e) {
        console.warn("切换登录账号失败");
        console.hide();
    }
    console.hide();
}


/**
 * 记录App一次运行的时间
 * @param {appName} appName 
 * @param {本次运行时间} recordTimes 
 */
function appRunTimeRecord(appName, recordTimes) {
    let key = appName + storageSign + getDate();
    var havedRunTimes = woolStorage.get("" + key + "");
    let value = "";
    if (!havedRunTimes) {
        woolStorage.put(key, parseInt(recordTimes));
    } else {
        value = parseInt(havedRunTimes) + parseInt(recordTimes);
        woolStorage.put(key, value);
    }
}

// 屏幕是否为锁定状态,返回{isScreenOn:0/1,isLocked:0/1,isSecure:0/1,}
function isDeviceLocked() {
    importClass(android.app.KeyguardManager);
    importClass(android.content.Context);
    var km = context.getSystemService(Context.KEYGUARD_SERVICE);
    return { 'isScreenOn': device.isScreenOn(), 'isLocked': km.isKeyguardLocked(), 'isSecure': km.isKeyguardSecure() };
}

// 函数封装ADB命令
function shell(cmd) {
    return runtime.exec(cmd).waitFor();
}