feat(platform): harden telemetry pipeline and unify Semi UI workspaces
This commit is contained in:
57
go/vehicle-gateway/internal/feichibridge/captcha.go
Normal file
57
go/vehicle-gateway/internal/feichibridge/captcha.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package feichibridge
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var captchaPattern = regexp.MustCompile(`^[0-9A-Z]{4}$`)
|
||||
|
||||
type CaptchaSolver interface {
|
||||
Solve(context.Context, []byte) (string, error)
|
||||
}
|
||||
|
||||
type DockerCaptchaSolver struct {
|
||||
Image string
|
||||
Timeout time.Duration
|
||||
}
|
||||
|
||||
func (s DockerCaptchaSolver) Solve(ctx context.Context, image []byte) (string, error) {
|
||||
if len(image) == 0 {
|
||||
return "", errors.New("captcha image is empty")
|
||||
}
|
||||
if strings.TrimSpace(s.Image) == "" {
|
||||
return "", errors.New("captcha OCR image is required")
|
||||
}
|
||||
timeout := s.Timeout
|
||||
if timeout <= 0 {
|
||||
timeout = 20 * time.Second
|
||||
}
|
||||
solveCtx, cancel := context.WithTimeout(ctx, timeout)
|
||||
defer cancel()
|
||||
command := exec.CommandContext(
|
||||
solveCtx,
|
||||
"docker", "run", "--rm", "--network=none", "-i", strings.TrimSpace(s.Image),
|
||||
)
|
||||
command.Stdin = bytes.NewReader(image)
|
||||
var stderr bytes.Buffer
|
||||
command.Stderr = &stderr
|
||||
output, err := command.Output()
|
||||
if err != nil {
|
||||
if solveCtx.Err() != nil {
|
||||
return "", fmt.Errorf("captcha OCR timed out: %w", solveCtx.Err())
|
||||
}
|
||||
return "", fmt.Errorf("captcha OCR failed: %w: %s", err, strings.TrimSpace(stderr.String()))
|
||||
}
|
||||
code := strings.ToUpper(strings.TrimSpace(string(output)))
|
||||
if !captchaPattern.MatchString(code) {
|
||||
return "", fmt.Errorf("captcha OCR returned invalid result %q", code)
|
||||
}
|
||||
return code, nil
|
||||
}
|
||||
Reference in New Issue
Block a user