add more sms fortmat support

This commit is contained in:
Ben Zhe 2025-07-03 08:07:25 +00:00
parent a0276a6c9f
commit e2f8258578
2 changed files with 51 additions and 26 deletions

View File

@ -5,22 +5,45 @@ import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.util.Log
import android.widget.Toast
import java.util.regex.Pattern
import org.fcitx.fcitx5.android.common.FcitxPluginService
import org.fcitx.fcitx5.android.common.ipc.FcitxRemoteConnection
import org.fcitx.fcitx5.android.common.ipc.bindFcitxRemoteService
fun extractOtp(message: String?): String? {
if (message == null) return null
val pattern = Pattern.compile(
"(?<!(\\d|\\d.|\\d\\s+|\\/))(\\d{4,8}|\\d{3}-\\d{3})(?!(\\d|.\\d|\\s+\\d|\\/|\\-))"
)
val matcher = pattern.matcher(message)
return if (matcher.find()) matcher.group(2).replace("-", "") else null
if (message == null) return null
val pattern =
Pattern.compile("""(?<!(\d|\d.|\d\s{1,4}|/))(\d{4,8}|\d{3}-\d{3})(?!(\d|\.\d|\s+\d|/|-))""")
val matcher = pattern.matcher(message)
val results = mutableListOf<String>()
val codePositions = mutableListOf<Pair<String, Int>>()
while (matcher.find()) {
val code = matcher.group(2).replace("-", "")
results.add(code)
codePositions.add(Pair(code, matcher.start(2)))
}
if (results.size > 1) {
val keywords = listOf("code", "otp", "", "", "コード", "코드", "код", "kodo")
val keywordPositions = keywords.flatMap { keyword ->
Regex(Regex.escape(keyword), RegexOption.IGNORE_CASE)
.findAll(message)
.map { it.range.first }
.toList()
}
if (keywordPositions.isNotEmpty()) {
// find the nearest one
val nearest = codePositions.minByOrNull { (code, pos) ->
keywordPositions.minOf { kp -> kotlin.math.abs(pos - kp) }
}
return nearest?.first
} else {
return results.firstOrNull()
}
}
else {
return results.firstOrNull()
}
}
class MainService : FcitxPluginService() {
@ -30,7 +53,7 @@ class MainService : FcitxPluginService() {
override fun start() {
registerSmsReceiver(this)
connection =
bindFcitxRemoteService(BuildConfig.MAIN_APPLICATION_ID) { log("Bind to fcitx remote") }
bindFcitxRemoteService(BuildConfig.MAIN_APPLICATION_ID) { log("Bind to fcitx remote") }
}
override fun stop() {
@ -47,19 +70,19 @@ class MainService : FcitxPluginService() {
private fun registerSmsReceiver(context: Context) {
if (receiver != null) return
receiver =
object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val messages = android.provider.Telephony.Sms.Intents.getMessagesFromIntent(intent)
for (sms in messages) {
val message = sms.messageBody
val code = extractOtp(message)
if (code != null) {
// showToast(context, "OTP Detected: $code")
tryInputOtp(context, code)
}
}
}
object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val messages = android.provider.Telephony.Sms.Intents.getMessagesFromIntent(intent)
for (sms in messages) {
val message = sms.messageBody
val code = extractOtp(message)
if (code != null) {
log("OTP Detected: $code")
tryInputOtp(context, code)
}
}
}
}
val filter = IntentFilter("android.provider.Telephony.SMS_RECEIVED")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.registerReceiver(receiver, filter, Context.RECEIVER_EXPORTED)
@ -75,10 +98,6 @@ class MainService : FcitxPluginService() {
}
}
private fun showToast(context: Context, text: String) {
Handler(Looper.getMainLooper()).post { Toast.makeText(context, text, Toast.LENGTH_LONG).show() }
}
private fun tryInputOtp(context: Context, code: String) {
try {
connection.remoteService?.updateOtp(code)

View File

@ -42,8 +42,14 @@ class SmSFormatTest {
assertEquals("050475", extractOtp("Ваш код перевірки Poe: 050475. Не повідомляйте цей код іншим."))
assertEquals("429309", extractOtp("[抖音] 429309 is your verification code, valid for 5 minutes."))
assertEquals("8650", extractOtp("<#> 8650 is your Venmo phone verification code."))
assertEquals("060973", extractOtp("12306用户注册或既有用户手机核验专用验证码060973。如非本人直接访问12306请停止操作切勿将验证码提供给第三方。【铁路客服】"))
assertEquals("505513", extractOtp("您在付款为防诈骗千万不要告诉他人验证码505513商户为汇付天下金额80元。如有疑问请停止操作。短信编号245747【工商银行】"))
assertEquals("370000", extractOtp("任何向你索要验证码的都是骗子千万别给您正在向www尾号4832转账验证码370000100元。"))
assertEquals("927711", extractOtp("TAN to confirm mandate for Segpay UK Test Please enter TAN 927711 to set up your mandate 10751532bd3573241262f56b4e76a003 securely."))
assertEquals("121093", extractOtp("Twój kod do Tindera to 121093 Nie udostępniaj @tinder.com #121093"))
assertNull(extractOtp("OKXUSDTsuccessfully withdrawn: 132,619.89 【okxcash.com】Account: DTm888 Key: Swksf367"))
assertNull(extractOtp("You can also tap on this link to verify your phone: v.whatsapp.com/696948"))
assertNull(extractOtp("https://www.photosfromyourevent.com/4669/wauem8/"))
}
}