您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
自用库
当前为
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.greasyfork.icu/scripts/520147/1509122/gifshowjs.js
auto.waitFor(); global.AppName = "快手极速版"; global.packageName = "com.kuaishou.nebula"; global.running = false; //是否正在刷视频中 global.working = false; //是否正在刷视频中 global.startSec = Date.now();//刷视频计时 global.img_block = storages.create("gifshow").get('img_block'); global.ver = 'v1.4';//版本号 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(textMatches(/金币暴涨|我的现金/).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); }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 = textMatches(/去看广告得.*/).visibleToUser(true).findOne(1000); if (x) { console.error('点击宝箱:',x.text()); click(x.bounds().centerX(), x.bounds().centerY());//再次点弹出宝箱层中的红色按钮 sleep(5000); } else { var popdiv=textMatches(/倒计时结束.*/).visibleToUser(true).findOne(1000); if(popdiv){ toastLog('宝箱:'+popdiv.text()); 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).findOne(1000); if (okbtn) { let btn = className('TextView').text('放弃奖励').visibleToUser(true).findOne(1000); if (btn) click(btn.bounds().centerX(), btn.bounds().centerY() - 120); var b = okbtn.text().match(/\d+/); var t = 1 * (b ? b[0] : 1) + random(9, 15); cutDownBySleep(t, '再看'); } okbtn = className('TextView').textMatches(/领取奖励|退出直播间/).visibleToUser(true).findOne(1000); if (okbtn) { click(okbtn.bounds().centerX(), okbtn.bounds().centerY()); cutDownBySleep(random(9, 15), okbtn.text()); } okbtn = className('Button').textMatches(/继续赚金币/).visibleToUser(true).findOne(1000); if (okbtn) { click(okbtn.bounds().centerX(), okbtn.bounds().centerY()); cutDownBySleep(random(9, 15), '继续'); } 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).findOne(1000); 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).findOne(1000); i++; } //看直播领金币 let title=className('TextView').text('看直播领金币').visibleToUser(true).findOne(1000); 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); 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); } } var btn=idMatches(/.*\/close|.*\/anchor_close/).visibleToUser(true).findOnce(); if (btn) { console.log('关闭弹出'); click(btn.bounds().centerX(), btn.bounds().centerY()); 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).findOne(1000); } } } //刷广告视频赚金币 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); cutDownBySleep(random(20, 30), '刷广告'); 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); } var btn = className('TextView').text('放弃奖励').visibleToUser(true).findOne(1000); 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(/退出.*/).findOne(1000); 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, 40); //随机恢复到首页 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).findOne(1000); 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-95; let icoX=[ plugdiv.bounds().left+95, plugdiv.bounds().left+270, plugdiv.bounds().left+430, plugdiv.bounds().left+580 ]; 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).findOne(1000); 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).findOne(1000); 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).findOne(1000);//直播间 if (living) { toastLog("1.退出直播间"); click(living.bounds().centerX(), living.bounds().centerY()); sleep(2000); var div0=text('退出直播间').visibleToUser(true).findOne(1000); 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).findOne(1000); 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( `<vertical id="frame" alpha="0" w="{{device.width-500}}px" h="150px"> <card w="auto" h="auto" layout_gravity="center" cardCornerRadius="5dp" cardBackgroundColor="#eeeeee" > <text id="title" text="" textColor="#333333" textSize="13sp" padding="12 8" /> </card> </vertical>` ); fwin.setTouchable(false); sleep(500); 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); fwin.setTouchable(false); let x = parseInt((device.width - fwin.width) / 2); let y = device.height-550; fwin.setPosition(x, y); }); sleep(1000); } fwin=null; floaty.closeAll(); sleep(500); } 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).findOne(1000); if (is_sure&&is_sure.enabled()) { try { var btn = className("Button").text('强行停止').visibleToUser(true).findOne(1000); if (btn) btn.click(); sleep(1000); btn = className("Button").text('强行停止').visibleToUser(true).findOne(1000); if (btn) btn.click(); sleep(1000); btn = className("Button").text('确定').visibleToUser(true).findOne(1000); 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); } }); } importClass(org.opencv.imgproc.Imgproc); importClass(org.opencv.core.Core); importClass(org.opencv.core.Rect); importClass(org.opencv.core.Mat); importClass(org.opencv.core.Point); importClass(org.opencv.core.Size); importClass(org.opencv.core.CvType); importClass(org.opencv.core.Scalar); importClass(org.opencv.imgcodecs.Imgcodecs); /** * @param {number[]} region 是一个两个或四个元素的数组。 * (region[0], region[1])表示找色区域的左上角;region[2]*region[3]表示找色区域的宽高。如果只有region只有两个元素,则找色区域为(region[0], region[1])到屏幕右下角。 * 如果不指定region选项,则找色区域为整张图片。 * @param {*} img * @returns {org.opencv.core.Rect} */ function buildRegion(region, img) { if (region == undefined) { region = []; } let x = region[0] === undefined ? 0 : region[0]; let y = region[1] === undefined ? 0 : region[1]; let width = region[2] === undefined ? img.getWidth() - x : region[2]; let height = region[3] === undefined ? img.getHeight() - y : region[3]; if (x < 0 || y < 0 || x + width > img.width || y + height > img.height) { throw new Error( 'out of region: region = [' + [x, y, width, height] + '], image.size = [' + [img.width, img.height] + ']' ); } return new Rect(x, y, width, height); } /** * @param {number} threshold 图片相似度。取值范围为0~1的浮点数。默认值为0.9 * @param {number[]} region 找图区域 * @param {number[]} scaleFactors 大图的宽高缩放因子,默认为 [1, 0.9, 1.1, 0.8, 1.2] * @param {number} max 找图结果最大数量,默认为5 * @param {boolean} grayTransform 是否进行灰度化预处理,默认为true。 * 通常情况下将图像转换为灰度图可以简化匹配过程并提高匹配的准确性,当然,如果你的匹配任务中颜色信息对匹配结果具有重要意义, * 可以跳过灰度化步骤,直接在彩色图像上进行模板匹配。 */ function MatchOptions(threshold, region, scaleFactors, max, grayTransform) { this.threshold = threshold; this.region = region; this.scaleFactors = scaleFactors; this.max = max; this.grayTransform = grayTransform; } const defaultMatchOptions = new MatchOptions(0.9, undefined, [[1, 1], [0.9, 0.9], [1.1, 1.1], [0.8, 0.8], [1.2, 1.2]], 5, true); // 校验参数 MatchOptions.check = function (options) { if (options == undefined) { return defaultMatchOptions; } // deep copy let newOptions = JSON.parse(JSON.stringify(options)); if (newOptions.threshold == undefined) { newOptions.threshold = defaultMatchOptions.threshold; } if (newOptions.region && !Array.isArray(newOptions.region)) { throw new TypeError('region type is number[]'); } if (newOptions.max == undefined) { newOptions.max = defaultMatchOptions.max; } if (newOptions.scaleFactors == undefined) { newOptions.scaleFactors = defaultMatchOptions.scaleFactors; } else if (!Array.isArray(newOptions.scaleFactors)) { throw new TypeError('scaleFactors'); } for (let index = 0; index < newOptions.scaleFactors.length; index++) { let factor = newOptions.scaleFactors[index]; if (Array.isArray(factor) && factor[0] > 0 && factor[1] > 0) { // nothing } else if (typeof factor === 'number') { newOptions.scaleFactors[index] = [factor, factor]; } else { throw new TypeError('scaleFactors'); } } if (newOptions.grayTransform === undefined) { newOptions.grayTransform = defaultMatchOptions.grayTransform; } return newOptions; }; function Match(point, similarity, scaleX, scaleY) { this.point = point; this.similarity = similarity; this.scaleX = scaleX; this.scaleY = scaleY; } /** * 找图,在图中找出所有匹配的位置 * @param {Image} img * @param {Image} template * @param {MatchOptions} options 参数见上方定义 * @returns {Match[]} */ function matchTemplate(img, template, options) { if (img == null || template == null) { throw new Error('ParamError'); } options = MatchOptions.check(options); //console.log('参数:', options); let largeMat = img.mat; let templateMat = template.mat; let largeGrayMat; let templateGrayMat; if (options.region) { options.region = buildRegion(options.region, img); largeMat = new Mat(largeMat, options.region); } // 灰度处理 if (options.grayTransform) { largeGrayMat = new Mat(); Imgproc.cvtColor(largeMat, largeGrayMat, Imgproc.COLOR_BGR2GRAY); templateGrayMat = new Mat(); Imgproc.cvtColor(templateMat, templateGrayMat, Imgproc.COLOR_BGR2GRAY); } // ================================================= let finalMatches = []; for (let factor of options.scaleFactors) { let [fx, fy] = factor; let resizedTemplate = new Mat(); Imgproc.resize(templateGrayMat || templateMat, resizedTemplate, new Size(), fx, fy, Imgproc.INTER_LINEAR); // 执行模板匹配,标准化相关性系数匹配法 let matchMat = new Mat(); Imgproc.matchTemplate(largeGrayMat || largeMat, resizedTemplate, matchMat, Imgproc.TM_CCOEFF_NORMED); let currentMatches = _getAllMatch(matchMat, resizedTemplate, options.threshold, factor, options.region); //console.log('缩放比:', factor, '可疑目标数:', currentMatches.length); for (let match of currentMatches) { if (finalMatches.length === 0) { finalMatches = currentMatches.slice(0, options.max); break; } if (!isOverlapping(finalMatches, match)) { finalMatches.push(match); } if (finalMatches.length >= options.max) { break; } } resizedTemplate.release(); matchMat.release(); if (finalMatches.length >= options.max) { break; } } largeMat !== img.mat && largeMat.release(); largeGrayMat && largeGrayMat.release(); templateGrayMat && templateGrayMat.release(); return finalMatches; } function _getAllMatch(tmResult, templateMat, threshold, factor, rect) { let currentMatches = []; let mmr = Core.minMaxLoc(tmResult); while (mmr.maxVal >= threshold) { // 每次取匹配结果中的最大值和位置,从而使结果按相似度指标从高到低排序 let pos = mmr.maxLoc; // Point let value = mmr.maxVal; let start = new Point(Math.max(0, pos.x - templateMat.width() / 2), Math.max(0, pos.y - templateMat.height() / 2)); let end = new Point( Math.min(tmResult.width() - 1, pos.x + templateMat.width() / 2), Math.min(tmResult.height() - 1, pos.y + templateMat.height() / 2) ); // 屏蔽已匹配到的区域 Imgproc.rectangle(tmResult, start, end, new Scalar(0), -1); mmr = Core.minMaxLoc(tmResult); if (rect) { pos.x += rect.x; pos.y += rect.y; start.x += rect.x; start.y += rect.y; end.x += rect.x; end.y += rect.y; } let match = new Match(pos, value, factor[0], factor[1]); // 保存匹配点的大致范围,用于后续去重。设置enumerable为false相当于声明其为私有属性 Object.defineProperty(match, 'matchAroundRect', { value: new Rect(start, end), writable: true, enumerable: false }); currentMatches.push(match); } return currentMatches; } /** * 判断新检测到的点位是否与之前的某个点位重合。 * @param {Match[]} matches * @param {Match} newMatch * @returns {boolean} */ function isOverlapping(matches, newMatch) { for (let existingMatch of matches) { // 也可判断两点间的距离,但是平方、开方运算不如比较范围简单高效 if (existingMatch.matchAroundRect.contains(newMatch.point)) { if (newMatch.similarity > existingMatch.similarity) { existingMatch.point = newMatch.point; existingMatch.similarity = newMatch.similarity; existingMatch.scaleX = newMatch.scaleX; existingMatch.scaleY = newMatch.scaleY; existingMatch.matchAroundRect = newMatch.matchAroundRect; } return true; } } return false; } /** * 根据搜图结果在原图上画框 * @param {Match[]} matches * @param {*} srcMat * @param {*} templateMat */ function showMatchRectangle(matches, srcMat, templateMat) { for (let match of matches) { let start = match.point; let end = new Point( match.point.x + templateMat.width() * match.scaleX, match.point.y + templateMat.height() * match.scaleY ); Imgproc.rectangle(srcMat, start, end, new Scalar(0, 0, 255), 3); } const saveName = '/sdcard/Download/temp.jpg'; let img2 = images.matToImage(srcMat); images.save(img2, saveName); app.viewFile(saveName); img2.recycle(); } /** 图像识别定位 * @param {images} templateImage64 预定的搜索模板图片base64 * @param {images} ScreenImage 被搜索图片,如果不提供则全屏截图 * @param {number[]} option 配置参数 * @return {result[]}[ { point: {27.0, 1615.0}, similarity: 1, scaleX: 1, scaleY: 1 } ] * @return {bounds{}}{ left: 27,top: 1615,right: 157,bottom: 1745,centerX: 92,centerY: 1680 } //option:{ threshold: 0.85, region: [0, 0], grayTransform: true, max: 3 } //img_block region: [device.width / 2, 200, device.width / 2, device.height / 3],grayTransform:true, */ function FindPicture(tempBase64,ScreenImage) { let templateImage64 = '', options = null; if (tempBase64 == 'img_block') { if (!img_block) return; templateImage64 = img_block; options = { threshold: 0.8, region: [device.width / 2, 200, device.width / 2, device.height / 3], grayTransform: true, max: 3 }; } else { return; } let largeImage = ScreenImage ? ScreenImage : captureScreen(); let template = images.fromBase64(templateImage64); //images.read(files.getSdcardPath() + '/脚本/template.jpg'); //console.log('大图尺寸:', [largeImage.getWidth(), largeImage.getHeight()]); //console.log('模板尺寸:', [template.getWidth(), template.getHeight()]); let bounds = null; let startTs = Date.now(); let result = matchTemplate(largeImage, template, options); if (result.length > 0) { let left = result[0].point.x; let top = result[0].point.y; let right = parseInt(left + template.getWidth() * result[0].scaleX); let bottom = parseInt(top + template.getHeight() * result[0].scaleY); let centerX = parseInt(left + (right - left) / 2); let centerY = parseInt(top + (bottom - top) / 2); bounds = { left: left, top: top, right: right, bottom: bottom, centerX: centerX, centerY: centerY }; } //console.log('识别耗时:', (Date.now() - startTs) / 1000); console.log(tempBase64, result.length==0?{}:result[0].point); // 将结果画框展示 //showMatchRectangle(result, largeImage.mat, template.mat); template.recycle(); setTimeout(function () { largeImage.recycle(); }, 6000); return bounds; } /** 拖动滑块*/ function dragSlider(ax,by,br,bigimg) { var img = bigimg; if(!bigimg){ var pic = images.grayscale(captureScreen()); //img = images.adaptiveThreshold(images.grayscale(pic), 255, "MEAN_C", "BINARY", 5, 10); img = images.inRange(pic, '#000000', '#666666'); } var newimg=images.cvtColor(img, "GRAY2RGBA"); //if(bigimg){ // images.save(newimg, files.getSdcardPath() + '/脚本/2.jpg', "jpg", 100); // app.viewFile(files.getSdcardPath() + '/脚本/2.jpg'); //} var t = random(1555,2222); var xy= FindPicture('img_block',newimg); //console.info("识别结果:" , xy); if (xy) { toastLog("识别成功:" +ax+", "+by); sml_move(ax, by, xy.centerX, by, t); } else if(!bigimg) { toastLog("识别有误,二次识别"); bigimg = images.inRange(pic, '#999999', '#ffffff'); //bigimg = images.adaptiveThreshold(images.grayscale(pic), 255, "MEAN_C", "BINARY", 5, 10); dragSlider(ax, by, br, bigimg); }else{ toastLog("识别有误,尝试滑动"); sml_move(ax, by, br-150, by, t); } } //=================================================================================== 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.show(); 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 accept = textMatches(/立即邀请/).visibleToUser(true).findOnce(); if (accept) { console.log('点立即邀请'); back(); } //var mypg = desc("返回").visibleToUser(true).findOnce(); //if(mypg){ //console.log("点击返回"); //click(mypg.bounds().centerX(), mypg.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()); } //currentActivity()='.*FaceRecognitionActivity'; var block=className('android.view.View').text('向右拖动滑块填充拼图').visibleToUser(true).findOnce(); if(block){ var aa=className('android.widget.Image').textMatches(/cutPic\?captchaSn.*/).visibleToUser(true).findOnce(); //log('向右拖动滑块填充拼图',block.bounds().left); var ax = aa.bounds().centerX(); var by = block.bounds().centerY(); var br = block.bounds().right; dragSlider(ax,by,br); } //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|.*ToastDialog|.*ScreenCaptureRequestActivity/); 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);//这个时间是线程休息时间 });