Files
geo/server/internal/tenant/app/meijiequan_challenge_resolver.go
T
root 9d6181260a
Desktop Client Build / Resolve Build Metadata (push) Successful in 43s
Frontend CI / Frontend (push) Successful in 3m49s
Backend CI / Backend (push) Failing after 7m10s
Desktop Client Build / Build Desktop Client (push) Successful in 23m4s
Desktop Client Build / Publish Client Artifacts to NAS (push) Successful in 28s
feat(media-supply): add media resource supply marketplace
Introduce an end-to-end media-supply feature: tenant-side resource sync
service/worker backed by a Meijiequan supplier client, ops-side management
APIs, and admin/ops web views for resources, orders, favorites and
submission. Adds a shared digitocr helper, MediaSupply config blocks for
tenant and ops, shared types, and migrations for supplier media resources,
price overrides, customer visibility and order refunds.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 23:17:01 +08:00

40 lines
1.4 KiB
Go

package app
import (
"bytes"
"context"
"errors"
"fmt"
// image/png is registered by the digitocr package; jpeg/gif are registered
// here so a future change of the captcha format still decodes.
_ "image/gif"
_ "image/jpeg"
"github.com/geo-platform/tenant-api/internal/shared/digitocr"
)
// meijiequanChallengeDigits is the fixed length of the meijiequan login captcha.
const meijiequanChallengeDigits = 4
var errMeijiequanChallengeEmpty = errors.New("meijiequan challenge image is empty")
// DigitOCRMeijiequanChallengeCodeResolver decodes the meijiequan numeric login
// captcha locally via the digitocr template matcher, enabling unattended login
// without an external OCR service.
type DigitOCRMeijiequanChallengeCodeResolver struct{}
// ResolveCode recognizes the digits in the captcha image. A decode failure is
// returned as a non-challenge error so the login flow retries with a fresh
// captcha rather than giving up immediately (as the manual resolver does).
func (DigitOCRMeijiequanChallengeCodeResolver) ResolveCode(_ context.Context, challenge MeijiequanChallenge) (string, error) {
if len(challenge.Image) == 0 {
return "", errMeijiequanChallengeEmpty
}
code, err := digitocr.RecognizeReader(bytes.NewReader(challenge.Image), digitocr.Options{Digits: meijiequanChallengeDigits})
if err != nil {
return "", fmt.Errorf("digitocr resolve meijiequan challenge: %w", err)
}
return code, nil
}