yidun检测、查询
This commit is contained in:
875
YIDUN_API_DOCUMENTATION.md
Normal file
875
YIDUN_API_DOCUMENTATION.md
Normal file
@@ -0,0 +1,875 @@
|
||||
# 易盾内容安全 API 调用文档
|
||||
|
||||
## 📋 目录
|
||||
|
||||
- [概述](#概述)
|
||||
- [配置说明](#配置说明)
|
||||
- [API接口列表](#api接口列表)
|
||||
- [文本检测](#1-文本检测)
|
||||
- [图片检测](#2-图片检测)
|
||||
- [视频检测](#3-视频检测)
|
||||
- [错误码说明](#错误码说明)
|
||||
|
||||
---
|
||||
|
||||
## 概述
|
||||
|
||||
本项目集成了网易易盾内容安全SDK,提供文本、图片、视频的内容安全检测服务。
|
||||
|
||||
### 产品凭证
|
||||
|
||||
| 检测类型 | SecretID | SecretKey | BusinessID |
|
||||
|---------|----------|-----------|------------|
|
||||
| **音视频检测** | f58a38341ca6227014df7c3bf0e6f16f | 526aa631ba5d518aedeb70b5a3b67371 | 需从易盾控制台获取 |
|
||||
| **图片检测** | 9a82f90bfec61eb40d1c95605b894817 | f73a78954417a3713c36ec2d14eb2b5f | 需从易盾控制台获取 |
|
||||
| **文本检测** | 待配置 | 待配置 | 待配置 |
|
||||
|
||||
### 服务地址
|
||||
|
||||
```
|
||||
http://localhost:3002
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 配置说明
|
||||
|
||||
配置文件位置:`config.yml`
|
||||
|
||||
```yaml
|
||||
yidun:
|
||||
# 音视频检测配置
|
||||
video:
|
||||
business_id: "YOUR_VIDEO_BUSINESS_ID"
|
||||
secret_id: "f58a38341ca6227014df7c3bf0e6f16f"
|
||||
secret_key: "526aa631ba5d518aedeb70b5a3b67371"
|
||||
|
||||
# 图片检测配置
|
||||
image:
|
||||
business_id: "YOUR_IMAGE_BUSINESS_ID"
|
||||
secret_id: "9a82f90bfec61eb40d1c95605b894817"
|
||||
secret_key: "f73a78954417a3713c36ec2d14eb2b5f"
|
||||
|
||||
# 文本检测配置
|
||||
text:
|
||||
business_id: "YOUR_TEXT_BUSINESS_ID"
|
||||
secret_id: "YOUR_TEXT_SECRET_ID"
|
||||
secret_key: "YOUR_TEXT_SECRET_KEY"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API接口列表
|
||||
|
||||
| 接口名称 | 请求方法 | 路径 | 说明 |
|
||||
|---------|---------|------|------|
|
||||
| 文本检测提交 | POST | `/yidun/detect-text` | 提交文本进行异步检测 |
|
||||
| 图片检测提交 | POST | `/yidun/detect-image` | 提交图片进行异步检测 |
|
||||
| 视频检测提交 | POST | `/yidun/detect-video` | 提交视频进行检测 |
|
||||
| 图片结果查询 | POST | `/yidun/GetImageResult` | 查询图片检测结果(轮询模式) |
|
||||
| 图片检测回调 | POST | `/yidun/receive-image-callback` | 接收图片检测结果推送(推送模式) |
|
||||
| 视频结果查询 | POST | `/yidun/GetVideoResult` | 查询视频检测结果(轮询模式) |
|
||||
| 视频检测回调 | POST | `/yidun/receive-video-callback` | 接收视频检测结果推送(推送模式) |
|
||||
|
||||
**注意**:检测结果是异步的,提交接口只返回 `task_id`,需要通过回调或轮询获取结果。
|
||||
|
||||
---
|
||||
|
||||
## 1. 文本检测
|
||||
|
||||
### 提交文本检测任务
|
||||
|
||||
**接口地址**: `POST /yidun/detect-text`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
| 参数名 | 类型 | 必填 | 说明 |
|
||||
|--------|------|------|------|
|
||||
| data_id | string | 是 | 数据唯一标识 |
|
||||
| content | string | 是 | 待检测的文本内容 |
|
||||
| ip | string | 否 | 用户IP地址 |
|
||||
| token | string | 否 | 用户token(反作弊) |
|
||||
|
||||
**请求示例**:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:3002/yidun/detect-text \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"data_id": "text-001",
|
||||
"content": "这是一段需要检测的文本内容",
|
||||
"ip": "192.168.1.100"
|
||||
}'
|
||||
```
|
||||
|
||||
**响应示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "",
|
||||
"data": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
|
||||
}
|
||||
```
|
||||
|
||||
**响应说明**:
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| data | string | 任务ID (task_id),用于后续查询检测结果 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 图片检测
|
||||
|
||||
### 2.1 提交图片检测任务
|
||||
|
||||
**接口地址**: `POST /yidun/detect-image`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
| 参数名 | 类型 | 必填 | 说明 |
|
||||
|--------|------|------|------|
|
||||
| data_id | string | 是 | 数据唯一标识 |
|
||||
| image_url | string | 是 | 图片URL地址 |
|
||||
| callback_url | string | 否 | 回调地址 |
|
||||
|
||||
**请求示例**:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:3002/yidun/detect-image \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"data_id": "img-001",
|
||||
"image_url": "https://example.com/image.jpg"
|
||||
}'
|
||||
```
|
||||
|
||||
**响应示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "",
|
||||
"data": {
|
||||
"taskId": "b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7",
|
||||
"name": "img-001",
|
||||
"dataId": "img-001",
|
||||
"dealingCount": 0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**响应说明**:
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| taskId | string | 任务ID,用于后续查询检测结果 |
|
||||
| name | string | 图片唯一标识 |
|
||||
| dataId | string | 客户图片唯一标识 |
|
||||
| dealingCount | int64 | 缓冲池排队待处理数据量 |
|
||||
|
||||
### 2.2 查询图片检测结果(轮询模式)
|
||||
|
||||
**接口地址**: `POST /yidun/GetImageResult`
|
||||
|
||||
**SDK调用信息**:
|
||||
- SDK方法: `ImageClient.ImageCallback(request)`
|
||||
- 请求地址: `http://as.dun.163.com/v5/image/callback/results`
|
||||
- 请求参数: `yidunRequestId` (taskId)
|
||||
|
||||
**请求示例**:
|
||||
|
||||
```bash
|
||||
curl -X POST "http://localhost:3002/yidun/GetImageResult" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"taskId": "b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7"}'
|
||||
```
|
||||
|
||||
**响应示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "",
|
||||
"data": {
|
||||
"taskId": "b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7",
|
||||
"status": 2,
|
||||
"suggestion": 0,
|
||||
"label": 100,
|
||||
"resultType": 2,
|
||||
"dataId": "img-001",
|
||||
"name": "img-001",
|
||||
"censorTime": 1629426386079,
|
||||
"url": "https://example.com/image.jpg",
|
||||
"antispam": {
|
||||
"taskId": "b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7",
|
||||
"name": "img-001",
|
||||
"dataId": "img-001",
|
||||
"status": 2,
|
||||
"suggestion": 0,
|
||||
"label": 100,
|
||||
"resultType": 2,
|
||||
"censorTime": 1629426386079,
|
||||
"censorSource": 0,
|
||||
"censorRound": 1,
|
||||
"labels": [
|
||||
{
|
||||
"label": 400,
|
||||
"level": 2,
|
||||
"rate": 1.0
|
||||
}
|
||||
],
|
||||
"censorLabels": [
|
||||
{
|
||||
"code": "审核标签编码",
|
||||
"customCode": "自定义标签编码",
|
||||
"name": "审核标签名称",
|
||||
"desc": "风景"
|
||||
}
|
||||
],
|
||||
"remark": "人审备注信息"
|
||||
},
|
||||
"ocr": { ... },
|
||||
"face": { ... },
|
||||
"quality": { ... },
|
||||
"logo": { ... },
|
||||
"discern": { ... },
|
||||
"ad": { ... },
|
||||
"userRisk": { ... },
|
||||
"anticheat": { ... },
|
||||
"riskControl": { ... },
|
||||
"aigc": { ... },
|
||||
"llmCheckInfo": [ ... ]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**antispam 字段完整说明**:
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| taskId | string | 任务ID |
|
||||
| name | string | 图片名称 |
|
||||
| dataId | string | 客户数据ID |
|
||||
| status | int | 检测状态:0=未开始,1=检测中,2=检测成功,3=检测失败 |
|
||||
| suggestion | int | 处置建议:0=通过,1=嫌疑,2=不通过 |
|
||||
| label | int | 一级分类 |
|
||||
| secondLabel | string | 二级分类 |
|
||||
| thirdLabel | string | 三级分类 |
|
||||
| riskDescription | string | 风险描述 |
|
||||
| resultType | int | 结果类型:1=机器结果,2=人审结果 |
|
||||
| censorTime | int64 | 审核完成时间(毫秒时间戳) |
|
||||
| censorSource | int | 审核来源 |
|
||||
| censorRound | int | 审核轮数 |
|
||||
| censorLabels | array | 审核标签数组 |
|
||||
| remark | string | 审核备注 |
|
||||
| overAllMarkDesc | string | 整体审核备注 |
|
||||
| detailMarks | array | 细节标注 |
|
||||
| labels | array | 分类标签详情 |
|
||||
| url | string | 图片URL |
|
||||
| imgMd5 | string | 图片MD5 |
|
||||
| frameSize | int | 分帧数 |
|
||||
| customLabels | array | 客户自定义标签 |
|
||||
| censorExtension | object | 人审拓展字段 |
|
||||
| strategyVersions | array | 策略版本 |
|
||||
| hitType | int | 命中策略类型 |
|
||||
| strategyType | int | 策略类型:1=公有策略,2=私有策略 |
|
||||
| hitResult | string | 命中结果 |
|
||||
| hitSource | int | 特征添加来源 |
|
||||
| hidden | bool | 是否有隐藏文件 |
|
||||
| hiddenFormat | string | 隐藏文件格式 |
|
||||
| publicOpinionInfo | string | 舆情信息 |
|
||||
|
||||
**labels 数组结构**:
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| label | int | 标签类型 |
|
||||
| level | int | 判断结果:0=正常,1=不确定,2=确定 |
|
||||
| rate | float | 置信度 |
|
||||
| subLabels | array | 二级分类详情 |
|
||||
| explain | string | LLM解释说明 |
|
||||
| isLlmCheck | bool | 是否LLM检测命中 |
|
||||
|
||||
**censorLabels 数组结构**:
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| code | string | 审核标签编码 |
|
||||
| customCode | string | 自定义标签编码 |
|
||||
| name | string | 审核标签名称 |
|
||||
| desc | string | 审核标签描述 |
|
||||
| parentLabelId | string | 父标签ID |
|
||||
| depth | int | 标签深度 |
|
||||
|
||||
### 2.3 接收图片检测回调(推送模式)
|
||||
|
||||
**接口地址**: `POST /yidun/receive-image-callback`
|
||||
|
||||
**易盾回调配置**:
|
||||
- HTTP URL: 回调地址 `callbackUrl`
|
||||
- HTTP Method: POST
|
||||
- Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
**请求参数** (form-data):
|
||||
|
||||
| 参数名 | 类型 | 必填 | 说明 |
|
||||
|--------|------|------|------|
|
||||
| secretId | string | 是 | 产品密钥ID |
|
||||
| businessId | string | 是 | 业务ID |
|
||||
| signature | string | 是 | 请求签名 |
|
||||
| callbackData | string | 是 | 回调数据(JSON字符串) |
|
||||
|
||||
**请求体示例**:
|
||||
|
||||
```
|
||||
callbackData={"antispam":{...}}&signature=xxx&secretId=xxx&businessId=xxx
|
||||
```
|
||||
|
||||
**回调数据格式**:
|
||||
|
||||
```json
|
||||
{
|
||||
"antispam": {
|
||||
"taskId": "a2e53718f9c348d09206e4671304ca7c",
|
||||
"suggestion": 2,
|
||||
"remark": "人审备注信息,填写才会返回",
|
||||
"dataId": "dataId",
|
||||
"name": "name",
|
||||
"labels": [
|
||||
{
|
||||
"label": 400,
|
||||
"level": 2,
|
||||
"rate": 1.0
|
||||
},
|
||||
{
|
||||
"label": 500,
|
||||
"level": 0,
|
||||
"rate": 1.0
|
||||
}
|
||||
],
|
||||
"censorLabels": [
|
||||
{
|
||||
"code": "审核标签编码",
|
||||
"customCode": "自定义标签编码",
|
||||
"name": "审核标签名称",
|
||||
"desc": "风景"
|
||||
}
|
||||
],
|
||||
"resultType": 2,
|
||||
"censorTime": 1622036595467,
|
||||
"censorSource": 0,
|
||||
"censorRound": 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Suggestion值说明**:
|
||||
|
||||
| 值 | 含义 |
|
||||
|----|------|
|
||||
| 0 | 通过 |
|
||||
| 1 | 嫌疑,需人工审核 |
|
||||
| 2 | 不通过 |
|
||||
|
||||
**Status值说明**:
|
||||
|
||||
| 值 | 含义 |
|
||||
|----|------|
|
||||
| 0 | 未开始 |
|
||||
| 1 | 检测中 |
|
||||
| 2 | 检测成功 |
|
||||
| 3 | 检测失败 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 视频检测
|
||||
|
||||
### 提交视频检测任务
|
||||
|
||||
**接口地址**: `POST /yidun/detect-video`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
| 参数名 | 类型 | 必填 | 说明 |
|
||||
|--------|------|------|------|
|
||||
| data_id | string | 是 | 数据唯一标识 |
|
||||
| video_url | string | 是 | 视频URL地址 |
|
||||
| callback_url | string | 否 | 回调地址 |
|
||||
|
||||
**请求示例**:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:3002/yidun/detect-video \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"data_id": "video-001",
|
||||
"video_url": "https://example.com/video.mp4"
|
||||
}'
|
||||
```
|
||||
|
||||
**响应示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "",
|
||||
"data": {
|
||||
"taskId": "c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8",
|
||||
"dataId": "video-001",
|
||||
"dealingCount": 0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**响应说明**:
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| taskId | string | 任务ID,用于后续查询检测结果 |
|
||||
| dataId | string | 调用检测时传递的数据ID |
|
||||
| dealingCount | int64 | 缓冲池排队待处理数据量 |
|
||||
|
||||
**注意**: 视频检测是异步的,检测时间取决于视频长度(几分钟到几十分钟)。建议配置回调地址接收结果。
|
||||
|
||||
### 3.2 查询视频检测结果(轮询模式)
|
||||
|
||||
**接口地址**: `POST /yidun/GetVideoResult`
|
||||
|
||||
**SDK调用信息**:
|
||||
- SDK方法: `VideoClient.Callback(request)`
|
||||
- 请求地址: `http://as.dun.163.com/v2/videosolution/callback/results`
|
||||
- 请求参数: `yidunRequestId` (taskId)
|
||||
|
||||
**请求示例**:
|
||||
|
||||
```bash
|
||||
curl -X POST "http://localhost:3002/yidun/GetVideoResult" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"taskId": "c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8"}'
|
||||
```
|
||||
|
||||
**响应示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "",
|
||||
"data": {
|
||||
"taskId": "18xrunm6fr35t49nnv506ukg02009q66",
|
||||
"status": 2,
|
||||
"suggestion": 2,
|
||||
"label": 100,
|
||||
"resultType": 1,
|
||||
"dataId": "video-001",
|
||||
"censorTime": 1633759853762,
|
||||
"duration": 71339,
|
||||
"antispam": {
|
||||
"taskId": "18xrunm6fr35t49nnv506ukg02009q66",
|
||||
"suggestion": 2,
|
||||
"status": 2,
|
||||
"resultType": 1,
|
||||
"censorSource": 2,
|
||||
"checkTime": 1633759861164,
|
||||
"censorTime": 1633759853762,
|
||||
"duration": 71339,
|
||||
"censorLabels": [
|
||||
{
|
||||
"code": "101",
|
||||
"desc": "自定义标签",
|
||||
"customCode": "68684"
|
||||
}
|
||||
],
|
||||
"evidences": {
|
||||
"images": [...],
|
||||
"text": {...},
|
||||
"audio": {...},
|
||||
"video": {...}
|
||||
}
|
||||
},
|
||||
"language": { ... },
|
||||
"voice": { ... },
|
||||
"asr": { ... },
|
||||
"ocr": { ... },
|
||||
"discern": { ... },
|
||||
"logo": { ... },
|
||||
"face": { ... },
|
||||
"aigc": { ... },
|
||||
"quality": { ... }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**antispam 字段完整说明**:
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| taskId | string | 任务ID |
|
||||
| dataId | string | 客户数据ID |
|
||||
| callback | string | 回调参数 |
|
||||
| suggestion | int | 处置建议:0=通过,1=嫌疑,2=不通过 |
|
||||
| status | int | 检测状态:0=未开始,1=检测中,2=检测成功,3=检测失败 |
|
||||
| resultType | int | 结果类型:1=机器结果,2=人审结果 |
|
||||
| censorRound | int | 人审轮次 |
|
||||
| censor | string | 人审操作人 |
|
||||
| censorSource | int | 审核来源:0=易盾人审,1=客户人审,2=易盾机审 |
|
||||
| checkTime | int64 | 机器检测结束时间 |
|
||||
| censorTime | int64 | 人工审核完成时间 |
|
||||
| duration | int64 | 音视频时长(毫秒) |
|
||||
| durationMs | int64 | 音频时长(毫秒) |
|
||||
| label | int | 一级垃圾类型 |
|
||||
| secondLabel | string | 二级垃圾类型 |
|
||||
| thirdLabel | string | 三级垃圾类型 |
|
||||
| riskDescription | string | 风险描述 |
|
||||
| picCount | int64 | 截图数量 |
|
||||
| censorLabels | array | 审核标签数组 |
|
||||
| censorExtension | object | 质检扩展结果 |
|
||||
| evidences | object | 机器检测证据信息 |
|
||||
| solutionExtra | object | 额外信息 |
|
||||
| reviewEvidences | object | 人审证据信息 |
|
||||
|
||||
**evidences 对象说明**:
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| text | object | 文本证据(标题、简介等) |
|
||||
| images | array | 图片证据(封面、截图中的图片) |
|
||||
| audio | object | 音频证据(人声内容) |
|
||||
| video | object | 视频证据(视频画面) |
|
||||
|
||||
**CensorSource值说明**:
|
||||
|
||||
| 值 | 含义 |
|
||||
|----|------|
|
||||
| 0 | 易盾人审 |
|
||||
| 1 | 客户人审 |
|
||||
| 2 | 易盾机审 |
|
||||
|
||||
### 3.3 接收视频检测回调(推送模式)
|
||||
|
||||
**接口地址**: `POST /yidun/receive-video-callback`
|
||||
|
||||
**易盾回调配置**:
|
||||
- HTTP URL: 回调地址 `callbackUrl`
|
||||
- HTTP Method: POST
|
||||
- Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
**请求参数** (form-data):
|
||||
|
||||
| 参数名 | 类型 | 必填 | 说明 |
|
||||
|--------|------|------|------|
|
||||
| secretId | string | 是 | 产品密钥ID |
|
||||
| signature | string | 是 | 请求签名 |
|
||||
| callbackData | string | 是 | 回调数据(JSON字符串) |
|
||||
|
||||
**请求体示例**:
|
||||
|
||||
```
|
||||
callbackData={"antispam":{...}}&signature=xxx&secretId=xxx
|
||||
```
|
||||
|
||||
**回调数据格式**:
|
||||
|
||||
```json
|
||||
{
|
||||
"antispam": {
|
||||
"taskId": "18xrunm6fr35t49nnv506ukg02009q66",
|
||||
"suggestion": 2,
|
||||
"status": 2,
|
||||
"resultType": 1,
|
||||
"censorSource": 2,
|
||||
"checkTime": 1633759861164,
|
||||
"censorTime": 1633759853762,
|
||||
"duration": 71339,
|
||||
"censorLabels": [
|
||||
{
|
||||
"code": "101",
|
||||
"desc": "自定义标签",
|
||||
"customCode": "68684"
|
||||
}
|
||||
],
|
||||
"evidences": {
|
||||
"images": [
|
||||
{
|
||||
"censorType": 0,
|
||||
"labels": [
|
||||
{
|
||||
"label": 100,
|
||||
"level": 2,
|
||||
"rate": 0.9999,
|
||||
"subLabels": [
|
||||
{
|
||||
"details": {
|
||||
"hitInfos": [
|
||||
{
|
||||
"group": "色情部位分组",
|
||||
"value": "女胸"
|
||||
}
|
||||
]
|
||||
},
|
||||
"rate": 1,
|
||||
"subLabel": 10002
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"name": "gpqis0e92czvfliemjpa3neg02009q6a",
|
||||
"resultType": 1,
|
||||
"status": 2,
|
||||
"suggestion": 2,
|
||||
"taskId": "0b2dd0e561a8457fbfcf7d79378eec37"
|
||||
}
|
||||
],
|
||||
"text": {
|
||||
"taskId": "44i3effo1j5w5for9l8xtdjg02009q6a",
|
||||
"suggestion": 2,
|
||||
"resultType": 1,
|
||||
"censorType": 0,
|
||||
"isRelatedHit": false,
|
||||
"labels": [
|
||||
{
|
||||
"label": 200,
|
||||
"level": 2,
|
||||
"subLabels": [
|
||||
{
|
||||
"subLabel": "200009",
|
||||
"details": {
|
||||
"hitInfos": [
|
||||
{
|
||||
"value": "加我",
|
||||
"positions": [
|
||||
{
|
||||
"fieldName": "content",
|
||||
"startPos": 5,
|
||||
"endPos": 8
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"audio": {
|
||||
"taskId": "18xrunm6fr35t49nnv506ukg02009q66",
|
||||
"dataId": "",
|
||||
"status": 2,
|
||||
"suggestion": 2,
|
||||
"label": 100,
|
||||
"resultType": 1,
|
||||
"callback": "",
|
||||
"censorSource": 2,
|
||||
"censorTime": 1633759861065,
|
||||
"segments": [
|
||||
{
|
||||
"startTime": 0,
|
||||
"endTime": 6,
|
||||
"content": "第一次用这个软件上了半天,全是长得漂亮呢?",
|
||||
"type": 0,
|
||||
"labels": [
|
||||
{
|
||||
"label": 100,
|
||||
"level": 2,
|
||||
"subLabels": [
|
||||
{
|
||||
"subLabel": "100001",
|
||||
"details": {
|
||||
"hitInfos": [
|
||||
{
|
||||
"value": "120",
|
||||
"startTime": 1684201,
|
||||
"endTime": 1684201
|
||||
}
|
||||
],
|
||||
"keywords": [
|
||||
{
|
||||
"word": "自定义敏感词"
|
||||
}
|
||||
],
|
||||
"libInfos": [
|
||||
{
|
||||
"listType": 1,
|
||||
"entity": "127.0.0.1"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"duration": 71
|
||||
},
|
||||
"video": {
|
||||
"taskId": "18xrunm6fr35t49nnv506ukg02009q66",
|
||||
"dataId": "",
|
||||
"status": 2,
|
||||
"suggestion": 2,
|
||||
"resultType": 1,
|
||||
"censorSource": 2,
|
||||
"censorTime": 1633759858920,
|
||||
"pictures": [
|
||||
{
|
||||
"type": 1,
|
||||
"url": "https://xxx.nosdn.127.net/xxx.jpg",
|
||||
"startTime": 5000,
|
||||
"endTime": 5000,
|
||||
"labels": [
|
||||
{
|
||||
"label": 100,
|
||||
"level": 2,
|
||||
"rate": 0.95157,
|
||||
"subLabels": [
|
||||
{
|
||||
"subLabel": 10007,
|
||||
"rate": 0.926,
|
||||
"details": {
|
||||
"hitInfos": [
|
||||
{
|
||||
"value": "卡通色情",
|
||||
"group": "色情部位分组"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"censorSource": 2,
|
||||
"frontPics": [
|
||||
{
|
||||
"url": "https://xxx.nosdn.127.net/xxx_0_0.jpg"
|
||||
}
|
||||
],
|
||||
"backPics": [
|
||||
{
|
||||
"url": "https://xxx.nosdn.127.net/xxx_2_10000.jpg"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Suggestion值说明**:
|
||||
|
||||
| 值 | 含义 |
|
||||
|----|------|
|
||||
| 0 | 通过 |
|
||||
| 1 | 嫌疑,需人工审核 |
|
||||
| 2 | 不通过 |
|
||||
|
||||
**Status值说明**:
|
||||
|
||||
| 值 | 含义 |
|
||||
|----|------|
|
||||
| 0 | 未开始 |
|
||||
| 1 | 检测中 |
|
||||
| 2 | 检测成功 |
|
||||
| 3 | 检测失败 |
|
||||
|
||||
**images/images.labels 结构说明**:
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| label | int | 标签类型 |
|
||||
| level | int | 级别:0=正常,1=嫌疑,2=确定违规 |
|
||||
| rate | float | 置信度 |
|
||||
| subLabels | array | 二级分类详情 |
|
||||
| subLabels.details.hitInfos | array | 命中信息 |
|
||||
| subLabels.details.hitInfos.group | string | 分组名称 |
|
||||
| subLabels.details.hitInfos.value | string | 命中值 |
|
||||
|
||||
**audio.segments 结构说明**:
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| startTime | int | 开始时间(秒) |
|
||||
| endTime | int | 结束时间(秒) |
|
||||
| content | string | 语音识别原文 |
|
||||
| type | int | 片段类型:0=语音识别,1=声纹检测 |
|
||||
| labels | array | 分类标签 |
|
||||
| labels.details.keywords | array | 自定义敏感词 |
|
||||
| labels.details.libInfos | array | 自定义名单 |
|
||||
| labels.details.hitInfos | array | 命中内容 |
|
||||
|
||||
**video.pictures 结构说明**:
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| type | int | 截图类型 |
|
||||
| url | string | 截图URL |
|
||||
| startTime | int64 | 开始时间(毫秒) |
|
||||
| endTime | int64 | 结束时间(毫秒) |
|
||||
| labels | array | 分类标签 |
|
||||
| frontPics | array | 关联前帧图片 |
|
||||
| backPics | array | 关联后帧图片 |
|
||||
|
||||
---
|
||||
|
||||
## 错误码说明
|
||||
|
||||
| code | 说明 |
|
||||
|------|------|
|
||||
| 0 | 成功 |
|
||||
| 400 | 请求参数错误 |
|
||||
| 500 | 服务器内部错误 |
|
||||
|
||||
**易盾API错误码**:
|
||||
|
||||
| 错误码 | 说明 |
|
||||
|--------|------|
|
||||
| 200 | 成功 |
|
||||
| 401 | 认证失败(SecretID/SecretKey错误) |
|
||||
| 403 | 权限不足 |
|
||||
| 429 | 请求频率超限 |
|
||||
|
||||
---
|
||||
|
||||
## Go代码调用示例
|
||||
|
||||
```go
|
||||
// 文本检测
|
||||
func detectText() (string, error) {
|
||||
req := map[string]interface{}{
|
||||
"data_id": "text-001",
|
||||
"content": "这是一段测试文本",
|
||||
}
|
||||
jsonData, _ := json.Marshal(req)
|
||||
resp, err := http.Post("http://localhost:3002/yidun/detect-text", "application/json", bytes.NewBuffer(jsonData))
|
||||
// ...
|
||||
}
|
||||
|
||||
// 图片检测
|
||||
func detectImage() (string, error) {
|
||||
req := map[string]interface{}{
|
||||
"data_id": "img-001",
|
||||
"image_url": "https://example.com/image.jpg",
|
||||
}
|
||||
jsonData, _ := json.Marshal(req)
|
||||
resp, err := http.Post("http://localhost:3002/yidun/detect-image", "application/json", bytes.NewBuffer(jsonData))
|
||||
// ...
|
||||
}
|
||||
|
||||
// 视频检测
|
||||
func detectVideo() (string, error) {
|
||||
req := map[string]interface{}{
|
||||
"data_id": "video-001",
|
||||
"video_url": "https://example.com/video.mp4",
|
||||
}
|
||||
jsonData, _ := json.Marshal(req)
|
||||
resp, err := http.Post("http://localhost:3002/yidun/detect-video", "application/json", bytes.NewBuffer(jsonData))
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**最后更新**: 2026-05-07
|
||||
29
config.yml
29
config.yml
@@ -46,4 +46,31 @@ consul:
|
||||
address: 116.204.74.41:8500
|
||||
# pass: jiahui8888
|
||||
jaeger: #链路追踪
|
||||
addr: 116.204.74.41:4318
|
||||
addr: 116.204.74.41:4318
|
||||
|
||||
yidun:
|
||||
# 音视频检测配置
|
||||
video:
|
||||
secret_id: "f58a38341ca6227014df7c3bf0e6f16f"
|
||||
secret_key: "526aa631ba5d518aedeb70b5a3b67371"
|
||||
region: "cn-hangzhou"
|
||||
protocol: "https"
|
||||
max_retry_count: 3
|
||||
|
||||
# 图片检测配置
|
||||
image:
|
||||
business_id: "20acccc525cbc5cb6bed3d8f6f6b2f77"
|
||||
secret_id: "9a82f90bfec61eb40d1c95605b894817"
|
||||
secret_key: "f73a78954417a3713c36ec2d14eb2b5f"
|
||||
region: "cn-hangzhou"
|
||||
protocol: "https"
|
||||
max_retry_count: 3
|
||||
|
||||
# 文本检测配置(如需要请补充)
|
||||
text:
|
||||
business_id: "YOUR_TEXT_BUSINESS_ID"
|
||||
secret_id: "YOUR_TEXT_SECRET_ID"
|
||||
secret_key: "YOUR_TEXT_SECRET_KEY"
|
||||
region: "cn-hangzhou"
|
||||
protocol: "https"
|
||||
max_retry_count: 3
|
||||
164
controller/yidun/yidun_controller.go
Normal file
164
controller/yidun/yidun_controller.go
Normal file
@@ -0,0 +1,164 @@
|
||||
package yidun
|
||||
|
||||
import (
|
||||
"cid/service/yidun"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/yidun/yidun-golang-sdk/yidun/service/antispam/text/v5/check/async/single"
|
||||
)
|
||||
|
||||
type yidunController struct{}
|
||||
|
||||
// YidunController 易盾控制器
|
||||
var YidunController = new(yidunController)
|
||||
|
||||
// DetectTextReq 文本检测请求
|
||||
type DetectTextReq struct {
|
||||
DataID string `json:"data_id"`
|
||||
Content string `json:"content" v:"required#待检测文本不能为空"`
|
||||
IP string `json:"ip"`
|
||||
Token string `json:"token"`
|
||||
}
|
||||
|
||||
// DetectImageReq 图片检测请求
|
||||
type DetectImageReq struct {
|
||||
DataID string `json:"data_id"`
|
||||
ImageURL string `json:"image_url" v:"required#图片URL不能为空"`
|
||||
CallbackURL string `json:"callback_url"`
|
||||
}
|
||||
|
||||
// DetectVideoReq 视频检测请求
|
||||
type DetectVideoReq struct {
|
||||
DataID string `json:"data_id"`
|
||||
VideoURL string `json:"video_url" v:"required#视频URL不能为空"`
|
||||
CallbackURL string `json:"callback_url"`
|
||||
}
|
||||
|
||||
// DetectText 文本检测
|
||||
func (c *yidunController) DetectText(ctx context.Context, req *DetectTextReq) (string, error) {
|
||||
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
|
||||
|
||||
businessId := g.Cfg().MustGet(ctx, "yidun.text.business_id").String()
|
||||
sdkReq := single.NewTextAsyncCheckRequest(businessId)
|
||||
sdkReq.SetDataID(req.DataID)
|
||||
sdkReq.SetContent(req.Content)
|
||||
if req.IP != "" {
|
||||
sdkReq.SetIP(req.IP)
|
||||
}
|
||||
if req.Token != "" {
|
||||
sdkReq.SetToken(req.Token)
|
||||
}
|
||||
|
||||
return yidun.TextDetection.DetectText(ctx, sdkReq)
|
||||
}
|
||||
|
||||
// DetectImage 图片检测
|
||||
func (c *yidunController) DetectImage(ctx context.Context, req *DetectImageReq) (*yidun.ImageSubmitResult, error) {
|
||||
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
|
||||
return yidun.ImageDetection.DetectImage(ctx, req.ImageURL, req.DataID, req.CallbackURL)
|
||||
}
|
||||
|
||||
// DetectVideo 视频检测
|
||||
func (c *yidunController) DetectVideo(ctx context.Context, req *DetectVideoReq) (*yidun.VideoSubmitResult, error) {
|
||||
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
|
||||
return yidun.VideoDetection.DetectVideo(ctx, req.VideoURL, req.DataID, req.CallbackURL)
|
||||
}
|
||||
|
||||
// ImageCallbackResult 图片检测回调响应
|
||||
type ImageCallbackResult struct {
|
||||
Code int `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
}
|
||||
|
||||
// ReceiveImageCallback 接收图片检测结果推送
|
||||
func (c *yidunController) ReceiveImageCallback(r *ghttp.Request) {
|
||||
ctx := r.Context()
|
||||
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
|
||||
|
||||
callbackData := r.GetForm("callbackData", "").String()
|
||||
if callbackData == "" {
|
||||
r.Response.WriteJson(ImageCallbackResult{Code: 400, Msg: "callbackData不能为空"})
|
||||
return
|
||||
}
|
||||
|
||||
err := yidun.ImageDetection.ProcessImageCallback(ctx, callbackData)
|
||||
if err != nil {
|
||||
g.Log().Errorf(ctx, "处理图片检测回调失败: %v", err)
|
||||
r.Response.WriteJson(ImageCallbackResult{Code: 500, Msg: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
r.Response.WriteJson(ImageCallbackResult{Code: 200, Msg: "success"})
|
||||
}
|
||||
|
||||
// VideoCallbackResult 视频检测回调响应
|
||||
type VideoCallbackResult struct {
|
||||
Code int `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
}
|
||||
|
||||
// ReceiveVideoCallback 接收视频检测结果推送
|
||||
func (c *yidunController) ReceiveVideoCallback(r *ghttp.Request) {
|
||||
ctx := r.Context()
|
||||
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
|
||||
|
||||
callbackData := r.GetForm("callbackData", "").String()
|
||||
if callbackData == "" {
|
||||
r.Response.WriteJson(VideoCallbackResult{Code: 400, Msg: "callbackData不能为空"})
|
||||
return
|
||||
}
|
||||
|
||||
err := yidun.VideoDetection.ProcessVideoCallback(ctx, callbackData)
|
||||
if err != nil {
|
||||
g.Log().Errorf(ctx, "处理视频检测回调失败: %v", err)
|
||||
r.Response.WriteJson(VideoCallbackResult{Code: 500, Msg: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
r.Response.WriteJson(VideoCallbackResult{Code: 200, Msg: "success"})
|
||||
}
|
||||
|
||||
// GetVideoResult 获取视频检测结果
|
||||
func (c *yidunController) GetVideoResult(r *ghttp.Request) {
|
||||
ctx := r.Context()
|
||||
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
|
||||
|
||||
taskId := r.Get("taskId", "").String()
|
||||
if taskId == "" {
|
||||
r.Response.WriteJson(g.Map{"code": 400, "msg": "taskId不能为空"})
|
||||
return
|
||||
}
|
||||
|
||||
result, err := yidun.VideoDetection.GetVideoResult(ctx, taskId)
|
||||
if err != nil {
|
||||
g.Log().Errorf(ctx, "查询视频检测结果失败: %v", err)
|
||||
r.Response.WriteJson(g.Map{"code": 500, "msg": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
r.Response.WriteJson(result)
|
||||
}
|
||||
|
||||
// GetImageResult 获取图片检测结果
|
||||
func (c *yidunController) GetImageResult(r *ghttp.Request) {
|
||||
ctx := r.Context()
|
||||
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
|
||||
|
||||
taskId := r.Get("taskId", "").String()
|
||||
if taskId == "" {
|
||||
r.Response.WriteJson(g.Map{"code": 400, "msg": "taskId不能为空"})
|
||||
return
|
||||
}
|
||||
|
||||
result, err := yidun.ImageDetection.GetImageResult(ctx, taskId)
|
||||
if err != nil {
|
||||
g.Log().Errorf(ctx, "查询图片检测结果失败: %v", err)
|
||||
r.Response.WriteJson(g.Map{"code": 500, "msg": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
r.Response.WriteJson(result)
|
||||
}
|
||||
14
go.mod
14
go.mod
@@ -7,6 +7,7 @@ require (
|
||||
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.5
|
||||
github.com/gogf/gf/contrib/nosql/redis/v2 v2.9.5
|
||||
github.com/gogf/gf/v2 v2.9.5
|
||||
github.com/yidun/yidun-golang-sdk v1.0.38
|
||||
golang.org/x/net v0.47.0
|
||||
)
|
||||
|
||||
@@ -26,6 +27,7 @@ require (
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/fatih/color v1.18.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||
github.com/go-ego/gse v1.0.2 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-sql-driver/mysql v1.7.1 // indirect
|
||||
@@ -61,14 +63,15 @@ require (
|
||||
github.com/olekukonko/errors v1.1.0 // indirect
|
||||
github.com/olekukonko/ll v0.0.9 // indirect
|
||||
github.com/olekukonko/tablewriter v1.1.0 // indirect
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/r3labs/diff/v2 v2.15.1 // indirect
|
||||
github.com/redis/go-redis/v9 v9.12.1 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/tiger1103/gfast-token v1.0.10 // indirect
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||
github.com/xdg-go/scram v1.1.2 // indirect
|
||||
github.com/xdg-go/stringprep v1.0.4 // indirect
|
||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
||||
github.com/tjfoc/gmsm v1.4.1 // indirect
|
||||
github.com/vcaesar/cedar v0.30.0 // indirect
|
||||
github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect
|
||||
go.mongodb.org/mongo-driver/v2 v2.4.0 // indirect
|
||||
go.opencensus.io v0.23.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
@@ -79,11 +82,10 @@ require (
|
||||
go.opentelemetry.io/otel/sdk v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.38.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.7.1 // indirect
|
||||
golang.org/x/crypto v0.44.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect
|
||||
golang.org/x/sync v0.18.0 // indirect
|
||||
golang.org/x/sys v0.38.0 // indirect
|
||||
golang.org/x/text v0.31.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 // indirect
|
||||
google.golang.org/grpc v1.75.0 // indirect
|
||||
|
||||
59
go.sum
59
go.sum
@@ -1,9 +1,4 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
gitea.com/red-future/common v0.0.6 h1:2Otksfcy5V5JCBcqd2eRKh4WwZ/iAiIhJZMr6uM1x+Q=
|
||||
gitea.com/red-future/common v0.0.6/go.mod h1:UI9N5UUjilbMPF7+/lypZSnqDVHigt14300oSRrAyZg=
|
||||
gitea.com/red-future/common v0.0.7/go.mod h1:JgBczlUF8xA8S0YbvDaMLxvvpmBGgjJA6po+EbodzZA=
|
||||
gitea.com/red-future/common v0.0.9/go.mod h1:JgBczlUF8xA8S0YbvDaMLxvvpmBGgjJA6po+EbodzZA=
|
||||
gitea.com/red-future/common v0.0.11/go.mod h1:B8syUI4XbLCDQSeRHURYxEwnWw8mEFgmqCxjC+lM+NU=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
|
||||
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
@@ -68,6 +63,8 @@ github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
||||
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
|
||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/go-ego/gse v1.0.2 h1:+27lYFPhQEhA9igtdOsJPRKYL/k3TwYsxBF5jr6KFv4=
|
||||
github.com/go-ego/gse v1.0.2/go.mod h1:Fy35G+q7VV7Et1zIKO8o/sW1kkugV3znXap/lF/11zc=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
@@ -105,12 +102,14 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
@@ -133,8 +132,7 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
|
||||
github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4=
|
||||
github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc=
|
||||
@@ -243,6 +241,8 @@ github.com/olekukonko/tablewriter v1.1.0/go.mod h1:5c+EBPeSqvXnLLgkm9isDdzR3wjfB
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
|
||||
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
@@ -264,6 +264,8 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/r3labs/diff/v2 v2.15.1 h1:EOrVqPUzi+njlumoqJwiS/TgGgmZo83619FNDB9xQUg=
|
||||
github.com/r3labs/diff/v2 v2.15.1/go.mod h1:I8noH9Fc2fjSaMxqF3G2lhDdC0b+JXCfyx85tWFM9kc=
|
||||
github.com/redis/go-redis/v9 v9.12.1 h1:k5iquqv27aBtnTm2tIkROUDp8JBXhXZIVu1InSgvovg=
|
||||
github.com/redis/go-redis/v9 v9.12.1/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
@@ -283,24 +285,26 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/tiger1103/gfast-token v1.0.10 h1:fNiBE/Dq5iTHvTGlCx3DmXa2o4hr0NtumFpffZ39k6s=
|
||||
github.com/tiger1103/gfast-token v1.0.10/go.mod h1:a/21mxmj7zFeNvjhZSC0XpEAFHfb1aT2k6DXnufFU1s=
|
||||
github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
|
||||
github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=
|
||||
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
|
||||
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
|
||||
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
|
||||
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
|
||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
|
||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
|
||||
github.com/vcaesar/cedar v0.30.0 h1:9fSDpM7FTjjUdPiBUUa0MWYMRGSEcqgFXvppZcZ4d7Y=
|
||||
github.com/vcaesar/cedar v0.30.0/go.mod h1:lyuGvALuZZDPNXwpzv/9LyxW+8Y6faN7zauFezNsnik=
|
||||
github.com/vcaesar/tt v0.20.1 h1:D/jUeeVCNbq3ad8M7hhtB3J9x5RZ6I1n1eZ0BJp7M+4=
|
||||
github.com/vcaesar/tt v0.20.1/go.mod h1:cH2+AwGAJm19Wa6xvEa+0r+sXDJBT0QgNQey6mwqLeU=
|
||||
github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI=
|
||||
github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
|
||||
github.com/yidun/yidun-golang-sdk v1.0.38 h1:4NjQdt2GGMgLToB2+zTA0L4YRpqY3ZQjVpl2ot1gwfk=
|
||||
github.com/yidun/yidun-golang-sdk v1.0.38/go.mod h1:+JGdWbkUvLi9uKTtHI+nrxajulfZKA7BXDPlzt1RCsU=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.mongodb.org/mongo-driver/v2 v2.4.0 h1:Oq6BmUAAFTzMeh6AonuDlgZMuAuEiUxoAD1koK5MuFo=
|
||||
go.mongodb.org/mongo-driver/v2 v2.4.0/go.mod h1:jHeEDJHJq7tm6ZF45Issun9dbogjfnPySb1vXA7EeAI=
|
||||
go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
|
||||
@@ -330,19 +334,15 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.44.0 h1:A97SsFvM3AIwEEmTBiaxPPTYpDC47w720rdiiUvgoAU=
|
||||
golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc=
|
||||
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20250128144449-3edf0e91c1ae h1:COZdc9Ut6wLq7MO9GIYxfZl4n4ScmgqQLoHocKXrxco=
|
||||
golang.org/x/exp v0.0.0-20250128144449-3edf0e91c1ae/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU=
|
||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw=
|
||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
|
||||
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -351,15 +351,16 @@ golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73r
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
@@ -370,7 +371,6 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
|
||||
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -391,25 +391,19 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
|
||||
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
|
||||
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@@ -421,7 +415,6 @@ golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtn
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
|
||||
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -432,6 +425,9 @@ gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
@@ -443,6 +439,7 @@ google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZi
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4=
|
||||
google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
|
||||
|
||||
14
main.go
14
main.go
@@ -4,12 +4,13 @@ import (
|
||||
"cid/controller/app"
|
||||
"cid/controller/data"
|
||||
"cid/controller/mapping"
|
||||
controllerYidun "cid/controller/yidun"
|
||||
serviceYidun "cid/service/yidun"
|
||||
"fmt"
|
||||
|
||||
_ "gitea.com/red-future/common/config"
|
||||
|
||||
_ "gitea.com/red-future/common/consul"
|
||||
"gitea.com/red-future/common/http"
|
||||
"gitea.com/red-future/common/jaeger"
|
||||
_ "gitea.com/red-future/common/ragflow" // RAGFlow 客户端自动初始化
|
||||
_ "github.com/gogf/gf/contrib/drivers/mysql/v2"
|
||||
_ "github.com/gogf/gf/contrib/nosql/redis/v2"
|
||||
"golang.org/x/net/context"
|
||||
@@ -19,6 +20,11 @@ func main() {
|
||||
ctx := context.Background()
|
||||
defer jaeger.ShutDown(ctx)
|
||||
|
||||
// 初始化易盾客户端
|
||||
if err := serviceYidun.InitYidunClients(ctx); err != nil {
|
||||
panic(fmt.Sprintf("初始化易盾客户端失败: %v", err))
|
||||
}
|
||||
|
||||
http.RouteRegister([]interface{}{
|
||||
// 平台管理
|
||||
data.Platform,
|
||||
@@ -30,6 +36,8 @@ func main() {
|
||||
mapping.DataMapping,
|
||||
// 应用管理
|
||||
app.Application,
|
||||
// 易盾内容安全
|
||||
controllerYidun.YidunController,
|
||||
})
|
||||
select {}
|
||||
}
|
||||
|
||||
389
service/yidun/image_detection_service.go
Normal file
389
service/yidun/image_detection_service.go
Normal file
@@ -0,0 +1,389 @@
|
||||
package yidun
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/yidun/yidun-golang-sdk/yidun/service/antispam/image/v5/callback"
|
||||
"github.com/yidun/yidun-golang-sdk/yidun/service/antispam/image/v5/check"
|
||||
"github.com/yidun/yidun-golang-sdk/yidun/service/antispam/image/v5/check/async"
|
||||
imagesync "github.com/yidun/yidun-golang-sdk/yidun/service/antispam/image/v5/check/sync"
|
||||
)
|
||||
|
||||
// ImageDetectionService 图片检测服务
|
||||
type ImageDetectionService struct{}
|
||||
|
||||
var ImageDetection = new(ImageDetectionService)
|
||||
|
||||
var (
|
||||
ErrImageStillProcessing = errors.New("图片仍在检测中,请稍后重试")
|
||||
ErrImageResultNotFound = errors.New("未找到图片检测结果")
|
||||
)
|
||||
|
||||
// ImageSubmitResult 图片检测提交结果
|
||||
type ImageSubmitResult struct {
|
||||
TaskID string `json:"taskId"` // 任务ID
|
||||
Name string `json:"name"` // 图片唯一标识
|
||||
DataID string `json:"dataId"` // 客户图片唯一标识
|
||||
DealingCount int64 `json:"dealingCount"` // 缓冲池排队待处理数据量
|
||||
}
|
||||
|
||||
// DetectImage 提交图片异步检测任务,返回完整响应
|
||||
func (s *ImageDetectionService) DetectImage(ctx context.Context, imageURL, dataID string, callbackURL string) (*ImageSubmitResult, 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 := async.NewImageV5AsyncCheckRequest(businessId)
|
||||
imageBean := check.NewImageBeanRequest()
|
||||
imageBean.SetData(imageURL)
|
||||
imageBean.SetName(dataID)
|
||||
imageBean.SetType(1) // 1: 图片URL
|
||||
if callbackURL != "" {
|
||||
imageBean.SetCallbackUrl(callbackURL)
|
||||
}
|
||||
request.SetImages([]check.ImageBeanRequest{*imageBean})
|
||||
|
||||
// 调用API
|
||||
response, err := DefaultClients.ImageClient.ImageAsyncCheck(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())
|
||||
}
|
||||
|
||||
result := &ImageSubmitResult{
|
||||
DealingCount: 0,
|
||||
}
|
||||
if response.Result != nil {
|
||||
if response.Result.DealingCount != nil {
|
||||
result.DealingCount = *response.Result.DealingCount
|
||||
}
|
||||
if response.Result.CheckImages != nil && len(*response.Result.CheckImages) > 0 {
|
||||
detail := (*response.Result.CheckImages)[0]
|
||||
if detail.TaskId != nil {
|
||||
result.TaskID = *detail.TaskId
|
||||
}
|
||||
if detail.Name != nil {
|
||||
result.Name = *detail.Name
|
||||
}
|
||||
if detail.DataId != nil {
|
||||
result.DataID = *detail.DataId
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g.Log().Infof(ctx, "图片检测任务提交成功, taskID: %s, dealingCount: %d", result.TaskID, result.DealingCount)
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// ImageResult 图片检测完整结果
|
||||
type ImageResult struct {
|
||||
TaskID string `json:"taskId"` // 任务ID
|
||||
Status int `json:"status"` // 检测状态:0=未开始,1=检测中,2=检测成功,3=检测失败
|
||||
Suggestion int `json:"suggestion"` // 处置建议:0=通过,1=嫌疑,2=不通过
|
||||
Label int `json:"label"` // 垃圾类型
|
||||
ResultType int `json:"resultType"` // 结果类型:1=机器结果,2=人审结果
|
||||
DataID string `json:"dataId"` // 数据ID
|
||||
Name string `json:"name"` // 图片标识
|
||||
CensorTime int64 `json:"censorTime"` // 审核完成时间(毫秒)
|
||||
Url string `json:"url"` // 图片URL
|
||||
|
||||
// 完整证据信息
|
||||
Antispam *imagesync.ImageV5AntispamResp `json:"antispam,omitempty"` // 反垃圾检测结果
|
||||
Ocr *imagesync.ImageV5OcrResp `json:"ocr,omitempty"` // OCR文字识别结果
|
||||
Face *imagesync.ImageV5FaceResp `json:"face,omitempty"` // 人脸检测结果
|
||||
Quality *imagesync.ImageV5QualityResp `json:"quality,omitempty"` // 图片质量结果
|
||||
Logo *imagesync.ImageV5LogoResp `json:"logo,omitempty"` // Logo识别结果
|
||||
Discern *imagesync.ImageV5DiscernResp `json:"discern,omitempty"` // 图片识别结果
|
||||
Ad *imagesync.ImageV5AdResp `json:"ad,omitempty"` // 广告识别结果
|
||||
UserRisk *imagesync.ImageV5UserRiskResp `json:"userRisk,omitempty"` // 用户画像结果
|
||||
Anticheat *imagesync.ImageAnticheatV5Resp `json:"anticheat,omitempty"` // 反作弊结果
|
||||
RiskControl *imagesync.ImageRiskControlV5Resp `json:"riskControl,omitempty"` // 智能风控结果
|
||||
Aigc *imagesync.ImageV5AigcResp `json:"aigc,omitempty"` // AIGC识别结果
|
||||
LlmCheckInfo *[]imagesync.LlmCheckInfo `json:"llmCheckInfo,omitempty"` // 大模型检测结果
|
||||
}
|
||||
|
||||
// GetImageResult 获取图片检测结果(轮询模式)
|
||||
func (s *ImageDetectionService) GetImageResult(ctx context.Context, taskID string) (*ImageResult, error) {
|
||||
if DefaultClients == nil || DefaultClients.ImageClient == nil {
|
||||
return nil, fmt.Errorf("易盾图片检测客户端未初始化")
|
||||
}
|
||||
|
||||
businessId := g.Cfg().MustGet(ctx, "yidun.image.business_id").String()
|
||||
g.Log().Infof(ctx, "查询图片检测结果, taskID: %s", taskID)
|
||||
|
||||
req := callback.NewImageCallbackRequest(businessId)
|
||||
req.SetYidunRequestId(taskID)
|
||||
|
||||
response, err := DefaultClients.ImageClient.ImageCallback(req)
|
||||
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, "未找到图片检测结果, taskID: %s", taskID)
|
||||
return nil, ErrImageStillProcessing
|
||||
}
|
||||
|
||||
// 查找指定taskID的结果
|
||||
for _, item := range *response.Result {
|
||||
if item.Antispam != nil && item.Antispam.TaskId != nil && *item.Antispam.TaskId == taskID {
|
||||
result := &ImageResult{
|
||||
Antispam: item.Antispam,
|
||||
Ocr: item.Ocr,
|
||||
Face: item.Face,
|
||||
Quality: item.Quality,
|
||||
Logo: item.Logo,
|
||||
Discern: item.Discern,
|
||||
Ad: item.Ad,
|
||||
UserRisk: item.UserRisk,
|
||||
Anticheat: item.Anticheat,
|
||||
RiskControl: item.RiskControl,
|
||||
Aigc: item.Aigc,
|
||||
LlmCheckInfo: item.LlmCheckInfo,
|
||||
}
|
||||
|
||||
result.TaskID = taskID
|
||||
if item.Antispam.Status != nil {
|
||||
result.Status = *item.Antispam.Status
|
||||
}
|
||||
if item.Antispam.Suggestion != nil {
|
||||
result.Suggestion = *item.Antispam.Suggestion
|
||||
}
|
||||
if item.Antispam.Label != nil {
|
||||
result.Label = *item.Antispam.Label
|
||||
}
|
||||
if item.Antispam.ResultType != nil {
|
||||
result.ResultType = *item.Antispam.ResultType
|
||||
}
|
||||
if item.Antispam.DataId != nil {
|
||||
result.DataID = *item.Antispam.DataId
|
||||
}
|
||||
if item.Antispam.Name != nil {
|
||||
result.Name = *item.Antispam.Name
|
||||
}
|
||||
if item.Antispam.CensorTime != nil {
|
||||
result.CensorTime = *item.Antispam.CensorTime
|
||||
}
|
||||
if item.Antispam.Url != nil {
|
||||
result.Url = *item.Antispam.Url
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
}
|
||||
|
||||
g.Log().Warningf(ctx, "未找到指定的taskID: %s", taskID)
|
||||
return nil, ErrImageResultNotFound
|
||||
}
|
||||
|
||||
// ImageCallbackData 推送模式回调数据完整结构
|
||||
type ImageCallbackData struct {
|
||||
Antispam *ImageCallbackAntispam `json:"antispam"` // 反垃圾检测结果
|
||||
}
|
||||
|
||||
type ImageCallbackAntispam struct {
|
||||
TaskId string `json:"taskId"` // 任务ID
|
||||
Name string `json:"name"` // 图片名称
|
||||
DataId string `json:"dataId"` // 客户数据ID
|
||||
Suggestion int `json:"suggestion"` // 处置建议:0=通过,1=嫌疑,2=不通过
|
||||
Label int `json:"label"` // 一级分类
|
||||
SecondLabel string `json:"secondLabel"` // 二级分类
|
||||
ThirdLabel string `json:"thirdLabel"` // 三级分类
|
||||
RiskDescription string `json:"riskDescription"` // 风险描述
|
||||
Status int `json:"status"` // 检测状态:0=未开始,1=检测中,2=检测成功,3=检测失败
|
||||
ResultType int `json:"resultType"` // 结果类型:1=机器结果,2=人审结果
|
||||
CensorTime int64 `json:"censorTime"` // 审核完成时间
|
||||
CensorSource int `json:"censorSource"` // 审核来源
|
||||
CensorRound int `json:"censorRound"` // 审核轮数
|
||||
CensorLabels []*CensorLabel `json:"censorLabels"` // 审核标签
|
||||
Remark string `json:"remark"` // 审核备注
|
||||
OverAllMarkDesc string `json:"overAllMarkDesc"` // 整体审核备注
|
||||
DetailMarks []*DetailMarkInfo `json:"detailMarks"` // 细节标注
|
||||
Labels []*ImageLabelInfo `json:"labels"` // 分类标签详情
|
||||
Url string `json:"url"` // 图片URL
|
||||
ImgMd5 string `json:"imgMd5"` // 图片MD5
|
||||
FrameSize int `json:"frameSize"` // 分帧数
|
||||
CustomLabels []*CustomLabelInfo `json:"customLabels"` // 客户自定义标签
|
||||
CensorExtension *CensorExtensionInfo `json:"censorExtension"` // 人审拓展字段
|
||||
StrategyVersions []*StrategyVersionInfo `json:"strategyVersions"` // 策略版本
|
||||
HitType int `json:"hitType"` // 命中策略类型
|
||||
StrategyType int `json:"strategyType"` // 策略类型:1=公有策略,2=私有策略
|
||||
HitResult string `json:"hitResult"` // 命中结果
|
||||
HitSource int `json:"hitSource"` // 特征添加来源
|
||||
Hidden bool `json:"hidden"` // 是否有隐藏文件
|
||||
HiddenFormat string `json:"hiddenFormat"` // 隐藏文件格式
|
||||
PublicOpinionInfo string `json:"publicOpinionInfo"` // 舆情信息
|
||||
}
|
||||
|
||||
// CensorLabel 审核标签信息
|
||||
type CensorLabel struct {
|
||||
Code string `json:"code"` // 审核标签编码
|
||||
CustomCode string `json:"customCode"` // 自定义标签编码
|
||||
Name string `json:"name"` // 审核标签名称
|
||||
Desc string `json:"desc"` // 审核标签描述
|
||||
ParentLabelId string `json:"parentLabelId"` // 父标签ID
|
||||
Depth int `json:"depth"` // 标签深度
|
||||
}
|
||||
|
||||
// ImageLabelInfo 分类标签详情
|
||||
type ImageLabelInfo struct {
|
||||
Label int `json:"label"` // 标签类型
|
||||
Level int `json:"level"` // 判断结果:0=正常,1=不确定,2=确定
|
||||
Rate float32 `json:"rate"` // 置信度
|
||||
SubLabels []*SubLabelDetailInfo `json:"subLabels"` // 二级分类详情
|
||||
Explain string `json:"explain"` // LLM解释说明
|
||||
IsLlmCheck bool `json:"isLlmCheck"` // 是否LLM检测命中
|
||||
}
|
||||
|
||||
// SubLabelDetailInfo 二级分类详情
|
||||
type SubLabelDetailInfo struct {
|
||||
SubLabel string `json:"subLabel"` // 二级分类标签
|
||||
Level int `json:"level"` // 级别
|
||||
SubLabelDepth int `json:"subLabelDepth"` // 细分类层级
|
||||
SecondLabel string `json:"secondLabel"` // 二级分类
|
||||
ThirdLabel string `json:"thirdLabel"` // 三级分类
|
||||
RiskDescription string `json:"riskDescription"` // 风险描述
|
||||
HitStrategy int `json:"hitStrategy"` // 命中标识
|
||||
Rate float32 `json:"rate"` // 置信度
|
||||
Explain string `json:"explain"` // 解释说明
|
||||
IsLlmCheck bool `json:"isLlmCheck"` // 是否LLM命中
|
||||
Details *SubLabelHitDetails `json:"details"` // 命中详情
|
||||
}
|
||||
|
||||
// SubLabelHitDetails 二级分类命中详情
|
||||
type SubLabelHitDetails struct {
|
||||
Keywords []*HitKeywordInfo `json:"keywords"` // 敏感词命中
|
||||
LibInfos []*HitLibInfo `json:"libInfos"` // 图片名单命中
|
||||
HitInfos []*HitInfo `json:"hitInfos"` // 其他命中信息
|
||||
Anticheat *AnticheatHitInfo `json:"anticheat"` // 反作弊命中
|
||||
Llm *LlmKeywordInfo `json:"llm"` // 大模型关键词
|
||||
}
|
||||
|
||||
// HitKeywordInfo 敏感词命中信息
|
||||
type HitKeywordInfo struct {
|
||||
Type int `json:"type"` // 命中类型
|
||||
Word string `json:"word"` // 敏感词
|
||||
Entity string `json:"entity"` // 图片名单URL
|
||||
HitCount int `json:"hitCount"` // 命中次数
|
||||
Value string `json:"value"` // 值
|
||||
Group string `json:"group"` // 分组
|
||||
X1 float32 `json:"x1"` // 坐标
|
||||
Y1 float32 `json:"y1"` // 坐标
|
||||
X2 float32 `json:"x2"` // 坐标
|
||||
Y2 float32 `json:"y2"` // 坐标
|
||||
ReleaseTime int64 `json:"releaseTime"` // 释放时间
|
||||
StrategyGroupName string `json:"strategyGroupName"` // 策略组名称
|
||||
StrategyGroupId int64 `json:"strategyGroupId"` // 策略组ID
|
||||
}
|
||||
|
||||
// HitLibInfo 图片名单命中信息
|
||||
type HitLibInfo struct {
|
||||
Type int `json:"type"` // 命中类型
|
||||
Entity string `json:"entity"` // 图片名单URL
|
||||
HitCount int `json:"hitCount"` // 命中次数
|
||||
ReleaseTime int64 `json:"releaseTime"` // 释放时间
|
||||
StrategyGroupName string `json:"strategyGroupName"` // 策略组名称
|
||||
StrategyGroupId int64 `json:"strategyGroupId"` // 策略组ID
|
||||
}
|
||||
|
||||
// HitInfo 其他命中信息
|
||||
type HitInfo struct {
|
||||
Type int `json:"type"` // 命中类型
|
||||
Value string `json:"value"` // 值
|
||||
Group string `json:"group"` // 分组
|
||||
X1 float32 `json:"x1"` // 坐标
|
||||
Y1 float32 `json:"y1"` // 坐标
|
||||
X2 float32 `json:"x2"` // 坐标
|
||||
Y2 float32 `json:"y2"` // 坐标
|
||||
}
|
||||
|
||||
// AnticheatHitInfo 反作弊命中信息
|
||||
type AnticheatHitInfo struct {
|
||||
HitType int `json:"hitType"` // 命中类型
|
||||
}
|
||||
|
||||
// LlmKeywordInfo 大模型关键词信息
|
||||
type LlmKeywordInfo struct {
|
||||
Keyword string `json:"keyword"` // 关键词
|
||||
}
|
||||
|
||||
// DetailMarkInfo 细节标注信息
|
||||
type DetailMarkInfo struct {
|
||||
Position []*MarkPointInfo `json:"position"` // 标注位置
|
||||
CensorLabels []*CensorLabel `json:"censorLabels"` // 标注标签
|
||||
Desc string `json:"desc"` // 标注备注
|
||||
}
|
||||
|
||||
// MarkPointInfo 标注点坐标
|
||||
type MarkPointInfo struct {
|
||||
X float32 `json:"x"` // X坐标
|
||||
Y float32 `json:"y"` // Y坐标
|
||||
}
|
||||
|
||||
// CustomLabelInfo 客户自定义标签
|
||||
type CustomLabelInfo struct {
|
||||
Name string `json:"name"` // 名称
|
||||
Code string `json:"code"` // 编码
|
||||
Depth int `json:"depth"` // 深度
|
||||
}
|
||||
|
||||
// CensorExtensionInfo 人审拓展字段
|
||||
type CensorExtensionInfo struct {
|
||||
QualityInspectionTaskId string `json:"qualityInspectionTaskId"` // 质检任务ID
|
||||
InspTaskCreateTime float64 `json:"inspTaskCreateTime"` // 质检任务创建时间
|
||||
QualityInspectionType float64 `json:"qualityInspectionType"` // 质检类型
|
||||
}
|
||||
|
||||
// StrategyVersionInfo 策略版本信息
|
||||
type StrategyVersionInfo struct {
|
||||
Label int `json:"label"` // 垃圾类别
|
||||
Version string `json:"version"` // 版本号
|
||||
}
|
||||
|
||||
// ProcessImageCallback 处理图片检测回调(推送模式)
|
||||
func (s *ImageDetectionService) ProcessImageCallback(ctx context.Context, callbackData string) error {
|
||||
if callbackData == "" {
|
||||
return fmt.Errorf("回调数据不能为空")
|
||||
}
|
||||
|
||||
var data ImageCallbackData
|
||||
if err := json.Unmarshal([]byte(callbackData), &data); err != nil {
|
||||
g.Log().Errorf(ctx, "解析回调数据失败: %v", err)
|
||||
return fmt.Errorf("解析回调数据失败: %w", err)
|
||||
}
|
||||
|
||||
if data.Antispam == nil {
|
||||
return fmt.Errorf("回调数据格式错误:缺少antispam字段")
|
||||
}
|
||||
|
||||
g.Log().Infof(ctx, "处理图片检测结果 - taskId: %s, suggestion: %d, resultType: %d",
|
||||
data.Antispam.TaskId, data.Antispam.Suggestion, data.Antispam.ResultType)
|
||||
|
||||
// TODO: 业务逻辑,如保存数据库、触发后续流程等
|
||||
// 可使用完整字段:data.Antispam.Labels, data.Antispam.CensorLabels, data.Antispam.Remark 等
|
||||
|
||||
return nil
|
||||
}
|
||||
51
service/yidun/text_detection_service.go
Normal file
51
service/yidun/text_detection_service.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package yidun
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/yidun/yidun-golang-sdk/yidun/service/antispam/text/v5/check/async/single"
|
||||
)
|
||||
|
||||
// TextDetectionService 文本检测服务
|
||||
type TextDetectionService struct{}
|
||||
|
||||
var TextDetection = new(TextDetectionService)
|
||||
|
||||
// DetectText 提交文本异步检测任务
|
||||
func (s *TextDetectionService) DetectText(ctx context.Context, req *single.TextAsyncCheckRequest) (string, error) {
|
||||
if DefaultClients == nil || DefaultClients.TextClient == nil {
|
||||
return "", fmt.Errorf("易盾文本检测客户端未初始化")
|
||||
}
|
||||
|
||||
response, err := DefaultClients.TextClient.AsyncCheckText(req)
|
||||
if err != nil {
|
||||
g.Log().Errorf(ctx, "文本检测提交失败: %v", err)
|
||||
return "", fmt.Errorf("文本检测提交失败: %w", err)
|
||||
}
|
||||
|
||||
if response.GetCode() != 200 {
|
||||
g.Log().Errorf(ctx, "文本检测API错误: code=%d, msg=%s", response.GetCode(), response.GetMsg())
|
||||
return "", fmt.Errorf("文本检测API错误: code=%d, msg=%s", response.GetCode(), response.GetMsg())
|
||||
}
|
||||
|
||||
var taskID string
|
||||
if response.Result != nil && len(response.Result.CheckTexts) > 0 {
|
||||
taskID = *response.Result.CheckTexts[0].TaskID
|
||||
}
|
||||
|
||||
g.Log().Infof(ctx, "文本检测任务提交成功, taskID: %s", taskID)
|
||||
return taskID, nil
|
||||
}
|
||||
|
||||
// GetTextResult 获取文本检测结果
|
||||
func (s *TextDetectionService) GetTextResult(ctx context.Context, taskID string) (interface{}, error) {
|
||||
if DefaultClients == nil || DefaultClients.TextClient == nil {
|
||||
return nil, fmt.Errorf("易盾文本检测客户端未初始化")
|
||||
}
|
||||
|
||||
g.Log().Infof(ctx, "查询文本检测结果, taskID: %s", taskID)
|
||||
// TODO: 根据实际业务需求实现查询逻辑
|
||||
return nil, nil
|
||||
}
|
||||
714
service/yidun/video_detection_service.go
Normal file
714
service/yidun/video_detection_service.go
Normal file
@@ -0,0 +1,714 @@
|
||||
package yidun
|
||||
|
||||
import (
|
||||
"context"
|
||||
"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"
|
||||
videocallback "github.com/yidun/yidun-golang-sdk/yidun/service/antispam/video/callback/v4/response"
|
||||
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 视频检测服务
|
||||
type VideoDetectionService struct{}
|
||||
|
||||
var VideoDetection = new(VideoDetectionService)
|
||||
|
||||
var (
|
||||
ErrVideoStillProcessing = errors.New("视频仍在检测中,请稍后重试")
|
||||
ErrVideoResultNotFound = errors.New("未找到视频检测结果")
|
||||
)
|
||||
|
||||
// VideoSubmitResult 视频检测提交结果
|
||||
type VideoSubmitResult struct {
|
||||
TaskID string `json:"taskId"` // 任务ID
|
||||
DataID string `json:"dataId"` // 数据ID
|
||||
DealingCount int64 `json:"dealingCount"` // 缓冲池排队待处理数据量
|
||||
}
|
||||
|
||||
// DetectVideo 提交视频检测任务,返回完整响应
|
||||
func (s *VideoDetectionService) DetectVideo(ctx context.Context, videoURL, dataID string, callbackURL string) (*VideoSubmitResult, error) {
|
||||
if DefaultClients == nil || DefaultClients.VideoClient == nil {
|
||||
return nil, fmt.Errorf("易盾视频检测客户端未初始化")
|
||||
}
|
||||
|
||||
if videoURL == "" {
|
||||
return nil, fmt.Errorf("视频URL不能为空")
|
||||
}
|
||||
|
||||
g.Log().Infof(ctx, "视频检测任务提交, url: %s", videoURL)
|
||||
|
||||
// 创建请求
|
||||
req := vsrequest.NewVideoSolutionSubmitV2Req()
|
||||
req.SetURL(videoURL)
|
||||
req.SetDataID(dataID)
|
||||
req.SetUniqueKey(dataID)
|
||||
if callbackURL != "" {
|
||||
req.SetCallbackURL(callbackURL)
|
||||
}
|
||||
|
||||
// 调用API
|
||||
response, err := DefaultClients.VideoClient.Submit(req)
|
||||
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())
|
||||
}
|
||||
|
||||
result := &VideoSubmitResult{}
|
||||
if response.Result != nil {
|
||||
if response.Result.TaskID != nil {
|
||||
result.TaskID = *response.Result.TaskID
|
||||
}
|
||||
if response.Result.DataID != nil {
|
||||
result.DataID = *response.Result.DataID
|
||||
}
|
||||
if response.Result.DealingCount != nil {
|
||||
result.DealingCount = *response.Result.DealingCount
|
||||
}
|
||||
}
|
||||
|
||||
g.Log().Infof(ctx, "视频检测任务提交成功, taskID: %s, dealingCount: %d", result.TaskID, result.DealingCount)
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// VideoResult 视频检测完整结果
|
||||
// 包含易盾返回的完整检测信息:文本、图片、音频、ASR等
|
||||
type VideoResult struct {
|
||||
TaskID string `json:"taskId"` // 任务ID
|
||||
Status int `json:"status"` // 检测状态:0=未开始,1=检测中,2=检测完成
|
||||
Suggestion int `json:"suggestion"` // 处置建议:0=通过,1=嫌疑,2=不通过
|
||||
Label int `json:"label"` // 垃圾类型
|
||||
ResultType int `json:"resultType"` // 结果类型:1=机器结果,2=人审结果
|
||||
DataID string `json:"dataId"` // 数据ID
|
||||
CensorTime int64 `json:"censorTime"` // 审核完成时间(毫秒)
|
||||
Duration int64 `json:"duration"` // 视频时长(毫秒)
|
||||
|
||||
// 完整证据信息
|
||||
Antispam *callbackresponse.VideoSolutionAntispamCallbackV2Response `json:"antispam,omitempty"` // 反垃圾检测结果
|
||||
Language *audiocallback.AudioLanguageCallbackV4Response `json:"language,omitempty"` // 语言检测结果
|
||||
Voice *audiocallback.AudioVoiceCallbackV4Response `json:"voice,omitempty"` // 语音识别结果
|
||||
Asr *audiocallback.AudioAsrCallbackV4Response `json:"asr,omitempty"` // ASR语音转文字结果
|
||||
Ocr *videocallback.VideoCallbackOcrV4Response `json:"ocr,omitempty"` // OCR文字识别结果
|
||||
Discern *videocallback.VideoCallbackDiscernV4Response `json:"discern,omitempty"` // 画面识别结果
|
||||
Logo *videocallback.VideoCallbackLogoV4Response `json:"logo,omitempty"` // Logo识别结果
|
||||
Face *videocallback.VideoCallbackFaceV4Response `json:"face,omitempty"` // 人脸识别结果
|
||||
Aigc *videocallback.VideoCallbackAigcV4Response `json:"aigc,omitempty"` // AIGC识别结果
|
||||
Quality *callbackresponse.VideoSolutionQualityCallbackV2Response `json:"quality,omitempty"` // 音视频质量检测结果
|
||||
}
|
||||
|
||||
// GetVideoResult 获取视频检测结果(轮询模式)
|
||||
// 返回完整的检测详情,包括文本、图片、音频、ASR等
|
||||
func (s *VideoDetectionService) GetVideoResult(ctx context.Context, taskID string) (*VideoResult, error) {
|
||||
if DefaultClients == nil || DefaultClients.VideoClient == nil {
|
||||
return nil, fmt.Errorf("易盾视频检测客户端未初始化")
|
||||
}
|
||||
|
||||
g.Log().Infof(ctx, "查询视频检测结果, taskID: %s", taskID)
|
||||
|
||||
req := callbackrequest.NewVideoSolutionCallbackV2Request()
|
||||
req.SetYidunRequestId(taskID)
|
||||
response, err := DefaultClients.VideoClient.Callback(req)
|
||||
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, "未找到视频检测结果, taskID: %s", taskID)
|
||||
return nil, ErrVideoStillProcessing
|
||||
}
|
||||
|
||||
// 查找指定taskID的结果
|
||||
for _, item := range *response.Result {
|
||||
if item.Antispam != nil && item.Antispam.TaskID != nil && *item.Antispam.TaskID == taskID {
|
||||
result := &VideoResult{
|
||||
Antispam: item.Antispam,
|
||||
Language: item.Language,
|
||||
Voice: item.Voice,
|
||||
Asr: item.Asr,
|
||||
Ocr: item.Ocr,
|
||||
Discern: item.Discern,
|
||||
Logo: item.Logo,
|
||||
Face: item.Face,
|
||||
Aigc: item.Aigc,
|
||||
Quality: item.Quality,
|
||||
}
|
||||
|
||||
result.TaskID = taskID
|
||||
if item.Antispam.Status != nil {
|
||||
result.Status = *item.Antispam.Status
|
||||
}
|
||||
if item.Antispam.Suggestion != nil {
|
||||
result.Suggestion = *item.Antispam.Suggestion
|
||||
}
|
||||
if item.Antispam.Label != nil {
|
||||
result.Label = *item.Antispam.Label
|
||||
}
|
||||
if item.Antispam.ResultType != nil {
|
||||
result.ResultType = *item.Antispam.ResultType
|
||||
}
|
||||
if item.Antispam.DataID != nil {
|
||||
result.DataID = *item.Antispam.DataID
|
||||
}
|
||||
if item.Antispam.CensorTime != nil {
|
||||
result.CensorTime = *item.Antispam.CensorTime
|
||||
}
|
||||
if item.Antispam.Duration != nil {
|
||||
result.Duration = *item.Antispam.Duration
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
}
|
||||
|
||||
g.Log().Warningf(ctx, "未找到指定的taskID: %s", taskID)
|
||||
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
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// 视频检测结果推送模式(易盾主动回调)
|
||||
// =============================================================================
|
||||
|
||||
// VideoCallbackData 推送模式回调数据完整结构
|
||||
type VideoCallbackData struct {
|
||||
Antispam *VideoCallbackAntispam `json:"antispam"` // 反垃圾检测结果
|
||||
}
|
||||
|
||||
type VideoCallbackAntispam struct {
|
||||
TaskID string `json:"taskId"` // 任务ID
|
||||
DataID string `json:"dataId"` // 客户数据ID
|
||||
Callback string `json:"callback"` // 回调参数
|
||||
Suggestion int `json:"suggestion"` // 处置建议:0=通过,1=嫌疑,2=不通过
|
||||
Status int `json:"status"` // 检测状态:0=未开始,1=检测中,2=检测成功,3=检测失败
|
||||
ResultType int `json:"resultType"` // 结果类型:1=机器结果,2=人审结果
|
||||
CensorRound int `json:"censorRound"` // 人审轮次
|
||||
Censor string `json:"censor"` // 人审操作人
|
||||
CensorSource int `json:"censorSource"` // 审核来源:0=易盾人审,1=客户人审,2=易盾机审
|
||||
CheckTime int64 `json:"checkTime"` // 机器检测结束时间
|
||||
CensorTime int64 `json:"censorTime"` // 人工审核完成时间
|
||||
Duration int64 `json:"duration"` // 音视频时长(毫秒)
|
||||
DurationMs int64 `json:"durationMs"` // 音频时长(毫秒)
|
||||
Label int `json:"label"` // 一级垃圾类型
|
||||
SecondLabel string `json:"secondLabel"` // 二级垃圾类型
|
||||
ThirdLabel string `json:"thirdLabel"` // 三级垃圾类型
|
||||
RiskDescription string `json:"riskDescription"` // 风险描述
|
||||
PicCount int64 `json:"picCount"` // 截图数量
|
||||
CensorLabels []*VideoCensorLabel `json:"censorLabels"` // 审核标签
|
||||
CensorExtension *VideoCensorExtension `json:"censorExtension"` // 质检扩展结果
|
||||
Evidences *VideoCallbackEvidence `json:"evidences"` // 机器检测证据信息
|
||||
SolutionExtra *VideoSolutionExtra `json:"solutionExtra"` // 额外信息
|
||||
ReviewEvidences *VideoReviewEvidence `json:"reviewEvidences"` // 人审证据信息
|
||||
}
|
||||
|
||||
// VideoCensorLabel 审核标签
|
||||
type VideoCensorLabel struct {
|
||||
Code string `json:"code"` // 审核标签编码
|
||||
Desc string `json:"desc"` // 审核标签描述
|
||||
Name string `json:"name"` // 审核标签名称
|
||||
CustomCode string `json:"customCode"` // 自定义标签编码
|
||||
ParentLabelId string `json:"parentLabelId"` // 父标签ID
|
||||
Depth int `json:"depth"` // 标签深度
|
||||
}
|
||||
|
||||
// VideoCensorExtension 质检扩展结果
|
||||
type VideoCensorExtension struct {
|
||||
QualityInspectionTaskId string `json:"qualityInspectionTaskId"` // 质检任务ID
|
||||
QualityInspectionType int `json:"qualityInspectionType"` // 质检类型
|
||||
InspTaskCreateTime int64 `json:"inspTaskCreateTime"` // 质检任务创建时间
|
||||
}
|
||||
|
||||
// VideoCallbackEvidence 机器检测证据信息
|
||||
type VideoCallbackEvidence struct {
|
||||
Text *VideoTextEvidence `json:"text,omitempty"` // 文本证据
|
||||
Images *[]VideoImageEvidence `json:"images,omitempty"` // 图片证据
|
||||
Audio *VideoAudioEvidence `json:"audio,omitempty"` // 音频证据
|
||||
Video *VideoVideoEvidence `json:"video,omitempty"` // 视频证据
|
||||
}
|
||||
|
||||
// VideoTextEvidence 文本证据
|
||||
type VideoTextEvidence struct {
|
||||
TaskID string `json:"taskId"` // 任务ID
|
||||
DataID string `json:"dataId"` // 数据ID
|
||||
Suggestion int `json:"suggestion"` // 处置建议
|
||||
ResultType int `json:"resultType"` // 结果类型
|
||||
CensorType int `json:"censorType"` // 审核类型
|
||||
IsRelatedHit bool `json:"isRelatedHit"` // 是否关联命中
|
||||
Labels []*VideoTextLabel `json:"labels"` // 分类标签
|
||||
}
|
||||
|
||||
// VideoTextLabel 文本分类标签
|
||||
type VideoTextLabel struct {
|
||||
Label int `json:"label"` // 标签类型
|
||||
Level int `json:"level"` // 级别
|
||||
SubLabels []*VideoTextSubLabel `json:"subLabels"` // 二级分类
|
||||
}
|
||||
|
||||
// VideoTextSubLabel 文本二级分类
|
||||
type VideoTextSubLabel struct {
|
||||
SubLabel string `json:"subLabel"` // 二级分类
|
||||
SubLabelDepth int `json:"subLabelDepth"` // 细分类层级
|
||||
SecondLabel string `json:"secondLabel"` // 二级分类
|
||||
ThirdLabel string `json:"thirdLabel"` // 三级分类
|
||||
Details *VideoTextSubLabelDetail `json:"details"` // 命中详情
|
||||
}
|
||||
|
||||
// VideoTextSubLabelDetail 文本二级分类命中详情
|
||||
type VideoTextSubLabelDetail struct {
|
||||
Keywords *[]VideoTextKeyword `json:"keywords,omitempty"` // 敏感词
|
||||
LibInfos *[]VideoTextLibInfo `json:"libInfos,omitempty"` // 名单信息
|
||||
Anticheat *VideoTextAnticheat `json:"anticheat,omitempty"` // 反作弊
|
||||
HitInfos *[]VideoTextHitInfo `json:"hitInfos,omitempty"` // 其他命中
|
||||
}
|
||||
|
||||
// VideoTextKeyword 敏感词信息
|
||||
type VideoTextKeyword struct {
|
||||
Word string `json:"word"` // 敏感词
|
||||
StrategyGroupId int64 `json:"strategyGroupId"` // 策略组ID
|
||||
StrategyGroupName string `json:"strategyGroupName"` // 策略组名称
|
||||
}
|
||||
|
||||
// VideoTextLibInfo 名单信息
|
||||
type VideoTextLibInfo struct {
|
||||
Type int `json:"type"` // 名单类型
|
||||
Entity string `json:"entity"` // 名单内容
|
||||
ReleaseTime int64 `json:"releaseTime"` // 释放时间
|
||||
}
|
||||
|
||||
// VideoTextAnticheat 反作弊信息
|
||||
type VideoTextAnticheat struct {
|
||||
HitType int `json:"hitType"` // 命中类型
|
||||
}
|
||||
|
||||
// VideoTextHitInfo 其他命中信息
|
||||
type VideoTextHitInfo struct {
|
||||
Value string `json:"value"` // 命中值
|
||||
Positions *[]VideoTextHitPosition `json:"positions"` // 命中位置
|
||||
}
|
||||
|
||||
// VideoTextHitPosition 命中位置
|
||||
type VideoTextHitPosition struct {
|
||||
FieldName string `json:"fieldName"` // 字段名
|
||||
StartPos int `json:"startPos"` // 开始位置
|
||||
EndPos int `json:"endPos"` // 结束位置
|
||||
}
|
||||
|
||||
// VideoImageEvidence 图片证据
|
||||
type VideoImageEvidence struct {
|
||||
Name string `json:"name"` // 图片名称
|
||||
DataID string `json:"dataId"` // 数据ID
|
||||
Suggestion int `json:"suggestion"` // 处置建议
|
||||
ResultType int `json:"resultType"` // 结果类型
|
||||
Status int `json:"status"` // 状态
|
||||
CensorType int `json:"censorType"` // 审核类型
|
||||
Labels []*VideoImageLabel `json:"labels"` // 分类标签
|
||||
TaskId string `json:"taskId"` // 任务ID
|
||||
}
|
||||
|
||||
// VideoImageLabel 图片分类标签
|
||||
type VideoImageLabel struct {
|
||||
Label int `json:"label"` // 标签类型
|
||||
Level int `json:"level"` // 级别
|
||||
Rate float32 `json:"rate"` // 置信度
|
||||
SubLabels []*VideoImageSubLabel `json:"subLabels"` // 二级分类
|
||||
}
|
||||
|
||||
// VideoImageSubLabel 图片二级分类
|
||||
type VideoImageSubLabel struct {
|
||||
SubLabel interface{} `json:"subLabel"` // 二级分类标签
|
||||
SubLabelDepth int `json:"subLabelDepth"` // 细分类层级
|
||||
SecondLabel string `json:"secondLabel"` // 二级分类
|
||||
ThirdLabel string `json:"thirdLabel"` // 三级分类
|
||||
HitStrategy int `json:"hitStrategy"` // 命中策略
|
||||
Rate float32 `json:"rate"` // 置信度
|
||||
Details *VideoImageSubDetail `json:"details"` // 命中详情
|
||||
Explain string `json:"explain"` // 解释
|
||||
IsLlmCheck bool `json:"isLlmCheck"` // 是否LLM命中
|
||||
}
|
||||
|
||||
// VideoImageSubDetail 图片二级分类命中详情
|
||||
type VideoImageSubDetail struct {
|
||||
Keywords *[]VideoImageHitInfo `json:"keywords,omitempty"` // 敏感词
|
||||
LibInfos *[]VideoImageLibInfo `json:"libInfos,omitempty"` // 名单信息
|
||||
HitInfos *[]VideoImageHitInfo `json:"hitInfos,omitempty"` // 其他命中
|
||||
Anticheat *VideoImageAnticheat `json:"anticheat,omitempty"` // 反作弊
|
||||
Llm *VideoImageLlm `json:"llm,omitempty"` // 大模型
|
||||
}
|
||||
|
||||
// VideoImageHitInfo 图片命中信息
|
||||
type VideoImageHitInfo struct {
|
||||
Type int `json:"type"` // 命中类型
|
||||
Word string `json:"word"` // 敏感词
|
||||
Entity string `json:"entity"` // 名单URL
|
||||
HitCount int `json:"hitCount"` // 命中次数
|
||||
Value string `json:"value"` // 值
|
||||
Group string `json:"group"` // 分组
|
||||
X1 float32 `json:"x1"` // 坐标
|
||||
Y1 float32 `json:"y1"` // 坐标
|
||||
X2 float32 `json:"x2"` // 坐标
|
||||
Y2 float32 `json:"y2"` // 坐标
|
||||
StrategyGroupName string `json:"strategyGroupName"` // 策略组名称
|
||||
StrategyGroupId int64 `json:"strategyGroupId"` // 策略组ID
|
||||
}
|
||||
|
||||
// VideoImageLibInfo 图片名单信息
|
||||
type VideoImageLibInfo struct {
|
||||
Type int `json:"type"` // 名单类型
|
||||
Entity string `json:"entity"` // 名单URL
|
||||
HitCount int `json:"hitCount"` // 命中次数
|
||||
ReleaseTime int64 `json:"releaseTime"` // 释放时间
|
||||
StrategyGroupName string `json:"strategyGroupName"` // 策略组名称
|
||||
StrategyGroupId int64 `json:"strategyGroupId"` // 策略组ID
|
||||
}
|
||||
|
||||
// VideoImageAnticheat 反作弊信息
|
||||
type VideoImageAnticheat struct {
|
||||
HitType int `json:"hitType"` // 命中类型
|
||||
}
|
||||
|
||||
// VideoImageLlm 大模型信息
|
||||
type VideoImageLlm struct {
|
||||
Keyword string `json:"keyword"` // 关键词
|
||||
}
|
||||
|
||||
// VideoAudioEvidence 音频证据
|
||||
type VideoAudioEvidence struct {
|
||||
TaskID string `json:"taskId"` // 任务ID
|
||||
DataID string `json:"dataId"` // 数据ID
|
||||
Status int `json:"status"` // 状态
|
||||
Suggestion int `json:"suggestion"` // 处置建议
|
||||
Label int `json:"label"` // 标签
|
||||
ResultType int `json:"resultType"` // 结果类型
|
||||
Callback string `json:"callback"` // 回调参数
|
||||
CensorSource int `json:"censorSource"` // 审核来源
|
||||
CensorTime int64 `json:"censorTime"` // 审核时间
|
||||
Duration int64 `json:"duration"` // 音频时长
|
||||
Segments []*VideoAudioSegment `json:"segments"` // 音频片段
|
||||
}
|
||||
|
||||
// VideoAudioSegment 音频片段
|
||||
type VideoAudioSegment struct {
|
||||
StartTime int `json:"startTime"` // 开始时间(秒)
|
||||
EndTime int `json:"endTime"` // 结束时间(秒)
|
||||
StartTimeMillis int64 `json:"startTimeMillis"` // 开始时间(毫秒)
|
||||
EndTimeMillis int64 `json:"endTimeMillis"` // 结束时间(毫秒)
|
||||
Content string `json:"content"` // 语音识别原文
|
||||
Type int `json:"type"` // 片段类型:0=语音识别,1=声纹检测
|
||||
LeaderName string `json:"leaderName"` // 声纹检测人名
|
||||
Labels []*VideoAudioLabel `json:"labels"` // 分类标签
|
||||
Url string `json:"url"` // 音频URL
|
||||
}
|
||||
|
||||
// VideoAudioLabel 音频分类标签
|
||||
type VideoAudioLabel struct {
|
||||
Label int `json:"label"` // 标签类型
|
||||
Level int `json:"level"` // 级别
|
||||
SubLabels []*VideoAudioSubLabel `json:"subLabels"` // 二级分类
|
||||
}
|
||||
|
||||
// VideoAudioSubLabel 音频二级分类
|
||||
type VideoAudioSubLabel struct {
|
||||
SubLabel string `json:"subLabel"` // 细分类
|
||||
SubLabelDepth int `json:"subLabelDepth"` // 细分类层级
|
||||
SecondLabel string `json:"secondLabel"` // 二级分类
|
||||
ThirdLabel string `json:"thirdLabel"` // 三级分类
|
||||
SuggestionRiskLevel int `json:"suggestionRiskLevel"` // 嫌疑级别
|
||||
Rate float64 `json:"rate"` // 置信度
|
||||
RiskDescription string `json:"riskDescription"` // 风险描述
|
||||
Details *VideoAudioSubLabelDetail `json:"details"` // 命中详情
|
||||
}
|
||||
|
||||
// VideoAudioSubLabelDetail 音频二级分类命中详情
|
||||
type VideoAudioSubLabelDetail struct {
|
||||
HitInfos *[]VideoAudioHitInfo `json:"hitInfos,omitempty"` // 命中内容
|
||||
Keywords *[]VideoAudioKeyword `json:"keywords,omitempty"` // 自定义敏感词
|
||||
LibInfos *[]VideoAudioLibInfo `json:"libInfos,omitempty"` // 自定义名单
|
||||
}
|
||||
|
||||
// VideoAudioHitInfo 音频命中内容
|
||||
type VideoAudioHitInfo struct {
|
||||
Value string `json:"value"` // 命中敏感词或声纹检测分值
|
||||
StartTime int `json:"startTime"` // 开始时间
|
||||
EndTime int `json:"endTime"` // 结束时间
|
||||
}
|
||||
|
||||
// VideoAudioKeyword 自定义敏感词
|
||||
type VideoAudioKeyword struct {
|
||||
Word string `json:"word"` // 敏感词
|
||||
StrategyGroupName string `json:"strategyGroupName"` // 策略组名称
|
||||
StrategyGroupId int64 `json:"strategyGroupId"` // 策略组ID
|
||||
}
|
||||
|
||||
// VideoAudioLibInfo 自定义名单
|
||||
type VideoAudioLibInfo struct {
|
||||
ListType int `json:"listType"` // 名单类型
|
||||
Entity string `json:"entity"` // 名单内容
|
||||
}
|
||||
|
||||
// VideoVideoEvidence 视频证据
|
||||
type VideoVideoEvidence struct {
|
||||
TaskID string `json:"taskId"` // 任务ID
|
||||
DataID string `json:"dataId"` // 数据ID
|
||||
Status int `json:"status"` // 状态
|
||||
Suggestion int `json:"suggestion"` // 处置建议
|
||||
ResultType int `json:"resultType"` // 结果类型
|
||||
CensorSource int `json:"censorSource"` // 审核来源
|
||||
CensorTime int64 `json:"censorTime"` // 审核时间
|
||||
Pictures []*VideoPicture `json:"pictures"` // 截图列表
|
||||
}
|
||||
|
||||
// VideoPicture 截图信息
|
||||
type VideoPicture struct {
|
||||
Type int `json:"type"` // 类型
|
||||
URL string `json:"url"` // 图片URL
|
||||
StartTime int64 `json:"startTime"` // 开始时间
|
||||
EndTime int64 `json:"endTime"` // 结束时间
|
||||
Labels []*VideoPictureLabel `json:"labels"` // 分类标签
|
||||
CensorSource int `json:"censorSource"` // 审核来源
|
||||
FrontPics []*VideoRelatedPic `json:"frontPics"` // 关联前帧
|
||||
BackPics []*VideoRelatedPic `json:"backPics"` // 关联后帧
|
||||
PictureID string `json:"pictureId"` // 图片ID
|
||||
}
|
||||
|
||||
// VideoPictureLabel 截图分类标签
|
||||
type VideoPictureLabel struct {
|
||||
Label int `json:"label"` // 标签类型
|
||||
Level int `json:"level"` // 级别
|
||||
Rate float32 `json:"rate"` // 置信度
|
||||
SubLabels []*VideoPictureSubLabel `json:"subLabels"` // 二级分类
|
||||
}
|
||||
|
||||
// VideoPictureSubLabel 截图二级分类
|
||||
type VideoPictureSubLabel struct {
|
||||
SubLabel interface{} `json:"subLabel"` // 二级分类标签
|
||||
SubLabelDepth int `json:"subLabelDepth"` // 细分类层级
|
||||
SecondLabel string `json:"secondLabel"` // 二级分类
|
||||
ThirdLabel string `json:"thirdLabel"` // 三级分类
|
||||
HitStrategy int `json:"hitStrategy"` // 命中策略
|
||||
Rate float32 `json:"rate"` // 置信度
|
||||
Details *VideoPictureSubDetail `json:"details"` // 命中详情
|
||||
Explain string `json:"explain"` // 解释
|
||||
IsLlmCheck bool `json:"isLlmCheck"` // 是否LLM命中
|
||||
}
|
||||
|
||||
// VideoPictureSubDetail 截图二级分类命中详情
|
||||
type VideoPictureSubDetail struct {
|
||||
Keywords *[]VideoPictureHitInfo `json:"keywords,omitempty"` // 敏感词
|
||||
LibInfos *[]VideoPictureLibInfo `json:"libInfos,omitempty"` // 名单信息
|
||||
HitInfos *[]VideoPictureHitInfo `json:"hitInfos,omitempty"` // 其他命中
|
||||
Anticheat *VideoPictureAnticheat `json:"anticheat,omitempty"` // 反作弊
|
||||
Llm *VideoPictureLlm `json:"llm,omitempty"` // 大模型
|
||||
}
|
||||
|
||||
// VideoPictureHitInfo 截图命中信息
|
||||
type VideoPictureHitInfo struct {
|
||||
Value string `json:"value"` // 命中值
|
||||
Group string `json:"group"` // 分组
|
||||
Type int `json:"type"` // 类型
|
||||
X1 float32 `json:"x1"` // 坐标
|
||||
Y1 float32 `json:"y1"` // 坐标
|
||||
X2 float32 `json:"x2"` // 坐标
|
||||
Y2 float32 `json:"y2"` // 坐标
|
||||
}
|
||||
|
||||
// VideoPictureLibInfo 截图名单信息
|
||||
type VideoPictureLibInfo struct {
|
||||
Type int `json:"type"` // 名单类型
|
||||
Entity string `json:"entity"` // 名单URL
|
||||
HitCount int `json:"hitCount"` // 命中次数
|
||||
ReleaseTime int64 `json:"releaseTime"` // 释放时间
|
||||
StrategyGroupName string `json:"strategyGroupName"` // 策略组名称
|
||||
StrategyGroupId int64 `json:"strategyGroupId"` // 策略组ID
|
||||
}
|
||||
|
||||
// VideoPictureAnticheat 反作弊信息
|
||||
type VideoPictureAnticheat struct {
|
||||
HitType int `json:"hitType"` // 命中类型
|
||||
}
|
||||
|
||||
// VideoPictureLlm 大模型信息
|
||||
type VideoPictureLlm struct {
|
||||
Keyword string `json:"keyword"` // 关键词
|
||||
}
|
||||
|
||||
// VideoRelatedPic 关联截图
|
||||
type VideoRelatedPic struct {
|
||||
URL string `json:"url"` // 图片URL
|
||||
}
|
||||
|
||||
// VideoSolutionExtra 额外信息
|
||||
type VideoSolutionExtra struct {
|
||||
FailUnit *VideoFailUnit `json:"failUnit,omitempty"` // 失败单元
|
||||
}
|
||||
|
||||
// VideoFailUnit 失败单元
|
||||
type VideoFailUnit struct {
|
||||
Images *[]VideoImageFailUnit `json:"images,omitempty"` // 图片失败单元
|
||||
Audio *VideoTargetFailUnit `json:"audio,omitempty"` // 音频失败单元
|
||||
Video *VideoTargetFailUnit `json:"video,omitempty"` // 视频失败单元
|
||||
}
|
||||
|
||||
// VideoImageFailUnit 图片失败单元
|
||||
type VideoImageFailUnit struct {
|
||||
FailureReason int `json:"failureReason"` // 失败原因
|
||||
Name string `json:"name"` // 名称
|
||||
}
|
||||
|
||||
// VideoTargetFailUnit 目标失败单元
|
||||
type VideoTargetFailUnit struct {
|
||||
FailureReason int `json:"failureReason"` // 失败原因
|
||||
}
|
||||
|
||||
// VideoReviewEvidence 人审证据信息
|
||||
type VideoReviewEvidence struct {
|
||||
Description string `json:"description"` // 描述
|
||||
Detail string `json:"detail"` // 详情
|
||||
Texts *[]VideoReviewText `json:"texts"` // 文本证据
|
||||
Images *[]VideoReviewImage `json:"images"` // 图片证据
|
||||
Audios *[]VideoReviewAudio `json:"audios"` // 音频证据
|
||||
Videos *[]VideoReviewVideo `json:"videos"` // 视频证据
|
||||
}
|
||||
|
||||
// VideoReviewText 人审文本证据
|
||||
type VideoReviewText struct {
|
||||
Snippet string `json:"snippet"` // 片段
|
||||
Description string `json:"description"` // 描述
|
||||
}
|
||||
|
||||
// VideoReviewImage 人审图片证据
|
||||
type VideoReviewImage struct {
|
||||
URL string `json:"url"` // 图片URL
|
||||
Description string `json:"description"` // 描述
|
||||
}
|
||||
|
||||
// VideoReviewAudio 人审音频证据
|
||||
type VideoReviewAudio struct {
|
||||
StartTime int64 `json:"startTime"` // 开始时间
|
||||
EndTime int64 `json:"endTime"` // 结束时间
|
||||
Description string `json:"description"` // 描述
|
||||
}
|
||||
|
||||
// VideoReviewVideo 人审视频证据
|
||||
type VideoReviewVideo struct {
|
||||
StartTime int64 `json:"startTime"` // 开始时间
|
||||
EndTime int64 `json:"endTime"` // 结束时间
|
||||
URL string `json:"url"` // 视频URL
|
||||
Description string `json:"description"` // 描述
|
||||
}
|
||||
|
||||
// ProcessVideoCallback 处理视频检测回调(推送模式)
|
||||
func (s *VideoDetectionService) ProcessVideoCallback(ctx context.Context, callbackData string) error {
|
||||
if callbackData == "" {
|
||||
return fmt.Errorf("回调数据不能为空")
|
||||
}
|
||||
|
||||
var data VideoCallbackData
|
||||
if err := json.Unmarshal([]byte(callbackData), &data); err != nil {
|
||||
g.Log().Errorf(ctx, "解析视频回调数据失败: %v", err)
|
||||
return fmt.Errorf("解析视频回调数据失败: %w", err)
|
||||
}
|
||||
|
||||
if data.Antispam == nil {
|
||||
return fmt.Errorf("视频回调数据格式错误:缺少antispam字段")
|
||||
}
|
||||
|
||||
g.Log().Infof(ctx, "处理视频检测结果 - taskId: %s, suggestion: %d, resultType: %d, status: %d",
|
||||
data.Antispam.TaskID, data.Antispam.Suggestion, data.Antispam.ResultType, data.Antispam.Status)
|
||||
|
||||
// TODO: 业务逻辑,如保存数据库、触发后续流程等
|
||||
// 可使用完整字段:data.Antispam.Evidences, data.Antispam.CensorLabels, data.Antispam.Duration 等
|
||||
|
||||
return nil
|
||||
}
|
||||
53
service/yidun/yidun_client.go
Normal file
53
service/yidun/yidun_client.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package yidun
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/yidun/yidun-golang-sdk/yidun/service/antispam/image/v5"
|
||||
text "github.com/yidun/yidun-golang-sdk/yidun/service/antispam/text"
|
||||
"github.com/yidun/yidun-golang-sdk/yidun/service/antispam/videosolution"
|
||||
)
|
||||
|
||||
// YidunClients 易盾客户端集合(直接使用SDK客户端)
|
||||
type YidunClients struct {
|
||||
TextClient *text.TextClient
|
||||
ImageClient *image.ImageClient
|
||||
VideoClient *videosolution.VideoSolutionClient
|
||||
}
|
||||
|
||||
var DefaultClients *YidunClients
|
||||
|
||||
// InitYidunClients 初始化所有易盾客户端
|
||||
func InitYidunClients(ctx context.Context) error {
|
||||
clients := &YidunClients{}
|
||||
|
||||
// 文本检测
|
||||
secretId := g.Cfg().MustGet(ctx, "yidun.text.secret_id").String()
|
||||
secretKey := g.Cfg().MustGet(ctx, "yidun.text.secret_key").String()
|
||||
if secretId != "" && secretKey != "" {
|
||||
clients.TextClient = text.NewTextClientWithAccessKey(secretId, secretKey)
|
||||
g.Log().Info(ctx, "文本检测客户端初始化成功")
|
||||
}
|
||||
|
||||
// 图片检测
|
||||
secretId = g.Cfg().MustGet(ctx, "yidun.image.secret_id").String()
|
||||
secretKey = g.Cfg().MustGet(ctx, "yidun.image.secret_key").String()
|
||||
businessId := g.Cfg().MustGet(ctx, "yidun.image.business_id").String()
|
||||
if secretId != "" && secretKey != "" {
|
||||
clients.ImageClient = image.NewImageClientWithAccessKey(secretId, secretKey)
|
||||
g.Log().Infof(ctx, "图片检测客户端初始化成功, business_id: %s", businessId)
|
||||
}
|
||||
|
||||
// 视频检测
|
||||
secretId = g.Cfg().MustGet(ctx, "yidun.video.secret_id").String()
|
||||
secretKey = g.Cfg().MustGet(ctx, "yidun.video.secret_key").String()
|
||||
businessId = g.Cfg().MustGet(ctx, "yidun.video.business_id").String()
|
||||
if secretId != "" && secretKey != "" {
|
||||
clients.VideoClient = videosolution.NewVideoSolutionClientWithAccessKey(secretId, secretKey)
|
||||
g.Log().Infof(ctx, "视频检测客户端初始化成功, business_id: %s", businessId)
|
||||
}
|
||||
|
||||
DefaultClients = clients
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user