dukcapil/internal/service/dukcapil_service.go
Aditya Siregar bc64eb20ea add dukcapil
2026-05-07 04:01:32 +07:00

71 lines
1.8 KiB
Go

package service
import (
"context"
"encoding/json"
"strconv"
"go-backend-template/internal/client"
"go-backend-template/internal/contract"
)
type DukcapilService interface {
FaceMatch(ctx context.Context, req *contract.FaceMatchRequest) (*contract.FaceMatchResponse, error)
}
type DukcapilServiceImpl struct {
client *client.DukcapilClient
}
func NewDukcapilService(c *client.DukcapilClient) *DukcapilServiceImpl {
return &DukcapilServiceImpl{client: c}
}
func (s *DukcapilServiceImpl) FaceMatch(ctx context.Context, req *contract.FaceMatchRequest) (*contract.FaceMatchResponse, error) {
upstream, err := s.client.FaceMatch(ctx, req)
if err != nil {
return nil, err
}
matches := parseFaceMatches(upstream.Response)
return &contract.FaceMatchResponse{
TID: upstream.TID,
ErrorCode: upstream.ErrorCode,
Error: upstream.Error,
RequestType: upstream.RequestType,
Threshold: upstream.FaceThreshold,
MaxResults: upstream.MaxResults,
Matches: matches,
Raw: upstream,
}, nil
}
// parseFaceMatches decodes the nested string field
// `{"face":{"FACE_T5":{"<NIK>":<score>, ...}}}` into a slice of results.
func parseFaceMatches(raw string) []contract.FaceMatchResult {
if raw == "" {
return nil
}
var envelope struct {
Face map[string]map[string]json.Number `json:"face"`
}
if err := json.Unmarshal([]byte(raw), &envelope); err != nil {
return nil
}
results := make([]contract.FaceMatchResult, 0)
for _, group := range envelope.Face {
for nik, scoreNum := range group {
score, err := strconv.ParseFloat(scoreNum.String(), 64)
if err != nil {
continue
}
results = append(results, contract.FaceMatchResult{NIK: nik, Score: score})
}
}
return results
}
// Compile-time assertion.
var _ DukcapilService = (*DukcapilServiceImpl)(nil)