From b7e213ff32f24aef103371c74180b760584715b6 Mon Sep 17 00:00:00 2001 From: "James (ClawdBot)" Date: Sun, 8 Feb 2026 02:31:11 -0500 Subject: [PATCH] feat: add sms.delete and sms.delete_thread commands --- .../inou/clawdnode/gateway/DirectGateway.kt | 22 ++++++++++++++ .../com/inou/clawdnode/sms/SmsProvider.kt | 30 +++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/app/src/main/java/com/inou/clawdnode/gateway/DirectGateway.kt b/app/src/main/java/com/inou/clawdnode/gateway/DirectGateway.kt index 7593ee2..533017d 100644 --- a/app/src/main/java/com/inou/clawdnode/gateway/DirectGateway.kt +++ b/app/src/main/java/com/inou/clawdnode/gateway/DirectGateway.kt @@ -276,6 +276,28 @@ object DirectGateway { ClawdNodeApp.instance.auditLog.log("COMMAND_EXECUTED", "sms.threads") } + "sms.delete" -> { + val id = params.optLong("id", -1) + if (id == -1L) { + sendResponse(commandId, false, "Missing 'id'") + } else { + val deleted = SmsProvider.deleteMessage(id) + sendDataResponse(commandId, JSONObject().put("deleted", deleted).put("id", id)) + } + ClawdNodeApp.instance.auditLog.log("COMMAND_EXECUTED", "sms.delete id=$id") + } + + "sms.delete_thread" -> { + val threadId = params.optLong("threadId", -1) + if (threadId == -1L) { + sendResponse(commandId, false, "Missing 'threadId'") + } else { + val rows = SmsProvider.deleteThread(threadId) + sendDataResponse(commandId, JSONObject().put("deleted", rows).put("threadId", threadId)) + } + ClawdNodeApp.instance.auditLog.log("COMMAND_EXECUTED", "sms.delete_thread threadId=$threadId") + } + "sms.send" -> { val to = params.optString("to") val body = params.optString("body") diff --git a/app/src/main/java/com/inou/clawdnode/sms/SmsProvider.kt b/app/src/main/java/com/inou/clawdnode/sms/SmsProvider.kt index 849d3fd..88cc0a9 100644 --- a/app/src/main/java/com/inou/clawdnode/sms/SmsProvider.kt +++ b/app/src/main/java/com/inou/clawdnode/sms/SmsProvider.kt @@ -205,6 +205,36 @@ object SmsProvider { return threads } + fun deleteMessage(id: Long): Boolean { + return try { + val rows = contentResolver.delete(Uri.parse("content://sms/$id"), null, null) + Log.i(TAG, "deleteMessage id=$id rows=$rows") + DebugClient.log("SMS deleted", mapOf("id" to id, "rows" to rows)) + rows > 0 + } catch (e: Exception) { + Log.e(TAG, "deleteMessage failed for id=$id", e) + DebugClient.error("SmsProvider.deleteMessage failed", e) + false + } + } + + fun deleteThread(threadId: Long): Int { + return try { + val rows = contentResolver.delete( + Uri.parse("content://sms/"), + "thread_id = ?", + arrayOf(threadId.toString()) + ) + Log.i(TAG, "deleteThread threadId=$threadId rows=$rows") + DebugClient.log("SMS thread deleted", mapOf("threadId" to threadId, "rows" to rows)) + rows + } catch (e: Exception) { + Log.e(TAG, "deleteThread failed for threadId=$threadId", e) + DebugClient.error("SmsProvider.deleteThread failed", e) + 0 + } + } + fun sendSms(to: String, body: String) { try { val smsManager = SmsManager.getDefault()