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 package sh.sar.textpipe.data.model
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable 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 @Serializable
data class SendSmsRequest( data class SendSmsRequest(
val to: String, @Serializable(with = StringOrListSerializer::class)
val to: List<String>,
val text: String val text: String
) )
@@ -27,7 +27,7 @@ fun Route.smsRoutes(smsRepository: SmsRepository) {
} }
// Validate request // Validate request
if (request.to.isBlank()) { if (request.to.isEmpty()) {
call.respond(HttpStatusCode.BadRequest, ErrorResponse("'to' field is required")) call.respond(HttpStatusCode.BadRequest, ErrorResponse("'to' field is required"))
return@post return@post
} }
@@ -36,13 +36,19 @@ fun Route.smsRoutes(smsRepository: SmsRepository) {
return@post return@post
} }
val response = smsRepository.sendSms(request.to, request.text, apiKey) val responses = request.to.mapNotNull { number ->
if (response == null) { smsRepository.sendSms(number, request.text, apiKey)
call.respond(HttpStatusCode.InternalServerError, ErrorResponse("Failed to send SMS")) }
if (responses.isEmpty()) {
call.respond(
HttpStatusCode.InternalServerError,
ErrorResponse("Failed to send SMS")
)
return@post return@post
} }
call.respond(HttpStatusCode.OK, response) call.respond(HttpStatusCode.OK, responses)
} }
get("/api/sms/messages") { get("/api/sms/messages") {