From 8339d390b07ed4c4341ef26b4f307607b2c3891d Mon Sep 17 00:00:00 2001 From: kavil Date: Wed, 8 May 2024 02:09:01 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/base/index.ts | 31 +++------ src/index.ts | 170 ++++++++++++++++++++++++++++++++++++++++------ src/lib/utils.ts | 101 +++++++++++++++++++-------- 3 files changed, 232 insertions(+), 70 deletions(-) diff --git a/src/base/index.ts b/src/base/index.ts index a2bf519..9ae895d 100644 --- a/src/base/index.ts +++ b/src/base/index.ts @@ -13,7 +13,7 @@ export abstract class DPStarter extends DPEvent { } init() { - console.log('init'); + console.log('初始化!'); this.doInit(); } @@ -24,9 +24,8 @@ export abstract class DPStarter extends DPEvent { this.init(); this.on('over', (task: DPTask) => { const index = this._tasks.indexOf(task); - task.removeAllListeners(); - this.removeTask(task); - if (index < this._tasks.length - 1) { + console.log('index:', index); + if (this._tasks[index + 1]) { this.doInit(); // 回到初始界面状态 this._tasks[index + 1].start(); } @@ -92,39 +91,31 @@ export class DPTask extends DPEvent { this._name = name; } - constructor(owner: DPStarter) { + constructor(owner: DPStarter, name = '') { super(); this.owner = owner; + this._name = name; + console.log('task created:', name); this.owner.addTask(this); } init() { - console.log('init'); this.status = TaskStatus.Init; } start() { - console.log('start'); this.status = TaskStatus.Running; if (!this._fn) { - console.error('任务未设置执行函数'); + console.error(`task-${this.name}:任务未设置执行函数`); return; } + console.log(`task-${this.name}:开始执行`); this._fn(); + this.stop(); } - pause() { - console.log('pause'); - this.status = TaskStatus.Paused; - } - - stop() { - console.log('stop'); + private stop() { + console.log(`task-${this.name}:结束`); this.status = TaskStatus.Stopped; } - - restart() { - console.log('restart'); - this.status = TaskStatus.Running; - } } diff --git a/src/index.ts b/src/index.ts index 953c4dc..e0fb52f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,6 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ import { DPStarter, DPTask } from './base/index'; -import { clickForce, findNextElement, withMakeSure } from './lib/utils'; +import { clickForce, clickForceXY, isNextElement, findPrevElement, withMakeSure } from './lib/utils'; // 弹窗关闭按钮 const modalCloseBtn = className('com.lynx.tasm.behavior.ui.LynxFlattenUI') @@ -7,17 +8,12 @@ const modalCloseBtn = className('com.lynx.tasm.behavior.ui.LynxFlattenUI') .clickable(true) .text(''); -// 可能出现的是否打开app弹窗确定按钮 -const openAppModal = id('android:id/button1'); - // 福利界面底部栏入口按钮 -const welfareEntry = id('di1').text('福利').visibleToUser().selected(false); +const welfareEntry = id('di1').text('福利').visibleToUser(); class Hongguo extends DPStarter { doInit() { - console.log('初始化!'); - withMakeSure(() => app.launch('com.phoenix.read'), { - hasModal: [() => openAppModal.findOne(500), () => modalCloseBtn.findOne(500)], // 有可能出现的弹窗 + withMakeSure('打开红果', () => app.launch('com.phoenix.read'), { landOver: [() => welfareEntry.findOne(500)] // 确认是否到达目的页 }); const widget = welfareEntry.findOne(500); @@ -27,30 +23,160 @@ class Hongguo extends DPStarter { const hongguo = new Hongguo(); -const task1 = new DPTask(hongguo); +const task1 = new DPTask(hongguo, '新人见面礼'); +const task2 = new DPTask(hongguo, '日常福利-签到'); +const task3 = new DPTask(hongguo, '看广告视频'); +const task4 = new DPTask(hongguo, '看短剧'); + // 新人见面礼立即领取 task1.run(() => { - const startBtn = className('com.lynx.tasm.behavior.ui.text.FlattenUIText').textContains('立即领取').visibleToUser(); + const startBtn = className('com.lynx.tasm.behavior.ui.text.FlattenUIText') + .boundsInside(0, 0, device.width / 2, device.height / 2) + .text('立即领取') + .visibleToUser(); + const getBtn = className('com.lynx.tasm.behavior.ui.text.FlattenUIText').text('立即领取').visibleToUser(); const getGoldNext = className('com.lynx.tasm.behavior.ui.text.FlattenUIText').text('金币奖励可在「福利」查看').visibleToUser(); - const overBtn = className('com.lynx.tasm.behavior.ui.text.FlattenUIText').textContains('明日再来').visibleToUser(); - console.log('task1 新人见面礼立即领取'); + const overBtn = className('com.lynx.tasm.behavior.ui.text.FlattenUIText').text('明日再来').visibleToUser(); + console.log('task1'); - withMakeSure(() => clickForce(startBtn.findOne(500)), { - landOver: [() => modalCloseBtn.findOne(500), () => getGoldNext.findOne(500)] // 确认是否到达目的页 - }); + const stepBtn1 = withMakeSure( + '立即领取', + () => { + clickForce(startBtn.findOne(500)); + return startBtn; + }, + { + landOver: [() => modalCloseBtn.findOne(500), () => getGoldNext.findOne(500)], // 确认是否到达目的页 + retry: 2 + } + ); + + if (stepBtn1) { + if (overBtn.findOne(500)) { + return clickForce(overBtn.findOne(500)); + } + withMakeSure('立即领取inModal', () => clickForce(getBtn.findOne(500)), { + landOver: [ + () => modalCloseBtn.findOne(500), + () => isNextElement(overBtn, getGoldNext, 'com.lynx.tasm.behavior.ui.text.FlattenUIText') + ] // 确认是否到达目的页 + }); - if (overBtn.findOne(500)) { return clickForce(overBtn.findOne(500)); } +}); - withMakeSure(() => clickForce(startBtn.findOne(500)), { - landOver: [ - () => modalCloseBtn.findOne(500), - () => findNextElement(overBtn, getGoldNext, 'com.lynx.tasm.behavior.ui.text.FlattenUIText') - ] // 确认是否到达目的页 +task2.run(() => { + console.log('task2'); + try { + const 日常福利区域 = className('com.lynx.tasm.behavior.ui.text.FlattenUIText').text('日常福利').visibleToUser().findOne(500)!; + swipe(日常福利区域.bounds().centerX(), 日常福利区域.bounds().centerY(), 日常福利区域.bounds().centerX(), 0, 500); + } catch (e) { + console.log(e); + } + const 签到Btn = className('com.lynx.tasm.behavior.ui.text.FlattenUIText').text('去签到').visibleToUser(); + const 已签到 = className('com.lynx.tasm.behavior.ui.text.FlattenUIText').text('已签到').visibleToUser(); + const 立即签到 = className('com.lynx.tasm.behavior.ui.text.FlattenUIText').textContains('立即签到').visibleToUser(); + const 看视频再领 = className('com.lynx.tasm.behavior.ui.text.UIText').textContains('看视频最高再领').visibleToUser(); + + if (已签到.findOne(500)) { + return; + } + withMakeSure('签到', () => clickForce(签到Btn.findOne(500)), { + landOver: [() => modalCloseBtn.findOne(500)], // 确认是否到达目的页 + retry: 2 }); + clickForce(立即签到.findOne(1500)); + clickForce(看视频再领.findOne(1500), false); + + lookAD(); + clickForce(modalCloseBtn.findOne(1500)); +}); - return clickForce(overBtn.findOne(500)); +task3.run(() => { + try { + const 日常福利区域 = className('com.lynx.tasm.behavior.ui.text.FlattenUIText').text('日常福利').visibleToUser().findOne(500)!; + swipe(日常福利区域.bounds().centerX(), 日常福利区域.bounds().centerY(), 日常福利区域.bounds().centerX(), 0, 500); + } catch (e) {} + const 立即领取 = className('com.lynx.tasm.behavior.ui.text.FlattenUIText').textContains('立即领取').visibleToUser(); + clickForce(立即领取.findOne(500)); + lookAD(); }); +task4.run(() => { + try { + const 日常福利区域 = className('com.lynx.tasm.behavior.ui.text.FlattenUIText').text('日常福利').visibleToUser().findOne(500)!; + swipe(日常福利区域.bounds().centerX(), 日常福利区域.bounds().centerY(), 日常福利区域.bounds().centerX(), 0, 500); + } catch (e) {} + const 去看剧 = className('com.lynx.tasm.behavior.ui.text.FlattenUIText').textContains('去看剧').visibleToUser(); + clickForce(去看剧.findOne(500)); + + const 领金币 = id('com.phoenix.read:id/nj').textContains('金币').visibleToUser(); + const 追剧 = className('android.widget.TextView').text('追剧'); + const 立即领取 = className('com.lynx.tasm.behavior.ui.text.FlattenUIText').text('立即领取').visibleToUser(); + const 再攒 = className('com.lynx.tasm.behavior.ui.text.FlattenUIText').textContains('再攒').visibleToUser(); + const 看视频再领 = className('com.lynx.tasm.behavior.ui.text.UIText').textContains('看视频').visibleToUser(); + + const startTime = new Date().getTime(); + + let looking = true; + while (looking) { + if (领金币.exists()) { + withMakeSure('领金币', () => clickForce(领金币.findOne(500)), { + retry: 2, + landOver: [() => 立即领取.findOne(500)] + }); + const current立即领取 = findPrevElement(再攒, 'com.lynx.tasm.behavior.ui.text.FlattenUIText'); + clickForce(current立即领取); + if (看视频再领.exists()) { + clickForce(看视频再领.findOne(1500), false); + lookAD(); + } + + console.log('task0'); + const 开宝箱 = className('com.lynx.tasm.behavior.ui.text.FlattenUIText').text('开宝箱得金币'); + if (开宝箱.exists()) { + withMakeSure('开宝箱', () => clickForce(开宝箱.findOne(500)), { + landOver: [() => modalCloseBtn.findOne(500)], // 确认是否到达目的页 + retry: 2 + }); + if (看视频再领.exists()) { + clickForce(看视频再领.findOne(1500), false); + lookAD(); + } + } + clickForce(modalCloseBtn.findOne(1500)); + clickForce(去看剧.findOne(500)); + } + if (!追剧.exists()) { + looking = false; + } + sleep(30000); + console.log(`已经看了${(new Date().getTime() - startTime) / 1000 / 60}分钟`); + // 8小时结束 + if (new Date().getTime() - startTime > 1000 * 60 * 60 * 8) { + looking = false; + } + } +}); + +function lookAD() { + const 领取成功 = className('com.lynx.tasm.behavior.ui.text.FlattenUIText').text('领取成功').visibleToUser(); + const 再次领取奖励 = className('com.lynx.tasm.behavior.ui.text.FlattenUIText').text('领取奖励').visibleToUser(); + sleep(5000); + let ok = false; + while (!ok) { + ok = 领取成功.exists(); + console.log('广告ing'); + sleep(2000); + } + const bounds = 领取成功.findOne(500)!.bounds(); + click(bounds.right + 5, bounds.top + 5); + sleep(1000); + if (再次领取奖励.exists()) { + clickForce(再次领取奖励.findOne(500), false); + lookAD(); + } +} + hongguo.start(); diff --git a/src/lib/utils.ts b/src/lib/utils.ts index 1318c7d..0896aea 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -1,5 +1,5 @@ // 找到控件区域点击 -export function clickForce(ele: UiObject | null) { +export function clickForce(ele: UiObject | null, muilt = true) { if (!ele) { console.log('控件不存在'); return; @@ -8,8 +8,10 @@ export function clickForce(ele: UiObject | null) { const x = bound.centerX(); const y = bound.centerY(); click(x, y); - click(x - 1, y + 1); - click(x + 1, y - 1); + if (muilt) { + click(x - 1, y + 1); + click(x + 1, y - 1); + } } export function clickForceXY(x: number, y: number, width: number, height: number) { @@ -20,7 +22,7 @@ export function clickForceXY(x: number, y: number, width: number, height: number click(x + 1, y - 1); } -export function findNextElement(ele: UiSelector, nextEle: UiSelector, classNameString: string, step: number = 1) { +export function isNextElement(ele: UiSelector, nextEle: UiSelector, classNameString: string, step = 1) { const findit = ele.findOne(500); const finditNext = nextEle.findOne(500); if (!findit || !finditNext) { @@ -43,7 +45,7 @@ export function findNextElement(ele: UiSelector, nextEle: UiSelector, classNameS return false; } -export function findPrevElement(ele: UiSelector, prevEle: UiSelector, classNameString: string, step: number = 1) { +export function isPrevElement(ele: UiSelector, prevEle: UiSelector, classNameString: string, step = 1) { const findit = ele.findOne(500); const finditPrev = prevEle.findOne(500); if (!findit || !finditPrev) { @@ -66,6 +68,34 @@ export function findPrevElement(ele: UiSelector, prevEle: UiSelector, classNameS return false; } +export function findPrevElement(ele: UiSelector, classNameString: string, step = 1) { + const findit = ele.findOne(500); + if (!findit) { + return null; + } + const eles = className(classNameString).find(); + const index = eles.findIndex((ele) => { + if (ele.bounds().centerX() === findit.bounds().centerX() && ele.bounds().centerY() === findit.bounds().centerY()) { + return ele; + } + }); + return eles[index - step]; +} + +export function findNextElement(ele: UiSelector, classNameString: string, step = 1) { + const findit = ele.findOne(500); + if (!findit) { + return null; + } + const eles = className(classNameString).find(); + const index = eles.findIndex((ele) => { + if (ele.bounds().centerX() === findit.bounds().centerX() && ele.bounds().centerY() === findit.bounds().centerY()) { + return ele; + } + }); + return eles[index + step]; +} + export interface MakeSureOptions { hasModal?: (() => UiObject | null)[]; retry?: number; @@ -73,36 +103,51 @@ export interface MakeSureOptions { } export function withMakeSure( + name: string, fn: () => T | null, - options: { hasModal?: (() => UiObject | null)[]; retry?: number; landOver?: (() => void)[] } + options: { hasModal?: (() => UiObject | null)[]; retry?: number; whileTimes?: number; landOver?: (() => any)[] } ) { - const { hasModal, landOver, retry = 5 } = options; - let result = fn() || true; + const { hasModal, landOver, retry = 3, whileTimes = 5 } = options; - let whileNum = 0; - let ok = false; + let result: boolean | T = false; - while (!ok) { - whileNum++; - if (whileNum > retry) { - result = false; - break; - } - if (hasModal) { - const modals = hasModal.map((fn) => fn()); - if (modals.length) { - modals.forEach((modal) => { - modal && clickForce(modal); - }); + let forNum = 0; + for (let i = 0; i < retry; i++) { + result = fn() || true; + + console.log(name, 'fn:', result); + + let whileNum = 0; + let ok = false; + + while (!ok) { + if (whileNum > whileTimes) { + result = false; + break; + } + if (hasModal) { + const modals = hasModal.map((fn) => fn()); + if (modals.length) { + modals.forEach((modal) => { + modal && clickForce(modal); + }); + } } + if (landOver) { + ok = landOver.every((fn) => !!fn()); + } else { + ok = true; + } + whileNum++; + sleep(500); } - if (landOver) { - ok = landOver.every((fn) => fn()); - } else { - ok = true; + + if (ok) { + break; } - sleep(500); + forNum++; } - console.log('fn:', fn, 'whileNum:', whileNum, 'result:', result); + + console.log(name, 'retry:', forNum, 'result:', result); return result as T; }