Files
miti99bot/internal/modules/twentyq/validate.go
T
tiennm99 daeaf0c605 chore: drop CF→AWS migration tooling and stale JS-port references
The CF→AWS data migration (closed 2026-05-16) is long done and the
tooling isn't wired into any production path. Remove the one-shot binary,
its support package, and the migration runbook.

In live code, replace 'JS-parity' / 'same shape as JS' / 'cross-runtime
KV migration' comments with the real, stable reason for each behavior
(wire-format invariant, null-vs-zero distinction, CloudWatch alarm field
name, etc.). 24 files touched across lolschedule, loldle, wordle, twentyq,
trading, misc, util, server, metrics, ai, keylock.

- delete cmd/migrate_cf_data/
- delete internal/migration/
- delete docs/cf-to-aws-migration-runbook.md
2026-05-25 09:39:17 +07:00

45 lines
1.5 KiB
Go

package twentyq
import (
"regexp"
"strings"
)
const (
minLen = 3
maxLen = 200
)
// openEndedRe rejects open-ended questions before spending a Gemini call.
// The prefix list is intentionally narrow (canonical interrogatives only)
// to avoid blocking borderline yes/no phrasings.
var openEndedRe = regexp.MustCompile(`(?i)^\s*(what|how|why|which|who|where|when|tell me|describe|explain)\b`)
// ValidateResult is the public outcome of validateQuestion. Either OK + the
// normalized form, or !OK + a user-visible reason (HTML allowed).
type ValidateResult struct {
OK bool
Normalized string
Reason string
}
// validateQuestion strips/collapses whitespace and rejects too-short,
// too-long, or open-ended inputs. Reason strings carry HTML <code> markup
// so the dispatcher's ReplyHTML wrapping is required for those branches.
func validateQuestion(raw string) ValidateResult {
if raw == "" {
return ValidateResult{Reason: "Please send a yes/no question after the command."}
}
collapsed := strings.Join(strings.Fields(raw), " ")
if len(collapsed) < minLen {
return ValidateResult{Reason: "Question too short — try something like <code>is it big?</code>."}
}
if len(collapsed) > maxLen {
return ValidateResult{Reason: "Question too long — keep it under 200 characters."}
}
if openEndedRe.MatchString(collapsed) {
return ValidateResult{Reason: "Yes/no questions only — try <code>is it ...?</code> or <code>does it ...?</code>."}
}
return ValidateResult{OK: true, Normalized: collapsed}
}