ios-hooks/AppRunMan/server/IPhoneHertbeat.m
2025-10-14 17:41:08 +08:00

352 lines
10 KiB
Objective-C
Executable File

//
// IPhoneHertbeat.m
// NotNil
//
// Created by mac on 2024/6/13.
//
#import "IPhoneHertbeat.h"
#import <Foundation/Foundation.h>
#import "XSPhoneConfig.h"
#import "XSPhoneInfo.h"
#import "XSHelper.h"
#import "XSHackIos.h"
#import "XSHttpHelper.h"
#import "XSIosTouch.h"
#import "MyAdServer.h"
#import "MyAdTask2.h"
#import "MyEventBus.h"
@interface IPhoneHertbeat ()
{
@private
XSPhoneConfig *iphone;
NSTimeInterval _lastCheckTaskTime;
XSHttpHelper *http;
NSDate *lastStop;
dispatch_source_t _timer; // 替换 NSTimer
dispatch_queue_t _workQueue;
}
@property (nonatomic, assign) NSTimeInterval lastTouchTime;
@property (nonatomic, assign) BOOL isProcessingTouch;
@property (nonatomic, strong) dispatch_queue_t touchQueue;
@property (nonatomic, assign) NSTimeInterval lastCheckTaskTime;
@property (nonatomic, strong) dispatch_source_t touchTimer;
@end
@implementation IPhoneHertbeat
+(instancetype)sharedInstance
{
static IPhoneHertbeat* _sharedInstance = nil;
static dispatch_once_t oncePredicate;
dispatch_once (&oncePredicate, ^{
_sharedInstance = [[IPhoneHertbeat alloc] init];
});
return _sharedInstance;
}
-(instancetype)init {
if (self = [super init]) {
self->iphone = [XSPhoneConfig sharedInstance];
// self.apps = [self getApps];
self->_lastCheckTaskTime = [XSHelper getCurTime];
self->http = [[XSHttpHelper alloc] init];
self.status = @"已停止";
self->lastStop = [NSDate date];
return self;
}
return nil;
}
- (void)stop {
if (_timer) {
dispatch_source_cancel(_timer);
_timer = nil;
}
}
- (void)dealloc {
[self stop];
[self cancelCurrentTask];
}
- (void) start {
if (_timer) return;
_workQueue = dispatch_queue_create("com.iphone.heartbeat.queue", DISPATCH_QUEUE_SERIAL);
_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, _workQueue);
dispatch_source_set_timer(_timer, dispatch_time(DISPATCH_TIME_NOW, 0), 5 * NSEC_PER_SEC, 0.1 * NSEC_PER_SEC);
__weak typeof(self) weakSelf = self;
dispatch_source_set_event_handler(_timer, ^{
@autoreleasepool {
[weakSelf ping];
}
});
dispatch_resume(_timer);
}
- (void) checkxxx {
NSDate *last = [[XSPhoneConfig sharedInstance] GetLastOverTime];
NSDate *date2 = [NSDate date];
// 获取相差的秒数
NSTimeInterval seconds = [date2 timeIntervalSinceDate:last];
if (seconds > 5 * 24 * 60 * 60) {
NSDate *currentDate = [NSDate date];
NSDate *fiveDaysLater = [currentDate dateByAddingTimeInterval:-4 * 24 * 60 * 60 - 3600];
[[XSPhoneConfig sharedInstance] SetLastOverTime:fiveDaysLater];
// XSReboot();
}
}
- (void) ping {
@try {
if (!self->iphone || !self->http) return;
NSString *server = self->iphone.ServerURL;
if (!server.length) {
NSLog(@"Invalid server URL");
return;
}
NSString *url = [NSString stringWithFormat:@"%@/ios/top_selection/heartbeat", server];
/**
{
"deviceId": "string",
"ip": "string",
"appId": "string",
"apps": [
"string"
],
"name": "string",
"message": "string",
"status": "string",
"life": true
}
*/
//self.status = [[XSConsole sharedInstance] status];
//self.appId = [[XSJsGlobalContext sharedInstance] get:@"ad_appid"];
@synchronized (self) {
if ([self.status isEqualToString:@"运行中"]) {
self->lastStop = [NSDate date];
}
// 检查自动重启
NSDate *curRunTime = [NSDate date];
NSTimeInterval elapsed = [curRunTime timeIntervalSinceDate:self->lastStop];
if (elapsed > 60 * 10 && !myadTaskManualStop) {
self->lastStop = [NSDate date];
dispatch_async(dispatch_get_main_queue(), ^{
[[MyAdTask2Mangger sharedInstance] start];
});
}
}
self.name = self->iphone.IPhoneName;
self.deviceId = self->iphone.DeviceId;
self.ip = [[XSPhoneInfo sharedInstance] IPAddress];
self.remoteIp = [[XSPhoneInfo sharedInstance] remoteIp];
self.diskSize = [[XSPhoneInfo sharedInstance] IPhoneStatus];
self.message = @"250916max";
// 构建请求数据
NSDictionary *heartbeatData = [self constructHeartbeatData];
if (!heartbeatData) {
NSLog(@"Failed to construct heartbeat data");
return;
}
/*
pushInfo(1,
[XSHelper dic2Json:dic],
^(NSString *data) {
if (data) {
NSLog(@"XS- log: %@", data);
[[XSPhoneConfig sharedInstance] SetLastOverTime: [NSDate date]];
} else {
NSLog(@"XS- heart beat error");
//[self checkxxx];
}
},^(NSError *err) {
NSLog(@"XS- %@", err);
//[self checkxxx];
});
*/
// 发送请求
[self sendHeartbeat:heartbeatData toURL:url];
// 检查任务
// [self checkAndPerformTasks];
} @catch (NSException *exception) {
NSLog(@"XS- app run man ping error: %@", exception);
} @finally {
NSLog(@"XS- ping end");
}
}
- (void)sendHeartbeat:(NSDictionary *)data toURL:(NSString *)url {
[self->http doPOST:url json:[XSHelper dic2Json:data] withCallback:^(NSData *responseData) {
if (responseData) {
NSString *json = [XSHelper data2str:responseData];
NSLog(@"Heartbeat success: %@", json);
NSDictionary *dic = [XSHelper json2Dictionary:json];
NSDictionary *json_data = dic[@"data"];
[[MyEventBus sharedInstance] postEvent:@"UpdateInfo" withObject:json_data];
} else {
NSLog(@"Empty heartbeat response");
}
} withError:^(NSError *err) {
NSLog(@"Heartbeat error: %@", err);
}];
}
- (NSDictionary *)constructHeartbeatData {
@try {
return @{
@"deviceId": self.deviceId ?: @"",
@"ip": self.ip ?: @"",
@"appId": self.appId ?: @"",
@"apps": self.apps ?: @[],
@"name": self.name ?: @"",
@"message": self.message ?: @"",
@"status": self.status ?: @"",
@"disk": self.diskSize ?: @"",
@"remoteIp": self.remoteIp ?: @""
};
} @catch (NSException *exception) {
NSLog(@"Error constructing heartbeat data: %@", exception);
return nil;
}
}
- (void)checkAndPerformTasks {
NSTimeInterval currentTime = [XSHelper getCurTime];
// 检查任务执行间隔
if (currentTime - self.lastCheckTaskTime <= 240) {
return;
}
// 更新最后检查时间
self.lastCheckTaskTime = currentTime;
__weak typeof(self) weakSelf = self;
// 使用专门的触摸队列
dispatch_async(self.touchQueue, ^{
@try {
[weakSelf safePerformTouchEvents];
} @catch (NSException *exception) {
NSLog(@"Error performing touch events: %@", exception);
}
});
}
- (void)safePerformTouchEvents {
// 检查触摸状态
if (self.isProcessingTouch) {
NSLog(@"Already processing touch events");
return;
}
// 获取前台应用
NSString *appId = XSFrontMostAppId();
if (!appId.length) {
NSLog(@"No foreground app detected");
return;
}
// 获取触摸实例
XSIosTouch *touch = [XSIosTouch sharedInstance];
if (!touch) {
NSLog(@"Touch instance not available");
return;
}
// 标记开始处理触摸
self.isProcessingTouch = YES;
__weak typeof(self) weakSelf = self;
// 执行第一次点击
dispatch_async(dispatch_get_main_queue(), ^{
@try {
// 检查最小触摸间隔
NSTimeInterval currentTime = [XSHelper getCurTime];
if (currentTime - weakSelf.lastTouchTime < 0.05) { // 50ms最小间隔
return;
}
weakSelf.lastTouchTime = currentTime;
[touch Tap:1 x:244 y:766];
// 延迟执行第二次点击
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)),
dispatch_get_main_queue(), ^{
@try {
// 再次检查前台应用
NSString *currentAppId = XSFrontMostAppId();
if (!currentAppId.length) {
NSLog(@"App not in foreground for second tap");
return;
}
// 检查最小触摸间隔
NSTimeInterval newCurrentTime = [XSHelper getCurTime];
if (newCurrentTime - weakSelf.lastTouchTime < 0.05) {
return;
}
weakSelf.lastTouchTime = newCurrentTime;
[touch Tap:1 x:382 y:766];
} @catch (NSException *exception) {
NSLog(@"Error in second tap: %@", exception);
} @finally {
// 确保处理状态被重置
weakSelf.isProcessingTouch = NO;
}
});
} @catch (NSException *exception) {
NSLog(@"Error in first tap: %@", exception);
weakSelf.isProcessingTouch = NO;
}
});
}
// 添加清理方法
- (void)cleanup {
self.isProcessingTouch = NO;
self.lastTouchTime = 0;
}
// 添加取消当前任务的方法
- (void)cancelCurrentTask {
if (self.touchTimer) {
dispatch_source_cancel(self.touchTimer);
self.touchTimer = nil;
}
[self cleanup];
}
// 添加重置方法
- (void)reset {
[self cancelCurrentTask];
[self cleanup];
}
@end