yidun送检功能

This commit is contained in:
2026-05-15 10:28:17 +08:00
parent 51d26aeee7
commit c8cc19e8e7
29 changed files with 5133 additions and 121 deletions

View File

@@ -92,6 +92,79 @@ func (s *ImageDetectionService) DetectImage(ctx context.Context, imageURL, dataI
return result, nil
}
// DetectImageSync 同步检测图片,提交并直接返回检测结果
// 适用于轮询模式(无回调),提交时实时返回结果,无需额外查询
func (s *ImageDetectionService) DetectImageSync(ctx context.Context, imageURL, dataID string) (*ImageResult, error) {
if DefaultClients == nil || DefaultClients.ImageClient == nil {
return nil, fmt.Errorf("易盾图片检测客户端未初始化")
}
if imageURL == "" {
return nil, fmt.Errorf("图片URL不能为空")
}
businessId := g.Cfg().MustGet(ctx, "yidun.image.business_id").String()
g.Log().Infof(ctx, "图片同步检测, url: %s, business_id: %s", imageURL, businessId)
// 创建同步检测请求
request := check.NewImageV5CheckRequest(businessId)
imageBean := check.NewImageBeanRequest()
imageBean.SetData(imageURL)
imageBean.SetName(dataID)
imageBean.SetType(1) // 1: 图片URL
request.SetImages([]check.ImageBeanRequest{*imageBean})
// 调用同步检测API
response, err := DefaultClients.ImageClient.ImageSyncCheck(request)
if err != nil {
g.Log().Errorf(ctx, "图片同步检测失败: %v", err)
return nil, fmt.Errorf("图片同步检测失败: %w", err)
}
if response.GetCode() != 200 {
g.Log().Errorf(ctx, "图片同步检测API错误: code=%d, msg=%s", response.GetCode(), response.GetMsg())
return nil, fmt.Errorf("图片同步检测API错误: code=%d, msg=%s", response.GetCode(), response.GetMsg())
}
if response.Result == nil || len(*response.Result) == 0 {
g.Log().Warningf(ctx, "图片同步检测结果为空, url: %s", imageURL)
return nil, ErrImageResultNotFound
}
// 提取结果
detail := (*response.Result)[0]
result := &ImageResult{
TaskID: dataID,
Name: dataID,
Url: imageURL,
}
if detail.Antispam != nil {
if detail.Antispam.TaskId != nil {
result.TaskID = *detail.Antispam.TaskId
}
if detail.Antispam.Status != nil {
result.Status = *detail.Antispam.Status
}
if detail.Antispam.Suggestion != nil {
result.Suggestion = *detail.Antispam.Suggestion
}
if detail.Antispam.Label != nil {
result.Label = *detail.Antispam.Label
}
if detail.Antispam.ResultType != nil {
result.ResultType = *detail.Antispam.ResultType
}
if detail.Antispam.CensorTime != nil {
result.CensorTime = *detail.Antispam.CensorTime
}
result.Antispam = detail.Antispam
}
g.Log().Infof(ctx, "图片同步检测完成, taskID: %s, suggestion: %d, status: %d",
result.TaskID, result.Suggestion, result.Status)
return result, nil
}
// ImageResult 图片检测完整结果
type ImageResult struct {
TaskID string `json:"taskId"` // 任务ID
@@ -144,7 +217,7 @@ func (s *ImageDetectionService) GetImageResult(ctx context.Context, taskID strin
if response.Result == nil || len(*response.Result) == 0 {
g.Log().Warningf(ctx, "未找到图片检测结果, taskID: %s", taskID)
return nil, ErrImageStillProcessing
return nil, ErrImageResultNotFound
}
// 查找指定taskID的结果

View File

@@ -5,7 +5,6 @@ import (
"encoding/json"
"errors"
"fmt"
"time"
"github.com/gogf/gf/v2/frame/g"
audiocallback "github.com/yidun/yidun-golang-sdk/yidun/service/antispam/audio/callback/v4/response"
@@ -13,7 +12,6 @@ import (
callbackrequest "github.com/yidun/yidun-golang-sdk/yidun/service/antispam/videosolution/callback/v2/request"
callbackresponse "github.com/yidun/yidun-golang-sdk/yidun/service/antispam/videosolution/callback/v2/response"
vsrequest "github.com/yidun/yidun-golang-sdk/yidun/service/antispam/videosolution/submit/v2/request"
submitresponse "github.com/yidun/yidun-golang-sdk/yidun/service/antispam/videosolution/submit/v2/response"
)
// VideoDetectionService 视频检测服务
@@ -43,27 +41,47 @@ func (s *VideoDetectionService) DetectVideo(ctx context.Context, videoURL, dataI
return nil, fmt.Errorf("视频URL不能为空")
}
g.Log().Infof(ctx, "视频检测任务提交, url: %s", videoURL)
g.Log().Infof(ctx, "视频检测任务提交, url: %s, dataID: %s", videoURL, dataID)
// 创建请求
req := vsrequest.NewVideoSolutionSubmitV2Req()
req.SetURL(videoURL)
req.SetDataID(dataID)
req.SetUniqueKey(dataID)
// 设置回调地址
if callbackURL != "" {
req.SetCallbackURL(callbackURL)
}
// 设置子产品标识(视频解决方案必须)
req.SetSubProduct("videoStream")
// 可选设置IP用于风险用户识别
// req.SetIP("127.0.0.1")
// 调用API
response, err := DefaultClients.VideoClient.Submit(req)
if err != nil {
g.Log().Errorf(ctx, "视频检测提交失败: %v", err)
return nil, fmt.Errorf("视频检测提交失败: %w", err)
g.Log().Errorf(ctx, "视频检测提交HTTP错误: %v", err)
return nil, fmt.Errorf("视频检测提交HTTP错误: %w", err)
}
if response.GetCode() != 200 {
g.Log().Errorf(ctx, "视频检测API错误: code=%d, msg=%s", response.GetCode(), response.GetMsg())
return nil, fmt.Errorf("视频检测API错误: code=%d, msg=%s", response.GetCode(), response.GetMsg())
// 根据错误码提供更详细的错误信息
errMsg := fmt.Sprintf("视频检测API错误: code=%d, msg=%s", response.GetCode(), response.GetMsg())
// 常见错误码说明
switch response.GetCode() {
case 417:
errMsg += " (可能原因: 视频URL无法访问或业务配置问题)"
case 400:
errMsg += " (可能原因: 请求参数错误)"
case 403:
errMsg += " (可能原因: 鉴权失败检查secretId和secretKey)"
}
return nil, fmt.Errorf(errMsg)
}
result := &VideoSubmitResult{}
@@ -132,7 +150,7 @@ func (s *VideoDetectionService) GetVideoResult(ctx context.Context, taskID strin
if response.Result == nil || len(*response.Result) == 0 {
g.Log().Warningf(ctx, "未找到视频检测结果, taskID: %s", taskID)
return nil, ErrVideoStillProcessing
return nil, ErrVideoResultNotFound
}
// 查找指定taskID的结果
@@ -182,82 +200,6 @@ func (s *VideoDetectionService) GetVideoResult(ctx context.Context, taskID strin
return nil, ErrVideoResultNotFound
}
// PollVideoResult 轮询获取视频检测结果
func (s *VideoDetectionService) PollVideoResult(ctx context.Context, taskID string, interval, maxWait time.Duration) (*VideoResult, error) {
if interval <= 0 {
interval = 1 * time.Second
}
if maxWait <= 0 {
maxWait = 5 * time.Minute
}
startTime := time.Now()
g.Log().Infof(ctx, "开始轮询视频检测结果, taskID: %s, interval: %v, maxWait: %v", taskID, interval, maxWait)
for time.Since(startTime) < maxWait {
select {
case <-ctx.Done():
return nil, fmt.Errorf("轮询取消: %w", ctx.Err())
default:
}
result, err := s.GetVideoResult(ctx, taskID)
if err == nil {
g.Log().Infof(ctx, "轮询成功, taskID: %s, elapsed: %v", taskID, time.Since(startTime))
return result, nil
}
if errors.Is(err, ErrVideoResultNotFound) {
g.Log().Infof(ctx, "视频仍在检测中,继续轮询, taskID: %s, elapsed: %v", taskID, time.Since(startTime))
} else {
g.Log().Warningf(ctx, "查询出错,继续重试, taskID: %s, error: %v", taskID, err)
}
time.Sleep(interval)
}
return nil, fmt.Errorf("轮询超时,已等待 %v", time.Since(startTime))
}
// GetSDKSubmitResponse 获取SDK原始提交响应包含完整易盾返回信息
func (s *VideoDetectionService) GetSDKSubmitResponse(ctx context.Context, videoURL, dataID string, callbackURL string) (*submitresponse.VideoSolutionSubmitV2Response, error) {
if DefaultClients == nil || DefaultClients.VideoClient == nil {
return nil, fmt.Errorf("易盾视频检测客户端未初始化")
}
req := vsrequest.NewVideoSolutionSubmitV2Req()
req.SetURL(videoURL)
req.SetDataID(dataID)
req.SetUniqueKey(dataID)
if callbackURL != "" {
req.SetCallbackURL(callbackURL)
}
response, err := DefaultClients.VideoClient.Submit(req)
if err != nil {
return nil, err
}
return response, nil
}
// GetSDKCallbackResponse 获取SDK原始回调响应包含完整易盾返回信息
func (s *VideoDetectionService) GetSDKCallbackResponse(ctx context.Context, taskID string) (*callbackresponse.VideoSolutionCallbackV2Response, error) {
if DefaultClients == nil || DefaultClients.VideoClient == nil {
return nil, fmt.Errorf("易盾视频检测客户端未初始化")
}
req := callbackrequest.NewVideoSolutionCallbackV2Request()
req.SetYidunRequestId(taskID)
response, err := DefaultClients.VideoClient.Callback(req)
if err != nil {
return nil, err
}
return response, nil
}
// =============================================================================
// 视频检测结果推送模式(易盾主动回调)
// =============================================================================