diff --git a/app/build.gradle.kts b/app/build.gradle.kts index a92b19d..a3aa866 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -16,8 +16,8 @@ android { applicationId = "com.rainy.token" minSdk = 31 targetSdk = 35 - versionCode = 46 - versionName = "1.7.26" + versionCode = 47 + versionName = "1.7.27" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { diff --git a/app/src/main/java/com/rainy/token/data/repository/TraeRepository.kt b/app/src/main/java/com/rainy/token/data/repository/TraeRepository.kt index ccdb8c4..e530c78 100644 --- a/app/src/main/java/com/rainy/token/data/repository/TraeRepository.kt +++ b/app/src/main/java/com/rainy/token/data/repository/TraeRepository.kt @@ -715,16 +715,19 @@ class TraeRepository constructor( val succeeded = code == 0L || code == 200L val lowerMsg = msg.lowercase() - val deviceBlock = msg.contains("设备") || lowerMsg.contains("device") || lowerMsg.contains("machine") + // 已签语义优先于「设备」判定:像「当前设备今日已经签到」这种文案虽然含“设备”, + // 但语义是今日已签,必须按 ALREADY 落本地记录,避免误判 DEVICE_BLOCKED 反复重试。 + val alreadyMsg = msg.contains("已签到") || msg.contains("已经签到") || msg.contains("重复签到") || + msg.contains("重复") || msg.contains("不能重复") || + msg.contains("明日再来") || msg.contains("今日已完成") || msg.contains("已领取") || + lowerMsg.contains("already") || lowerMsg.contains("checked") || lowerMsg.contains("claimed") || + lowerMsg.contains("duplicate") || lowerMsg.contains("repeat") + val deviceBlock = !alreadyMsg && ( + msg.contains("设备") || lowerMsg.contains("device") || lowerMsg.contains("machine") + ) // 权威口径幂等兜底码是 10001(trae-checkin-helper 逆向);历史实现用 1001, // 两者都认,避免把已签误判为 FAILED 硬错误。 - val already = (code == 1001L || code == 10001L) || (!deviceBlock && ( - msg.contains("已签到") || msg.contains("已经签到") || msg.contains("重复签到") || - msg.contains("重复") || msg.contains("不能重复") || - msg.contains("明日再来") || msg.contains("今日已完成") || msg.contains("已领取") || - lowerMsg.contains("already") || lowerMsg.contains("checked") || lowerMsg.contains("claimed") || - lowerMsg.contains("duplicate") || lowerMsg.contains("repeat") - )) + val already = (code == 1001L || code == 10001L) || alreadyMsg // 服务端临时限流/排队(账号、设备或活动人数限制):提示可稍后重试,不算硬错误。 val retryable = !already && !deviceBlock && ( msg.contains("参与") || msg.contains("稍后重试") || msg.contains("火爆") || diff --git a/app/src/main/java/com/rainy/token/ui/dashboard/autocheckin/AutoCheckinManager.kt b/app/src/main/java/com/rainy/token/ui/dashboard/autocheckin/AutoCheckinManager.kt index c5c5cd1..fde316d 100644 --- a/app/src/main/java/com/rainy/token/ui/dashboard/autocheckin/AutoCheckinManager.kt +++ b/app/src/main/java/com/rainy/token/ui/dashboard/autocheckin/AutoCheckinManager.kt @@ -192,8 +192,15 @@ class AutoCheckinManager @Inject constructor( ) ServiceResult(service, label, false, true, 0, "", false) } - // INTL 不支持签到:静默跳过,不进弹窗(避免误报「已签到」) - TraeRepository.CheckinOutcome.INTL_UNSUPPORTED -> null + // INTL 不支持自动签到:当天落一条已签记录防反复重试,静默跳过不进弹窗 + TraeRepository.CheckinOutcome.INTL_UNSUPPORTED -> { + checkinStatusStore.record( + ServiceType.TRAE, + account.id, + CheckinStatusStore.STATUS_ALREADY + ) + null + } TraeRepository.CheckinOutcome.DEVICE_BLOCKED -> { recordFailure(service, account.id, CheckinStatusStore.STATUS_DEVICE_BLOCKED) ServiceResult(service, label, false, false, 0, r.message, failed = true) @@ -250,9 +257,15 @@ class AutoCheckinManager @Inject constructor( ) ServiceResult(service, label, false, true, 0, "", false) } - WorkBuddyRepository.CheckinOutcome.NO_CAMPAIGN -> - // 国际站没有签到活动不是账号失败:静默跳过,不记失败日志 - ServiceResult(service, label, false, false, 0, s.message, false) + // 国际站无签到活动不是账号失败:当天落已签记录防反复重试,静默跳过不进弹窗 + WorkBuddyRepository.CheckinOutcome.NO_CAMPAIGN -> { + checkinStatusStore.record( + ServiceType.WORKBUDDY, + account.id, + CheckinStatusStore.STATUS_ALREADY + ) + null + } WorkBuddyRepository.CheckinOutcome.FAILED -> { recordFailure(service, account.id, CheckinStatusStore.STATUS_FAILED) ServiceResult(service, label, false, false, 0, s.message, failed = true)