A lightweight overlay protocol for enhancing SMS with modern messaging features
Version 1.0 | Compact Header Format | Zero Internet Required
The Qwisha Protocol is an overlay protocol that extends standard SMS with advanced messaging features including message editing, deletion, replies, and search capabilities—all without requiring an internet connection.
Header Size: ~20-30 bytes
Overhead: Minimal
Commands: 4 (s, r, e, d)
Format: ASCII-compatible
| Field | Description |
|---|---|
@ |
Protocol identifier (must be first character) |
i |
Message ID - Unique identifier for this message |
c |
Command - Action type (s, r, e, d) |
r |
Reference ID - ID of message being replied to/edited/deleted (optional) |
CONTENT |
Message content (separated by space after header) |
@i=abc123;c=s;r=null Hello World
@i=xyz789;c=r;r=abc123 Yes, I agree!
@i=edit456;c=e;r=abc123 Hello Updated World
@i=del789;c=d;r=abc123
Note: Delete commands may not include content
Message IDs are short alphanumeric strings (typically 6-12 characters) generated using a collision-resistant algorithm.
// Example ID generation (pseudocode)
function generateShortId(): String {
return base64(sha256(timestamp + random + deviceId)).substring(0, 8)
}
Send a new message
Usage: @i=<MSGID>;c=s <CONTENT>
Reference ID: Optional (null or omitted)
@i=msg001;c=s Hello, how are you?
Reply to a specific message
Usage: @i=<MSGID>;c=r;r=<REFID> <CONTENT>
Reference ID: Required (ID of message being replied to)
@i=msg002;c=r;r=msg001 I'm doing great, thanks!
Edit an existing message
Usage: @i=<MSGID>;c=e;r=<REFID> <NEW_CONTENT>
Reference ID: Required (ID of message being edited)
Only the original sender can edit messages
@i=edit001;c=e;r=msg001 Hello, how are you doing?
Delete a message from both devices
Usage: @i=<MSGID>;c=d;r=<REFID>
Reference ID: Required (ID of message being deleted)
Content: Optional (typically omitted)
Only the original sender can delete messages
@i=del001;c=d;r=msg001
fun parseQwishaMessage(body: String): QwishaMessage? {
// Check if message starts with protocol identifier
if (!body.startsWith("@")) {
return null // Regular SMS
}
// Find header end (first space)
val headerEnd = body.indexOf(' ')
if (headerEnd == -1) {
return parseHeaderOnly(body) // Delete command
}
// Extract header and content
val header = body.substring(1, headerEnd)
val content = body.substring(headerEnd + 1)
// Parse header fields
val fields = header.split(";").associate { part ->
val (key, value) = part.split("=", limit = 2)
key to value
}
return QwishaMessage(
id = fields["i"] ?: return null,
command = fields["c"] ?: return null,
refId = fields["r"]?.takeIf { it != "null" && it.isNotEmpty() },
content = content
)
}
fun buildQwishaMessage(
msgId: String,
command: String,
refId: String? = null,
content: String
): String {
val header = buildString {
append("@i=$msgId;c=$command")
if (refId != null) {
append(";r=$refId")
}
}
return "$header $content"
}
// Examples:
// buildQwishaMessage("abc123", "s", null, "Hello")
// → "@i=abc123;c=s Hello"
//
// buildQwishaMessage("xyz789", "r", "abc123", "Hi!")
// → "@i=xyz789;c=r;r=abc123 Hi!"
@Entity
data class Message(
@PrimaryKey val id: String, // Message ID from protocol
val threadId: String, // Phone number
val content: String, // Message content
val outgoing: Boolean, // Sent vs received
val replyTo: String?, // Reference ID for replies
val status: String, // sent, delivered, read, failed
val timestamp: Long, // Unix timestamp
val hasOverlayHeader: Boolean = false // Protocol message flag
)
The protocol supports both new single-letter commands (s, r, e, d) and legacy full-word commands (send, reply, edit, delete) for backward compatibility.
// Both formats are accepted:
@i=abc123;c=s Hello // New format
@i=abc123;c=send Hello // Legacy format