multi-recipient-sms

This commit is contained in:
2026-08-27 20:08:02 +05:00
parent 6e42941b0f
commit c2a0846949
2 changed files with 63 additions and 11 deletions
@@ -1,10 +1,56 @@
package sh.sar.textpipe.data.model
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.SerializationException
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonDecoder
import kotlinx.serialization.json.JsonEncoder
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.jsonPrimitive
object StringOrListSerializer : KSerializer<List<String>> {
override val descriptor: SerialDescriptor =
PrimitiveSerialDescriptor("StringOrList", PrimitiveKind.STRING)
override fun deserialize(decoder: Decoder): List<String> {
val jsonDecoder = decoder as? JsonDecoder
?: throw SerializationException("This serializer only supports JSON")
return when (val element = jsonDecoder.decodeJsonElement()) {
is JsonPrimitive -> listOf(element.content)
is JsonArray -> element.map { it.jsonPrimitive.content }
else -> throw SerializationException(
"'to' must be a phone number string or an array of phone numbers"
)
}
}
override fun serialize(
encoder: Encoder,
value: List<String>
) {
val jsonEncoder = encoder as? JsonEncoder
?: throw SerializationException("This serializer only supports JSON")
jsonEncoder.encodeJsonElement(
JsonArray(value.map { JsonPrimitive(it) })
)
}
}
@Serializable
data class SendSmsRequest(
val to: String,
@Serializable(with = StringOrListSerializer::class)
val to: List<String>,
val text: String
)
@@ -27,22 +27,28 @@ fun Route.smsRoutes(smsRepository: SmsRepository) {
}
// Validate request
if (request.to.isBlank()) {
call.respond(HttpStatusCode.BadRequest, ErrorResponse("'to' field is required"))
return@post
}
if (request.to.isEmpty()) {
call.respond(HttpStatusCode.BadRequest, ErrorResponse("'to' field is required"))
return@post
}
if (request.text.isBlank()) {
call.respond(HttpStatusCode.BadRequest, ErrorResponse("'text' field is required"))
return@post
}
val response = smsRepository.sendSms(request.to, request.text, apiKey)
if (response == null) {
call.respond(HttpStatusCode.InternalServerError, ErrorResponse("Failed to send SMS"))
return@post
}
val responses = request.to.mapNotNull { number ->
smsRepository.sendSms(number, request.text, apiKey)
}
call.respond(HttpStatusCode.OK, response)
if (responses.isEmpty()) {
call.respond(
HttpStatusCode.InternalServerError,
ErrorResponse("Failed to send SMS")
)
return@post
}
call.respond(HttpStatusCode.OK, responses)
}
get("/api/sms/messages") {