(client: TelegramClient, userId: number, input: string, incomingMsgId: number)
| 1042 | const state = states.get(userId); |
| 1043 | if (!state || !isStateCurrent(state)) return; |
| 1044 | |
| 1045 | if (!input.trim()) return; |
| 1046 | |
| 1047 | if (incomingMsgId) state.msgIds.push(incomingMsgId); |
| 1048 | |
| 1049 | if (!state.answer) { |
| 1050 | log(LogLevel.WARN, `handleReply: empty answer for user ${userId}`); |
| 1051 | removeCaptchaState(userId); |
| 1052 | await cleanupCaptchaMessages(client, userId, state); |
| 1053 | try { await client.sendMessage(userId, { message: "❌ 验证状态异常,请联系对方重置。", parseMode: "html" }); } catch {} |
| 1054 | return; |
| 1055 | } |
| 1056 | |
| 1057 | const isImgMode = state.mode === CaptchaMode.IMG_DIGIT || state.mode === CaptchaMode.IMG_MIXED; |
| 1058 | const inputNorm = input.trim().toUpperCase(); |
| 1059 | const answerNorm = state.answer.trim().toUpperCase(); |
| 1060 | |
| 1061 | const correct = isImgMode |
| 1062 | ? levenshtein(inputNorm, answerNorm) <= 1 |
| 1063 | : inputNorm === answerNorm; |
| 1064 | |
| 1065 | if (correct) { |
| 1066 | removeCaptchaState(userId); |
| 1067 | await cleanupCaptchaMessages(client, userId, state); |
| 1068 | const name = await getDisplayName(client, userId).catch(() => String(userId)); |
| 1069 | if (!isStateCurrent(state)) return; |
| 1070 | rec.addVerified(userId, name, usernameCache.get(userId)); |
| 1071 | rec.delFailed(userId); |
| 1072 | log(LogLevel.INFO, `User ${userId} passed captcha`); |
| 1073 | await runPassActions(client, userId); |
| 1074 | if (!isStateCurrent(state)) return; |
| 1075 | try { |
| 1076 | await client.sendMessage(userId, { message: "✅ 验证通过!欢迎与我对话。", parseMode: "html" }); |
| 1077 | } catch {} |
| 1078 | return; |
| 1079 | } |
| 1080 | |
| 1081 | state.tries++; |
| 1082 | const max = cfg.maxTries(); |
| 1083 | const remaining = max > 0 ? max - state.tries : Infinity; |
| 1084 | |
| 1085 | if (max > 0 && state.tries >= max) { |
| 1086 | removeCaptchaState(userId); |
| 1087 | await cleanupCaptchaMessages(client, userId, state); |
| 1088 | const name = await getDisplayName(client, userId).catch(() => String(userId)); |
| 1089 | if (!isStateCurrent(state)) return; |
| 1090 | rec.addFailed(userId, name, "max_tries", usernameCache.get(userId)); |
| 1091 | rec.delVerified(userId); |
| 1092 | log(LogLevel.INFO, `User ${userId} failed captcha (max tries)`); |
| 1093 | try { |
| 1094 | await client.sendMessage(userId, { message: "❌ 验证失败次数过多,对话已被限制。", parseMode: "html" }); |
| 1095 | } catch {} |
| 1096 | if (!isStateCurrent(state)) return; |
| 1097 | await runFailActions(client, userId); |
| 1098 | } else { |
| 1099 | const hint = remaining === Infinity ? "请重试。" : `请重试(剩余次数:${remaining})`; |
| 1100 | try { |
| 1101 | const hintMsg = await client.sendMessage(userId, { message: `❌ 答案错误,${htmlEscape(hint)}`, parseMode: "html" }); |
no test coverage detected