tiktok.js

自用程序调用库

目前為 2024-11-26 提交的版本,檢視 最新版本

此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.cn-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();
}