♻️ use minio instead of mongodb

This commit is contained in:
2025-02-05 18:08:29 +08:00
parent a3d4f2c8d1
commit d2b0d7b42e
53 changed files with 2446 additions and 702 deletions

486
.idea/GOHCache.xml generated

File diff suppressed because it is too large Load Diff

View File

@@ -19,7 +19,7 @@ type ScaStorageFace struct {
FaceName string `gorm:"column:face_name;type:varchar(255);comment:人脸名称" json:"face_name"` // 人脸名称
FaceVector string `gorm:"column:face_vector;type:json;comment:人脸特征向量" json:"face_vector"` // 人脸特征向量
FaceImagePath string `gorm:"column:face_image_path;type:varchar(255);comment:人脸图像路径" json:"face_image_path"` // 人脸图像路径
FaceType string `gorm:"column:face_type;type:varchar(50);comment:人脸类型标识" json:"face_type"` // 人脸类型标识
FaceType int64 `gorm:"column:face_type;type:int(10);comment:人脸类型标识" json:"face_type"` // 人脸类型标识
CreatedAt time.Time `gorm:"column:created_at;type:timestamp;autoCreateTime;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp;autoUpdateTime;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp;comment:删除时间" json:"deleted_at"` // 删除时间

View File

@@ -32,7 +32,7 @@ func newScaStorageFace(db *gorm.DB, opts ...gen.DOOption) scaStorageFace {
_scaStorageFace.FaceName = field.NewString(tableName, "face_name")
_scaStorageFace.FaceVector = field.NewString(tableName, "face_vector")
_scaStorageFace.FaceImagePath = field.NewString(tableName, "face_image_path")
_scaStorageFace.FaceType = field.NewString(tableName, "face_type")
_scaStorageFace.FaceType = field.NewInt64(tableName, "face_type")
_scaStorageFace.CreatedAt = field.NewTime(tableName, "created_at")
_scaStorageFace.UpdatedAt = field.NewTime(tableName, "updated_at")
_scaStorageFace.DeletedAt = field.NewField(tableName, "deleted_at")
@@ -52,7 +52,7 @@ type scaStorageFace struct {
FaceName field.String // 人脸名称
FaceVector field.String // 人脸特征向量
FaceImagePath field.String // 人脸图像路径
FaceType field.String // 人脸类型标识
FaceType field.Int64 // 人脸类型标识
CreatedAt field.Time // 创建时间
UpdatedAt field.Time // 更新时间
DeletedAt field.Field // 删除时间
@@ -77,7 +77,7 @@ func (s *scaStorageFace) updateTableName(table string) *scaStorageFace {
s.FaceName = field.NewString(table, "face_name")
s.FaceVector = field.NewString(table, "face_vector")
s.FaceImagePath = field.NewString(table, "face_image_path")
s.FaceType = field.NewString(table, "face_type")
s.FaceType = field.NewInt64(table, "face_type")
s.CreatedAt = field.NewTime(table, "created_at")
s.UpdatedAt = field.NewTime(table, "updated_at")
s.DeletedAt = field.NewField(table, "deleted_at")

View File

@@ -28,6 +28,38 @@ message CaffeClassificationResponse {
string class_name = 2;
float score = 3;
}
// 查询人脸样本库
message QueryFaceLibraryRequest {
string user_id = 1;
int64 type = 2;
}
message FaceLibrary {
int64 id = 1;
string face_name = 2;
string face_image = 3;
}
message QueryFaceLibraryResponse {
repeated FaceLibrary faces = 1;
}
// 添加或修改人脸样本名称
message ModifyFaceNameRequest {
string user_id = 1;
int64 face_id = 2;
string face_name = 3;
}
message ModifyFaceNameResponse {
int64 face_id = 1;
string face_name = 2;
}
// 修改人脸类型
message ModifyFaceTypeRequest {
string user_id = 1;
repeated int64 face_id = 2;
int64 type = 3;
}
message ModifyFaceTypeResponse {
string result = 1;
}
service AiService {
// FaceRecognition
rpc FaceRecognition (FaceRecognitionRequest) returns (FaceRecognitionResponse);
@@ -35,4 +67,12 @@ service AiService {
rpc TfClassification (TfClassificationRequest) returns (TfClassificationResponse);
// CaffeClassification
rpc CaffeClassification (CaffeClassificationRequest) returns (CaffeClassificationResponse);
}
// QueryFaceLibrary
rpc QueryFaceLibrary (QueryFaceLibraryRequest) returns (QueryFaceLibraryResponse);
// ModifyFaceName
rpc ModifyFaceName (ModifyFaceNameRequest) returns (ModifyFaceNameResponse);
// ModifyFaceType
rpc ModifyFaceType (ModifyFaceTypeRequest) returns (ModifyFaceTypeResponse);
}

View File

@@ -16,8 +16,15 @@ import (
type (
CaffeClassificationRequest = pb.CaffeClassificationRequest
CaffeClassificationResponse = pb.CaffeClassificationResponse
FaceLibrary = pb.FaceLibrary
FaceRecognitionRequest = pb.FaceRecognitionRequest
FaceRecognitionResponse = pb.FaceRecognitionResponse
ModifyFaceNameRequest = pb.ModifyFaceNameRequest
ModifyFaceNameResponse = pb.ModifyFaceNameResponse
ModifyFaceTypeRequest = pb.ModifyFaceTypeRequest
ModifyFaceTypeResponse = pb.ModifyFaceTypeResponse
QueryFaceLibraryRequest = pb.QueryFaceLibraryRequest
QueryFaceLibraryResponse = pb.QueryFaceLibraryResponse
TfClassificationRequest = pb.TfClassificationRequest
TfClassificationResponse = pb.TfClassificationResponse
@@ -28,6 +35,12 @@ type (
TfClassification(ctx context.Context, in *TfClassificationRequest, opts ...grpc.CallOption) (*TfClassificationResponse, error)
// CaffeClassification
CaffeClassification(ctx context.Context, in *CaffeClassificationRequest, opts ...grpc.CallOption) (*CaffeClassificationResponse, error)
// QueryFaceLibrary
QueryFaceLibrary(ctx context.Context, in *QueryFaceLibraryRequest, opts ...grpc.CallOption) (*QueryFaceLibraryResponse, error)
// ModifyFaceName
ModifyFaceName(ctx context.Context, in *ModifyFaceNameRequest, opts ...grpc.CallOption) (*ModifyFaceNameResponse, error)
// ModifyFaceType
ModifyFaceType(ctx context.Context, in *ModifyFaceTypeRequest, opts ...grpc.CallOption) (*ModifyFaceTypeResponse, error)
}
defaultAiService struct {
@@ -58,3 +71,21 @@ func (m *defaultAiService) CaffeClassification(ctx context.Context, in *CaffeCla
client := pb.NewAiServiceClient(m.cli.Conn())
return client.CaffeClassification(ctx, in, opts...)
}
// QueryFaceLibrary
func (m *defaultAiService) QueryFaceLibrary(ctx context.Context, in *QueryFaceLibraryRequest, opts ...grpc.CallOption) (*QueryFaceLibraryResponse, error) {
client := pb.NewAiServiceClient(m.cli.Conn())
return client.QueryFaceLibrary(ctx, in, opts...)
}
// ModifyFaceName
func (m *defaultAiService) ModifyFaceName(ctx context.Context, in *ModifyFaceNameRequest, opts ...grpc.CallOption) (*ModifyFaceNameResponse, error) {
client := pb.NewAiServiceClient(m.cli.Conn())
return client.ModifyFaceName(ctx, in, opts...)
}
// ModifyFaceType
func (m *defaultAiService) ModifyFaceType(ctx context.Context, in *ModifyFaceTypeRequest, opts ...grpc.CallOption) (*ModifyFaceTypeResponse, error) {
client := pb.NewAiServiceClient(m.cli.Conn())
return client.ModifyFaceType(ctx, in, opts...)
}

View File

@@ -22,3 +22,13 @@ RedisConf:
Pass: LDQ20020618xxx
# Redis 数据库
DB: 0
# Minio配置
Minio:
# Minio 地址
Endpoint: 1.95.0.111:9000
# Minio 访问密钥
AccessKeyID: JNLVxMGro1XXwajodLBX
# Minio 访问密钥
SecretAccessKey: XEHkwExqQdAlEPfpRk36xpc0Sie8hZkcmlhXQJXw
# Minio 使用SSL
UseSSL: false

View File

@@ -15,4 +15,10 @@ type Config struct {
Pass string
DB int
}
Minio struct {
Endpoint string
AccessKeyID string
SecretAccessKey string
UseSSL bool
}
}

View File

@@ -7,12 +7,12 @@ import (
"fmt"
"github.com/Kagami/go-face"
"github.com/ccpwcn/kgo"
"github.com/minio/minio-go/v7"
"github.com/zeromicro/go-zero/core/logx"
"image"
"image/jpeg"
_ "image/png"
"os"
"path/filepath"
"path"
"schisandra-album-cloud-microservices/app/aisvc/model/mysql/model"
"schisandra-album-cloud-microservices/app/aisvc/rpc/internal/svc"
"schisandra-album-cloud-microservices/app/aisvc/rpc/pb"
@@ -60,7 +60,7 @@ func (l *FaceRecognitionLogic) FaceRecognition(in *pb.FaceRecognitionRequest) (*
return nil, nil
}
hashKey := fmt.Sprintf("user:%s:faces", in.GetUserId())
hashKey := constant.FaceVectorPrefix + in.GetUserId()
// 从 Redis 加载人脸数据
samples, ids, err := l.loadFacesFromRedisHash(hashKey)
if err != nil {
@@ -89,10 +89,10 @@ func (l *FaceRecognitionLogic) FaceRecognition(in *pb.FaceRecognitionRequest) (*
l.svcCtx.FaceRecognizer.SetSamples(samples, ids)
// 人脸分类
classify := l.svcCtx.FaceRecognizer.ClassifyThreshold(faceFeatures.Descriptor, 0.6)
if classify >= 0 && classify < len(ids) {
classify := l.svcCtx.FaceRecognizer.ClassifyThreshold(faceFeatures.Descriptor, 0.3)
if classify > 0 {
return &pb.FaceRecognitionResponse{
FaceId: int64(ids[classify]),
FaceId: int64(classify),
}, nil
}
@@ -131,7 +131,7 @@ func (l *FaceRecognitionLogic) saveNewFace(in *pb.FaceRecognitionRequest, faceFe
}
// 保存人脸图片到本地
faceImagePath, err := l.saveCroppedFaceToLocal(in.GetFace(), faceFeatures.Rectangle, "face_samples", in.GetUserId())
faceImagePath, err := l.saveCroppedFaceToLocal(in.GetFace(), faceFeatures.Rectangle, in.GetUserId())
if err != nil {
return nil, err
}
@@ -161,7 +161,7 @@ func (l *FaceRecognitionLogic) loadExistingFaces(userId string) ([]face.Descript
storageFace := l.svcCtx.DB.ScaStorageFace
existingFaces, err := storageFace.
Select(storageFace.FaceVector, storageFace.ID).
Where(storageFace.UserID.Eq(userId), storageFace.FaceType.Eq(constant.FaceTypeSample)).
Where(storageFace.UserID.Eq(userId)).
Find()
if err != nil {
return nil, nil, err
@@ -215,7 +215,6 @@ func (l *FaceRecognitionLogic) saveFaceToDatabase(userId string, descriptor face
storageFace := model.ScaStorageFace{
FaceVector: string(jsonBytes),
FaceImagePath: faceImagePath,
FaceType: constant.FaceTypeSample,
UserID: userId,
}
err = l.svcCtx.DB.ScaStorageFace.Create(&storageFace)
@@ -225,17 +224,12 @@ func (l *FaceRecognitionLogic) saveFaceToDatabase(userId string, descriptor face
return &storageFace, nil
}
func (l *FaceRecognitionLogic) saveCroppedFaceToLocal(faceImage []byte, rect image.Rectangle, baseSavePath string, userID string) (string, error) {
// 动态生成用户目录和时间分级目录
subDir := filepath.Join(baseSavePath, userID, time.Now().Format("2006/01")) // 格式:<baseSavePath>/<userID>/YYYY/MM
// 缓存目录检查,避免重复调用 os.MkdirAll
if !l.isDirectoryCached(subDir) {
if err := os.MkdirAll(subDir, os.ModePerm); err != nil {
return "", fmt.Errorf("failed to create directory: %w", err)
}
l.cacheDirectory(subDir) // 缓存已创建的目录路径
}
func (l *FaceRecognitionLogic) saveCroppedFaceToLocal(faceImage []byte, rect image.Rectangle, userID string) (string, error) {
objectKey := path.Join(
userID,
time.Now().Format("2006/01"), // 按年/月划分目录
fmt.Sprintf("%s_%s.jpg", time.Now().Format("20060102150405"), kgo.SimpleUuid()),
)
// 解码图像
img, _, err := image.Decode(bytes.NewReader(faceImage))
@@ -258,42 +252,35 @@ func (l *FaceRecognitionLogic) saveCroppedFaceToLocal(faceImage []byte, rect ima
SubImage(r image.Rectangle) image.Image
}).SubImage(extendedRect)
// 生成唯一文件名(时间戳 + UUID
fileName := fmt.Sprintf("%s_%s.jpg", time.Now().Format("20060102_150405"), kgo.SimpleUuid())
outputPath := filepath.Join(subDir, fileName)
// 写入文件
if err = l.writeImageToFile(outputPath, croppedImage); err != nil {
return "", err
// 将图像编码为JPEG字节流
var buf bytes.Buffer
if err = jpeg.Encode(&buf, croppedImage, nil); err != nil {
return "", fmt.Errorf("failed to encode image to JPEG: %w", err)
}
exists, err := l.svcCtx.MinioClient.BucketExists(l.ctx, constant.FaceBucketName)
if err != nil || !exists {
err = l.svcCtx.MinioClient.MakeBucket(l.ctx, constant.FaceBucketName, minio.MakeBucketOptions{Region: "us-east-1", ObjectLocking: true})
if err != nil {
logx.Errorf("Failed to create MinIO bucket: %v", err)
return "", err
}
}
return outputPath, nil
}
// 判断目录是否已缓存
func (l *FaceRecognitionLogic) isDirectoryCached(dir string) bool {
_, exists := l.directoryCache.Load(dir)
return exists
}
// 缓存目录
func (l *FaceRecognitionLogic) cacheDirectory(dir string) {
l.directoryCache.Store(dir, struct{}{})
}
// 将图像写入文件
func (l *FaceRecognitionLogic) writeImageToFile(path string, img image.Image) error {
file, err := os.Create(path)
// 上传到MinIO
_, err = l.svcCtx.MinioClient.PutObject(
l.ctx,
constant.FaceBucketName,
objectKey,
bytes.NewReader(buf.Bytes()),
int64(buf.Len()),
minio.PutObjectOptions{
ContentType: "image/jpeg",
},
)
if err != nil {
return fmt.Errorf("failed to create file: %w", err)
return "", fmt.Errorf("failed to upload image to MinIO: %w", err)
}
defer func(file *os.File) {
_ = file.Close()
}(file)
if err = jpeg.Encode(file, img, nil); err != nil {
return fmt.Errorf("failed to encode and save image: %w", err)
}
return nil
return objectKey, nil
}
// 从 Redis 的 Hash 中加载人脸数据

View File

@@ -0,0 +1,40 @@
package aiservicelogic
import (
"context"
"errors"
"schisandra-album-cloud-microservices/app/aisvc/rpc/internal/svc"
"schisandra-album-cloud-microservices/app/aisvc/rpc/pb"
"github.com/zeromicro/go-zero/core/logx"
)
type ModifyFaceNameLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func NewModifyFaceNameLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ModifyFaceNameLogic {
return &ModifyFaceNameLogic{
ctx: ctx,
svcCtx: svcCtx,
Logger: logx.WithContext(ctx),
}
}
func (l *ModifyFaceNameLogic) ModifyFaceName(in *pb.ModifyFaceNameRequest) (*pb.ModifyFaceNameResponse, error) {
storageFace := l.svcCtx.DB.ScaStorageFace
affected, err := storageFace.Where(storageFace.ID.Eq(in.GetFaceId()), storageFace.UserID.Eq(in.GetUserId())).Update(storageFace.FaceName, in.GetFaceName())
if err != nil {
return nil, err
}
if affected.RowsAffected == 0 {
return nil, errors.New("update failed, no rows affected")
}
return &pb.ModifyFaceNameResponse{
FaceId: in.GetFaceId(),
FaceName: in.GetFaceName(),
}, nil
}

View File

@@ -0,0 +1,43 @@
package aiservicelogic
import (
"context"
"errors"
"schisandra-album-cloud-microservices/app/aisvc/rpc/internal/svc"
"schisandra-album-cloud-microservices/app/aisvc/rpc/pb"
"github.com/zeromicro/go-zero/core/logx"
)
type ModifyFaceTypeLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func NewModifyFaceTypeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ModifyFaceTypeLogic {
return &ModifyFaceTypeLogic{
ctx: ctx,
svcCtx: svcCtx,
Logger: logx.WithContext(ctx),
}
}
// ModifyFaceType
func (l *ModifyFaceTypeLogic) ModifyFaceType(in *pb.ModifyFaceTypeRequest) (*pb.ModifyFaceTypeResponse, error) {
storageFace := l.svcCtx.DB.ScaStorageFace
faceIds := in.GetFaceId()
info, err := storageFace.Where(storageFace.ID.In(faceIds...), storageFace.UserID.Eq(in.GetUserId())).Update(storageFace.FaceType, in.GetType())
if err != nil {
return nil, err
}
if info.RowsAffected == 0 {
return &pb.ModifyFaceTypeResponse{
Result: "fail",
}, errors.New("face not found")
}
return &pb.ModifyFaceTypeResponse{
Result: "success",
}, nil
}

View File

@@ -0,0 +1,102 @@
package aiservicelogic
import (
"context"
"fmt"
"net/url"
"schisandra-album-cloud-microservices/app/aisvc/model/mysql/model"
"schisandra-album-cloud-microservices/common/constant"
"strconv"
"sync"
"time"
"schisandra-album-cloud-microservices/app/aisvc/rpc/internal/svc"
"schisandra-album-cloud-microservices/app/aisvc/rpc/pb"
"github.com/zeromicro/go-zero/core/logx"
)
type QueryFaceLibraryLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
wg sync.WaitGroup
mu sync.Mutex
}
type FaceLibrary struct {
ID int64 `json:"id"`
FaceImage []byte `json:"face_image"`
FaceName string `json:"face_name"`
}
func NewQueryFaceLibraryLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryFaceLibraryLogic {
return &QueryFaceLibraryLogic{
ctx: ctx,
svcCtx: svcCtx,
Logger: logx.WithContext(ctx),
wg: sync.WaitGroup{},
mu: sync.Mutex{},
}
}
// QueryFaceLibrary queries the face library
func (l *QueryFaceLibraryLogic) QueryFaceLibrary(in *pb.QueryFaceLibraryRequest) (*pb.QueryFaceLibraryResponse, error) {
if in.GetUserId() == "" {
return nil, fmt.Errorf("user ID is required")
}
storageFace := l.svcCtx.DB.ScaStorageFace
samples, err := storageFace.Select(
storageFace.ID,
storageFace.FaceVector,
storageFace.FaceImagePath,
storageFace.FaceName).
Where(storageFace.UserID.Eq(in.GetUserId()), storageFace.FaceType.Eq(in.GetType())).
Find()
if err != nil {
return nil, fmt.Errorf("failed to query face library: %v", err)
}
if len(samples) == 0 {
return nil, nil
}
faceLibrary := make([]*pb.FaceLibrary, len(samples))
for i, sample := range samples {
l.wg.Add(1)
go func(i int, sample *model.ScaStorageFace) {
defer l.wg.Done()
redisKey := constant.FaceSamplePrefix + in.GetUserId() + ":" + strconv.FormatInt(sample.ID, 10)
file, err := l.svcCtx.RedisClient.Get(l.ctx, redisKey).Result()
if err == nil {
l.mu.Lock()
faceLibrary[i] = &pb.FaceLibrary{
Id: sample.ID,
FaceName: sample.FaceName,
FaceImage: file,
}
l.mu.Unlock()
return
}
reqParams := make(url.Values)
presignedURL, err := l.svcCtx.MinioClient.PresignedGetObject(l.ctx, constant.FaceBucketName, sample.FaceImagePath, time.Hour*24, reqParams)
err = l.svcCtx.RedisClient.Set(l.ctx, redisKey, presignedURL.String(), time.Hour*24).Err()
if err != nil {
return
}
l.mu.Lock()
faceLibrary[i] = &pb.FaceLibrary{
Id: sample.ID,
FaceName: sample.FaceName,
FaceImage: presignedURL.String(),
}
l.mu.Unlock()
}(i, sample)
}
l.wg.Wait()
return &pb.QueryFaceLibraryResponse{
Faces: faceLibrary,
}, nil
}

View File

@@ -40,3 +40,21 @@ func (s *AiServiceServer) CaffeClassification(ctx context.Context, in *pb.CaffeC
l := aiservicelogic.NewCaffeClassificationLogic(ctx, s.svcCtx)
return l.CaffeClassification(in)
}
// QueryFaceLibrary
func (s *AiServiceServer) QueryFaceLibrary(ctx context.Context, in *pb.QueryFaceLibraryRequest) (*pb.QueryFaceLibraryResponse, error) {
l := aiservicelogic.NewQueryFaceLibraryLogic(ctx, s.svcCtx)
return l.QueryFaceLibrary(in)
}
// ModifyFaceName
func (s *AiServiceServer) ModifyFaceName(ctx context.Context, in *pb.ModifyFaceNameRequest) (*pb.ModifyFaceNameResponse, error) {
l := aiservicelogic.NewModifyFaceNameLogic(ctx, s.svcCtx)
return l.ModifyFaceName(in)
}
// ModifyFaceType
func (s *AiServiceServer) ModifyFaceType(ctx context.Context, in *pb.ModifyFaceTypeRequest) (*pb.ModifyFaceTypeResponse, error) {
l := aiservicelogic.NewModifyFaceTypeLogic(ctx, s.svcCtx)
return l.ModifyFaceType(in)
}

View File

@@ -2,6 +2,7 @@ package svc
import (
"github.com/Kagami/go-face"
"github.com/minio/minio-go/v7"
"github.com/redis/go-redis/v9"
"gocv.io/x/gocv"
"schisandra-album-cloud-microservices/app/aisvc/model/mysql"
@@ -9,6 +10,7 @@ import (
"schisandra-album-cloud-microservices/app/aisvc/rpc/internal/config"
"schisandra-album-cloud-microservices/common/caffe_classifier"
"schisandra-album-cloud-microservices/common/face_recognizer"
"schisandra-album-cloud-microservices/common/miniox"
"schisandra-album-cloud-microservices/common/redisx"
"schisandra-album-cloud-microservices/common/tf_classifier"
)
@@ -22,6 +24,7 @@ type ServiceContext struct {
TfDesc []string
CaffeNet *gocv.Net
CaffeDesc []string
MinioClient *minio.Client
}
func NewServiceContext(c config.Config) *ServiceContext {
@@ -38,5 +41,6 @@ func NewServiceContext(c config.Config) *ServiceContext {
TfDesc: tfDesc,
CaffeNet: caffeClassifier,
CaffeDesc: caffeDesc,
MinioClient: miniox.NewMinio(c.Minio.Endpoint, c.Minio.AccessKeyID, c.Minio.SecretAccessKey, c.Minio.UseSSL),
}
}

View File

@@ -317,6 +317,388 @@ func (x *CaffeClassificationResponse) GetScore() float32 {
return 0
}
// 查询人脸样本库
type QueryFaceLibraryRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
UserId string `protobuf:"bytes,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
Type int64 `protobuf:"varint,2,opt,name=type,proto3" json:"type,omitempty"`
}
func (x *QueryFaceLibraryRequest) Reset() {
*x = QueryFaceLibraryRequest{}
mi := &file_aisvc_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *QueryFaceLibraryRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*QueryFaceLibraryRequest) ProtoMessage() {}
func (x *QueryFaceLibraryRequest) ProtoReflect() protoreflect.Message {
mi := &file_aisvc_proto_msgTypes[6]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use QueryFaceLibraryRequest.ProtoReflect.Descriptor instead.
func (*QueryFaceLibraryRequest) Descriptor() ([]byte, []int) {
return file_aisvc_proto_rawDescGZIP(), []int{6}
}
func (x *QueryFaceLibraryRequest) GetUserId() string {
if x != nil {
return x.UserId
}
return ""
}
func (x *QueryFaceLibraryRequest) GetType() int64 {
if x != nil {
return x.Type
}
return 0
}
type FaceLibrary struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
FaceName string `protobuf:"bytes,2,opt,name=face_name,json=faceName,proto3" json:"face_name,omitempty"`
FaceImage string `protobuf:"bytes,3,opt,name=face_image,json=faceImage,proto3" json:"face_image,omitempty"`
}
func (x *FaceLibrary) Reset() {
*x = FaceLibrary{}
mi := &file_aisvc_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *FaceLibrary) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*FaceLibrary) ProtoMessage() {}
func (x *FaceLibrary) ProtoReflect() protoreflect.Message {
mi := &file_aisvc_proto_msgTypes[7]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use FaceLibrary.ProtoReflect.Descriptor instead.
func (*FaceLibrary) Descriptor() ([]byte, []int) {
return file_aisvc_proto_rawDescGZIP(), []int{7}
}
func (x *FaceLibrary) GetId() int64 {
if x != nil {
return x.Id
}
return 0
}
func (x *FaceLibrary) GetFaceName() string {
if x != nil {
return x.FaceName
}
return ""
}
func (x *FaceLibrary) GetFaceImage() string {
if x != nil {
return x.FaceImage
}
return ""
}
type QueryFaceLibraryResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Faces []*FaceLibrary `protobuf:"bytes,1,rep,name=faces,proto3" json:"faces,omitempty"`
}
func (x *QueryFaceLibraryResponse) Reset() {
*x = QueryFaceLibraryResponse{}
mi := &file_aisvc_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *QueryFaceLibraryResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*QueryFaceLibraryResponse) ProtoMessage() {}
func (x *QueryFaceLibraryResponse) ProtoReflect() protoreflect.Message {
mi := &file_aisvc_proto_msgTypes[8]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use QueryFaceLibraryResponse.ProtoReflect.Descriptor instead.
func (*QueryFaceLibraryResponse) Descriptor() ([]byte, []int) {
return file_aisvc_proto_rawDescGZIP(), []int{8}
}
func (x *QueryFaceLibraryResponse) GetFaces() []*FaceLibrary {
if x != nil {
return x.Faces
}
return nil
}
// 添加或修改人脸样本名称
type ModifyFaceNameRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
UserId string `protobuf:"bytes,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
FaceId int64 `protobuf:"varint,2,opt,name=face_id,json=faceId,proto3" json:"face_id,omitempty"`
FaceName string `protobuf:"bytes,3,opt,name=face_name,json=faceName,proto3" json:"face_name,omitempty"`
}
func (x *ModifyFaceNameRequest) Reset() {
*x = ModifyFaceNameRequest{}
mi := &file_aisvc_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ModifyFaceNameRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ModifyFaceNameRequest) ProtoMessage() {}
func (x *ModifyFaceNameRequest) ProtoReflect() protoreflect.Message {
mi := &file_aisvc_proto_msgTypes[9]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ModifyFaceNameRequest.ProtoReflect.Descriptor instead.
func (*ModifyFaceNameRequest) Descriptor() ([]byte, []int) {
return file_aisvc_proto_rawDescGZIP(), []int{9}
}
func (x *ModifyFaceNameRequest) GetUserId() string {
if x != nil {
return x.UserId
}
return ""
}
func (x *ModifyFaceNameRequest) GetFaceId() int64 {
if x != nil {
return x.FaceId
}
return 0
}
func (x *ModifyFaceNameRequest) GetFaceName() string {
if x != nil {
return x.FaceName
}
return ""
}
type ModifyFaceNameResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
FaceId int64 `protobuf:"varint,1,opt,name=face_id,json=faceId,proto3" json:"face_id,omitempty"`
FaceName string `protobuf:"bytes,2,opt,name=face_name,json=faceName,proto3" json:"face_name,omitempty"`
}
func (x *ModifyFaceNameResponse) Reset() {
*x = ModifyFaceNameResponse{}
mi := &file_aisvc_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ModifyFaceNameResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ModifyFaceNameResponse) ProtoMessage() {}
func (x *ModifyFaceNameResponse) ProtoReflect() protoreflect.Message {
mi := &file_aisvc_proto_msgTypes[10]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ModifyFaceNameResponse.ProtoReflect.Descriptor instead.
func (*ModifyFaceNameResponse) Descriptor() ([]byte, []int) {
return file_aisvc_proto_rawDescGZIP(), []int{10}
}
func (x *ModifyFaceNameResponse) GetFaceId() int64 {
if x != nil {
return x.FaceId
}
return 0
}
func (x *ModifyFaceNameResponse) GetFaceName() string {
if x != nil {
return x.FaceName
}
return ""
}
// 修改人脸类型
type ModifyFaceTypeRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
UserId string `protobuf:"bytes,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
FaceId []int64 `protobuf:"varint,2,rep,packed,name=face_id,json=faceId,proto3" json:"face_id,omitempty"`
Type int64 `protobuf:"varint,3,opt,name=type,proto3" json:"type,omitempty"`
}
func (x *ModifyFaceTypeRequest) Reset() {
*x = ModifyFaceTypeRequest{}
mi := &file_aisvc_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ModifyFaceTypeRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ModifyFaceTypeRequest) ProtoMessage() {}
func (x *ModifyFaceTypeRequest) ProtoReflect() protoreflect.Message {
mi := &file_aisvc_proto_msgTypes[11]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ModifyFaceTypeRequest.ProtoReflect.Descriptor instead.
func (*ModifyFaceTypeRequest) Descriptor() ([]byte, []int) {
return file_aisvc_proto_rawDescGZIP(), []int{11}
}
func (x *ModifyFaceTypeRequest) GetUserId() string {
if x != nil {
return x.UserId
}
return ""
}
func (x *ModifyFaceTypeRequest) GetFaceId() []int64 {
if x != nil {
return x.FaceId
}
return nil
}
func (x *ModifyFaceTypeRequest) GetType() int64 {
if x != nil {
return x.Type
}
return 0
}
type ModifyFaceTypeResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Result string `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"`
}
func (x *ModifyFaceTypeResponse) Reset() {
*x = ModifyFaceTypeResponse{}
mi := &file_aisvc_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ModifyFaceTypeResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ModifyFaceTypeResponse) ProtoMessage() {}
func (x *ModifyFaceTypeResponse) ProtoReflect() protoreflect.Message {
mi := &file_aisvc_proto_msgTypes[12]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ModifyFaceTypeResponse.ProtoReflect.Descriptor instead.
func (*ModifyFaceTypeResponse) Descriptor() ([]byte, []int) {
return file_aisvc_proto_rawDescGZIP(), []int{12}
}
func (x *ModifyFaceTypeResponse) GetResult() string {
if x != nil {
return x.Result
}
return ""
}
var File_aisvc_proto protoreflect.FileDescriptor
var file_aisvc_proto_rawDesc = []byte{
@@ -345,22 +727,71 @@ var file_aisvc_proto_rawDesc = []byte{
0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65,
0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52,
0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x32, 0xfe, 0x01, 0x0a, 0x09, 0x41, 0x69, 0x53, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x12, 0x4a, 0x0a, 0x0f, 0x46, 0x61, 0x63, 0x65, 0x52, 0x65, 0x63, 0x6f,
0x67, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x2e, 0x61, 0x69, 0x2e, 0x46, 0x61, 0x63,
0x65, 0x52, 0x65, 0x63, 0x6f, 0x67, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x61, 0x69, 0x2e, 0x46, 0x61, 0x63, 0x65, 0x52, 0x65, 0x63,
0x6f, 0x67, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x12, 0x4d, 0x0a, 0x10, 0x54, 0x66, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x66, 0x69, 0x63, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x2e, 0x61, 0x69, 0x2e, 0x54, 0x66, 0x43, 0x6c, 0x61, 0x73,
0x73, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x1c, 0x2e, 0x61, 0x69, 0x2e, 0x54, 0x66, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x66,
0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
0x56, 0x0a, 0x13, 0x43, 0x61, 0x66, 0x66, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x66, 0x69,
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x2e, 0x61, 0x69, 0x2e, 0x43, 0x61, 0x66, 0x66,
0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x61, 0x69, 0x2e, 0x43, 0x61, 0x66, 0x66,
0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52,
0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x22, 0x46, 0x0a, 0x17, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46,
0x61, 0x63, 0x65, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79,
0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x59,
0x0a, 0x0b, 0x46, 0x61, 0x63, 0x65, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x12, 0x0e, 0x0a,
0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a,
0x09, 0x66, 0x61, 0x63, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
0x52, 0x08, 0x66, 0x61, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x61,
0x63, 0x65, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
0x66, 0x61, 0x63, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x22, 0x41, 0x0a, 0x18, 0x51, 0x75, 0x65,
0x72, 0x79, 0x46, 0x61, 0x63, 0x65, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x05, 0x66, 0x61, 0x63, 0x65, 0x73, 0x18, 0x01,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x61, 0x69, 0x2e, 0x46, 0x61, 0x63, 0x65, 0x4c, 0x69,
0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x05, 0x66, 0x61, 0x63, 0x65, 0x73, 0x22, 0x66, 0x0a, 0x15,
0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x46, 0x61, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17,
0x0a, 0x07, 0x66, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52,
0x06, 0x66, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x61, 0x63, 0x65, 0x5f,
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x61, 0x63, 0x65,
0x4e, 0x61, 0x6d, 0x65, 0x22, 0x4e, 0x0a, 0x16, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x46, 0x61,
0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x17,
0x0a, 0x07, 0x66, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52,
0x06, 0x66, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x61, 0x63, 0x65, 0x5f,
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x61, 0x63, 0x65,
0x4e, 0x61, 0x6d, 0x65, 0x22, 0x5d, 0x0a, 0x15, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x46, 0x61,
0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a,
0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x61, 0x63, 0x65, 0x5f, 0x69,
0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x03, 0x52, 0x06, 0x66, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12,
0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x74,
0x79, 0x70, 0x65, 0x22, 0x30, 0x0a, 0x16, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x46, 0x61, 0x63,
0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a,
0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72,
0x65, 0x73, 0x75, 0x6c, 0x74, 0x32, 0xdf, 0x03, 0x0a, 0x09, 0x41, 0x69, 0x53, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x12, 0x4a, 0x0a, 0x0f, 0x46, 0x61, 0x63, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x67,
0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x2e, 0x61, 0x69, 0x2e, 0x46, 0x61, 0x63, 0x65,
0x52, 0x65, 0x63, 0x6f, 0x67, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x61, 0x69, 0x2e, 0x46, 0x61, 0x63, 0x65, 0x52, 0x65, 0x63, 0x6f,
0x67, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
0x4d, 0x0a, 0x10, 0x54, 0x66, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x2e, 0x61, 0x69, 0x2e, 0x54, 0x66, 0x43, 0x6c, 0x61, 0x73, 0x73,
0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x1c, 0x2e, 0x61, 0x69, 0x2e, 0x54, 0x66, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x66, 0x69,
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56,
0x0a, 0x13, 0x43, 0x61, 0x66, 0x66, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x66, 0x69, 0x63,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x2e, 0x61, 0x69, 0x2e, 0x43, 0x61, 0x66, 0x66, 0x65,
0x43, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x61, 0x69, 0x2e, 0x43, 0x61, 0x66, 0x66, 0x65,
0x43, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x10, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46,
0x61, 0x63, 0x65, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x12, 0x1b, 0x2e, 0x61, 0x69, 0x2e,
0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x61, 0x63, 0x65, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x61, 0x69, 0x2e, 0x51, 0x75, 0x65,
0x72, 0x79, 0x46, 0x61, 0x63, 0x65, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x0e, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x46,
0x61, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x19, 0x2e, 0x61, 0x69, 0x2e, 0x4d, 0x6f, 0x64,
0x69, 0x66, 0x79, 0x46, 0x61, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x61, 0x69, 0x2e, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x46, 0x61,
0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47,
0x0a, 0x0e, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x46, 0x61, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65,
0x12, 0x19, 0x2e, 0x61, 0x69, 0x2e, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x46, 0x61, 0x63, 0x65,
0x54, 0x79, 0x70, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x61, 0x69,
0x2e, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x46, 0x61, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
@@ -377,7 +808,7 @@ func file_aisvc_proto_rawDescGZIP() []byte {
return file_aisvc_proto_rawDescData
}
var file_aisvc_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_aisvc_proto_msgTypes = make([]protoimpl.MessageInfo, 13)
var file_aisvc_proto_goTypes = []any{
(*FaceRecognitionRequest)(nil), // 0: ai.FaceRecognitionRequest
(*FaceRecognitionResponse)(nil), // 1: ai.FaceRecognitionResponse
@@ -385,19 +816,33 @@ var file_aisvc_proto_goTypes = []any{
(*TfClassificationResponse)(nil), // 3: ai.TfClassificationResponse
(*CaffeClassificationRequest)(nil), // 4: ai.CaffeClassificationRequest
(*CaffeClassificationResponse)(nil), // 5: ai.CaffeClassificationResponse
(*QueryFaceLibraryRequest)(nil), // 6: ai.QueryFaceLibraryRequest
(*FaceLibrary)(nil), // 7: ai.FaceLibrary
(*QueryFaceLibraryResponse)(nil), // 8: ai.QueryFaceLibraryResponse
(*ModifyFaceNameRequest)(nil), // 9: ai.ModifyFaceNameRequest
(*ModifyFaceNameResponse)(nil), // 10: ai.ModifyFaceNameResponse
(*ModifyFaceTypeRequest)(nil), // 11: ai.ModifyFaceTypeRequest
(*ModifyFaceTypeResponse)(nil), // 12: ai.ModifyFaceTypeResponse
}
var file_aisvc_proto_depIdxs = []int32{
0, // 0: ai.AiService.FaceRecognition:input_type -> ai.FaceRecognitionRequest
2, // 1: ai.AiService.TfClassification:input_type -> ai.TfClassificationRequest
4, // 2: ai.AiService.CaffeClassification:input_type -> ai.CaffeClassificationRequest
1, // 3: ai.AiService.FaceRecognition:output_type -> ai.FaceRecognitionResponse
3, // 4: ai.AiService.TfClassification:output_type -> ai.TfClassificationResponse
5, // 5: ai.AiService.CaffeClassification:output_type -> ai.CaffeClassificationResponse
3, // [3:6] is the sub-list for method output_type
0, // [0:3] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
7, // 0: ai.QueryFaceLibraryResponse.faces:type_name -> ai.FaceLibrary
0, // 1: ai.AiService.FaceRecognition:input_type -> ai.FaceRecognitionRequest
2, // 2: ai.AiService.TfClassification:input_type -> ai.TfClassificationRequest
4, // 3: ai.AiService.CaffeClassification:input_type -> ai.CaffeClassificationRequest
6, // 4: ai.AiService.QueryFaceLibrary:input_type -> ai.QueryFaceLibraryRequest
9, // 5: ai.AiService.ModifyFaceName:input_type -> ai.ModifyFaceNameRequest
11, // 6: ai.AiService.ModifyFaceType:input_type -> ai.ModifyFaceTypeRequest
1, // 7: ai.AiService.FaceRecognition:output_type -> ai.FaceRecognitionResponse
3, // 8: ai.AiService.TfClassification:output_type -> ai.TfClassificationResponse
5, // 9: ai.AiService.CaffeClassification:output_type -> ai.CaffeClassificationResponse
8, // 10: ai.AiService.QueryFaceLibrary:output_type -> ai.QueryFaceLibraryResponse
10, // 11: ai.AiService.ModifyFaceName:output_type -> ai.ModifyFaceNameResponse
12, // 12: ai.AiService.ModifyFaceType:output_type -> ai.ModifyFaceTypeResponse
7, // [7:13] is the sub-list for method output_type
1, // [1:7] is the sub-list for method input_type
1, // [1:1] is the sub-list for extension type_name
1, // [1:1] is the sub-list for extension extendee
0, // [0:1] is the sub-list for field type_name
}
func init() { file_aisvc_proto_init() }
@@ -411,7 +856,7 @@ func file_aisvc_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_aisvc_proto_rawDesc,
NumEnums: 0,
NumMessages: 6,
NumMessages: 13,
NumExtensions: 0,
NumServices: 1,
},

View File

@@ -22,6 +22,9 @@ const (
AiService_FaceRecognition_FullMethodName = "/ai.AiService/FaceRecognition"
AiService_TfClassification_FullMethodName = "/ai.AiService/TfClassification"
AiService_CaffeClassification_FullMethodName = "/ai.AiService/CaffeClassification"
AiService_QueryFaceLibrary_FullMethodName = "/ai.AiService/QueryFaceLibrary"
AiService_ModifyFaceName_FullMethodName = "/ai.AiService/ModifyFaceName"
AiService_ModifyFaceType_FullMethodName = "/ai.AiService/ModifyFaceType"
)
// AiServiceClient is the client API for AiService service.
@@ -34,6 +37,12 @@ type AiServiceClient interface {
TfClassification(ctx context.Context, in *TfClassificationRequest, opts ...grpc.CallOption) (*TfClassificationResponse, error)
// CaffeClassification
CaffeClassification(ctx context.Context, in *CaffeClassificationRequest, opts ...grpc.CallOption) (*CaffeClassificationResponse, error)
// QueryFaceLibrary
QueryFaceLibrary(ctx context.Context, in *QueryFaceLibraryRequest, opts ...grpc.CallOption) (*QueryFaceLibraryResponse, error)
// ModifyFaceName
ModifyFaceName(ctx context.Context, in *ModifyFaceNameRequest, opts ...grpc.CallOption) (*ModifyFaceNameResponse, error)
// ModifyFaceType
ModifyFaceType(ctx context.Context, in *ModifyFaceTypeRequest, opts ...grpc.CallOption) (*ModifyFaceTypeResponse, error)
}
type aiServiceClient struct {
@@ -74,6 +83,36 @@ func (c *aiServiceClient) CaffeClassification(ctx context.Context, in *CaffeClas
return out, nil
}
func (c *aiServiceClient) QueryFaceLibrary(ctx context.Context, in *QueryFaceLibraryRequest, opts ...grpc.CallOption) (*QueryFaceLibraryResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(QueryFaceLibraryResponse)
err := c.cc.Invoke(ctx, AiService_QueryFaceLibrary_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *aiServiceClient) ModifyFaceName(ctx context.Context, in *ModifyFaceNameRequest, opts ...grpc.CallOption) (*ModifyFaceNameResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ModifyFaceNameResponse)
err := c.cc.Invoke(ctx, AiService_ModifyFaceName_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *aiServiceClient) ModifyFaceType(ctx context.Context, in *ModifyFaceTypeRequest, opts ...grpc.CallOption) (*ModifyFaceTypeResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ModifyFaceTypeResponse)
err := c.cc.Invoke(ctx, AiService_ModifyFaceType_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// AiServiceServer is the server API for AiService service.
// All implementations must embed UnimplementedAiServiceServer
// for forward compatibility.
@@ -84,6 +123,12 @@ type AiServiceServer interface {
TfClassification(context.Context, *TfClassificationRequest) (*TfClassificationResponse, error)
// CaffeClassification
CaffeClassification(context.Context, *CaffeClassificationRequest) (*CaffeClassificationResponse, error)
// QueryFaceLibrary
QueryFaceLibrary(context.Context, *QueryFaceLibraryRequest) (*QueryFaceLibraryResponse, error)
// ModifyFaceName
ModifyFaceName(context.Context, *ModifyFaceNameRequest) (*ModifyFaceNameResponse, error)
// ModifyFaceType
ModifyFaceType(context.Context, *ModifyFaceTypeRequest) (*ModifyFaceTypeResponse, error)
mustEmbedUnimplementedAiServiceServer()
}
@@ -103,6 +148,15 @@ func (UnimplementedAiServiceServer) TfClassification(context.Context, *TfClassif
func (UnimplementedAiServiceServer) CaffeClassification(context.Context, *CaffeClassificationRequest) (*CaffeClassificationResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method CaffeClassification not implemented")
}
func (UnimplementedAiServiceServer) QueryFaceLibrary(context.Context, *QueryFaceLibraryRequest) (*QueryFaceLibraryResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method QueryFaceLibrary not implemented")
}
func (UnimplementedAiServiceServer) ModifyFaceName(context.Context, *ModifyFaceNameRequest) (*ModifyFaceNameResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ModifyFaceName not implemented")
}
func (UnimplementedAiServiceServer) ModifyFaceType(context.Context, *ModifyFaceTypeRequest) (*ModifyFaceTypeResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ModifyFaceType not implemented")
}
func (UnimplementedAiServiceServer) mustEmbedUnimplementedAiServiceServer() {}
func (UnimplementedAiServiceServer) testEmbeddedByValue() {}
@@ -178,6 +232,60 @@ func _AiService_CaffeClassification_Handler(srv interface{}, ctx context.Context
return interceptor(ctx, in, info, handler)
}
func _AiService_QueryFaceLibrary_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(QueryFaceLibraryRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AiServiceServer).QueryFaceLibrary(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: AiService_QueryFaceLibrary_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AiServiceServer).QueryFaceLibrary(ctx, req.(*QueryFaceLibraryRequest))
}
return interceptor(ctx, in, info, handler)
}
func _AiService_ModifyFaceName_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ModifyFaceNameRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AiServiceServer).ModifyFaceName(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: AiService_ModifyFaceName_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AiServiceServer).ModifyFaceName(ctx, req.(*ModifyFaceNameRequest))
}
return interceptor(ctx, in, info, handler)
}
func _AiService_ModifyFaceType_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ModifyFaceTypeRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AiServiceServer).ModifyFaceType(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: AiService_ModifyFaceType_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AiServiceServer).ModifyFaceType(ctx, req.(*ModifyFaceTypeRequest))
}
return interceptor(ctx, in, info, handler)
}
// AiService_ServiceDesc is the grpc.ServiceDesc for AiService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
@@ -197,6 +305,18 @@ var AiService_ServiceDesc = grpc.ServiceDesc{
MethodName: "CaffeClassification",
Handler: _AiService_CaffeClassification_Handler,
},
{
MethodName: "QueryFaceLibrary",
Handler: _AiService_QueryFaceLibrary_Handler,
},
{
MethodName: "ModifyFaceName",
Handler: _AiService_ModifyFaceName_Handler,
},
{
MethodName: "ModifyFaceType",
Handler: _AiService_ModifyFaceType_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "aisvc.proto",

View File

@@ -255,35 +255,35 @@ service auth {
type (
// 评论提交请求参数
CommentRequest {
Content string `json:"content"`
Images []string `json:"images,optional"`
TopicId string `json:"topic_id"`
Author string `json:"author"`
Key string `json:"key"`
Point []int64 `json:"point"`
Content string `json:"content"`
Images string `json:"images,optional"`
TopicId string `json:"topic_id"`
Author string `json:"author"`
Key string `json:"key"`
Point []int64 `json:"point"`
}
// 回复评论提交请求参数
ReplyCommentRequest {
Content string `json:"content"`
Images []string `json:"images,optional"`
TopicId string `json:"topic_id" `
ReplyId int64 `json:"reply_id" `
ReplyUser string `json:"reply_user" `
Author string `json:"author"`
Key string `json:"key"`
Point []int64 `json:"point"`
Content string `json:"content"`
Images string `json:"images,optional"`
TopicId string `json:"topic_id" `
ReplyId int64 `json:"reply_id" `
ReplyUser string `json:"reply_user" `
Author string `json:"author"`
Key string `json:"key"`
Point []int64 `json:"point"`
}
// 回复回复请求参数
ReplyReplyRequest {
Content string `json:"content"`
Images []string `json:"images,optional"`
TopicId string `json:"topic_id"`
ReplyTo int64 `json:"reply_to"`
ReplyId int64 `json:"reply_id"`
ReplyUser string `json:"reply_user" `
Author string `json:"author"`
Key string `json:"key"`
Point []int64 `json:"point"`
Content string `json:"content"`
Images string `json:"images,optional"`
TopicId string `json:"topic_id"`
ReplyTo int64 `json:"reply_to"`
ReplyId int64 `json:"reply_id"`
ReplyUser string `json:"reply_user" `
Author string `json:"author"`
Key string `json:"key"`
Point []int64 `json:"point"`
}
// 评论列表请求参数
CommentListRequest {
@@ -314,26 +314,26 @@ type (
type (
// CommentContent 评论内容
CommentContent {
NickName string `json:"nickname"`
Avatar string `json:"avatar"`
Level int64 `json:"level,omitempty" default:"0"`
Id int64 `json:"id"`
UserId string `json:"user_id"`
TopicId string `json:"topic_id"`
Content string `json:"content"`
ReplyTo int64 `json:"reply_to,omitempty"`
ReplyId int64 `json:"reply_id,omitempty"`
ReplyUser string `json:"reply_user,omitempty"`
ReplyNickname string `json:"reply_nickname,omitempty"`
IsAuthor int64 `json:"is_author"`
Likes int64 `json:"likes"`
ReplyCount int64 `json:"reply_count"`
CreatedTime string `json:"created_time"`
Location string `json:"location"`
Browser string `json:"browser"`
OperatingSystem string `json:"operating_system"`
IsLiked bool `json:"is_liked" default:"false"`
Images []string `json:"images,omitempty"`
NickName string `json:"nickname"`
Avatar string `json:"avatar"`
Level int64 `json:"level,omitempty" default:"0"`
Id int64 `json:"id"`
UserId string `json:"user_id"`
TopicId string `json:"topic_id"`
Content string `json:"content"`
ReplyTo int64 `json:"reply_to,omitempty"`
ReplyId int64 `json:"reply_id,omitempty"`
ReplyUser string `json:"reply_user,omitempty"`
ReplyNickname string `json:"reply_nickname,omitempty"`
IsAuthor int64 `json:"is_author"`
Likes int64 `json:"likes"`
ReplyCount int64 `json:"reply_count"`
CreatedTime string `json:"created_time"`
Location string `json:"location"`
Browser string `json:"browser"`
OperatingSystem string `json:"operating_system"`
IsLiked bool `json:"is_liked" default:"false"`
Images string `json:"images,omitempty"`
}
// CommentListPageResponse 评论返回值
CommentListPageResponse {
@@ -365,7 +365,7 @@ type (
timeout: 10s // 超时时间
maxBytes: 1048576 // 最大请求大小
signature: false // 是否开启签名验证
middleware: SecurityHeadersMiddleware,CasbinVerifyMiddleware,AuthorizationMiddleware,NonceMiddleware // 注册中间件
middleware: SecurityHeadersMiddleware,CasbinVerifyMiddleware,NonceMiddleware // 注册中间件
MaxConns: true // 是否开启最大连接数限制
Recover: true // 是否开启自动恢复
jwt: Auth // 是否开启jwt验证
@@ -427,6 +427,28 @@ type (
Bucket string `json:"bucket"`
Region string `json:"region"`
}
FaceSampleLibrary {
ID int64 `json:"id"`
FaceName string `json:"face_name"`
FaceImage string `json:"face_image"`
}
FaceSampleLibraryListRequest {
Type int64 `json:"type"`
}
FaceSampleLibraryListResponse {
faces []FaceSampleLibrary `json:"faces"`
}
ModifyFaceNameRequestAndResponse {
ID int64 `json:"id"`
FaceName string `json:"face_name"`
}
ModifyFaceTypeRequest {
IDs []int64 `json:"ids"`
FaceType int64 `json:"face_type"`
}
ModifyFaceTypeResponse {
result string `json:"result"`
}
)
// 文件上传
@@ -436,7 +458,7 @@ type (
timeout: 20s // 超时时间
maxBytes: 104857600 // 最大请求大小
signature: false // 是否开启签名验证
middleware: SecurityHeadersMiddleware,CasbinVerifyMiddleware,AuthorizationMiddleware,NonceMiddleware // 注册中间件
middleware: SecurityHeadersMiddleware,CasbinVerifyMiddleware,NonceMiddleware // 注册中间件
MaxConns: true // 是否开启最大连接数限制
Recover: true // 是否开启自动恢复
jwt: Auth // 是否开启jwt验证
@@ -449,5 +471,17 @@ service auth {
// 设置存储配置
@handler setStorageConfig
post /config (StorageConfigRequest) returns (string)
// 获取人脸样本库列表
@handler getFaceSampleLibraryList
post /face/sample/list (FaceSampleLibraryListRequest) returns (FaceSampleLibraryListResponse)
// 修改人脸样本名称
@handler modifyFaceLibraryName
post /face/sample/modify/name (ModifyFaceNameRequestAndResponse) returns (ModifyFaceNameRequestAndResponse)
// 修改人脸样本类型
@handler modifyFaceLibraryType
post /face/sample/modify/type (ModifyFaceTypeRequest) returns (ModifyFaceTypeResponse)
}

View File

@@ -170,6 +170,17 @@ SMS:
Username: landaiqing
# 短信宝用户密码
Password: $LDQ20020618xxx$
# 高德地图配置
Map:
# 高德地图API Key
Key: 54823a494909959a9c8cd8af101bbc32
Key: 54823a494909959a9c8cd8af101bbc32
# Minio配置
Minio:
# Minio 地址
Endpoint: 1.95.0.111:9000
# Minio 访问密钥
AccessKeyID: JNLVxMGro1XXwajodLBX
# Minio 访问密钥
SecretAccessKey: XEHkwExqQdAlEPfpRk36xpc0Sie8hZkcmlhXQJXw
# Minio 使用SSL
UseSSL: false

View File

@@ -74,4 +74,10 @@ type Config struct {
Map struct {
Key string
}
Minio struct {
Endpoint string
AccessKeyID string
SecretAccessKey string
UseSSL bool
}
}

View File

@@ -62,7 +62,7 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
server.AddRoutes(
rest.WithMiddlewares(
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware, serverCtx.CasbinVerifyMiddleware, serverCtx.AuthorizationMiddleware, serverCtx.NonceMiddleware},
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware, serverCtx.CasbinVerifyMiddleware, serverCtx.NonceMiddleware},
[]rest.Route{
{
Method: http.MethodPost,
@@ -186,13 +186,28 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
server.AddRoutes(
rest.WithMiddlewares(
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware, serverCtx.CasbinVerifyMiddleware, serverCtx.AuthorizationMiddleware, serverCtx.NonceMiddleware},
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware, serverCtx.CasbinVerifyMiddleware, serverCtx.NonceMiddleware},
[]rest.Route{
{
Method: http.MethodPost,
Path: "/config",
Handler: storage.SetStorageConfigHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/face/sample/list",
Handler: storage.GetFaceSampleLibraryListHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/face/sample/modify/name",
Handler: storage.ModifyFaceLibraryNameHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/face/sample/modify/type",
Handler: storage.ModifyFaceLibraryTypeHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/uploads",

View File

@@ -0,0 +1,29 @@
package storage
import (
"github.com/zeromicro/go-zero/rest/httpx"
"net/http"
"schisandra-album-cloud-microservices/app/auth/api/internal/types"
"schisandra-album-cloud-microservices/app/auth/api/internal/logic/storage"
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
"schisandra-album-cloud-microservices/common/xhttp"
)
func GetFaceSampleLibraryListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.FaceSampleLibraryListRequest
if err := httpx.Parse(r, &req); err != nil {
xhttp.JsonBaseResponseCtx(r.Context(), w, err)
return
}
l := storage.NewGetFaceSampleLibraryListLogic(r.Context(), svcCtx)
resp, err := l.GetFaceSampleLibraryList(&req)
if err != nil {
xhttp.JsonBaseResponseCtx(r.Context(), w, err)
} else {
xhttp.JsonBaseResponseCtx(r.Context(), w, resp)
}
}
}

View File

@@ -0,0 +1,29 @@
package storage
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"schisandra-album-cloud-microservices/app/auth/api/internal/logic/storage"
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
"schisandra-album-cloud-microservices/app/auth/api/internal/types"
"schisandra-album-cloud-microservices/common/xhttp"
)
func ModifyFaceLibraryNameHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.ModifyFaceNameRequestAndResponse
if err := httpx.Parse(r, &req); err != nil {
xhttp.JsonBaseResponseCtx(r.Context(), w, err)
return
}
l := storage.NewModifyFaceLibraryNameLogic(r.Context(), svcCtx)
resp, err := l.ModifyFaceLibraryName(&req)
if err != nil {
xhttp.JsonBaseResponseCtx(r.Context(), w, err)
} else {
xhttp.JsonBaseResponseCtx(r.Context(), w, resp)
}
}
}

View File

@@ -0,0 +1,29 @@
package storage
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"schisandra-album-cloud-microservices/app/auth/api/internal/logic/storage"
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
"schisandra-album-cloud-microservices/app/auth/api/internal/types"
"schisandra-album-cloud-microservices/common/xhttp"
)
func ModifyFaceLibraryTypeHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.ModifyFaceTypeRequest
if err := httpx.Parse(r, &req); err != nil {
xhttp.JsonBaseResponseCtx(r.Context(), w, err)
return
}
l := storage.NewModifyFaceLibraryTypeLogic(r.Context(), svcCtx)
resp, err := l.ModifyFaceLibraryType(&req)
if err != nil {
xhttp.JsonBaseResponseCtx(r.Context(), w, err)
} else {
xhttp.JsonBaseResponseCtx(r.Context(), w, resp)
}
}
}

View File

@@ -34,7 +34,7 @@ func (l *GenerateClientIdLogic) GenerateClientId(clientIP string) (resp string,
return clientId, nil
}
simpleUuid := kgo.SimpleUuid()
if err = l.svcCtx.RedisClient.SetEx(l.ctx, constant.UserClientPrefix+clientIP, simpleUuid, time.Hour*24*7).Err(); err != nil {
if err = l.svcCtx.RedisClient.SetEx(l.ctx, constant.UserClientPrefix+clientIP, simpleUuid, time.Hour*24*3).Err(); err != nil {
return "", errors.New(http.StatusInternalServerError, err.Error())
}
return simpleUuid, nil

View File

@@ -2,17 +2,14 @@ package comment
import (
"context"
"encoding/base64"
"errors"
"fmt"
"net/url"
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
"schisandra-album-cloud-microservices/app/auth/api/internal/types"
"schisandra-album-cloud-microservices/app/auth/model/mongodb"
"schisandra-album-cloud-microservices/common/constant"
"schisandra-album-cloud-microservices/common/utils"
"sync"
"time"
"github.com/chenmingyong0423/go-mongox/v2/builder/query"
"github.com/zeromicro/go-zero/core/logx"
"gorm.io/gen/field"
)
@@ -60,6 +57,7 @@ func (l *GetCommentListLogic) GetCommentList(req *types.CommentListRequest) (res
comment.Browser,
comment.OperatingSystem,
comment.Location,
comment.ImagePath,
user.Avatar,
user.Nickname,
).LeftJoin(user, comment.UserID.EqCol(user.UID)).
@@ -82,7 +80,7 @@ func (l *GetCommentListLogic) GetCommentList(req *types.CommentListRequest) (res
for _, commentList := range commentQueryList {
commentIds = append(commentIds, commentList.ID)
}
l.wg.Add(2)
l.wg.Add(1)
// *************** 获取评论点赞状态 **********
likeMap := make(map[int64]bool)
@@ -102,36 +100,22 @@ func (l *GetCommentListLogic) GetCommentList(req *types.CommentListRequest) (res
likeMap[like.CommentID] = true
}
}()
// ***************获取评论图片 **********
commentImageMap := make(map[int64][]string)
go func() {
defer l.wg.Done()
newCollection := mongodb.MustNewCollection[types.CommentImages](l.svcCtx.MongoClient, constant.COMMENT_IMAGES)
commentImages, err := newCollection.Finder().
Filter(query.Eq("topic_id", req.TopicId)).
Filter(query.In("comment_id", commentIds...)).
Find(l.ctx)
if err != nil {
logx.Error(err)
return
}
for _, image := range commentImages {
if len(image.Images) == 0 {
continue
}
imagesBase64 := make([]string, len(image.Images))
for i, img := range image.Images {
imagesBase64[i] = fmt.Sprintf("data:%s;base64,%s", utils.GetMimeType(img), base64.StdEncoding.EncodeToString(img))
}
commentImageMap[image.CommentId] = imagesBase64
}
}()
l.wg.Wait()
// *************** 组装数据 **********
result := make([]types.CommentContent, 0, len(commentQueryList))
for _, commentData := range commentQueryList {
var imagePath string
if commentData.ImagePath != "" {
reqParams := make(url.Values)
presignedURL, err := l.svcCtx.MinioClient.PresignedGetObject(l.ctx, constant.CommentImagesBucketName, commentData.ImagePath, time.Hour*24, reqParams)
if err != nil {
logx.Error(err)
continue
}
imagePath = presignedURL.String()
}
commentContent := types.CommentContent{
Avatar: commentData.Avatar,
NickName: commentData.Nickname,
@@ -148,7 +132,7 @@ func (l *GetCommentListLogic) GetCommentList(req *types.CommentListRequest) (res
Browser: commentData.Browser,
OperatingSystem: commentData.OperatingSystem,
IsLiked: likeMap[commentData.ID],
Images: commentImageMap[commentData.ID],
Images: imagePath,
}
result = append(result, commentContent)
}

View File

@@ -2,17 +2,13 @@ package comment
import (
"context"
"encoding/base64"
"errors"
"fmt"
"net/url"
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
"schisandra-album-cloud-microservices/app/auth/api/internal/types"
"schisandra-album-cloud-microservices/app/auth/model/mongodb"
"schisandra-album-cloud-microservices/common/constant"
"schisandra-album-cloud-microservices/common/utils"
"sync"
"github.com/chenmingyong0423/go-mongox/v2/builder/query"
"time"
"github.com/zeromicro/go-zero/core/logx"
)
@@ -59,6 +55,7 @@ func (l *GetReplyListLogic) GetReplyList(req *types.ReplyListRequest) (resp *typ
reply.ReplyUser,
reply.ReplyTo,
reply.ReplyID,
reply.ImagePath,
commentUser.Avatar,
commentUser.Nickname,
replyUser.Nickname.As("reply_nickname"),
@@ -82,7 +79,7 @@ func (l *GetReplyListLogic) GetReplyList(req *types.ReplyListRequest) (resp *typ
for _, commentList := range replyQueryList {
commentIds = append(commentIds, commentList.ID)
}
l.wg.Add(2)
l.wg.Add(1)
// *************** 获取评论点赞状态 **********
likeMap := make(map[int64]bool)
@@ -102,36 +99,22 @@ func (l *GetReplyListLogic) GetReplyList(req *types.ReplyListRequest) (resp *typ
likeMap[like.CommentID] = true
}
}()
// ***************获取评论图片 **********
commentImageMap := make(map[int64][]string)
go func() {
defer l.wg.Done()
newCollection := mongodb.MustNewCollection[types.CommentImages](l.svcCtx.MongoClient, constant.COMMENT_IMAGES)
commentImages, err := newCollection.Finder().
Filter(query.Eq("topic_id", req.TopicId)).
Filter(query.In("comment_id", commentIds...)).
Find(l.ctx)
if err != nil {
logx.Error(err)
return
}
for _, image := range commentImages {
if len(image.Images) == 0 {
continue
}
imagesBase64 := make([]string, len(image.Images))
for i, img := range image.Images {
imagesBase64[i] = fmt.Sprintf("data:%s;base64,%s", utils.GetMimeType(img), base64.StdEncoding.EncodeToString(img))
}
commentImageMap[image.CommentId] = imagesBase64
}
}()
l.wg.Wait()
// *************** 组装数据 **********
result := make([]types.CommentContent, 0, len(replyQueryList))
for _, replyData := range replyQueryList {
var imagePath string
if replyData.ImagePath != "" {
reqParams := make(url.Values)
presignedURL, err := l.svcCtx.MinioClient.PresignedGetObject(l.ctx, constant.CommentImagesBucketName, replyData.ImagePath, time.Hour*24, reqParams)
if err != nil {
logx.Error(err)
continue
}
imagePath = presignedURL.String()
}
commentContent := types.CommentContent{
Avatar: replyData.Avatar,
NickName: replyData.Nickname,
@@ -148,7 +131,7 @@ func (l *GetReplyListLogic) GetReplyList(req *types.ReplyListRequest) (resp *typ
Browser: replyData.Browser,
OperatingSystem: replyData.OperatingSystem,
IsLiked: likeMap[replyData.ID],
Images: commentImageMap[replyData.ID],
Images: imagePath,
ReplyUser: replyData.ReplyUser,
ReplyTo: replyData.ReplyTo,
ReplyId: replyData.ReplyId,

View File

@@ -1,13 +1,18 @@
package comment
import (
"bytes"
"context"
"errors"
"fmt"
"github.com/ccpwcn/kgo"
"github.com/minio/minio-go/v7"
"net/http"
"path"
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
"schisandra-album-cloud-microservices/app/auth/api/internal/types"
"schisandra-album-cloud-microservices/app/auth/model/mongodb"
"schisandra-album-cloud-microservices/app/auth/model/mysql/model"
"strconv"
"schisandra-album-cloud-microservices/common/captcha/verify"
"schisandra-album-cloud-microservices/common/constant"
@@ -41,9 +46,6 @@ func (l *SubmitCommentLogic) SubmitComment(r *http.Request, req *types.CommentRe
if !res {
return nil, errors2.New(http.StatusInternalServerError, i18n.FormatText(l.ctx, "captcha.verificationFailure"))
}
if len(req.Images) > 3 {
return nil, errors2.New(http.StatusInternalServerError, i18n.FormatText(l.ctx, "comment.tooManyImages"))
}
userAgent := r.Header.Get("User-Agent")
if userAgent == "" {
return nil, errors2.New(http.StatusInternalServerError, i18n.FormatText(l.ctx, "comment.commentError"))
@@ -74,6 +76,7 @@ func (l *SubmitCommentLogic) SubmitComment(r *http.Request, req *types.CommentRe
commentContent := l.svcCtx.Sensitive.Replace(xssFilterContent, '*')
topicType := constant.CommentTopicType
commentType := constant.COMMENT
commentReply := l.svcCtx.DB.ScaCommentReply
comment := &model.ScaCommentReply{
Content: commentContent,
UserID: uid,
@@ -87,28 +90,52 @@ func (l *SubmitCommentLogic) SubmitComment(r *http.Request, req *types.CommentRe
OperatingSystem: operatingSystem,
Agent: userAgent,
}
err = l.svcCtx.DB.ScaCommentReply.Create(comment)
err = commentReply.Create(comment)
if err != nil {
return nil, err
}
if len(req.Images) > 0 {
imagesData, err := utils.ProcessImages(req.Images)
if req.Images != "" {
imagesData, err := utils.Base64ToBytes(req.Images)
if err != nil {
return nil, err
}
commentImages := &types.CommentImages{
UserId: uid,
TopicId: req.TopicId,
CommentId: comment.ID,
Images: imagesData,
objectKey := path.Join(
req.TopicId,
time.Now().Format("2006/01"), // 按年/月划分目录
strconv.FormatInt(comment.ID, 10),
fmt.Sprintf("%s_%s.jpg", uid, kgo.SimpleUuid()),
)
exists, err := l.svcCtx.MinioClient.BucketExists(l.ctx, constant.CommentImagesBucketName)
if err != nil || !exists {
err = l.svcCtx.MinioClient.MakeBucket(l.ctx, constant.CommentImagesBucketName, minio.MakeBucketOptions{Region: "us-east-1", ObjectLocking: true})
if err != nil {
logx.Errorf("Failed to create MinIO bucket: %v", err)
return nil, err
}
}
newCollection := mongodb.MustNewCollection[types.CommentImages](l.svcCtx.MongoClient, constant.COMMENT_IMAGES)
_, err = newCollection.Creator().InsertOne(l.ctx, commentImages)
// 上传到MinIO
_, err = l.svcCtx.MinioClient.PutObject(
l.ctx,
constant.CommentImagesBucketName,
objectKey,
bytes.NewReader(imagesData),
int64(len(imagesData)),
minio.PutObjectOptions{
ContentType: "image/jpeg",
},
)
if err != nil {
logx.Errorf("Failed to upload image to MinIO: %v", err)
return nil, err
}
info, err := commentReply.Where(commentReply.ID.Eq(comment.ID)).Update(commentReply.ImagePath, objectKey)
if err != nil || info.RowsAffected == 0 {
return nil, errors.New("update image path failed")
}
}
commentResponse := &types.CommentResponse{
Id: comment.ID,

View File

@@ -1,18 +1,23 @@
package comment
import (
"bytes"
"context"
"errors"
"fmt"
"github.com/ccpwcn/kgo"
"github.com/minio/minio-go/v7"
"net/http"
"path"
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
"schisandra-album-cloud-microservices/app/auth/api/internal/types"
"schisandra-album-cloud-microservices/app/auth/model/mongodb"
"schisandra-album-cloud-microservices/app/auth/model/mysql/model"
"schisandra-album-cloud-microservices/common/captcha/verify"
"schisandra-album-cloud-microservices/common/constant"
errors2 "schisandra-album-cloud-microservices/common/errors"
"schisandra-album-cloud-microservices/common/i18n"
"schisandra-album-cloud-microservices/common/utils"
"strconv"
"time"
"github.com/mssola/useragent"
@@ -39,9 +44,6 @@ func (l *SubmitReplyCommentLogic) SubmitReplyComment(r *http.Request, req *types
if !res {
return nil, errors2.New(http.StatusInternalServerError, i18n.FormatText(l.ctx, "captcha.verificationFailure"))
}
if len(req.Images) > 3 {
return nil, errors2.New(http.StatusInternalServerError, i18n.FormatText(l.ctx, "comment.tooManyImages"))
}
userAgent := r.Header.Get("User-Agent")
if userAgent == "" {
return nil, errors2.New(http.StatusInternalServerError, i18n.FormatText(l.ctx, "comment.commentError"))
@@ -105,24 +107,47 @@ func (l *SubmitReplyCommentLogic) SubmitReplyComment(r *http.Request, req *types
}
if len(req.Images) > 0 {
imagesData, err := utils.ProcessImages(req.Images)
if req.Images != "" {
imagesData, err := utils.Base64ToBytes(req.Images)
if err != nil {
return nil, err
}
objectKey := path.Join(
req.TopicId,
time.Now().Format("2006/01"), // 按年/月划分目录
strconv.FormatInt(reply.ID, 10),
fmt.Sprintf("%s_%s.jpg", uid, kgo.SimpleUuid()),
)
commentImages := &types.CommentImages{
UserId: uid,
TopicId: req.TopicId,
CommentId: reply.ID,
Images: imagesData,
exists, err := l.svcCtx.MinioClient.BucketExists(l.ctx, constant.CommentImagesBucketName)
if err != nil || !exists {
err = l.svcCtx.MinioClient.MakeBucket(l.ctx, constant.CommentImagesBucketName, minio.MakeBucketOptions{Region: "us-east-1", ObjectLocking: true})
if err != nil {
logx.Errorf("Failed to create MinIO bucket: %v", err)
return nil, err
}
}
newCollection := mongodb.MustNewCollection[types.CommentImages](l.svcCtx.MongoClient, constant.COMMENT_IMAGES)
_, err = newCollection.Creator().InsertOne(l.ctx, commentImages)
// 上传到MinIO
_, err = l.svcCtx.MinioClient.PutObject(
l.ctx,
constant.CommentImagesBucketName,
objectKey,
bytes.NewReader(imagesData),
int64(len(imagesData)),
minio.PutObjectOptions{
ContentType: "image/jpeg",
},
)
if err != nil {
logx.Errorf("Failed to upload image to MinIO: %v", err)
return nil, err
}
info, err := commentReply.Where(commentReply.ID.Eq(reply.ID)).Update(commentReply.ImagePath, objectKey)
if err != nil || info.RowsAffected == 0 {
return nil, errors.New("update image path failed")
}
}
commentResponse := &types.CommentResponse{

View File

@@ -1,18 +1,23 @@
package comment
import (
"bytes"
"context"
"errors"
"fmt"
"github.com/ccpwcn/kgo"
"github.com/minio/minio-go/v7"
"net/http"
"path"
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
"schisandra-album-cloud-microservices/app/auth/api/internal/types"
"schisandra-album-cloud-microservices/app/auth/model/mongodb"
"schisandra-album-cloud-microservices/app/auth/model/mysql/model"
"schisandra-album-cloud-microservices/common/captcha/verify"
"schisandra-album-cloud-microservices/common/constant"
errors2 "schisandra-album-cloud-microservices/common/errors"
"schisandra-album-cloud-microservices/common/i18n"
"schisandra-album-cloud-microservices/common/utils"
"strconv"
"time"
"github.com/mssola/useragent"
@@ -39,9 +44,6 @@ func (l *SubmitReplyReplyLogic) SubmitReplyReply(r *http.Request, req *types.Rep
if !res {
return nil, errors2.New(http.StatusInternalServerError, i18n.FormatText(l.ctx, "captcha.verificationFailure"))
}
if len(req.Images) > 3 {
return nil, errors2.New(http.StatusInternalServerError, i18n.FormatText(l.ctx, "comment.tooManyImages"))
}
userAgent := r.Header.Get("User-Agent")
if userAgent == "" {
return nil, errors2.New(http.StatusInternalServerError, i18n.FormatText(l.ctx, "comment.commentError"))
@@ -112,24 +114,47 @@ func (l *SubmitReplyReplyLogic) SubmitReplyReply(r *http.Request, req *types.Rep
}
// 处理图片
if len(req.Images) > 0 {
imagesData, err := utils.ProcessImages(req.Images)
if req.Images != "" {
imagesData, err := utils.Base64ToBytes(req.Images)
if err != nil {
return nil, err
}
commentImages := &types.CommentImages{
UserId: uid,
TopicId: req.TopicId,
CommentId: replyReply.ID,
Images: imagesData,
objectKey := path.Join(
req.TopicId,
time.Now().Format("2006/01"), // 按年/月划分目录
strconv.FormatInt(replyReply.ID, 10),
fmt.Sprintf("%s_%s.jpg", uid, kgo.SimpleUuid()),
)
exists, err := l.svcCtx.MinioClient.BucketExists(l.ctx, constant.CommentImagesBucketName)
if err != nil || !exists {
err = l.svcCtx.MinioClient.MakeBucket(l.ctx, constant.CommentImagesBucketName, minio.MakeBucketOptions{Region: "us-east-1", ObjectLocking: true})
if err != nil {
logx.Errorf("Failed to create MinIO bucket: %v", err)
return nil, err
}
}
newCollection := mongodb.MustNewCollection[types.CommentImages](l.svcCtx.MongoClient, constant.COMMENT_IMAGES)
_, err = newCollection.Creator().InsertOne(l.ctx, commentImages)
// 上传到MinIO
_, err = l.svcCtx.MinioClient.PutObject(
l.ctx,
constant.CommentImagesBucketName,
objectKey,
bytes.NewReader(imagesData),
int64(len(imagesData)),
minio.PutObjectOptions{
ContentType: "image/jpeg",
},
)
if err != nil {
logx.Errorf("Failed to upload image to MinIO: %v", err)
return nil, err
}
info, err := commentReply.Where(commentReply.ID.Eq(replyReply.ID)).Update(commentReply.ImagePath, objectKey)
if err != nil || info.RowsAffected == 0 {
return nil, errors.New("update image path failed")
}
}
// 构建响应

View File

@@ -0,0 +1,48 @@
package storage
import (
"context"
"errors"
"schisandra-album-cloud-microservices/app/aisvc/rpc/pb"
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
"schisandra-album-cloud-microservices/app/auth/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GetFaceSampleLibraryListLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetFaceSampleLibraryListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetFaceSampleLibraryListLogic {
return &GetFaceSampleLibraryListLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetFaceSampleLibraryListLogic) GetFaceSampleLibraryList(req *types.FaceSampleLibraryListRequest) (resp *types.FaceSampleLibraryListResponse, err error) {
uid, ok := l.ctx.Value("user_id").(string)
if !ok {
return nil, errors.New("user_id not found")
}
faceLibrary, err := l.svcCtx.AiSvcRpc.QueryFaceLibrary(l.ctx, &pb.QueryFaceLibraryRequest{UserId: uid, Type: req.Type})
if err != nil {
return nil, err
}
var faceSampleLibraries []types.FaceSampleLibrary
for _, face := range faceLibrary.GetFaces() {
faceSampleLibraries = append(faceSampleLibraries, types.FaceSampleLibrary{
ID: face.GetId(),
FaceName: face.GetFaceName(),
FaceImage: face.GetFaceImage(),
})
}
return &types.FaceSampleLibraryListResponse{
Faces: faceSampleLibraries,
}, nil
}

View File

@@ -0,0 +1,38 @@
package storage
import (
"context"
"errors"
"schisandra-album-cloud-microservices/app/aisvc/rpc/pb"
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
"schisandra-album-cloud-microservices/app/auth/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type ModifyFaceLibraryNameLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewModifyFaceLibraryNameLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ModifyFaceLibraryNameLogic {
return &ModifyFaceLibraryNameLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *ModifyFaceLibraryNameLogic) ModifyFaceLibraryName(req *types.ModifyFaceNameRequestAndResponse) (resp *types.ModifyFaceNameRequestAndResponse, err error) {
uid, ok := l.ctx.Value("user_id").(string)
if !ok {
return nil, errors.New("user_id not found")
}
faceInfo, err := l.svcCtx.AiSvcRpc.ModifyFaceName(l.ctx, &pb.ModifyFaceNameRequest{UserId: uid, FaceId: req.ID, FaceName: req.FaceName})
if err != nil {
return nil, err
}
return &types.ModifyFaceNameRequestAndResponse{ID: faceInfo.GetFaceId(), FaceName: faceInfo.GetFaceName()}, nil
}

View File

@@ -0,0 +1,46 @@
package storage
import (
"context"
"errors"
"schisandra-album-cloud-microservices/app/aisvc/rpc/pb"
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
"schisandra-album-cloud-microservices/app/auth/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type ModifyFaceLibraryTypeLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewModifyFaceLibraryTypeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ModifyFaceLibraryTypeLogic {
return &ModifyFaceLibraryTypeLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *ModifyFaceLibraryTypeLogic) ModifyFaceLibraryType(req *types.ModifyFaceTypeRequest) (resp *types.ModifyFaceTypeResponse, err error) {
uid, ok := l.ctx.Value("user_id").(string)
if !ok {
return nil, errors.New("user_id not found")
}
faceInfo, err := l.svcCtx.AiSvcRpc.ModifyFaceType(l.ctx, &pb.ModifyFaceTypeRequest{UserId: uid, FaceId: req.IDs, Type: req.FaceType})
if err != nil {
return nil, err
}
storageInfo := l.svcCtx.DB.ScaStorageInfo
resultInfo, err := storageInfo.Where(storageInfo.FaceID.In(req.IDs...)).Update(storageInfo.Hide, req.FaceType)
if err != nil {
return nil, err
}
if resultInfo.RowsAffected != int64(len(req.IDs)) {
return nil, errors.New("update failed")
}
return &types.ModifyFaceTypeResponse{Result: faceInfo.Result}, nil
}

View File

@@ -1,20 +0,0 @@
package middleware
import (
"net/http"
"schisandra-album-cloud-microservices/common/middleware"
)
type AuthorizationMiddleware struct {
}
func NewAuthorizationMiddleware() *AuthorizationMiddleware {
return &AuthorizationMiddleware{}
}
func (m *AuthorizationMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
middleware.AuthorizationMiddleware(w, r)
next(w, r)
}
}

View File

@@ -4,23 +4,23 @@ import (
"github.com/ArtisanCloud/PowerWeChat/v3/src/officialAccount"
"github.com/casbin/casbin/v2"
"github.com/lionsoul2014/ip2region/binding/golang/xdb"
"github.com/minio/minio-go/v7"
"github.com/redis/go-redis/v9"
"github.com/wenlng/go-captcha/v2/rotate"
"github.com/wenlng/go-captcha/v2/slide"
"github.com/zeromicro/go-zero/rest"
"github.com/zeromicro/go-zero/zrpc"
sensitive "github.com/zmexing/go-sensitive-word"
"go.mongodb.org/mongo-driver/v2/mongo"
"schisandra-album-cloud-microservices/app/aisvc/rpc/client/aiservice"
"schisandra-album-cloud-microservices/app/auth/api/internal/config"
"schisandra-album-cloud-microservices/app/auth/api/internal/middleware"
"schisandra-album-cloud-microservices/app/auth/model/mongodb"
"schisandra-album-cloud-microservices/app/auth/model/mysql"
"schisandra-album-cloud-microservices/app/auth/model/mysql/query"
"schisandra-album-cloud-microservices/common/captcha/initialize"
"schisandra-album-cloud-microservices/common/casbinx"
"schisandra-album-cloud-microservices/common/gao_map"
"schisandra-album-cloud-microservices/common/ip2region"
"schisandra-album-cloud-microservices/common/miniox"
"schisandra-album-cloud-microservices/common/redisx"
"schisandra-album-cloud-microservices/common/sensitivex"
"schisandra-album-cloud-microservices/common/storage"
@@ -33,19 +33,18 @@ type ServiceContext struct {
AiSvcRpc aiservice.AiService
SecurityHeadersMiddleware rest.Middleware
CasbinVerifyMiddleware rest.Middleware
AuthorizationMiddleware rest.Middleware
NonceMiddleware rest.Middleware
DB *query.Query
RedisClient *redis.Client
Ip2Region *xdb.Searcher
CasbinEnforcer *casbin.SyncedCachedEnforcer
WechatOfficial *officialAccount.OfficialAccount
MongoClient *mongo.Database
RotateCaptcha rotate.Captcha
SlideCaptcha slide.Captcha
Sensitive *sensitive.Manager
StorageManager *manager.Manager
GaoMap *gao_map.AmapClient
MinioClient *minio.Client
}
func NewServiceContext(c config.Config) *ServiceContext {
@@ -56,7 +55,6 @@ func NewServiceContext(c config.Config) *ServiceContext {
Config: c,
SecurityHeadersMiddleware: middleware.NewSecurityHeadersMiddleware().Handle,
CasbinVerifyMiddleware: middleware.NewCasbinVerifyMiddleware(casbinEnforcer).Handle,
AuthorizationMiddleware: middleware.NewAuthorizationMiddleware().Handle,
NonceMiddleware: middleware.NewNonceMiddleware(redisClient).Handle,
DB: queryDB,
RedisClient: redisClient,
@@ -65,10 +63,10 @@ func NewServiceContext(c config.Config) *ServiceContext {
WechatOfficial: wechat_official.NewWechatPublic(c.Wechat.AppID, c.Wechat.AppSecret, c.Wechat.Token, c.Wechat.AESKey, c.Redis.Host, c.Redis.Pass, c.Redis.DB),
RotateCaptcha: initialize.NewRotateCaptcha(),
SlideCaptcha: initialize.NewSlideCaptcha(),
MongoClient: mongodb.NewMongoDB(c.Mongo.Uri, c.Mongo.Username, c.Mongo.Password, c.Mongo.AuthSource, c.Mongo.Database),
Sensitive: sensitivex.NewSensitive(),
StorageManager: storage.InitStorageManager(),
GaoMap: gao_map.NewAmapClient(c.Map.Key, ""),
AiSvcRpc: aiservice.NewAiService(zrpc.MustNewClient(c.AiSvcRpc)),
MinioClient: miniox.NewMinio(c.Minio.Endpoint, c.Minio.AccessKeyID, c.Minio.SecretAccessKey, c.Minio.UseSSL),
}
}

View File

@@ -2,19 +2,8 @@ package types
import (
"time"
"github.com/chenmingyong0423/go-mongox/v2"
)
// CommentImages 评论 图片
type CommentImages struct {
mongox.Model `bson:",inline"`
TopicId string `json:"topic_id" bson:"topic_id"`
CommentId int64 `json:"comment_id" bson:"comment_id"`
UserId string `json:"user_id" bson:"user_id"`
Images [][]byte `json:"images" bson:"images"`
}
// CommentListQueryResult 评论列表查询结果
type CommentListQueryResult struct {
ID int64 `json:"id"`
@@ -30,6 +19,7 @@ type CommentListQueryResult struct {
Location string `json:"location"`
Avatar string `json:"avatar"`
Nickname string `json:"nickname"`
ImagePath string `json:"image_path"`
}
// ReplyListQueryResult 回复列表查询结果
@@ -51,4 +41,5 @@ type ReplyListQueryResult struct {
ReplyId int64 `json:"reply_id"`
ReplyTo int64 `json:"reply_to"`
ReplyNickname string `json:"reply_nickname"`
ImagePath string `json:"image_path"`
}

View File

@@ -12,26 +12,26 @@ type AccountLoginRequest struct {
}
type CommentContent struct {
NickName string `json:"nickname"`
Avatar string `json:"avatar"`
Level int64 `json:"level,omitempty" default:"0"`
Id int64 `json:"id"`
UserId string `json:"user_id"`
TopicId string `json:"topic_id"`
Content string `json:"content"`
ReplyTo int64 `json:"reply_to,omitempty"`
ReplyId int64 `json:"reply_id,omitempty"`
ReplyUser string `json:"reply_user,omitempty"`
ReplyNickname string `json:"reply_nickname,omitempty"`
IsAuthor int64 `json:"is_author"`
Likes int64 `json:"likes"`
ReplyCount int64 `json:"reply_count"`
CreatedTime string `json:"created_time"`
Location string `json:"location"`
Browser string `json:"browser"`
OperatingSystem string `json:"operating_system"`
IsLiked bool `json:"is_liked" default:"false"`
Images []string `json:"images,omitempty"`
NickName string `json:"nickname"`
Avatar string `json:"avatar"`
Level int64 `json:"level,omitempty" default:"0"`
Id int64 `json:"id"`
UserId string `json:"user_id"`
TopicId string `json:"topic_id"`
Content string `json:"content"`
ReplyTo int64 `json:"reply_to,omitempty"`
ReplyId int64 `json:"reply_id,omitempty"`
ReplyUser string `json:"reply_user,omitempty"`
ReplyNickname string `json:"reply_nickname,omitempty"`
IsAuthor int64 `json:"is_author"`
Likes int64 `json:"likes"`
ReplyCount int64 `json:"reply_count"`
CreatedTime string `json:"created_time"`
Location string `json:"location"`
Browser string `json:"browser"`
OperatingSystem string `json:"operating_system"`
IsLiked bool `json:"is_liked" default:"false"`
Images string `json:"images,omitempty"`
}
type CommentDisLikeRequest struct {
@@ -59,12 +59,12 @@ type CommentListRequest struct {
}
type CommentRequest struct {
Content string `json:"content"`
Images []string `json:"images,optional"`
TopicId string `json:"topic_id"`
Author string `json:"author"`
Key string `json:"key"`
Point []int64 `json:"point"`
Content string `json:"content"`
Images string `json:"images,optional"`
TopicId string `json:"topic_id"`
Author string `json:"author"`
Key string `json:"key"`
Point []int64 `json:"point"`
}
type CommentResponse struct {
@@ -82,6 +82,20 @@ type CommentResponse struct {
ReplyTo int64 `json:"reply_to,omitempty"`
}
type FaceSampleLibrary struct {
ID int64 `json:"id"`
FaceName string `json:"face_name"`
FaceImage string `json:"face_image"`
}
type FaceSampleLibraryListRequest struct {
Type int64 `json:"type"`
}
type FaceSampleLibraryListResponse struct {
Faces []FaceSampleLibrary `json:"faces"`
}
type LoginResponse struct {
AccessToken string `json:"access_token"`
ExpireAt int64 `json:"expire_at"`
@@ -92,6 +106,20 @@ type LoginResponse struct {
Status int64 `json:"status"`
}
type ModifyFaceNameRequestAndResponse struct {
ID int64 `json:"id"`
FaceName string `json:"face_name"`
}
type ModifyFaceTypeRequest struct {
IDs []int64 `json:"ids"`
FaceType int64 `json:"face_type"`
}
type ModifyFaceTypeResponse struct {
Result string `json:"result"`
}
type OAuthCallbackRequest struct {
Code string `form:"code"`
}
@@ -116,14 +144,14 @@ type RefreshTokenResponse struct {
}
type ReplyCommentRequest struct {
Content string `json:"content"`
Images []string `json:"images,optional"`
TopicId string `json:"topic_id" `
ReplyId int64 `json:"reply_id" `
ReplyUser string `json:"reply_user" `
Author string `json:"author"`
Key string `json:"key"`
Point []int64 `json:"point"`
Content string `json:"content"`
Images string `json:"images,optional"`
TopicId string `json:"topic_id" `
ReplyId int64 `json:"reply_id" `
ReplyUser string `json:"reply_user" `
Author string `json:"author"`
Key string `json:"key"`
Point []int64 `json:"point"`
}
type ReplyListRequest struct {
@@ -134,15 +162,15 @@ type ReplyListRequest struct {
}
type ReplyReplyRequest struct {
Content string `json:"content"`
Images []string `json:"images,optional"`
TopicId string `json:"topic_id"`
ReplyTo int64 `json:"reply_to"`
ReplyId int64 `json:"reply_id"`
ReplyUser string `json:"reply_user" `
Author string `json:"author"`
Key string `json:"key"`
Point []int64 `json:"point"`
Content string `json:"content"`
Images string `json:"images,optional"`
TopicId string `json:"topic_id"`
ReplyTo int64 `json:"reply_to"`
ReplyId int64 `json:"reply_id"`
ReplyUser string `json:"reply_user" `
Author string `json:"author"`
Key string `json:"key"`
Point []int64 `json:"point"`
}
type ResetPasswordRequest struct {

View File

@@ -1,12 +0,0 @@
package mongodb
import (
"github.com/chenmingyong0423/go-mongox/v2"
"go.mongodb.org/mongo-driver/v2/mongo"
)
// MustNewCollection creates a new Collection instance with the given name.
func MustNewCollection[T any](mongoClient *mongo.Database, collectionName string) *mongox.Collection[T] {
collection := mongoClient.Collection(collectionName)
return mongox.NewCollection[T](collection)
}

View File

@@ -1,26 +0,0 @@
package mongodb
import (
"context"
"go.mongodb.org/mongo-driver/v2/mongo"
"go.mongodb.org/mongo-driver/v2/mongo/options"
"go.mongodb.org/mongo-driver/v2/mongo/readpref"
)
// NewMongoDB initializes the MongoDB connection and returns the database object
func NewMongoDB(uri string, username string, password string, authSource string, database string) *mongo.Database {
client, err := mongo.Connect(options.Client().ApplyURI(uri).SetAuth(options.Credential{
Username: username,
Password: password,
AuthSource: authSource,
}))
if err != nil {
panic(err)
}
err = client.Ping(context.Background(), readpref.Primary())
if err != nil {
panic(err)
}
db := client.Database(database)
return db
}

View File

@@ -115,6 +115,7 @@ func main() {
scaUserFollows := g.GenerateModel("sca_user_follows", fieldOpts...)
scaUserLevel := g.GenerateModel("sca_user_level", fieldOpts...)
scaUserMessage := g.GenerateModel("sca_user_message", fieldOpts...)
scaStorageAlbum := g.GenerateModel("sca_storage_album", fieldOpts...)
g.ApplyBasic(
scaAuthMenu,
@@ -133,6 +134,7 @@ func main() {
scaUserFollows,
scaUserLevel,
scaUserMessage,
scaStorageAlbum,
)
g.Execute()

View File

@@ -27,6 +27,7 @@ type ScaCommentReply struct {
Author int64 `gorm:"column:author;type:tinyint(4);comment:评论回复是否作者 0否 1是" json:"author"` // 评论回复是否作者 0否 1是
Likes int64 `gorm:"column:likes;type:bigint(20);comment:点赞数" json:"likes"` // 点赞数
ReplyCount int64 `gorm:"column:reply_count;type:bigint(20);comment:回复数量" json:"reply_count"` // 回复数量
ImagePath string `gorm:"column:image_path;type:text;comment:评论图片地址" json:"image_path"` // 评论图片地址
Browser string `gorm:"column:browser;type:varchar(50);comment:浏览器" json:"browser"` // 浏览器
OperatingSystem string `gorm:"column:operating_system;type:varchar(50);comment:操作系统" json:"operating_system"` // 操作系统
CommentIP string `gorm:"column:comment_ip;type:varchar(50);comment:IP地址" json:"comment_ip"` // IP地址

View File

@@ -0,0 +1,29 @@
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
package model
import (
"time"
"gorm.io/gorm"
)
const TableNameScaStorageAlbum = "sca_storage_album"
// ScaStorageAlbum mapped from table <sca_storage_album>
type ScaStorageAlbum struct {
ID int64 `gorm:"column:id;type:bigint(20);primaryKey;autoIncrement:true;comment:主键;primary_key" json:"id,string"` // 主键
UserID string `gorm:"column:user_id;type:varchar(50);comment:用户ID" json:"user_id"` // 用户ID
AlbumName string `gorm:"column:album_name;type:varchar(50);comment:相册名称" json:"album_name"` // 相册名称
AlbumType string `gorm:"column:album_type;type:varchar(50);comment:相册类型" json:"album_type"` // 相册类型
CreatedAt time.Time `gorm:"column:created_at;type:timestamp;autoCreateTime;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp;autoUpdateTime;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp;comment:删除时间" json:"deleted_at"` // 删除时间
}
// TableName ScaStorageAlbum's table name
func (*ScaStorageAlbum) TableName() string {
return TableNameScaStorageAlbum
}

View File

@@ -34,6 +34,8 @@ type ScaStorageInfo struct {
Gps string `gorm:"column:gps;type:varchar(255);comment:GPS" json:"gps"` // GPS
Screenshot string `gorm:"column:screenshot;type:varchar(50);comment:是否是截图" json:"screenshot"` // 是否是截图
Exif string `gorm:"column:exif;type:json;comment:exif 信息" json:"exif"` // exif 信息
Hide int64 `gorm:"column:hide;type:int(11) unsigned zerofill;comment:是否隐藏0 不隐藏 1 隐藏)" json:"hide"` // 是否隐藏0 不隐藏 1 隐藏)
AlbumID int64 `gorm:"column:album_id;type:bigint(20);comment:相册ID" json:"album_id"` // 相册ID
CreatedAt time.Time `gorm:"column:created_at;type:timestamp;autoCreateTime;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp;autoUpdateTime;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp;comment:删除时间" json:"deleted_at"` // 删除时间

View File

@@ -26,6 +26,7 @@ var (
ScaCommentLike *scaCommentLike
ScaCommentReply *scaCommentReply
ScaMessageReport *scaMessageReport
ScaStorageAlbum *scaStorageAlbum
ScaStorageConfig *scaStorageConfig
ScaStorageInfo *scaStorageInfo
ScaStorageTag *scaStorageTag
@@ -46,6 +47,7 @@ func SetDefault(db *gorm.DB, opts ...gen.DOOption) {
ScaCommentLike = &Q.ScaCommentLike
ScaCommentReply = &Q.ScaCommentReply
ScaMessageReport = &Q.ScaMessageReport
ScaStorageAlbum = &Q.ScaStorageAlbum
ScaStorageConfig = &Q.ScaStorageConfig
ScaStorageInfo = &Q.ScaStorageInfo
ScaStorageTag = &Q.ScaStorageTag
@@ -67,6 +69,7 @@ func Use(db *gorm.DB, opts ...gen.DOOption) *Query {
ScaCommentLike: newScaCommentLike(db, opts...),
ScaCommentReply: newScaCommentReply(db, opts...),
ScaMessageReport: newScaMessageReport(db, opts...),
ScaStorageAlbum: newScaStorageAlbum(db, opts...),
ScaStorageConfig: newScaStorageConfig(db, opts...),
ScaStorageInfo: newScaStorageInfo(db, opts...),
ScaStorageTag: newScaStorageTag(db, opts...),
@@ -89,6 +92,7 @@ type Query struct {
ScaCommentLike scaCommentLike
ScaCommentReply scaCommentReply
ScaMessageReport scaMessageReport
ScaStorageAlbum scaStorageAlbum
ScaStorageConfig scaStorageConfig
ScaStorageInfo scaStorageInfo
ScaStorageTag scaStorageTag
@@ -112,6 +116,7 @@ func (q *Query) clone(db *gorm.DB) *Query {
ScaCommentLike: q.ScaCommentLike.clone(db),
ScaCommentReply: q.ScaCommentReply.clone(db),
ScaMessageReport: q.ScaMessageReport.clone(db),
ScaStorageAlbum: q.ScaStorageAlbum.clone(db),
ScaStorageConfig: q.ScaStorageConfig.clone(db),
ScaStorageInfo: q.ScaStorageInfo.clone(db),
ScaStorageTag: q.ScaStorageTag.clone(db),
@@ -142,6 +147,7 @@ func (q *Query) ReplaceDB(db *gorm.DB) *Query {
ScaCommentLike: q.ScaCommentLike.replaceDB(db),
ScaCommentReply: q.ScaCommentReply.replaceDB(db),
ScaMessageReport: q.ScaMessageReport.replaceDB(db),
ScaStorageAlbum: q.ScaStorageAlbum.replaceDB(db),
ScaStorageConfig: q.ScaStorageConfig.replaceDB(db),
ScaStorageInfo: q.ScaStorageInfo.replaceDB(db),
ScaStorageTag: q.ScaStorageTag.replaceDB(db),
@@ -162,6 +168,7 @@ type queryCtx struct {
ScaCommentLike IScaCommentLikeDo
ScaCommentReply IScaCommentReplyDo
ScaMessageReport IScaMessageReportDo
ScaStorageAlbum IScaStorageAlbumDo
ScaStorageConfig IScaStorageConfigDo
ScaStorageInfo IScaStorageInfoDo
ScaStorageTag IScaStorageTagDo
@@ -182,6 +189,7 @@ func (q *Query) WithContext(ctx context.Context) *queryCtx {
ScaCommentLike: q.ScaCommentLike.WithContext(ctx),
ScaCommentReply: q.ScaCommentReply.WithContext(ctx),
ScaMessageReport: q.ScaMessageReport.WithContext(ctx),
ScaStorageAlbum: q.ScaStorageAlbum.WithContext(ctx),
ScaStorageConfig: q.ScaStorageConfig.WithContext(ctx),
ScaStorageInfo: q.ScaStorageInfo.WithContext(ctx),
ScaStorageTag: q.ScaStorageTag.WithContext(ctx),

View File

@@ -39,6 +39,7 @@ func newScaCommentReply(db *gorm.DB, opts ...gen.DOOption) scaCommentReply {
_scaCommentReply.Author = field.NewInt64(tableName, "author")
_scaCommentReply.Likes = field.NewInt64(tableName, "likes")
_scaCommentReply.ReplyCount = field.NewInt64(tableName, "reply_count")
_scaCommentReply.ImagePath = field.NewString(tableName, "image_path")
_scaCommentReply.Browser = field.NewString(tableName, "browser")
_scaCommentReply.OperatingSystem = field.NewString(tableName, "operating_system")
_scaCommentReply.CommentIP = field.NewString(tableName, "comment_ip")
@@ -70,6 +71,7 @@ type scaCommentReply struct {
Author field.Int64 // 评论回复是否作者 0否 1是
Likes field.Int64 // 点赞数
ReplyCount field.Int64 // 回复数量
ImagePath field.String // 评论图片地址
Browser field.String // 浏览器
OperatingSystem field.String // 操作系统
CommentIP field.String // IP地址
@@ -107,6 +109,7 @@ func (s *scaCommentReply) updateTableName(table string) *scaCommentReply {
s.Author = field.NewInt64(table, "author")
s.Likes = field.NewInt64(table, "likes")
s.ReplyCount = field.NewInt64(table, "reply_count")
s.ImagePath = field.NewString(table, "image_path")
s.Browser = field.NewString(table, "browser")
s.OperatingSystem = field.NewString(table, "operating_system")
s.CommentIP = field.NewString(table, "comment_ip")
@@ -132,7 +135,7 @@ func (s *scaCommentReply) GetFieldByName(fieldName string) (field.OrderExpr, boo
}
func (s *scaCommentReply) fillFieldMap() {
s.fieldMap = make(map[string]field.Expr, 21)
s.fieldMap = make(map[string]field.Expr, 22)
s.fieldMap["id"] = s.ID
s.fieldMap["user_id"] = s.UserID
s.fieldMap["topic_id"] = s.TopicID
@@ -145,6 +148,7 @@ func (s *scaCommentReply) fillFieldMap() {
s.fieldMap["author"] = s.Author
s.fieldMap["likes"] = s.Likes
s.fieldMap["reply_count"] = s.ReplyCount
s.fieldMap["image_path"] = s.ImagePath
s.fieldMap["browser"] = s.Browser
s.fieldMap["operating_system"] = s.OperatingSystem
s.fieldMap["comment_ip"] = s.CommentIP

View File

@@ -0,0 +1,404 @@
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
package query
import (
"context"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"gorm.io/gorm/schema"
"gorm.io/gen"
"gorm.io/gen/field"
"gorm.io/plugin/dbresolver"
"schisandra-album-cloud-microservices/app/auth/model/mysql/model"
)
func newScaStorageAlbum(db *gorm.DB, opts ...gen.DOOption) scaStorageAlbum {
_scaStorageAlbum := scaStorageAlbum{}
_scaStorageAlbum.scaStorageAlbumDo.UseDB(db, opts...)
_scaStorageAlbum.scaStorageAlbumDo.UseModel(&model.ScaStorageAlbum{})
tableName := _scaStorageAlbum.scaStorageAlbumDo.TableName()
_scaStorageAlbum.ALL = field.NewAsterisk(tableName)
_scaStorageAlbum.ID = field.NewInt64(tableName, "id")
_scaStorageAlbum.UserID = field.NewString(tableName, "user_id")
_scaStorageAlbum.AlbumName = field.NewString(tableName, "album_name")
_scaStorageAlbum.AlbumType = field.NewString(tableName, "album_type")
_scaStorageAlbum.CreatedAt = field.NewTime(tableName, "created_at")
_scaStorageAlbum.UpdatedAt = field.NewTime(tableName, "updated_at")
_scaStorageAlbum.DeletedAt = field.NewField(tableName, "deleted_at")
_scaStorageAlbum.fillFieldMap()
return _scaStorageAlbum
}
type scaStorageAlbum struct {
scaStorageAlbumDo
ALL field.Asterisk
ID field.Int64 // 主键
UserID field.String // 用户ID
AlbumName field.String // 相册名称
AlbumType field.String // 相册类型
CreatedAt field.Time // 创建时间
UpdatedAt field.Time // 更新时间
DeletedAt field.Field // 删除时间
fieldMap map[string]field.Expr
}
func (s scaStorageAlbum) Table(newTableName string) *scaStorageAlbum {
s.scaStorageAlbumDo.UseTable(newTableName)
return s.updateTableName(newTableName)
}
func (s scaStorageAlbum) As(alias string) *scaStorageAlbum {
s.scaStorageAlbumDo.DO = *(s.scaStorageAlbumDo.As(alias).(*gen.DO))
return s.updateTableName(alias)
}
func (s *scaStorageAlbum) updateTableName(table string) *scaStorageAlbum {
s.ALL = field.NewAsterisk(table)
s.ID = field.NewInt64(table, "id")
s.UserID = field.NewString(table, "user_id")
s.AlbumName = field.NewString(table, "album_name")
s.AlbumType = field.NewString(table, "album_type")
s.CreatedAt = field.NewTime(table, "created_at")
s.UpdatedAt = field.NewTime(table, "updated_at")
s.DeletedAt = field.NewField(table, "deleted_at")
s.fillFieldMap()
return s
}
func (s *scaStorageAlbum) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
_f, ok := s.fieldMap[fieldName]
if !ok || _f == nil {
return nil, false
}
_oe, ok := _f.(field.OrderExpr)
return _oe, ok
}
func (s *scaStorageAlbum) fillFieldMap() {
s.fieldMap = make(map[string]field.Expr, 7)
s.fieldMap["id"] = s.ID
s.fieldMap["user_id"] = s.UserID
s.fieldMap["album_name"] = s.AlbumName
s.fieldMap["album_type"] = s.AlbumType
s.fieldMap["created_at"] = s.CreatedAt
s.fieldMap["updated_at"] = s.UpdatedAt
s.fieldMap["deleted_at"] = s.DeletedAt
}
func (s scaStorageAlbum) clone(db *gorm.DB) scaStorageAlbum {
s.scaStorageAlbumDo.ReplaceConnPool(db.Statement.ConnPool)
return s
}
func (s scaStorageAlbum) replaceDB(db *gorm.DB) scaStorageAlbum {
s.scaStorageAlbumDo.ReplaceDB(db)
return s
}
type scaStorageAlbumDo struct{ gen.DO }
type IScaStorageAlbumDo interface {
gen.SubQuery
Debug() IScaStorageAlbumDo
WithContext(ctx context.Context) IScaStorageAlbumDo
WithResult(fc func(tx gen.Dao)) gen.ResultInfo
ReplaceDB(db *gorm.DB)
ReadDB() IScaStorageAlbumDo
WriteDB() IScaStorageAlbumDo
As(alias string) gen.Dao
Session(config *gorm.Session) IScaStorageAlbumDo
Columns(cols ...field.Expr) gen.Columns
Clauses(conds ...clause.Expression) IScaStorageAlbumDo
Not(conds ...gen.Condition) IScaStorageAlbumDo
Or(conds ...gen.Condition) IScaStorageAlbumDo
Select(conds ...field.Expr) IScaStorageAlbumDo
Where(conds ...gen.Condition) IScaStorageAlbumDo
Order(conds ...field.Expr) IScaStorageAlbumDo
Distinct(cols ...field.Expr) IScaStorageAlbumDo
Omit(cols ...field.Expr) IScaStorageAlbumDo
Join(table schema.Tabler, on ...field.Expr) IScaStorageAlbumDo
LeftJoin(table schema.Tabler, on ...field.Expr) IScaStorageAlbumDo
RightJoin(table schema.Tabler, on ...field.Expr) IScaStorageAlbumDo
Group(cols ...field.Expr) IScaStorageAlbumDo
Having(conds ...gen.Condition) IScaStorageAlbumDo
Limit(limit int) IScaStorageAlbumDo
Offset(offset int) IScaStorageAlbumDo
Count() (count int64, err error)
Scopes(funcs ...func(gen.Dao) gen.Dao) IScaStorageAlbumDo
Unscoped() IScaStorageAlbumDo
Create(values ...*model.ScaStorageAlbum) error
CreateInBatches(values []*model.ScaStorageAlbum, batchSize int) error
Save(values ...*model.ScaStorageAlbum) error
First() (*model.ScaStorageAlbum, error)
Take() (*model.ScaStorageAlbum, error)
Last() (*model.ScaStorageAlbum, error)
Find() ([]*model.ScaStorageAlbum, error)
FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.ScaStorageAlbum, err error)
FindInBatches(result *[]*model.ScaStorageAlbum, batchSize int, fc func(tx gen.Dao, batch int) error) error
Pluck(column field.Expr, dest interface{}) error
Delete(...*model.ScaStorageAlbum) (info gen.ResultInfo, err error)
Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
Updates(value interface{}) (info gen.ResultInfo, err error)
UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
UpdateFrom(q gen.SubQuery) gen.Dao
Attrs(attrs ...field.AssignExpr) IScaStorageAlbumDo
Assign(attrs ...field.AssignExpr) IScaStorageAlbumDo
Joins(fields ...field.RelationField) IScaStorageAlbumDo
Preload(fields ...field.RelationField) IScaStorageAlbumDo
FirstOrInit() (*model.ScaStorageAlbum, error)
FirstOrCreate() (*model.ScaStorageAlbum, error)
FindByPage(offset int, limit int) (result []*model.ScaStorageAlbum, count int64, err error)
ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
Scan(result interface{}) (err error)
Returning(value interface{}, columns ...string) IScaStorageAlbumDo
UnderlyingDB() *gorm.DB
schema.Tabler
}
func (s scaStorageAlbumDo) Debug() IScaStorageAlbumDo {
return s.withDO(s.DO.Debug())
}
func (s scaStorageAlbumDo) WithContext(ctx context.Context) IScaStorageAlbumDo {
return s.withDO(s.DO.WithContext(ctx))
}
func (s scaStorageAlbumDo) ReadDB() IScaStorageAlbumDo {
return s.Clauses(dbresolver.Read)
}
func (s scaStorageAlbumDo) WriteDB() IScaStorageAlbumDo {
return s.Clauses(dbresolver.Write)
}
func (s scaStorageAlbumDo) Session(config *gorm.Session) IScaStorageAlbumDo {
return s.withDO(s.DO.Session(config))
}
func (s scaStorageAlbumDo) Clauses(conds ...clause.Expression) IScaStorageAlbumDo {
return s.withDO(s.DO.Clauses(conds...))
}
func (s scaStorageAlbumDo) Returning(value interface{}, columns ...string) IScaStorageAlbumDo {
return s.withDO(s.DO.Returning(value, columns...))
}
func (s scaStorageAlbumDo) Not(conds ...gen.Condition) IScaStorageAlbumDo {
return s.withDO(s.DO.Not(conds...))
}
func (s scaStorageAlbumDo) Or(conds ...gen.Condition) IScaStorageAlbumDo {
return s.withDO(s.DO.Or(conds...))
}
func (s scaStorageAlbumDo) Select(conds ...field.Expr) IScaStorageAlbumDo {
return s.withDO(s.DO.Select(conds...))
}
func (s scaStorageAlbumDo) Where(conds ...gen.Condition) IScaStorageAlbumDo {
return s.withDO(s.DO.Where(conds...))
}
func (s scaStorageAlbumDo) Order(conds ...field.Expr) IScaStorageAlbumDo {
return s.withDO(s.DO.Order(conds...))
}
func (s scaStorageAlbumDo) Distinct(cols ...field.Expr) IScaStorageAlbumDo {
return s.withDO(s.DO.Distinct(cols...))
}
func (s scaStorageAlbumDo) Omit(cols ...field.Expr) IScaStorageAlbumDo {
return s.withDO(s.DO.Omit(cols...))
}
func (s scaStorageAlbumDo) Join(table schema.Tabler, on ...field.Expr) IScaStorageAlbumDo {
return s.withDO(s.DO.Join(table, on...))
}
func (s scaStorageAlbumDo) LeftJoin(table schema.Tabler, on ...field.Expr) IScaStorageAlbumDo {
return s.withDO(s.DO.LeftJoin(table, on...))
}
func (s scaStorageAlbumDo) RightJoin(table schema.Tabler, on ...field.Expr) IScaStorageAlbumDo {
return s.withDO(s.DO.RightJoin(table, on...))
}
func (s scaStorageAlbumDo) Group(cols ...field.Expr) IScaStorageAlbumDo {
return s.withDO(s.DO.Group(cols...))
}
func (s scaStorageAlbumDo) Having(conds ...gen.Condition) IScaStorageAlbumDo {
return s.withDO(s.DO.Having(conds...))
}
func (s scaStorageAlbumDo) Limit(limit int) IScaStorageAlbumDo {
return s.withDO(s.DO.Limit(limit))
}
func (s scaStorageAlbumDo) Offset(offset int) IScaStorageAlbumDo {
return s.withDO(s.DO.Offset(offset))
}
func (s scaStorageAlbumDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IScaStorageAlbumDo {
return s.withDO(s.DO.Scopes(funcs...))
}
func (s scaStorageAlbumDo) Unscoped() IScaStorageAlbumDo {
return s.withDO(s.DO.Unscoped())
}
func (s scaStorageAlbumDo) Create(values ...*model.ScaStorageAlbum) error {
if len(values) == 0 {
return nil
}
return s.DO.Create(values)
}
func (s scaStorageAlbumDo) CreateInBatches(values []*model.ScaStorageAlbum, batchSize int) error {
return s.DO.CreateInBatches(values, batchSize)
}
// Save : !!! underlying implementation is different with GORM
// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
func (s scaStorageAlbumDo) Save(values ...*model.ScaStorageAlbum) error {
if len(values) == 0 {
return nil
}
return s.DO.Save(values)
}
func (s scaStorageAlbumDo) First() (*model.ScaStorageAlbum, error) {
if result, err := s.DO.First(); err != nil {
return nil, err
} else {
return result.(*model.ScaStorageAlbum), nil
}
}
func (s scaStorageAlbumDo) Take() (*model.ScaStorageAlbum, error) {
if result, err := s.DO.Take(); err != nil {
return nil, err
} else {
return result.(*model.ScaStorageAlbum), nil
}
}
func (s scaStorageAlbumDo) Last() (*model.ScaStorageAlbum, error) {
if result, err := s.DO.Last(); err != nil {
return nil, err
} else {
return result.(*model.ScaStorageAlbum), nil
}
}
func (s scaStorageAlbumDo) Find() ([]*model.ScaStorageAlbum, error) {
result, err := s.DO.Find()
return result.([]*model.ScaStorageAlbum), err
}
func (s scaStorageAlbumDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.ScaStorageAlbum, err error) {
buf := make([]*model.ScaStorageAlbum, 0, batchSize)
err = s.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
defer func() { results = append(results, buf...) }()
return fc(tx, batch)
})
return results, err
}
func (s scaStorageAlbumDo) FindInBatches(result *[]*model.ScaStorageAlbum, batchSize int, fc func(tx gen.Dao, batch int) error) error {
return s.DO.FindInBatches(result, batchSize, fc)
}
func (s scaStorageAlbumDo) Attrs(attrs ...field.AssignExpr) IScaStorageAlbumDo {
return s.withDO(s.DO.Attrs(attrs...))
}
func (s scaStorageAlbumDo) Assign(attrs ...field.AssignExpr) IScaStorageAlbumDo {
return s.withDO(s.DO.Assign(attrs...))
}
func (s scaStorageAlbumDo) Joins(fields ...field.RelationField) IScaStorageAlbumDo {
for _, _f := range fields {
s = *s.withDO(s.DO.Joins(_f))
}
return &s
}
func (s scaStorageAlbumDo) Preload(fields ...field.RelationField) IScaStorageAlbumDo {
for _, _f := range fields {
s = *s.withDO(s.DO.Preload(_f))
}
return &s
}
func (s scaStorageAlbumDo) FirstOrInit() (*model.ScaStorageAlbum, error) {
if result, err := s.DO.FirstOrInit(); err != nil {
return nil, err
} else {
return result.(*model.ScaStorageAlbum), nil
}
}
func (s scaStorageAlbumDo) FirstOrCreate() (*model.ScaStorageAlbum, error) {
if result, err := s.DO.FirstOrCreate(); err != nil {
return nil, err
} else {
return result.(*model.ScaStorageAlbum), nil
}
}
func (s scaStorageAlbumDo) FindByPage(offset int, limit int) (result []*model.ScaStorageAlbum, count int64, err error) {
result, err = s.Offset(offset).Limit(limit).Find()
if err != nil {
return
}
if size := len(result); 0 < limit && 0 < size && size < limit {
count = int64(size + offset)
return
}
count, err = s.Offset(-1).Limit(-1).Count()
return
}
func (s scaStorageAlbumDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
count, err = s.Count()
if err != nil {
return
}
err = s.Offset(offset).Limit(limit).Scan(result)
return
}
func (s scaStorageAlbumDo) Scan(result interface{}) (err error) {
return s.DO.Scan(result)
}
func (s scaStorageAlbumDo) Delete(models ...*model.ScaStorageAlbum) (result gen.ResultInfo, err error) {
return s.DO.Delete(models)
}
func (s *scaStorageAlbumDo) withDO(do gen.Dao) *scaStorageAlbumDo {
s.DO = *do.(*gen.DO)
return s
}

View File

@@ -47,6 +47,8 @@ func newScaStorageInfo(db *gorm.DB, opts ...gen.DOOption) scaStorageInfo {
_scaStorageInfo.Gps = field.NewString(tableName, "gps")
_scaStorageInfo.Screenshot = field.NewString(tableName, "screenshot")
_scaStorageInfo.Exif = field.NewString(tableName, "exif")
_scaStorageInfo.Hide = field.NewInt64(tableName, "hide")
_scaStorageInfo.AlbumID = field.NewInt64(tableName, "album_id")
_scaStorageInfo.CreatedAt = field.NewTime(tableName, "created_at")
_scaStorageInfo.UpdatedAt = field.NewTime(tableName, "updated_at")
_scaStorageInfo.DeletedAt = field.NewField(tableName, "deleted_at")
@@ -80,6 +82,8 @@ type scaStorageInfo struct {
Gps field.String // GPS
Screenshot field.String // 是否是截图
Exif field.String // exif 信息
Hide field.Int64 // 是否隐藏0 不隐藏 1 隐藏)
AlbumID field.Int64 // 相册ID
CreatedAt field.Time // 创建时间
UpdatedAt field.Time // 更新时间
DeletedAt field.Field // 删除时间
@@ -119,6 +123,8 @@ func (s *scaStorageInfo) updateTableName(table string) *scaStorageInfo {
s.Gps = field.NewString(table, "gps")
s.Screenshot = field.NewString(table, "screenshot")
s.Exif = field.NewString(table, "exif")
s.Hide = field.NewInt64(table, "hide")
s.AlbumID = field.NewInt64(table, "album_id")
s.CreatedAt = field.NewTime(table, "created_at")
s.UpdatedAt = field.NewTime(table, "updated_at")
s.DeletedAt = field.NewField(table, "deleted_at")
@@ -138,7 +144,7 @@ func (s *scaStorageInfo) GetFieldByName(fieldName string) (field.OrderExpr, bool
}
func (s *scaStorageInfo) fillFieldMap() {
s.fieldMap = make(map[string]field.Expr, 23)
s.fieldMap = make(map[string]field.Expr, 25)
s.fieldMap["id"] = s.ID
s.fieldMap["user_id"] = s.UserID
s.fieldMap["provider"] = s.Provider
@@ -159,6 +165,8 @@ func (s *scaStorageInfo) fillFieldMap() {
s.fieldMap["gps"] = s.Gps
s.fieldMap["screenshot"] = s.Screenshot
s.fieldMap["exif"] = s.Exif
s.fieldMap["hide"] = s.Hide
s.fieldMap["album_id"] = s.AlbumID
s.fieldMap["created_at"] = s.CreatedAt
s.fieldMap["updated_at"] = s.UpdatedAt
s.fieldMap["deleted_at"] = s.DeletedAt

View File

@@ -0,0 +1,6 @@
package constant
const (
FaceBucketName = "faces"
CommentImagesBucketName = "comments"
)

View File

@@ -1,5 +1,6 @@
package constant
const (
FaceTypeSample = "sample"
FaceTypePerson = iota
FaceTypeHidden
)

View File

@@ -15,5 +15,6 @@ const (
)
const (
FaceSamplePrefix = "face:sample:"
FaceSamplePrefix = "face:samples:"
FaceVectorPrefix = "face:vectors:"
)

View File

@@ -12,7 +12,7 @@ func CasbinMiddleware(w http.ResponseWriter, r *http.Request, casbin *casbin.Syn
userId := r.Header.Get(constant.UID_HEADER_KEY)
correct, err := casbin.Enforce(userId, r.URL.Path, r.Method)
if err != nil || !correct {
xhttp.JsonBaseResponseCtx(r.Context(), w, errors.New(http.StatusForbidden, "forbidden"))
xhttp.JsonBaseResponseCtx(r.Context(), w, errors.New(http.StatusNotFound, "not found"))
return
}
}

17
common/miniox/minio.go Normal file
View File

@@ -0,0 +1,17 @@
package miniox
import (
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
)
func NewMinio(endpoint, accessKeyID, secretAccessKey string, useSSL bool) *minio.Client {
client, err := minio.New(endpoint, &minio.Options{
Creds: credentials.NewStaticV4(accessKeyID, secretAccessKey, ""),
Secure: useSSL,
})
if err != nil {
panic(err)
}
return client
}

View File

@@ -1,117 +1,23 @@
package utils
import (
"bytes"
"encoding/base64"
"errors"
"fmt"
"image"
_ "image/jpeg" // 引入 jpeg 解码器
_ "image/png" // 引入 png 解码器
"io"
"regexp"
"strings"
"sync"
)
var wg sync.WaitGroup
// GetMimeType 获取 MIME 类型
func GetMimeType(data []byte) string {
if len(data) < 4 {
return "application/octet-stream" // 默认类型
}
// 判断 JPEG
if data[0] == 0xFF && data[1] == 0xD8 {
return "image/jpeg"
}
// 判断 PNG
if len(data) >= 8 && data[0] == 0x89 && data[1] == 0x50 && data[2] == 0x4E && data[3] == 0x47 &&
data[4] == 0x0D && data[5] == 0x0A && data[6] == 0x1A && data[7] == 0x0A {
return "image/png"
}
// 判断 GIF
if len(data) >= 6 && data[0] == 'G' && data[1] == 'I' && data[2] == 'F' {
return "image/gif"
}
// 判断 WEBP
if len(data) >= 12 && data[0] == 0x52 && data[1] == 0x49 && data[2] == 0x46 && data[3] == 0x46 &&
data[8] == 0x57 && data[9] == 0x45 && data[10] == 0x42 && data[11] == 0x50 {
return "image/webp"
}
// 判断svg
if len(data) >= 4 && data[0] == '<' && data[1] == '?' && data[2] == 'x' && data[3] == 'm' {
return "image/svg+xml"
}
// 判断JPG
if len(data) >= 3 && data[0] == 0xFF && data[1] == 0xD8 && data[2] == 0xFF {
return "image/jpeg"
}
return "application/octet-stream" // 默认类型
}
// ProcessImages 处理图片,将 base64 字符串转换为字节数组
func ProcessImages(images []string) ([][]byte, error) {
var imagesData [][]byte
dataChan := make(chan []byte, len(images))
re := regexp.MustCompile(`^data:image/\w+;base64,`)
for _, img := range images {
wg.Add(1)
go func(img string) {
defer wg.Done()
imgWithoutPrefix := re.ReplaceAllString(img, "")
data, err := Base64ToBytes(imgWithoutPrefix)
if err != nil {
return // 出错时直接返回
}
dataChan <- data
}(img)
}
wg.Wait()
close(dataChan)
for data := range dataChan {
imagesData = append(imagesData, data)
}
return imagesData, nil
}
// Base64ToBytes 将base64字符串转换为字节数组
func Base64ToBytes(base64Str string) ([]byte, error) {
reader := base64.NewDecoder(base64.StdEncoding, strings.NewReader(base64Str))
re := regexp.MustCompile(`^data:image/\w+;base64,`)
imgWithoutPrefix := re.ReplaceAllString(base64Str, "")
reader := base64.NewDecoder(base64.StdEncoding, strings.NewReader(imgWithoutPrefix))
data, err := io.ReadAll(reader)
if err != nil {
return nil, errors.New("failed to decode base64 string")
}
return data, nil
}
// Base64ToImage 将 Base64 字符串转换为 image.Image 格式
func Base64ToImage(base64Str string) (image.Image, error) {
// 使用正则表达式去除前缀
re := regexp.MustCompile(`^data:image/([a-zA-Z]*);base64,`)
// 去除前缀部分
base64Str = re.ReplaceAllString(base64Str, "")
// 解码 Base64 字符串
data, err := base64.StdEncoding.DecodeString(base64Str)
if err != nil {
return nil, fmt.Errorf("failed to decode base64 string: %v", err)
}
// 使用 image.Decode 解码字节数据
img, _, err := image.Decode(bytes.NewReader(data))
if err != nil {
return nil, fmt.Errorf("failed to decode image: %v", err)
}
return img, nil
}

67
go.mod
View File

@@ -10,8 +10,7 @@ require (
github.com/asjdf/gorm-cache v1.2.3
github.com/casbin/casbin/v2 v2.103.0
github.com/casbin/gorm-adapter/v3 v3.32.0
github.com/ccpwcn/kgo v1.2.8
github.com/chenmingyong0423/go-mongox/v2 v2.0.0
github.com/ccpwcn/kgo v1.2.9
github.com/corona10/goimagehash v1.1.0
github.com/duke-git/lancet/v2 v2.3.4
github.com/golang-jwt/jwt/v5 v5.2.1
@@ -19,8 +18,9 @@ require (
github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20241220152942-06eb5c6e8230
github.com/lxzan/gws v1.8.8
github.com/microcosm-cc/bluemonday v1.0.27
github.com/minio/minio-go/v7 v7.0.84
github.com/mssola/useragent v1.0.0
github.com/nicksnyder/go-i18n/v2 v2.4.1
github.com/nicksnyder/go-i18n/v2 v2.5.1
github.com/pelletier/go-toml/v2 v2.2.3
github.com/pkg6/go-sms v0.1.2
github.com/redis/go-redis/v9 v9.7.0
@@ -28,14 +28,13 @@ require (
github.com/wenlng/go-captcha-assets v1.0.1
github.com/wenlng/go-captcha/v2 v2.0.2
github.com/yitter/idgenerator-go v1.3.3
github.com/zeromicro/go-zero v1.7.6
github.com/zeromicro/go-zero v1.8.0
github.com/zmexing/go-sensitive-word v1.3.0
go.mongodb.org/mongo-driver/v2 v2.0.0
gocv.io/x/gocv v0.40.0
golang.org/x/crypto v0.32.0
golang.org/x/text v0.21.0
google.golang.org/grpc v1.69.4
google.golang.org/protobuf v1.36.3
golang.org/x/text v0.22.0
google.golang.org/grpc v1.70.0
google.golang.org/protobuf v1.36.4
gorm.io/driver/mysql v1.5.7
gorm.io/gen v0.3.26
gorm.io/gorm v1.25.12
@@ -50,13 +49,13 @@ require (
github.com/aymerick/douceur v0.2.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bluele/gcache v0.0.2 // indirect
github.com/bmatcuk/doublestar/v4 v4.8.0 // indirect
github.com/bmatcuk/doublestar/v4 v4.8.1 // indirect
github.com/casbin/govaluate v1.3.0 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/clbanning/mxj v1.8.4 // indirect
github.com/clbanning/mxj/v2 v2.7.0 // indirect
github.com/cloudflare/circl v1.5.0 // indirect
github.com/cloudflare/circl v1.6.0 // indirect
github.com/coreos/go-semver v0.3.1 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
@@ -66,31 +65,29 @@ require (
github.com/emicklei/go-restful/v3 v3.12.1 // indirect
github.com/fatih/color v1.18.0 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
github.com/glebarez/go-sqlite v1.22.0 // indirect
github.com/glebarez/sqlite v1.11.0 // indirect
github.com/go-ini/ini v1.67.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.24.0 // indirect
github.com/go-playground/assert/v2 v2.2.0 // indirect
github.com/go-sql-driver/mysql v1.8.1 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/goccy/go-json v0.10.5 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
github.com/golang-sql/sqlexp v0.1.0 // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/gnostic-models v0.6.9 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20250121033306-997b0b79cac0 // indirect
github.com/google/pprof v0.0.0-20250202011525-fc3143867406 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/css v1.0.1 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.0 // indirect
@@ -107,12 +104,13 @@ require (
github.com/json-iterator/go v1.1.12 // indirect
github.com/karlseguin/ccache/v3 v3.0.6 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
github.com/lib/pq v1.10.7 // indirect
github.com/mailru/easyjson v0.9.0 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/microsoft/go-mssqldb v1.8.0 // indirect
github.com/minio/md5-simd v1.1.2 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
@@ -131,18 +129,15 @@ require (
github.com/prometheus/common v0.62.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/quic-go/qpack v0.5.1 // indirect
github.com/quic-go/quic-go v0.48.2 // indirect
github.com/quic-go/quic-go v0.49.0 // indirect
github.com/refraction-networking/utls v1.6.7 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rs/xid v1.6.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/x448/float16 v0.8.4 // 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
go.etcd.io/etcd/api/v3 v3.5.17 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.17 // indirect
go.etcd.io/etcd/client/v3 v3.5.17 // indirect
go.etcd.io/etcd/api/v3 v3.5.18 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.18 // indirect
go.etcd.io/etcd/client/v3 v3.5.18 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/otel v1.34.0 // indirect
go.opentelemetry.io/otel/exporters/jaeger v1.17.0 // indirect
@@ -159,18 +154,18 @@ require (
go.uber.org/mock v0.5.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 // indirect
golang.org/x/image v0.23.0 // indirect
golang.org/x/mod v0.22.0 // indirect
golang.org/x/exp v0.0.0-20250128182459-e0ece0dbea4c // indirect
golang.org/x/image v0.24.0 // indirect
golang.org/x/mod v0.23.0 // indirect
golang.org/x/net v0.34.0 // indirect
golang.org/x/oauth2 v0.25.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.29.0 // indirect
golang.org/x/term v0.28.0 // indirect
golang.org/x/time v0.9.0 // indirect
golang.org/x/oauth2 v0.26.0 // indirect
golang.org/x/sync v0.11.0 // indirect
golang.org/x/sys v0.30.0 // indirect
golang.org/x/term v0.29.0 // indirect
golang.org/x/time v0.10.0 // indirect
golang.org/x/tools v0.29.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250204164813-702378808489 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250204164813-702378808489 // indirect
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
@@ -185,7 +180,7 @@ require (
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 // indirect
k8s.io/utils v0.0.0-20241210054802-24370beab758 // indirect
modernc.org/libc v1.61.9 // indirect
modernc.org/libc v1.61.11 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.8.2 // indirect
modernc.org/sqlite v1.34.5 // indirect

152
go.sum
View File

@@ -49,8 +49,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw=
github.com/bluele/gcache v0.0.2/go.mod h1:m15KV+ECjptwSPxKhOhQoAFQVtUFjTVkc3H8o0t/fp0=
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
github.com/bmatcuk/doublestar/v4 v4.8.0 h1:DSXtrypQddoug1459viM9X9D3dp1Z7993fw36I2kNcQ=
github.com/bmatcuk/doublestar/v4 v4.8.0/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
github.com/bmatcuk/doublestar/v4 v4.8.1 h1:54Bopc5c2cAvhLRAzqOGCYHYyhcDHsFF4wWIR5wKP38=
github.com/bmatcuk/doublestar/v4 v4.8.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
@@ -61,20 +61,18 @@ github.com/casbin/gorm-adapter/v3 v3.32.0 h1:Au+IOILBIE9clox5BJhI2nA3p9t7Ep1ePlu
github.com/casbin/gorm-adapter/v3 v3.32.0/go.mod h1:Zre/H8p17mpv5U3EaWgPoxLILLdXO3gHW5aoQQpUDZI=
github.com/casbin/govaluate v1.3.0 h1:VA0eSY0M2lA86dYd5kPPuNZMUD9QkWnOCnavGrw9myc=
github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
github.com/ccpwcn/kgo v1.2.8 h1:BP7mHtv5qsNAMJ0vANlbPgN0ou8RAvcnC6g7jqZy5uQ=
github.com/ccpwcn/kgo v1.2.8/go.mod h1:y6G244zGfW95c6aCcw00TdZR6JUfBCmQ4acJcFdaktA=
github.com/ccpwcn/kgo v1.2.9 h1:5PmBebj7O5Wnt+eQCdl4KhEFoUCx0G2qK5lWuxGsoOA=
github.com/ccpwcn/kgo v1.2.9/go.mod h1:y6G244zGfW95c6aCcw00TdZR6JUfBCmQ4acJcFdaktA=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chenmingyong0423/go-mongox/v2 v2.0.0 h1:76n276epp1cfKSbCwQRDGcpzkMTlzIXWM2dZEbbfyG8=
github.com/chenmingyong0423/go-mongox/v2 v2.0.0/go.mod h1:bGxuW2xChkIq6tX3tphYYjHCZOkaoCOowJKIO2Q26nQ=
github.com/clbanning/mxj v1.8.4 h1:HuhwZtbyvyOw+3Z1AowPkU87JkJUSv751ELWaiTpj8I=
github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng=
github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME=
github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
github.com/cloudflare/circl v1.5.0 h1:hxIWksrX6XN5a1L2TI/h53AGPhNHoUBo+TD1ms9+pys=
github.com/cloudflare/circl v1.5.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
github.com/cloudflare/circl v1.6.0 h1:cr5JKic4HI+LkINy2lg3W2jF8sHCVTBncJr5gIIq7qk=
github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
@@ -101,13 +99,13 @@ 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/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec+ruQ=
github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc=
github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw=
github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
github.com/go-bindata/go-bindata v3.1.2+incompatible/go.mod h1:xK8Dsgwmeed+BBsSy2XTopBn/8uK2HWuGSnA11C3Joo=
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
@@ -121,18 +119,13 @@ github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+Gr
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.24.0 h1:KHQckvo8G6hlWnrPX4NJJ+aBfWNAE/HH+qdL2cBpCmg=
github.com/go-playground/validator/v10 v10.24.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
@@ -153,8 +146,6 @@ github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=
github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
@@ -167,10 +158,8 @@ github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20250120214715-4e5bb2051dab h1:FcOz+Hn0n9Ek4Ij6mvYUhvHGg0+EhV9ImR+PMmTP0S0=
github.com/google/pprof v0.0.0-20250120214715-4e5bb2051dab/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/pprof v0.0.0-20250121033306-997b0b79cac0 h1:EinjE47mmVVsxcjIwVKQWNY+3P+5R2BhkbULjhEDThc=
github.com/google/pprof v0.0.0-20250121033306-997b0b79cac0/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/pprof v0.0.0-20250202011525-fc3143867406 h1:wlQI2cYY0BsWmmPPAnxfQ8SDW0S3Jasn+4B8kXFxprg=
github.com/google/pprof v0.0.0-20250202011525-fc3143867406/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -180,9 +169,6 @@ github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.0 h1:VD1gqscl4nYs1YxVuSdemTrSgTKrwOWDK0FVFMqm+Cg=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.0/go.mod h1:4EgsQoS4TOhJizV+JTFg40qx1Ofh3XmXEQNBpgvNT40=
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
@@ -224,14 +210,15 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20241220152942-06eb5c6e8230 h1:B0oaMTAQKDZd8cwYT0qsAI7+c3KbFeBNA8GhgoBMXWw=
@@ -252,6 +239,10 @@ github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB
github.com/microsoft/go-mssqldb v1.7.2/go.mod h1:kOvZKUdrhhFQmxLZqbwUV0rHkNkZpthMITIb2Ko1IoA=
github.com/microsoft/go-mssqldb v1.8.0 h1:7cyZ/AT7ycDsEoWPIXibd+aVKFtteUNhDGf3aobP+tw=
github.com/microsoft/go-mssqldb v1.8.0/go.mod h1:6znkekS3T2vp0waiMhen4GPU1BiAsrP+iXHcE7a7rFo=
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
github.com/minio/minio-go/v7 v7.0.84 h1:D1HVmAF8JF8Bpi6IU4V9vIEj+8pc+xU88EWMs2yed0E=
github.com/minio/minio-go/v7 v7.0.84/go.mod h1:57YXpvc5l3rjPdhqNrDsvVlY0qPI6UTk1bflAe+9doY=
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
@@ -273,8 +264,8 @@ github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdh
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/nicksnyder/go-i18n/v2 v2.4.1 h1:zwzjtX4uYyiaU02K5Ia3zSkpJZrByARkRB4V3YPrr0g=
github.com/nicksnyder/go-i18n/v2 v2.4.1/go.mod h1:++Pl70FR6Cki7hdzZRnEEqdc2dJt+SAGotyFg/SvZMk=
github.com/nicksnyder/go-i18n/v2 v2.5.1 h1:IxtPxYsR9Gp60cGXjfuR/llTqV8aYMsC472zD0D1vHk=
github.com/nicksnyder/go-i18n/v2 v2.5.1/go.mod h1:DrhgsSDZxoAfvVrBVLXoxZn/pN5TXqaDbq7ju94viiQ=
github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU=
github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk=
github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
@@ -311,8 +302,8 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
github.com/quic-go/quic-go v0.48.2 h1:wsKXZPeGWpMpCGSWqOcqpW2wZYic/8T3aqiOID0/KWE=
github.com/quic-go/quic-go v0.48.2/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs=
github.com/quic-go/quic-go v0.49.0 h1:w5iJHXwHxs1QxyBv1EHKuC50GX5to8mJAxvtnttJp94=
github.com/quic-go/quic-go v0.49.0/go.mod h1:s2wDnmCdooUQBmQfpUSTCYBl1/D4FcqbULMMkASvR6s=
github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E=
github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw=
github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM=
@@ -321,6 +312,8 @@ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
@@ -349,36 +342,26 @@ github.com/wenlng/go-captcha/v2 v2.0.2 h1:8twz6pI6xZwPvEGFezoFX395oFso1MuOlJt/tL
github.com/wenlng/go-captcha/v2 v2.0.2/go.mod h1:5hac1em3uXoyC5ipZ0xFv9umNM/waQvYAQdr0cx/h34=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
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/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
github.com/yitter/idgenerator-go v1.3.3 h1:i6rzmpbCL0vlmr/tuW5+lSQzNuDG9vYBjIYRvnRcHE8=
github.com/yitter/idgenerator-go v1.3.3/go.mod h1:VVjbqFjGUsIkaXVkXEdmx1LiXUL3K1NvyxWPJBPbBpE=
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/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.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M=
github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
github.com/zeromicro/go-zero v1.7.6 h1:SArK4xecdrpVY3ZFJcbc0IZCx+NuWyHNjCv9f1+Gwrc=
github.com/zeromicro/go-zero v1.7.6/go.mod h1:SmGykRm5e0Z4CGNj+GaSKDffaHzQV56fel0FkymTLlE=
github.com/zeromicro/go-zero v1.8.0 h1:4g/8VW+fOyM51HZYPeI3mXIZdEX+Fl6SsdYX2H5PYw4=
github.com/zeromicro/go-zero v1.8.0/go.mod h1:xDBF+/iDzj30zPvu6HNUIbpz1J6+/g3Sx9D/DytJfss=
github.com/zmexing/go-sensitive-word v1.3.0 h1:dB9S9kNklksOODGLLAov0RaVCwC2w9Kwxz6NZMdM6rk=
github.com/zmexing/go-sensitive-word v1.3.0/go.mod h1:wkNIpkq1iPOe3l7l83zvnnV5mm20jfj2x8V8kjOTsUM=
go.etcd.io/etcd/api/v3 v3.5.17 h1:cQB8eb8bxwuxOilBpMJAEo8fAONyrdXTHUNcMd8yT1w=
go.etcd.io/etcd/api/v3 v3.5.17/go.mod h1:d1hvkRuXkts6PmaYk2Vrgqbv7H4ADfAKhyJqHNLJCB4=
go.etcd.io/etcd/client/pkg/v3 v3.5.17 h1:XxnDXAWq2pnxqx76ljWwiQ9jylbpC4rvkAeRVOUKKVw=
go.etcd.io/etcd/client/pkg/v3 v3.5.17/go.mod h1:4DqK1TKacp/86nJk4FLQqo6Mn2vvQFBmruW3pP14H/w=
go.etcd.io/etcd/client/v3 v3.5.17 h1:o48sINNeWz5+pjy/Z0+HKpj/xSnBkuVhVvXkjEXbqZY=
go.etcd.io/etcd/client/v3 v3.5.17/go.mod h1:j2d4eXTHWkT2ClBgnnEPm/Wuu7jsqku41v9DZ3OtjQo=
go.mongodb.org/mongo-driver/v2 v2.0.0 h1:Jfd7XpdZa9yk3eY774bO7SWVb30noLSirL9nKTpavhI=
go.mongodb.org/mongo-driver/v2 v2.0.0/go.mod h1:nSjmNq4JUstE8IRZKTktLgMHM4F1fccL6HGX1yh+8RA=
go.etcd.io/etcd/api/v3 v3.5.18 h1:Q4oDAKnmwqTo5lafvB+afbgCDF7E35E4EYV2g+FNGhs=
go.etcd.io/etcd/api/v3 v3.5.18/go.mod h1:uY03Ob2H50077J7Qq0DeehjM/A9S8PhVfbQ1mSaMopU=
go.etcd.io/etcd/client/pkg/v3 v3.5.18 h1:mZPOYw4h8rTk7TeJ5+3udUkfVGBqc+GCjOJYd68QgNM=
go.etcd.io/etcd/client/pkg/v3 v3.5.18/go.mod h1:BxVf2o5wXG9ZJV+/Cu7QNUiJYk4A29sAhoI5tIRsCu4=
go.etcd.io/etcd/client/v3 v3.5.18 h1:nvvYmNHGumkDjZhTHgVU36A9pykGa2K4lAJ0yY7hcXA=
go.etcd.io/etcd/client/v3 v3.5.18/go.mod h1:kmemwOsPU9broExyhYsBxX4spCTDX3yLgPMWtpBXG6E=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
@@ -399,8 +382,8 @@ go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS
go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc=
go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8=
go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU=
go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ=
go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
@@ -430,18 +413,18 @@ golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 h1:yqrTHse8TCMW1M1ZCP+VAR/l0kKxwaAIqN/il7x4voA=
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU=
golang.org/x/exp v0.0.0-20250128182459-e0ece0dbea4c h1:KL/ZBHXgKGVmuZBZ01Lt57yE5ws8ZPSkkihmEyq7FXc=
golang.org/x/exp v0.0.0-20250128182459-e0ece0dbea4c/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU=
golang.org/x/image v0.16.0/go.mod h1:ugSZItdV4nOxyqp56HmXwH0Ry0nBCpjnZdpDaIHdoPs=
golang.org/x/image v0.23.0 h1:HseQ7c2OpPKTPVzNjG5fwJsOTCiiwS4QdsYi5XU6H68=
golang.org/x/image v0.23.0/go.mod h1:wJJBTdLfCCf3tiHa1fNxpZmUI4mmoZvwMCPP0ddoNKY=
golang.org/x/image v0.24.0 h1:AN7zRgVsbvmTfNyqIbbOraYL8mSwcKncEj8ofjgzcMQ=
golang.org/x/image v0.24.0/go.mod h1:4b/ITuLfqYq1hqZcjofwctIhi7sZh2WaCjvsBNjjya8=
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.4.2/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.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=
golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -462,16 +445,16 @@ golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70=
golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE=
golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
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.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -491,8 +474,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
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/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
@@ -503,12 +486,11 @@ golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/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.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
@@ -517,10 +499,10 @@ golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4=
golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -535,14 +517,14 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1:gap6+3Gk41EItBuyi4XX/bp4oqJ3UwuIMl25yGinuAA=
google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:Ic02D47M+zbarjYYUlK57y316f2MoN0gjAwI3f2S95o=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50=
google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A=
google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4=
google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU=
google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
google.golang.org/genproto/googleapis/api v0.0.0-20250204164813-702378808489 h1:fCuMM4fowGzigT89NCIsW57Pk9k2D12MMi2ODn+Nk+o=
google.golang.org/genproto/googleapis/api v0.0.0-20250204164813-702378808489/go.mod h1:iYONQfRdizDB8JJBybql13nArx91jcUk7zCXEsOofM4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250204164813-702378808489 h1:5bKytslY8ViY0Cj/ewmRtrWHW64bNF03cAatUUFCdFI=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250204164813-702378808489/go.mod h1:8BS3B93F/U1juMFq9+EDk+qOT5CO1R9IzXxG3PTqiRk=
google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
@@ -598,14 +580,14 @@ k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJ
k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
modernc.org/cc/v4 v4.24.4 h1:TFkx1s6dCkQpd6dKurBNmpo+G8Zl4Sq/ztJ+2+DEsh0=
modernc.org/cc/v4 v4.24.4/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
modernc.org/ccgo/v4 v4.23.13 h1:PFiaemQwE/jdwi8XEHyEV+qYWoIuikLP3T4rvDeJb00=
modernc.org/ccgo/v4 v4.23.13/go.mod h1:vdN4h2WR5aEoNondUx26K7G8X+nuBscYnAEWSRmN2/0=
modernc.org/ccgo/v4 v4.23.15 h1:wFDan71KnYqeHz4eF63vmGE6Q6Pc0PUGDpP0PRMYjDc=
modernc.org/ccgo/v4 v4.23.15/go.mod h1:nJX30dks/IWuBOnVa7VRii9Me4/9TZ1SC9GNtmARTy0=
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
modernc.org/gc/v2 v2.6.1 h1:+Qf6xdG8l7B27TQ8D8lw/iFMUj1RXRBOuMUWziJOsk8=
modernc.org/gc/v2 v2.6.1/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
modernc.org/libc v1.61.9 h1:PLSBXVkifXGELtJ5BOnBUyAHr7lsatNwFU/RRo4kfJM=
modernc.org/libc v1.61.9/go.mod h1:61xrnzk/aR8gr5bR7Uj/lLFLuXu2/zMpIjcry63Eumk=
modernc.org/gc/v2 v2.6.2 h1:YBXi5Kqp6aCK3fIxwKQ3/fErvawVKwjOLItxj1brGds=
modernc.org/gc/v2 v2.6.2/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
modernc.org/libc v1.61.11 h1:6sZG8uB6EMMG7iTLPTndi8jyTdgAQNIeLGjCFICACZw=
modernc.org/libc v1.61.11/go.mod h1:HHX+srFdn839oaJRd0W8hBM3eg+mieyZCAjWwB08/nM=
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
modernc.org/memory v1.8.2 h1:cL9L4bcoAObu4NkxOlKWBWtNHIsnnACGF/TbqQ6sbcI=