package com.smsgateway import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import java.net.URLEncoder import org.json.JSONArray import org.json.JSONObject import android.content.Context import com.smsgateway.SmsGatewayConfig import android.util.Log import okhttp3.* import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.RequestBody.Companion.toRequestBody import java.nio.charset.StandardCharsets import com.smsgateway.SmsGatewayConstants.TAG object SmsGatewayTelegramHelper { fun send(config: SmsGatewayConfig, payload: JSONObject) { val chatIds: JSONArray = config.telegramChatIds val token: String = config.telegramToken ?: "" val parseMode: String = config.telegramParseMode if (chatIds.length() > 0 && token.length > 0) { val msgBody = payload.getString("msg") val sender = payload.getString("sender") val timestamp = payload.getString("timestamp") val phoneNumber = payload.getString("phoneNumber") val message = createMsgTemplate(msgBody, sender, phoneNumber, timestamp) Log.d(TAG, "Sending message: $message") CoroutineScope(Dispatchers.IO).launch { val client = okhttp3.OkHttpClient() for (i in 0 until chatIds.length()) { try { val chatId = chatIds.getString(i) ?: "" if(chatId.toString().length == 0) { continue // skip empty chat Ids } // val url = "https://api.telegram.org/bot${token}/sendMessage" + // "?chat_id=$chatId&text=$message&parse_mode=$parseMode" // val request = okhttp3.Request.Builder().url(url).get().build() // val response = client.newCall(request).execute() val url = "https://api.telegram.org/bot${token}/sendMessage" val jsonBody = JSONObject() jsonBody.put("chat_id", chatId) jsonBody.put("text", message) // Already escaped jsonBody.put("parse_mode", parseMode) val mediaType = "application/json; charset=utf-8".toMediaTypeOrNull() val body = jsonBody.toString().toRequestBody(mediaType) val request = okhttp3.Request.Builder() .url(url) .post(body) .build() val response = client.newCall(request).execute() val responseBody = response.body?.string() ?: "null" Log.i(TAG, "Sent to Telegram chat $chatId: ${response.code} -> $responseBody") } catch (e: Exception) { Log.e(TAG, "Telegram Error: ${e.localizedMessage}") } } } } } private fun escapeMarkdownV2(text: String): String { val regex = Regex("""([_*\[\]()~`>#+\-=|{}.!])""") return text.replace(regex) { "\\${it.value}" } } private fun escapeHtml(text: String): String { return text .replace("&", "&") .replace("<", "<") .replace(">", ">") .replace("\"", """) } fun encodeURIComponent(input: String): String { val result = StringBuilder() for (c in input) { if (isSafeChar(c)) { result.append(c) } else { val bytes = c.toString().toByteArray(StandardCharsets.UTF_8) for (b in bytes) { result.append('%') result.append(String.format("%02X", b.toInt() and 0xFF)) } } } return result.toString() } private fun isSafeChar(c: Char): Boolean { return when (c) { in 'a'..'z', in 'A'..'Z', in '0'..'9' -> true '-', '_', '.', '!', '~', '*', '\'', '(', ')' -> true else -> false } } private fun createMsgTemplate(msgBody: String, sender: String, phoneNumber: String, timestamp: String): String { val escapedMsg = escapeHtml(msgBody) val escapedSender = escapeHtml(sender) val escapedPhone = escapeHtml(phoneNumber) val escapedTime = escapeHtml(timestamp) return """ Date: $escapedTime From: $escapedSender TO: $escapedPhone Message:
$escapedMsg
""".trimIndent() } }