// // MyScriptTask.m // nochange // // Created by mac on 2024/7/23. // #import "MyScriptTask.h" #import "XSHelper.h" #import "XSPhoneConfig.h" #import "XSPhoneInfo.h" #import "MyEventBus.h" #import "XSHackIos.h" #define total_ad_click 3 @interface MyScriptTask() { @private // 单次app任务 NSString* _taskId; NSString* _appId; BOOL _lastAppTaskComplete; NSTimeInterval _lastAppTaskTime; NSTimeInterval _lastOcrTime; int _lastAppTaskCount; int _total; BOOL _stop; int _taskTimeout; int _workType; BOOL _lastTaskComplete; // 一个点击任务是否完成,按钮点击,广告展示,广告点击,广告回到页面 NSTimeInterval _lastTaskTime; int _step; // 0 等待点击 1: 点击完成,2: 点击广告;3:广告点击完成, int _adTouchBefore; int _count; int _safeTop; NSMutableDictionary *_adShows; NSString *_idfa; CGFloat device_screen_width; CGFloat device_screen_height; int _loadCount; } @property (nonatomic, strong) NSMutableArray *inStack; @property (nonatomic, strong) NSMutableArray *outStack; @property (nonatomic, strong) dispatch_queue_t concurrentQueue; @end @implementation MyScriptTask - (instancetype)init { self = [super init]; if (self) { _currentId = 0; _concurrentQueue = dispatch_queue_create("com.xyzshell.adtask.queue", DISPATCH_QUEUE_CONCURRENT); _inStack = [NSMutableArray array]; _outStack = [NSMutableArray array]; _adShows = [[NSMutableDictionary alloc] init]; _taskTimeout = 30; _workType = 1; _lastTaskComplete = YES; _stop = NO; _total = 0; _count = 0; _lastAppTaskComplete = YES; _lastAppTaskTime = [self getCurTime]; _lastAppTaskCount = 0; _safeTop = 20; _adTouchBefore = 3; _taskId = @"0"; _appId = @""; _loadCount = 0; _lastOcrTime = [self getCurTime]; NSLog(@"OhNo Server Start %@", [[XSPhoneConfig sharedInstance] IPhoneName]); CGFloat screen_scale = [[UIScreen mainScreen] scale]; self->device_screen_width = [UIScreen mainScreen].bounds.size.width * screen_scale; self->device_screen_height = [UIScreen mainScreen].bounds.size.height * screen_scale; } return self; } - (void) showStatus: (NSString *)data { [[MyEventBus sharedInstance] postEvent:@"UpdateStatus" withObject:data]; } - (void) start { _stop = NO; [self runStartApp]; } - (void) stop { _stop = YES; } - (int64_t)nextId { @synchronized (self) { self.currentId++; return self.currentId; } } - (int)enqueue:(id)item { int load = 0; dispatch_barrier_async(self.concurrentQueue, ^{ NSDictionary *dic = item; NSLog(@"-ad log- add task:\n %@", dic); NSMutableDictionary *taskDic = [[NSMutableDictionary alloc] initWithDictionary:dic]; [taskDic setValue:@([self nextId]) forKey:@"_id"]; [self->_adShows setValue: dic[@"ad_time"] forKey:dic[@"adId"]]; self ->_adTouchBefore = [dic[@"ad_touchBeforeMs"] intValue]; [self.inStack addObject:taskDic]; self->_count++; [self showStatus:[NSString stringWithFormat: @"队列任务数量:%d, loads:%@", self->_count, dic[@"ad_loads"]]]; }); return load; } - (id)dequeue { __block id result = nil; dispatch_barrier_sync(self.concurrentQueue, ^{ if ([self.outStack count] == 0) { NSUInteger count = [self.inStack count]; while (count > 0) { [self.outStack addObject:[self.inStack lastObject]]; [self.inStack removeLastObject]; count--; } } if ([self.outStack count] > 0) { result = [self.outStack lastObject]; [self.outStack removeLastObject]; } }); return result; } - (void) reset { _lastTaskComplete = YES; _lastTaskTime = [self getCurTime]; } - (BOOL) isRun { return !_stop;; } - (void) run { dispatch_queue_t queue = dispatch_get_global_queue(0,0); dispatch_async(queue, ^{ self.timer = [NSTimer timerWithTimeInterval:2 target:self selector:@selector(proc) userInfo:nil repeats:YES]; //timer 加入runloop [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSDefaultRunLoopMode]; //开启runloop [[NSRunLoop currentRunLoop] run]; }); } - (void) completeTask { _lastTaskComplete = YES; _lastTaskTime = [self getCurTime]; _lastAppTaskCount++; } - (void) adClosed: (ScriptTask *)task { [self showStatus:[NSString stringWithFormat:@"关闭:%@", task->adId]]; [self completeTask]; } - (void) loadIncrCount { self->_loadCount = self->_loadCount + 1; } -(void) restart { dispatch_barrier_sync(self.concurrentQueue, ^{ _loadCount = 0; _lastTaskComplete = YES; _lastTaskTime = [self getCurTime]; _lastAppTaskComplete = YES; _lastAppTaskTime = [self getCurTime]; _lastAppTaskCount = 0; [self.outStack removeAllObjects]; [self.inStack removeAllObjects]; [_adShows removeAllObjects]; _count = 0; }); } - (void) killApp: (NSString *)pkgName { XSKillAppByName(pkgName); } - (void) runStartApp { [self restart]; NSLog(@"-ad log- runStartApp"); getChangeInfo(_idfa, ^(NSDictionary *dic) { if (!dic || [dic isEqual: [NSNull null]]) { NSLog(@"get change info dic is null"); return; } NSDictionary *workInfo = dic[@"workerInfo"]; if (!workInfo || [workInfo isEqual:[NSNull null]]) { NSLog(@"-ad log- not have task"); return; } NSNumber *workType = workInfo[@"workType"]; self->_workType = [workType intValue]; if (self->_workType <= -1) { NSLog(@"-ad log- not have task"); return; } self->_taskId = dic[@"id"]; self->_idfa = dic[@"idfa"]; saveChangeDataFile(dic); // NSNumber *taskTimeout = workInfo[@"taskTimeout"]; self->_appId = dic[@"appId"]; NSLog(@"-ad log- change %@", self->_appId); NSDictionary *safeAreaInsets = dic[@"safeAreaInsets"]; if (safeAreaInsets) { NSString *top = safeAreaInsets[@"top"]; if (top) { self->_safeTop = [top intValue]; } } // 获取任务,开始启动 //ScriptTask oldtask = { // .appId = self->_appId //}; [self killApp:self->_appId]; // [self runStopScript:&oldtask]; // 获取任务,开始启动 //ScriptTask task = { // .appId = self->_appId, //}; dispatch_async(dispatch_get_main_queue(), ^{ XSRemoteUnlock(); usleep(5000); XSRemoteUnlock(); }); //[self runSystemRestartScript]; // TODO: 备份数据 NSString *appInfoPath = XSGetAppInfoPath(self->_appId); NSDictionary *appInfo = XSGetAppInfo(appInfoPath); XSClearAll(self->_appId); XSSaveAppInfo(appInfo, appInfoPath); [[UIApplication sharedApplication] performSelectorOnMainThread:@selector(beginIgnoringInteractionEvents) withObject:nil waitUntilDone:YES]; [[UIApplication sharedApplication] performSelectorOnMainThread:@selector(endIgnoringInteractionEvents) withObject:nil waitUntilDone:YES]; //[self runStartScript:&task]; XSBringAppForeground(self->_appId); }, ^(NSError *err) { }); } - (void) proc { @try { [self _proc]; } @catch (NSException *exception) { NSLog(@"-ad- erro"); } } - (void) _proc { if (_stop) { return; } NSLog(@"start proc task........"); if (_workType < 1) { if (_count > 1 && ([self getCurTime] - _lastAppTaskTime) > 6) { [self runStartApp]; } else if (([self getCurTime] - _lastAppTaskTime) > 20){ [self runStartApp]; } return; } if (_workType == 4) { if (_lastTaskComplete == YES) { _lastTaskComplete = NO; _lastTaskTime = [self getCurTime]; ScriptTask sctask = { .idfa = _idfa, .appId = _appId, .ad = true, .adId = @"" }; AdTaskLogData logData = { .title = @"广告展示", .idfa = _idfa, .appid = _appId, .adid = @"", .message = @"", .level = 1, .ecpm = @(0) }; self->_adTouchBefore = 10000; [[MyScriptTask sharedInstance] saveAdTaskLog:&logData]; [[MyScriptTask sharedInstance] runAdTouchScript:&sctask]; return; } else { if (([self getCurTime] - _lastTaskTime) > 18) { [self runStartApp]; return; } } } if (self->_loadCount > 0) { if (_lastAppTaskCount >= self->_loadCount) { sleep(2); [self runStartApp]; return; } } if (([self getCurTime] - _lastAppTaskTime) > 80) { [self runStartApp]; return; } if (_lastTaskComplete == NO) { // 上次任务没有执行完,30秒不等待,继续下一个任务 if (_lastTaskTime && ([self getCurTime] - _lastTaskTime) < _taskTimeout) { NSLog(@"last task running"); return; } } @try { id task = [self dequeue]; if (task) { _lastTaskComplete = NO; if (_lastAppTaskComplete == YES) { _lastAppTaskComplete = NO; } // 处理任务 _lastTaskTime = [self getCurTime]; NSMutableDictionary *taskData = task; NSLog(@"pad roc task: \n%@", taskData); NSString *type = taskData[@"type"]; if ([type isEqual:@"click_btn"]) { NSLog(@"ad proc task: click_btn - begin"); [self showStatus:[NSString stringWithFormat:@"点击:%@", taskData[@"adId"]]]; NSNumber *x = taskData[@"x"]; NSNumber *y = taskData[@"y"]; FixedPoint point = { .x = [x intValue], .y = [y intValue] }; ScriptTask st = { .btnLoc = &point, .appId=_appId }; [self runAdShowScript:&st]; } } else { if (_lastTaskTime && ([self getCurTime] - _lastTaskTime) > 20) { [self runStartApp]; return; } } } @catch (NSException *exception) { NSLog(@"ad proc ex name: %@", exception.name); NSLog(@"ad proc ex reason: %@", exception.reason); [self completeTask]; } @finally { NSLog(@"ad proc end"); } } - (BOOL) replaceScript: (NSString *)tplName scriptName: (NSString *)scriptName callback: (ScriptReplaceCallback)callback { NSString *scriptTpl = [self readScript:tplName]; if (scriptTpl == nil) { NSLog(@"ad read script is nil"); return NO; } NSLog(@"ad tpl script: %@", tplName); NSMutableString *newScript = [NSMutableString stringWithString:scriptTpl]; callback(newScript); // NSLog(@"ad new script: %@", newScript); return [self saveScript:[newScript copy] name:scriptName]; } - (void) runAdShowScript: (ScriptTask *) taskData { // 1. 写入按钮点击脚本 NSLog(@"ad runAdShowScript"); NSString *curApp = XSFrontMostAppId(); if(![self->_appId isEqual:curApp]) { XSBringAppForeground(self->_appId); sleep(2); } usleep(5000); int x = taskData->btnLoc->x * 2; int y = taskData->btnLoc->y; int ny = y * 2 + (self->_safeTop / 2) - 10; /* BOOL flag = [self replaceScript:SCRIPT_TOUCH_BTN_TPL scriptName:SCRIPT_TOUCH_BTN callback:^(NSMutableString *newScript) { [MyHelper replaceMulStr:newScript oldStr:@"local btn_x = __BTN_X__" newStr:[NSString stringWithFormat:@"local btn_x = %d", x]]; [MyHelper replaceMulStr:newScript oldStr:@"local btn_y = __BTN_Y__" newStr:[NSString stringWithFormat:@"local btn_y = %d", ny]]; [MyHelper replaceMulStr:newScript oldStr:@"__APPID__" newStr:taskData->appId]; }]; // 2. 运行脚本 if (flag) { NSLog(@"save script ok: %@", SCRIPT_TOUCH_BTN); NSString *res = [self runScript:SCRIPT_TOUCH_BTN]; if (res) { NSLog(@"ad run script success: %@", SCRIPT_TOUCH_BTN); [self showStatus:[NSString stringWithFormat:@"运行点击按钮成功,%@",res]]; } else { [self showStatus:[NSString stringWithFormat:@"运行点击按钮失败,%@",res]]; } } else { NSLog(@"save script error: %@", SCRIPT_TOUCH_BTN); [self showStatus:@"保存按钮点击脚本失败"]; } //*/ } - (void) runStopScript: (ScriptTask *) taskData { BOOL flag = [self replaceScript:SCRIPT_KILL_ALL_TPL scriptName:SCRIPT_KILL_ALL callback:^(NSMutableString *newScript) { [XSHelper replaceMulStr:newScript oldStr:@"__APPID__" newStr:taskData->appId]; }]; if (flag) { // 结束所有相关app NSString *res = [self runScript:SCRIPT_KILL_ALL]; if (res) { NSLog(@"-ad -log %@",res); } } } - (int) runAdTouchScript: (ScriptTask *) taskData { if (!taskData->ad) { // 没有广告展示 NSLog(@"-ad log- touch btn No ad"); [self completeTask]; [self showStatus: [NSString stringWithFormat:@"广告展示失败:%@", taskData->adId]]; return 0; } _lastTaskTime = [self getCurTime]; /* NSLog(@"-ad log- run ad touch script: %@", SCRIPT_TOUCH_AD); BOOL flag = [self replaceScript:SCRIPT_TOUCH_AD_TPL scriptName:SCRIPT_TOUCH_AD callback:^(NSMutableString *newScript) { [MyHelper replaceMulStr:newScript oldStr:@"__APPID__" newStr:taskData->appId]; [MyHelper replaceMulStr:newScript oldStr:@"__BEFORE__" newStr:[NSString stringWithFormat:@"%d", self->_adTouchBefore]]; }]; if (flag) { NSString *res = [self runScript:SCRIPT_TOUCH_AD]; if (res) { NSLog(@"sc res: %@", res); } } */ [self runTouchAdJs:self->_adTouchBefore]; int show_ms = 5000; if ([_adShows objectForKey:taskData->adId]) { NSNumber *shows = _adShows[taskData->adId]; show_ms = [shows intValue]; } [self showStatus: [NSString stringWithFormat:@"广告展,%@", taskData->adId]]; // 点击广告 return show_ms; } - (void) runStartScript: (ScriptTask *) taskData { // 启动app 开始任务 // 清除队列里面所有任务, 重置状态 [self showStatus:@"start new task"]; _lastTaskTime = [self getCurTime]; BOOL flag = [self replaceScript:SCRIPT_START_TPL scriptName:SCRIPT_START callback:^(NSMutableString *newScript) { [XSHelper replaceMulStr:newScript oldStr:@"__APPID__" newStr:taskData->appId]; }]; if (flag) { NSString *res = [self runScript:SCRIPT_START]; if (res) { NSLog(@"-ad- start task:%@", res); } } } - (void) runSystemRestartScript { NSString *res = [self runScript:@"close_not_now.lua"]; if (res) { NSLog(@"kill a all"); } } - (NSString *) runScript: (NSString *)script { /* NSString *url = [NSString stringWithFormat:@"http://127.0.0.1:8080/control/start_playing?path=/%@", script]; [XSHelper doGET:url withCallback:^(NSData* _data) { if (_data) { NSString *res = [MyHelper data2str:_data]; [self showStatus:[NSString stringWithFormat: @"运行脚本成功,%@", res]]; } } withError:^(NSError *err) { NSLog(@"run autouch script error"); }]; NSLog(@"run autouch script error"); */ return nil; } - (NSString *) stopScript: (NSString *)script { /* NSString *url = [NSString stringWithFormat:@"http://127.0.0.1:8080/control/stop_playing?path=/%@", script]; [_http doGET:url callback:^(NSData* _data) { if (_data) { NSString *res = [MyHelper data2str:_data]; [self showStatus:[NSString stringWithFormat: @"停止脚本成功,%@", res]]; } }]; NSLog(@"run autouch script error"); */ return nil; } - (NSString *) readScript: (NSString *)name { NSString *scriptPath = [self getScriptPath:name]; return [XSHelper readFileText:scriptPath]; } - (BOOL) saveScript: (NSString *)script name:(NSString *)name { NSString *scriptPath = [self getScriptPath:name]; return [XSHelper saveFile:scriptPath text:script]; } - (NSString *) getScriptPath: (NSString *) name { return [NSString stringWithFormat:@"/var/mobile/Library/AutoTouch/Scripts/%@", name]; } - (NSTimeInterval) getCurTime { // 获取当前日期和时间 NSDate *now = [NSDate date]; return [now timeIntervalSince1970]; } - (void) logServer: (NSString *) info title: (NSString *)title { } - (void) saveAdTaskLog: (AdTaskLogData *)data { data->taskId = _taskId; data->iphoneId = [[XSPhoneConfig sharedInstance] IPhoneName]; data->ipAddr = [[XSPhoneInfo sharedInstance] IPAddress]; pushAdTaskLog(data); } - (NSString*) statusStr { NSString *runStatusStr = _stop ? @"已停止": @"运行中"; return [NSString stringWithFormat:@"%@", runStatusStr]; } - (NSString*) appid { return _appId; } - (void) runTouchAdJs: (NSInteger) befor { /* JsRunner *runner = [[JsRunner alloc] init]; NSString *tmpCode = @"var beforeTouch = %@;" "var cur_app_id = \"%@\";" "var screen_w = %@;" "var screen_h = %@;"; NSString *code = [NSString stringWithFormat:tmpCode, @(befor / 1000), [self appid], @(self->device_screen_width), @(self->device_screen_height)]; NSLog(@"runTouchAdJs:%@", code); [runner runCode:code]; [runner runJS:@"/var/mobile/Library/AutoTouch/Scripts/touch_ad.js" timeout:50 completion:^(JSValue *result, BOOL timedOut) { NSLog(@"runTouchAdJs end"); }]; */ } +(instancetype)sharedInstance { static MyScriptTask* _sharedInstance = nil; static dispatch_once_t oncePredicate; dispatch_once (&oncePredicate, ^{ _sharedInstance = [[MyScriptTask alloc] init]; }); return _sharedInstance; } @end