TaskRunner.kt 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838
  1. package com.example.modifier.service
  2. import android.content.Context
  3. import android.text.TextUtils
  4. import android.util.Base64
  5. import android.util.Log
  6. import android.view.accessibility.AccessibilityNodeInfo
  7. import com.example.modifier.baseTag
  8. import com.example.modifier.TraverseResult
  9. import com.example.modifier.constants.CMD_BACK
  10. import com.example.modifier.constants.CMD_CONVERSATION_LIST_ACTIVITY
  11. import com.example.modifier.constants.CMD_MESSAGING_APP
  12. import com.example.modifier.constants.CMD_RCS_SETTINGS_ACTIVITY
  13. import com.example.modifier.constants.PACKAGE_GMS
  14. import com.example.modifier.constants.PACKAGE_MESSAGING
  15. import com.example.modifier.data.AppPreferences
  16. import com.example.modifier.data.AppState
  17. import com.example.modifier.enums.RcsConfigureState
  18. import com.example.modifier.enums.RcsConnectionStatus
  19. import com.example.modifier.enums.RequestNumberState
  20. import com.example.modifier.extension.kill
  21. import com.example.modifier.http.api.DeviceApi
  22. import com.example.modifier.http.api.RcsNumberApi
  23. import com.example.modifier.http.api.SysConfigApi
  24. import com.example.modifier.http.ktorClient
  25. import com.example.modifier.http.request.RcsNumberRequest
  26. import com.example.modifier.http.response.DeviceResponse
  27. import com.example.modifier.http.response.RcsNumberResponse
  28. import com.example.modifier.http.response.SysConfigResponse
  29. import com.example.modifier.model.InstallApkAction
  30. import com.example.modifier.model.RunScriptAction
  31. import com.example.modifier.model.SpoofedSimInfo
  32. import com.example.modifier.model.TaskAction
  33. import com.example.modifier.model.TaskConfig
  34. import com.example.modifier.model.TaskExecutionResult
  35. import com.example.modifier.model.UpdateDeviceAction
  36. import com.example.modifier.repo.AppPreferencesRepository
  37. import com.example.modifier.repo.AppStateRepository
  38. import com.example.modifier.repo.BackupRepository
  39. import com.example.modifier.repo.GoogleMessageStateRepository
  40. import com.example.modifier.repo.SpoofedSimInfoRepository
  41. import com.example.modifier.utils.changeClashProfile
  42. import com.example.modifier.utils.clearConv
  43. import com.example.modifier.utils.genICCID
  44. import com.example.modifier.utils.genIMEI
  45. import com.example.modifier.utils.genIMSI
  46. import com.example.modifier.utils.isClashInstalled
  47. import com.example.modifier.utils.isOldVersion
  48. import com.example.modifier.utils.resetAll
  49. import com.example.modifier.utils.shellRun
  50. import com.example.modifier.utils.smsIntent
  51. import com.example.modifier.utils.spoofSmsIntent
  52. import com.example.modifier.utils.stopClash
  53. import com.example.modifier.utils.uniqueId
  54. import io.ktor.client.HttpClient
  55. import io.ktor.client.call.body
  56. import io.ktor.client.engine.okhttp.OkHttp
  57. import io.ktor.client.plugins.HttpResponseValidator
  58. import io.ktor.client.plugins.ServerResponseException
  59. import io.ktor.client.plugins.resources.get
  60. import io.ktor.client.plugins.resources.post
  61. import io.ktor.client.plugins.resources.put
  62. import io.ktor.client.plugins.timeout
  63. import io.ktor.client.request.prepareGet
  64. import io.ktor.client.request.setBody
  65. import io.ktor.http.ContentType
  66. import io.ktor.http.contentType
  67. import io.ktor.utils.io.ByteReadChannel
  68. import io.ktor.utils.io.core.isEmpty
  69. import io.ktor.utils.io.core.readBytes
  70. import kotlinx.coroutines.CoroutineScope
  71. import kotlinx.coroutines.Dispatchers
  72. import kotlinx.coroutines.delay
  73. import kotlinx.coroutines.flow.StateFlow
  74. import kotlinx.coroutines.launch
  75. import kotlinx.coroutines.withContext
  76. import kotlinx.coroutines.withTimeout
  77. import kotlinx.coroutines.withTimeoutOrNull
  78. import java.io.File
  79. import java.time.LocalDateTime
  80. import java.time.temporal.ChronoUnit
  81. import kotlin.time.Duration.Companion.days
  82. import kotlin.time.Duration.Companion.hours
  83. import kotlin.time.Duration.Companion.minutes
  84. import kotlin.time.Duration.Companion.seconds
  85. class TaskRunner(
  86. private val context: Context,
  87. private val screenInspector: ScreenInspector,
  88. private val screenController: ScreenController,
  89. private val appStateRepository: AppStateRepository,
  90. private val appPreferencesRepository: AppPreferencesRepository,
  91. private val spoofedSimInfoRepository: SpoofedSimInfoRepository,
  92. private val googleMessageStateRepository: GoogleMessageStateRepository,
  93. private val backupRepository: BackupRepository
  94. ) {
  95. private val tag = "$baseTag/TaskRunner"
  96. private var lastSend = 0L
  97. private var currentTaskId = 0
  98. private var requestMode = 1
  99. private lateinit var appState: StateFlow<AppState>
  100. private lateinit var appPreferences: StateFlow<AppPreferences>
  101. private lateinit var spoofedSimInfo: StateFlow<SpoofedSimInfo>
  102. init {
  103. CoroutineScope(Dispatchers.IO).launch {
  104. appState = appStateRepository.stateFlow()
  105. appPreferences = appPreferencesRepository.stateFlow()
  106. spoofedSimInfo = spoofedSimInfoRepository.stateFlow()
  107. }
  108. }
  109. suspend fun send(
  110. to: String,
  111. body: String,
  112. taskConfig: TaskConfig
  113. ): Boolean {
  114. Log.i(tag, "Sending SMS to $to: $body")
  115. context.startActivity(smsIntent(to, body))
  116. try {
  117. Log.i(
  118. tag,
  119. "Command executed successfully, waiting for app to open..."
  120. )
  121. delay(1000)
  122. var success = false
  123. var traverseResult = TraverseResult()
  124. withTimeoutOrNull(taskConfig.rcsWait) {
  125. repeat(999) {
  126. traverseResult = TraverseResult()
  127. screenInspector.traverseNode(traverseResult)
  128. if (traverseResult.isRcsCapable && traverseResult.sendBtn != null) {
  129. return@withTimeoutOrNull
  130. }
  131. delay(200)
  132. }
  133. }
  134. if (traverseResult.isRcsCapable && traverseResult.sendBtn != null && taskConfig.e2ee > 0) {
  135. withTimeoutOrNull(taskConfig.e2eeTimeout) {
  136. repeat(999) {
  137. traverseResult = TraverseResult()
  138. screenInspector.traverseNode(traverseResult)
  139. if (traverseResult.encrypted) {
  140. return@withTimeoutOrNull
  141. }
  142. delay(200)
  143. }
  144. }
  145. }
  146. if (traverseResult.isRcsCapable) {
  147. if (traverseResult.sendBtn == null) {
  148. Log.i(tag, "Send button not found")
  149. } else if (taskConfig.e2ee == 2 && !traverseResult.encrypted) {
  150. Log.i(tag, "E2EE not detected")
  151. } else {
  152. Log.i(tag, "Clicking send button")
  153. val dt = System.currentTimeMillis() - lastSend
  154. if (taskConfig.rcsInterval > 0 && dt < taskConfig.rcsInterval) {
  155. Log.i(tag, "Waiting for RCS interval")
  156. delay(taskConfig.rcsInterval - dt)
  157. }
  158. traverseResult.sendBtn!!.performAction(AccessibilityNodeInfo.ACTION_CLICK)
  159. lastSend = System.currentTimeMillis()
  160. success = true
  161. }
  162. } else {
  163. Log.i(tag, "RCS not detected")
  164. }
  165. appStateRepository.incrementExecutedNum(success)
  166. Log.i(
  167. tag,
  168. "executedNum: ${appState.value.executedNum}, successNum: ${appState.value.successNum}"
  169. )
  170. delay(1000)
  171. return success
  172. } catch (e: Exception) {
  173. e.printStackTrace()
  174. }
  175. return false
  176. }
  177. suspend fun runTask(
  178. taskAction: TaskAction,
  179. onSuccess: (TaskExecutionResult) -> Unit,
  180. onError: (Exception) -> Unit
  181. ) {
  182. if (appState.value.busy) {
  183. onError(Exception("device busy"))
  184. return
  185. }
  186. try {
  187. val taskConfig = taskAction.data.config
  188. currentTaskId = taskAction.data.taskId
  189. requestMode = if (taskAction.data.config.useBackup) 2 else 1
  190. if (taskAction.data.config.checkConnection) {
  191. appStateRepository.updateRuntimeFlags(checkingConnection = true)
  192. if (!checkRcsAvailability()) {
  193. onError(Exception("RCS not available"))
  194. requestNumber()
  195. appStateRepository.updateRuntimeFlags(checkingConnection = false)
  196. return
  197. }
  198. appStateRepository.updateRuntimeFlags(checkingConnection = false)
  199. }
  200. appStateRepository.updateRuntimeFlags(running = true, checkingConnection = false)
  201. val success = ArrayList<Int>()
  202. val fail = ArrayList<Int>()
  203. for (i in 0 until taskAction.data.tasks.size) {
  204. val taskItem = taskAction.data.tasks[i]
  205. try {
  206. if (send(
  207. taskItem.number,
  208. taskItem.message,
  209. taskConfig
  210. )
  211. ) {
  212. success.add(taskItem.id)
  213. } else {
  214. fail.add(taskItem.id)
  215. }
  216. } catch (e: Exception) {
  217. Log.e(tag, "runTaskError: ${e.message}", e)
  218. fail.add(taskItem.id)
  219. }
  220. }
  221. shellRun(CMD_BACK)
  222. onSuccess(TaskExecutionResult(success, fail))
  223. if (taskConfig.requestNumberInterval in 1..appState.value.successNum) {
  224. delay(3000)
  225. requestNumber()
  226. } else if (taskConfig.cleanCount in 1..appState.value.executedNum && !appPreferences.value.preventClean) {
  227. delay(3000)
  228. clearConv();
  229. shellRun(CMD_MESSAGING_APP)
  230. delay(3000)
  231. appStateRepository.resetExecutedNum()
  232. } else {
  233. delay(2000)
  234. }
  235. appStateRepository.updateRuntimeFlags(running = false)
  236. } catch (e: Exception) {
  237. Log.e(tag, "runTaskError: ${e.message}", e)
  238. onError(e)
  239. appStateRepository.updateRuntimeFlags(running = false)
  240. }
  241. }
  242. suspend fun reset() {
  243. if (isOldVersion(context)) {
  244. withTimeout(1.hours) {
  245. while (true) {
  246. delay(100)
  247. appStateRepository.updateRuntimeFlags(requestNumberState = RequestNumberState.RESET)
  248. googleMessageStateRepository.updateRcsState(RcsConfigureState.NOT_CONFIGURED)
  249. spoofedSimInfoRepository.mock()
  250. resetAll()
  251. var switchAppear = googleMessageStateRepository.waitForRcsState(
  252. arrayOf(RcsConfigureState.WAITING_FOR_TOS),
  253. 2.minutes
  254. )?.let {
  255. it == RcsConfigureState.WAITING_FOR_TOS
  256. }
  257. if (switchAppear != true) {
  258. shellRun(
  259. PACKAGE_GMS.kill(), PACKAGE_MESSAGING.kill(), "sleep 1",
  260. CMD_MESSAGING_APP
  261. )
  262. switchAppear = googleMessageStateRepository.waitForRcsState(
  263. arrayOf(RcsConfigureState.WAITING_FOR_TOS),
  264. 5.minutes
  265. )?.let {
  266. it == RcsConfigureState.WAITING_FOR_TOS
  267. }
  268. if (switchAppear != true) {
  269. Log.e(
  270. tag,
  271. "RCS not entered default on state, retrying..."
  272. )
  273. continue
  274. }
  275. }
  276. if (!screenController.toggleRcsSwitch(false)) {
  277. Log.e(tag, "RCS switch not turned off, retrying...")
  278. continue
  279. }
  280. if (!screenController.toggleRcsSwitch(true)) {
  281. Log.e(tag, "RCS switch not turned on, retrying...")
  282. continue
  283. }
  284. var resetSuccess = googleMessageStateRepository.waitForRcsState(
  285. arrayOf(
  286. RcsConfigureState.READY
  287. ), 30.seconds
  288. ).let { it == RcsConfigureState.READY }
  289. if (!resetSuccess) {
  290. screenController.toggleRcsSwitch(false)
  291. delay(1000)
  292. screenController.toggleRcsSwitch(true)
  293. resetSuccess = googleMessageStateRepository.waitForRcsState(
  294. arrayOf(
  295. RcsConfigureState.READY
  296. ), 1.minutes
  297. ).let { it == RcsConfigureState.READY }
  298. }
  299. Log.i(tag, "waitForRcsState: $resetSuccess")
  300. appStateRepository.resetRequestedNum()
  301. if (resetSuccess) {
  302. delay(3000)
  303. break
  304. }
  305. }
  306. }
  307. } else {
  308. withTimeout(1.hours) {
  309. while (true) {
  310. delay(100)
  311. appStateRepository.updateRuntimeFlags(requestNumberState = RequestNumberState.RESET)
  312. googleMessageStateRepository.updateRcsState(RcsConfigureState.NOT_CONFIGURED)
  313. spoofedSimInfoRepository.mock()
  314. resetAll()
  315. var switchAppear = googleMessageStateRepository.waitForRcsState(
  316. arrayOf(RcsConfigureState.WAITING_FOR_DEFAULT_ON),
  317. 1.minutes
  318. )?.let {
  319. it == RcsConfigureState.WAITING_FOR_DEFAULT_ON
  320. }
  321. if (switchAppear != true) {
  322. shellRun(
  323. PACKAGE_GMS.kill(), PACKAGE_MESSAGING.kill(), "sleep 1",
  324. CMD_MESSAGING_APP
  325. )
  326. switchAppear = googleMessageStateRepository.waitForRcsState(
  327. arrayOf(RcsConfigureState.WAITING_FOR_DEFAULT_ON),
  328. 2.minutes
  329. )?.let {
  330. it == RcsConfigureState.WAITING_FOR_DEFAULT_ON
  331. }
  332. if (switchAppear != true) {
  333. Log.e(
  334. tag,
  335. "RCS not entered default on state, retrying..."
  336. )
  337. continue
  338. }
  339. }
  340. val switchOn = screenController.toggleRcsSwitch(true)
  341. if (!switchOn) {
  342. Log.e(tag, "RCS switch not turned on, retrying...")
  343. continue
  344. }
  345. var resetSuccess = googleMessageStateRepository.waitForRcsState(
  346. arrayOf(
  347. RcsConfigureState.READY
  348. ), 30.seconds
  349. ).let { it == RcsConfigureState.READY }
  350. if (!resetSuccess) {
  351. screenController.toggleRcsSwitch(false)
  352. delay(1000)
  353. screenController.toggleRcsSwitch(true)
  354. resetSuccess = googleMessageStateRepository.waitForRcsState(
  355. arrayOf(
  356. RcsConfigureState.READY
  357. ), 1.minutes
  358. ).let { it == RcsConfigureState.READY }
  359. }
  360. Log.i(tag, "waitForRcsState: $resetSuccess")
  361. appStateRepository.resetRequestedNum()
  362. if (resetSuccess) {
  363. delay(3000)
  364. break
  365. }
  366. }
  367. }
  368. }
  369. }
  370. suspend fun requestNumber(
  371. reset: Boolean = false,
  372. noBackup: Boolean = false,
  373. fresh: Boolean = false
  374. ) {
  375. appStateRepository.updateRuntimeFlags(suspended = false)
  376. if (appPreferences.value.preventRequest) {
  377. return
  378. }
  379. if (appState.value.requesting) {
  380. return
  381. }
  382. appStateRepository.updateRuntimeFlags(requesting = true)
  383. clearConv()
  384. if (spoofedSimInfo.value.available) {
  385. appStateRepository.updateRuntimeFlags(requestNumberState = RequestNumberState.BACKUP)
  386. backupRepository.backup(
  387. spoofedSimInfo = spoofedSimInfo.value,
  388. type = "auto",
  389. sendCount = appState.value.executedNum,
  390. fresh = fresh
  391. )
  392. }
  393. appStateRepository.incrementRequestedNum()
  394. var requestSuccess = false
  395. var retry = 0
  396. var needRest = reset
  397. withTimeoutOrNull(2.hours) {
  398. while (true) {
  399. delay(200)
  400. needRest = needRest || retry > 2 || appState.value.requestedNum > 5
  401. try {
  402. val device =
  403. ktorClient(appPreferences.value.server).get(DeviceApi.Id(id = appPreferences.value.id))
  404. .body<DeviceResponse>()
  405. if (isClashInstalled(context)) {
  406. val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
  407. if (TextUtils.isEmpty(device.clashProfile)) {
  408. prefs.edit()
  409. .remove("clash_profile")
  410. .apply()
  411. stopClash()
  412. } else {
  413. val oldProfile = prefs.getString("clash_profile", "")
  414. if (oldProfile != device.clashProfile) {
  415. prefs.edit()
  416. .putString("clash_profile", device.clashProfile)
  417. .apply()
  418. changeClashProfile(
  419. device.pinCountry!!, Base64.encodeToString(
  420. device.clashProfile!!.toByteArray(),
  421. Base64.DEFAULT
  422. )
  423. )
  424. delay(5000)
  425. }
  426. }
  427. }
  428. if (requestMode == 2 && !noBackup) {
  429. val backup = backupRepository.findBackupForRestore(
  430. spoofedSimInfo.value.number,
  431. System.currentTimeMillis() - 2.days.inWholeMilliseconds
  432. )
  433. if (backup != null) {
  434. if (backupRepository.restore(backup)) {
  435. requestSuccess = true
  436. break
  437. } else {
  438. appStateRepository.updateRuntimeFlags(requestNumberState = RequestNumberState.BACKUP)
  439. backupRepository.backup(
  440. spoofedSimInfo = spoofedSimInfo.value,
  441. type = "auto",
  442. sendCount = 0
  443. )
  444. continue
  445. }
  446. }
  447. }
  448. if (needRest && !appPreferences.value.preventReset) {
  449. reset()
  450. retry = 0
  451. needRest = false
  452. }
  453. googleMessageStateRepository.updateRcsState(RcsConfigureState.NOT_CONFIGURED)
  454. appStateRepository.updateRuntimeFlags(requestNumberState = RequestNumberState.REQUEST)
  455. val req = RcsNumberRequest(
  456. deviceId = appPreferences.value.id,
  457. taskId = currentTaskId
  458. )
  459. if (!TextUtils.isEmpty(device.pinCountry)) {
  460. req.country = device.pinCountry
  461. }
  462. val response = ktorClient(appPreferences.value.server).put(
  463. RcsNumberApi()
  464. ) {
  465. contentType(ContentType.Application.Json)
  466. setBody(req)
  467. timeout {
  468. requestTimeoutMillis = 60 * 1000
  469. socketTimeoutMillis = 60 * 1000
  470. }
  471. }
  472. var rcsNumber = response.body<RcsNumberResponse>()
  473. Log.i(tag, "requestNumber response: $rcsNumber")
  474. appStateRepository.updateRuntimeFlags(requestNumberState = RequestNumberState.OTP_1)
  475. spoofedSimInfoRepository.updateSpoofedSimInfo(
  476. SpoofedSimInfo(
  477. number = rcsNumber.number,
  478. mcc = rcsNumber.mcc,
  479. mnc = rcsNumber.mnc,
  480. iccid = genICCID(rcsNumber.mnc, rcsNumber.areaCode),
  481. imsi = genIMSI(rcsNumber.mcc + rcsNumber.mnc),
  482. imei = genIMEI(),
  483. country = rcsNumber.country,
  484. areaCode = rcsNumber.areaCode,
  485. available = false,
  486. carrierId = rcsNumber.carrierId,
  487. carrierName = rcsNumber.carrierName,
  488. )
  489. )
  490. shellRun(CMD_MESSAGING_APP)
  491. if (rcsNumber.expiryTime.isBefore(LocalDateTime.now())) {
  492. Log.e(tag, "RCS number expired, retrying...")
  493. continue
  494. }
  495. var sendOtpTimeout = ChronoUnit.SECONDS.between(
  496. LocalDateTime.now(),
  497. rcsNumber.expiryTime
  498. ).seconds
  499. if (sendOtpTimeout < 60.seconds) {
  500. Log.e(tag, "OTP timeout too short, retrying...")
  501. continue
  502. }
  503. if (sendOtpTimeout > 2.minutes) {
  504. sendOtpTimeout = 2.minutes
  505. }
  506. if (googleMessageStateRepository.waitForRcsState(
  507. arrayOf(RcsConfigureState.WAITING_FOR_OTP),
  508. sendOtpTimeout
  509. ) != RcsConfigureState.WAITING_FOR_OTP
  510. ) {
  511. if (!screenController.toggleRcsSwitch(true)) {
  512. needRest = true
  513. }
  514. if (RcsConfigureState.REPLAY_REQUEST == googleMessageStateRepository.rcsConfigureState.value) {
  515. Log.e(tag, "REPLAY_REQUEST detected, may reset after 3 retry ($retry)")
  516. retry++
  517. }
  518. Log.e(tag, "RCS not entered waiting for OTP state, retrying...")
  519. continue
  520. }
  521. launch {
  522. try {
  523. ktorClient(appPreferences.value.server).post(
  524. RcsNumberApi.Id.OtpState(
  525. RcsNumberApi.Id(
  526. RcsNumberApi(),
  527. rcsNumber.id
  528. )
  529. )
  530. )
  531. } catch (e: Exception) {
  532. Log.e(tag, "Send OtpState Error: ${e.message}", e)
  533. }
  534. }
  535. if (rcsNumber.expiryTime.isBefore(LocalDateTime.now())) {
  536. Log.e(tag, "RCS number expired, retrying...")
  537. continue
  538. }
  539. appStateRepository.updateRuntimeFlags(requestNumberState = RequestNumberState.OTP_2)
  540. withTimeoutOrNull(60.seconds) {
  541. while (true) {
  542. try {
  543. rcsNumber =
  544. ktorClient(appPreferences.value.server).get(RcsNumberApi.Id(id = rcsNumber.id))
  545. .body<RcsNumberResponse>()
  546. Log.i(tag, "wait for otp response: $rcsNumber")
  547. if (rcsNumber.status == RcsNumberResponse.STATUS_SUCCESS || rcsNumber.status == RcsNumberResponse.STATUS_EXPIRED) {
  548. break
  549. }
  550. } catch (exception: Exception) {
  551. Log.e(tag, "wait for otp Error: ${exception.stackTrace}")
  552. }
  553. delay(2.seconds)
  554. }
  555. }
  556. if (rcsNumber.status != RcsNumberResponse.STATUS_SUCCESS) {
  557. Log.e(tag, "OTP not received, retrying...")
  558. continue
  559. }
  560. val match =
  561. Regex("Your Messenger verification code is G-(\\d{6})")
  562. .find(rcsNumber.message!!)
  563. if (match != null) {
  564. appStateRepository.updateRuntimeFlags(requestNumberState = RequestNumberState.CONFIG)
  565. val otp = match.groupValues[1]
  566. Log.i(tag, "OTP: $otp")
  567. val sender = "3538"
  568. val msg = "Your Messenger verification code is G-$otp"
  569. val configured = run configuring@{
  570. repeat(2) {
  571. spoofSmsIntent(sender, msg)
  572. val state =
  573. googleMessageStateRepository.waitForRcsState(
  574. arrayOf(
  575. RcsConfigureState.CONFIGURED,
  576. RcsConfigureState.RETRY
  577. ), 60.seconds
  578. )
  579. when (state) {
  580. RcsConfigureState.CONFIGURED -> {
  581. return@configuring true
  582. }
  583. RcsConfigureState.RETRY -> {
  584. googleMessageStateRepository.waitForRcsState(
  585. arrayOf(RcsConfigureState.WAITING_FOR_OTP),
  586. 60.seconds
  587. )
  588. }
  589. else -> {
  590. Log.e(tag, "verifyOtp fail, retrying...")
  591. }
  592. }
  593. }
  594. false
  595. }
  596. if (!configured) {
  597. Log.e(tag, "RCS not configured, retrying...")
  598. continue
  599. } else {
  600. launch {
  601. try {
  602. ktorClient(appPreferences.value.server).post(
  603. RcsNumberApi.Id.Configured(
  604. RcsNumberApi.Id(
  605. RcsNumberApi(),
  606. rcsNumber.id
  607. )
  608. )
  609. )
  610. } catch (e: Exception) {
  611. Log.e(
  612. tag,
  613. "Send ConfiguredState Error: ${e.message}",
  614. e
  615. )
  616. }
  617. }
  618. requestSuccess = true
  619. break
  620. }
  621. }
  622. } catch (e: Exception) {
  623. Log.e(tag, "requestNumberError: ${e.message}", e)
  624. }
  625. }
  626. }
  627. if (requestSuccess) {
  628. spoofedSimInfoRepository.updateSpoofedSimInfo(
  629. spoofedSimInfo = spoofedSimInfo.value.copy(
  630. available = true
  631. ),
  632. suspend = false
  633. )
  634. appStateRepository.resetSuccessNum()
  635. appStateRepository.resetExecutedNum()
  636. Log.i(tag, "requestNumber success")
  637. delay(5000)
  638. shellRun(PACKAGE_MESSAGING.kill(), "sleep 1", CMD_MESSAGING_APP)
  639. delay(2000)
  640. } else {
  641. Log.e(tag, "requestNumber failed")
  642. appStateRepository.updateSend(false)
  643. }
  644. appStateRepository.updateRuntimeFlags(
  645. requesting = false,
  646. requestNumberState = RequestNumberState.IDLE,
  647. suspended = !requestSuccess
  648. )
  649. }
  650. private suspend fun checkRcsConnectivity(): Boolean = run checkRcsConnection@{
  651. repeat(3) {
  652. Log.i(tag, "Checking RCS status...")
  653. shellRun(
  654. CMD_CONVERSATION_LIST_ACTIVITY,
  655. CMD_RCS_SETTINGS_ACTIVITY,
  656. "sleep 1",
  657. )
  658. val res = TraverseResult()
  659. screenInspector.traverseNode(res)
  660. if (res.rcsConnectionStatus == RcsConnectionStatus.CONNECTED) {
  661. Log.i(tag, "RCS is connected")
  662. shellRun(CMD_BACK)
  663. return@checkRcsConnection true
  664. } else {
  665. Log.i(tag, "RCS not connected, retrying...")
  666. }
  667. shellRun(CMD_BACK, "sleep ${it * 2}")
  668. }
  669. false
  670. }
  671. suspend fun checkRcsAvailability(): Boolean {
  672. val availability = run checkAvailability@{
  673. val rcsConnected = checkRcsConnectivity()
  674. if (!rcsConnected) {
  675. return@checkAvailability false
  676. }
  677. val checkRcsAvailabilityNumbers = mutableListOf<String>()
  678. try {
  679. val config = ktorClient(appPreferences.value.server).get(
  680. SysConfigApi.Id(
  681. SysConfigApi(),
  682. "check_availability_numbers"
  683. )
  684. )
  685. .body<SysConfigResponse>()
  686. Log.i(tag, "sysConfig response: $config")
  687. checkRcsAvailabilityNumbers.addAll(
  688. config.value.split(",").map { it.trim() })
  689. } catch (exception: Exception) {
  690. Log.e(
  691. tag,
  692. "sysConfig Error: ${exception.message}",
  693. exception
  694. )
  695. }
  696. if (checkRcsAvailabilityNumbers.isEmpty()) {
  697. Log.e(tag, "checkRcsAvailabilityNumbers is empty")
  698. return@checkAvailability true
  699. }
  700. checkRcsAvailabilityNumbers.forEach {
  701. context.startActivity(smsIntent(it, ""))
  702. val s = withTimeoutOrNull(5.seconds) {
  703. while (true) {
  704. val traverseResult = TraverseResult()
  705. screenInspector.traverseNode(traverseResult)
  706. if (traverseResult.isRcsCapable) {
  707. return@withTimeoutOrNull true
  708. } else {
  709. Log.i(
  710. tag,
  711. "checkRcsAvailability: RCS not detected"
  712. )
  713. }
  714. delay(200)
  715. }
  716. }
  717. if (s == true) {
  718. Log.i(tag, "checkRcsAvailability: $it success")
  719. delay(1000)
  720. return@checkAvailability true
  721. }
  722. }
  723. false
  724. }
  725. return availability
  726. }
  727. suspend fun installApk(
  728. installApkAction: InstallApkAction,
  729. onSuccess: () -> Unit,
  730. onError: (Exception) -> Unit
  731. ) {
  732. try {
  733. val file = withContext(Dispatchers.IO) {
  734. File.createTempFile("files", ".apk")
  735. }
  736. HttpClient(OkHttp) {
  737. HttpResponseValidator {
  738. validateResponse { response ->
  739. if (response.status.value !in 200..299) {
  740. throw ServerResponseException(
  741. response,
  742. "Error " + response.status.value.toString()
  743. )
  744. }
  745. }
  746. }
  747. }.prepareGet(installApkAction.data.apkUrl)
  748. .execute { httpResponse ->
  749. val channel: ByteReadChannel = httpResponse.body()
  750. while (!channel.isClosedForRead) {
  751. val packet = channel.readRemaining(DEFAULT_BUFFER_SIZE.toLong())
  752. while (!packet.isEmpty) {
  753. val bytes = packet.readBytes()
  754. file.appendBytes(bytes)
  755. }
  756. }
  757. }
  758. Log.i(tag, "Apk file saved to ${file.path}")
  759. shellRun("pm install -d -r ${file.path}")
  760. onSuccess()
  761. file.delete()
  762. } catch (e: Exception) {
  763. Log.e(tag, "Failed to install apk", e)
  764. onError(e)
  765. }
  766. }
  767. suspend fun runScript(
  768. installApkAction: RunScriptAction,
  769. onSuccess: (String, String) -> Unit,
  770. onError: (Exception) -> Unit
  771. ) {
  772. try {
  773. val (out, err) = shellRun(*installApkAction.data.script.split("\n").toTypedArray())
  774. onSuccess(out, err)
  775. } catch (e: Exception) {
  776. Log.e(tag, "Failed to run script", e)
  777. onError(e)
  778. }
  779. }
  780. suspend fun updateDevice(
  781. updateDeviceAction: UpdateDeviceAction,
  782. onSuccess: () -> Unit,
  783. onError: (Exception) -> Unit
  784. ) {
  785. try {
  786. if (updateDeviceAction.data.id != null) {
  787. appPreferencesRepository.updateId(updateDeviceAction.data.id)
  788. }
  789. if (updateDeviceAction.data.name != null) {
  790. appPreferencesRepository.updateName(updateDeviceAction.data.name)
  791. }
  792. onSuccess()
  793. } catch (e: Exception) {
  794. Log.e(tag, "Failed to update device", e)
  795. onError(e)
  796. }
  797. }
  798. }