v0.0.9 Интегрирован сервис модерации контента при создании поста
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
82d7866796
commit
1a3267a4cc
4
go.mod
4
go.mod
@ -14,6 +14,7 @@ require (
|
||||
github.com/prometheus/client_golang v1.22.0
|
||||
github.com/vektah/gqlparser/v2 v2.5.25
|
||||
golang.org/x/crypto v0.37.0
|
||||
google.golang.org/grpc v1.73.0
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||
)
|
||||
|
||||
@ -30,7 +31,10 @@ require (
|
||||
github.com/prometheus/common v0.62.0 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
github.com/sosodev/duration v1.3.1 // indirect
|
||||
golang.org/x/net v0.39.0 // indirect
|
||||
golang.org/x/sys v0.32.0 // indirect
|
||||
golang.org/x/text v0.24.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
)
|
||||
|
||||
24
go.sum
24
go.sum
@ -25,10 +25,16 @@ github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54 h1:SG7nF6SRlWhcT7c
|
||||
github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA=
|
||||
github.com/go-chi/chi/v5 v5.2.1 h1:KOIHODQj58PmL80G2Eak4WdvUzjSJSm0vG72crDCqb8=
|
||||
github.com/go-chi/chi/v5 v5.2.1/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
@ -70,12 +76,30 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/vektah/gqlparser/v2 v2.5.25 h1:FmWtFEa+invTIzWlWK6Vk7BVEZU/97QBzeI8Z1JjGt8=
|
||||
github.com/vektah/gqlparser/v2 v2.5.25/go.mod h1:D1/VCZtV3LPnQrcPBeR/q5jkSQIPti0uYCP/RI0gIeo=
|
||||
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.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
|
||||
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
|
||||
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
|
||||
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
|
||||
go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
|
||||
go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
|
||||
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
|
||||
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
|
||||
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
|
||||
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
|
||||
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
|
||||
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
|
||||
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
|
||||
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
|
||||
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 h1:e0AIkUUhxyBKh6ssZNrAMeqhA7RKUj42346d1y02i2g=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||
google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok=
|
||||
google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc=
|
||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
|
||||
|
||||
@ -14,6 +14,7 @@ import (
|
||||
"tailly_back_v2/internal/domain"
|
||||
"tailly_back_v2/internal/repository"
|
||||
"tailly_back_v2/internal/utils"
|
||||
"tailly_back_v2/pkg/moderation"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
@ -80,6 +81,22 @@ func (s *postService) Create(ctx context.Context, authorID int, title, content s
|
||||
return nil, errors.New("image too large (max 10MB)")
|
||||
}
|
||||
|
||||
// Создаем клиент модерации
|
||||
modClient, err := moderation.NewModerationClient("localhost:50051")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create moderation client: %v", err)
|
||||
}
|
||||
defer modClient.Close()
|
||||
|
||||
// Проверяем изображение
|
||||
allowed, err := modClient.CheckImage(ctx, imgBase64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("image moderation failed: %v", err)
|
||||
}
|
||||
if !allowed {
|
||||
return nil, errors.New("image rejected by moderation service")
|
||||
}
|
||||
|
||||
randName := utils.GenerateId() + ".jpg"
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
40
pkg/moderation/moderation.go
Normal file
40
pkg/moderation/moderation.go
Normal file
@ -0,0 +1,40 @@
|
||||
package moderation
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
pb "tailly_back_v2/pkg/moderation/proto"
|
||||
)
|
||||
|
||||
type ModerationClient struct {
|
||||
conn *grpc.ClientConn
|
||||
client pb.ModerationServiceClient
|
||||
}
|
||||
|
||||
func NewModerationClient(addr string) (*ModerationClient, error) {
|
||||
conn, err := grpc.Dial(addr, grpc.WithInsecure())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &ModerationClient{
|
||||
conn: conn,
|
||||
client: pb.NewModerationServiceClient(conn),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *ModerationClient) CheckImage(ctx context.Context, imageData []byte) (bool, error) {
|
||||
resp, err := c.client.CheckImage(ctx, &pb.ImageRequest{
|
||||
ImageData: imageData,
|
||||
})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return resp.OverallDecision == "allowed", nil
|
||||
}
|
||||
|
||||
func (c *ModerationClient) Close() {
|
||||
c.conn.Close()
|
||||
}
|
||||
400
pkg/moderation/proto/moderation.pb.go
Normal file
400
pkg/moderation/proto/moderation.pb.go
Normal file
@ -0,0 +1,400 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.36.6
|
||||
// protoc v3.21.12
|
||||
// source: moderation.proto
|
||||
|
||||
package __
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
unsafe "unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type ImageRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
ImageData []byte `protobuf:"bytes,1,opt,name=image_data,json=imageData,proto3" json:"image_data,omitempty"`
|
||||
ImageUrl string `protobuf:"bytes,2,opt,name=image_url,json=imageUrl,proto3" json:"image_url,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ImageRequest) Reset() {
|
||||
*x = ImageRequest{}
|
||||
mi := &file_moderation_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ImageRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ImageRequest) ProtoMessage() {}
|
||||
|
||||
func (x *ImageRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_moderation_proto_msgTypes[0]
|
||||
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 ImageRequest.ProtoReflect.Descriptor instead.
|
||||
func (*ImageRequest) Descriptor() ([]byte, []int) {
|
||||
return file_moderation_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *ImageRequest) GetImageData() []byte {
|
||||
if x != nil {
|
||||
return x.ImageData
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ImageRequest) GetImageUrl() string {
|
||||
if x != nil {
|
||||
return x.ImageUrl
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type VideoRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
VideoUrl string `protobuf:"bytes,1,opt,name=video_url,json=videoUrl,proto3" json:"video_url,omitempty"`
|
||||
FrameSampleRate int32 `protobuf:"varint,2,opt,name=frame_sample_rate,json=frameSampleRate,proto3" json:"frame_sample_rate,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *VideoRequest) Reset() {
|
||||
*x = VideoRequest{}
|
||||
mi := &file_moderation_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *VideoRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*VideoRequest) ProtoMessage() {}
|
||||
|
||||
func (x *VideoRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_moderation_proto_msgTypes[1]
|
||||
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 VideoRequest.ProtoReflect.Descriptor instead.
|
||||
func (*VideoRequest) Descriptor() ([]byte, []int) {
|
||||
return file_moderation_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *VideoRequest) GetVideoUrl() string {
|
||||
if x != nil {
|
||||
return x.VideoUrl
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *VideoRequest) GetFrameSampleRate() int32 {
|
||||
if x != nil {
|
||||
return x.FrameSampleRate
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type ModerationResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
OverallDecision string `protobuf:"bytes,1,opt,name=overall_decision,json=overallDecision,proto3" json:"overall_decision,omitempty"`
|
||||
Predictions []*Prediction `protobuf:"bytes,2,rep,name=predictions,proto3" json:"predictions,omitempty"`
|
||||
Message string `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ModerationResponse) Reset() {
|
||||
*x = ModerationResponse{}
|
||||
mi := &file_moderation_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ModerationResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ModerationResponse) ProtoMessage() {}
|
||||
|
||||
func (x *ModerationResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_moderation_proto_msgTypes[2]
|
||||
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 ModerationResponse.ProtoReflect.Descriptor instead.
|
||||
func (*ModerationResponse) Descriptor() ([]byte, []int) {
|
||||
return file_moderation_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *ModerationResponse) GetOverallDecision() string {
|
||||
if x != nil {
|
||||
return x.OverallDecision
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ModerationResponse) GetPredictions() []*Prediction {
|
||||
if x != nil {
|
||||
return x.Predictions
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ModerationResponse) GetMessage() string {
|
||||
if x != nil {
|
||||
return x.Message
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Prediction struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Category string `protobuf:"bytes,1,opt,name=category,proto3" json:"category,omitempty"`
|
||||
Score float32 `protobuf:"fixed32,2,opt,name=score,proto3" json:"score,omitempty"`
|
||||
Decision string `protobuf:"bytes,3,opt,name=decision,proto3" json:"decision,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *Prediction) Reset() {
|
||||
*x = Prediction{}
|
||||
mi := &file_moderation_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *Prediction) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Prediction) ProtoMessage() {}
|
||||
|
||||
func (x *Prediction) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_moderation_proto_msgTypes[3]
|
||||
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 Prediction.ProtoReflect.Descriptor instead.
|
||||
func (*Prediction) Descriptor() ([]byte, []int) {
|
||||
return file_moderation_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *Prediction) GetCategory() string {
|
||||
if x != nil {
|
||||
return x.Category
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Prediction) GetScore() float32 {
|
||||
if x != nil {
|
||||
return x.Score
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Prediction) GetDecision() string {
|
||||
if x != nil {
|
||||
return x.Decision
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type ModerationSettings struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
CategoryThresholds map[string]float32 `protobuf:"bytes,1,rep,name=category_thresholds,json=categoryThresholds,proto3" json:"category_thresholds,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"fixed32,2,opt,name=value"`
|
||||
AlwaysBlockCategories []string `protobuf:"bytes,2,rep,name=always_block_categories,json=alwaysBlockCategories,proto3" json:"always_block_categories,omitempty"`
|
||||
AlwaysAllowCategories []string `protobuf:"bytes,3,rep,name=always_allow_categories,json=alwaysAllowCategories,proto3" json:"always_allow_categories,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ModerationSettings) Reset() {
|
||||
*x = ModerationSettings{}
|
||||
mi := &file_moderation_proto_msgTypes[4]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ModerationSettings) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ModerationSettings) ProtoMessage() {}
|
||||
|
||||
func (x *ModerationSettings) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_moderation_proto_msgTypes[4]
|
||||
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 ModerationSettings.ProtoReflect.Descriptor instead.
|
||||
func (*ModerationSettings) Descriptor() ([]byte, []int) {
|
||||
return file_moderation_proto_rawDescGZIP(), []int{4}
|
||||
}
|
||||
|
||||
func (x *ModerationSettings) GetCategoryThresholds() map[string]float32 {
|
||||
if x != nil {
|
||||
return x.CategoryThresholds
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ModerationSettings) GetAlwaysBlockCategories() []string {
|
||||
if x != nil {
|
||||
return x.AlwaysBlockCategories
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ModerationSettings) GetAlwaysAllowCategories() []string {
|
||||
if x != nil {
|
||||
return x.AlwaysAllowCategories
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_moderation_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_moderation_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\x10moderation.proto\x12\n" +
|
||||
"moderation\"J\n" +
|
||||
"\fImageRequest\x12\x1d\n" +
|
||||
"\n" +
|
||||
"image_data\x18\x01 \x01(\fR\timageData\x12\x1b\n" +
|
||||
"\timage_url\x18\x02 \x01(\tR\bimageUrl\"W\n" +
|
||||
"\fVideoRequest\x12\x1b\n" +
|
||||
"\tvideo_url\x18\x01 \x01(\tR\bvideoUrl\x12*\n" +
|
||||
"\x11frame_sample_rate\x18\x02 \x01(\x05R\x0fframeSampleRate\"\x93\x01\n" +
|
||||
"\x12ModerationResponse\x12)\n" +
|
||||
"\x10overall_decision\x18\x01 \x01(\tR\x0foverallDecision\x128\n" +
|
||||
"\vpredictions\x18\x02 \x03(\v2\x16.moderation.PredictionR\vpredictions\x12\x18\n" +
|
||||
"\amessage\x18\x03 \x01(\tR\amessage\"Z\n" +
|
||||
"\n" +
|
||||
"Prediction\x12\x1a\n" +
|
||||
"\bcategory\x18\x01 \x01(\tR\bcategory\x12\x14\n" +
|
||||
"\x05score\x18\x02 \x01(\x02R\x05score\x12\x1a\n" +
|
||||
"\bdecision\x18\x03 \x01(\tR\bdecision\"\xb4\x02\n" +
|
||||
"\x12ModerationSettings\x12g\n" +
|
||||
"\x13category_thresholds\x18\x01 \x03(\v26.moderation.ModerationSettings.CategoryThresholdsEntryR\x12categoryThresholds\x126\n" +
|
||||
"\x17always_block_categories\x18\x02 \x03(\tR\x15alwaysBlockCategories\x126\n" +
|
||||
"\x17always_allow_categories\x18\x03 \x03(\tR\x15alwaysAllowCategories\x1aE\n" +
|
||||
"\x17CategoryThresholdsEntry\x12\x10\n" +
|
||||
"\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" +
|
||||
"\x05value\x18\x02 \x01(\x02R\x05value:\x028\x012\xa7\x01\n" +
|
||||
"\x11ModerationService\x12H\n" +
|
||||
"\n" +
|
||||
"CheckImage\x12\x18.moderation.ImageRequest\x1a\x1e.moderation.ModerationResponse\"\x00\x12H\n" +
|
||||
"\n" +
|
||||
"CheckVideo\x12\x18.moderation.VideoRequest\x1a\x1e.moderation.ModerationResponse\"\x00B\x03Z\x01.b\x06proto3"
|
||||
|
||||
var (
|
||||
file_moderation_proto_rawDescOnce sync.Once
|
||||
file_moderation_proto_rawDescData []byte
|
||||
)
|
||||
|
||||
func file_moderation_proto_rawDescGZIP() []byte {
|
||||
file_moderation_proto_rawDescOnce.Do(func() {
|
||||
file_moderation_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_moderation_proto_rawDesc), len(file_moderation_proto_rawDesc)))
|
||||
})
|
||||
return file_moderation_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_moderation_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
|
||||
var file_moderation_proto_goTypes = []any{
|
||||
(*ImageRequest)(nil), // 0: moderation.ImageRequest
|
||||
(*VideoRequest)(nil), // 1: moderation.VideoRequest
|
||||
(*ModerationResponse)(nil), // 2: moderation.ModerationResponse
|
||||
(*Prediction)(nil), // 3: moderation.Prediction
|
||||
(*ModerationSettings)(nil), // 4: moderation.ModerationSettings
|
||||
nil, // 5: moderation.ModerationSettings.CategoryThresholdsEntry
|
||||
}
|
||||
var file_moderation_proto_depIdxs = []int32{
|
||||
3, // 0: moderation.ModerationResponse.predictions:type_name -> moderation.Prediction
|
||||
5, // 1: moderation.ModerationSettings.category_thresholds:type_name -> moderation.ModerationSettings.CategoryThresholdsEntry
|
||||
0, // 2: moderation.ModerationService.CheckImage:input_type -> moderation.ImageRequest
|
||||
1, // 3: moderation.ModerationService.CheckVideo:input_type -> moderation.VideoRequest
|
||||
2, // 4: moderation.ModerationService.CheckImage:output_type -> moderation.ModerationResponse
|
||||
2, // 5: moderation.ModerationService.CheckVideo:output_type -> moderation.ModerationResponse
|
||||
4, // [4:6] is the sub-list for method output_type
|
||||
2, // [2:4] is the sub-list for method input_type
|
||||
2, // [2:2] is the sub-list for extension type_name
|
||||
2, // [2:2] is the sub-list for extension extendee
|
||||
0, // [0:2] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_moderation_proto_init() }
|
||||
func file_moderation_proto_init() {
|
||||
if File_moderation_proto != nil {
|
||||
return
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_moderation_proto_rawDesc), len(file_moderation_proto_rawDesc)),
|
||||
NumEnums: 0,
|
||||
NumMessages: 6,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
GoTypes: file_moderation_proto_goTypes,
|
||||
DependencyIndexes: file_moderation_proto_depIdxs,
|
||||
MessageInfos: file_moderation_proto_msgTypes,
|
||||
}.Build()
|
||||
File_moderation_proto = out.File
|
||||
file_moderation_proto_goTypes = nil
|
||||
file_moderation_proto_depIdxs = nil
|
||||
}
|
||||
37
pkg/moderation/proto/moderation.proto
Normal file
37
pkg/moderation/proto/moderation.proto
Normal file
@ -0,0 +1,37 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package moderation;
|
||||
option go_package = ".";
|
||||
|
||||
service ModerationService {
|
||||
rpc CheckImage (ImageRequest) returns (ModerationResponse) {}
|
||||
rpc CheckVideo (VideoRequest) returns (ModerationResponse) {}
|
||||
}
|
||||
|
||||
message ImageRequest {
|
||||
bytes image_data = 1;
|
||||
string image_url = 2;
|
||||
}
|
||||
|
||||
message VideoRequest {
|
||||
string video_url = 1;
|
||||
int32 frame_sample_rate = 2;
|
||||
}
|
||||
|
||||
message ModerationResponse {
|
||||
string overall_decision = 1;
|
||||
repeated Prediction predictions = 2;
|
||||
string message = 3;
|
||||
}
|
||||
|
||||
message Prediction {
|
||||
string category = 1;
|
||||
float score = 2;
|
||||
string decision = 3;
|
||||
}
|
||||
|
||||
message ModerationSettings {
|
||||
map<string, float> category_thresholds = 1;
|
||||
repeated string always_block_categories = 2;
|
||||
repeated string always_allow_categories = 3;
|
||||
}
|
||||
159
pkg/moderation/proto/moderation_grpc.pb.go
Normal file
159
pkg/moderation/proto/moderation_grpc.pb.go
Normal file
@ -0,0 +1,159 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc v3.21.12
|
||||
// source: moderation.proto
|
||||
|
||||
package __
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.64.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
ModerationService_CheckImage_FullMethodName = "/moderation.ModerationService/CheckImage"
|
||||
ModerationService_CheckVideo_FullMethodName = "/moderation.ModerationService/CheckVideo"
|
||||
)
|
||||
|
||||
// ModerationServiceClient is the client API for ModerationService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type ModerationServiceClient interface {
|
||||
CheckImage(ctx context.Context, in *ImageRequest, opts ...grpc.CallOption) (*ModerationResponse, error)
|
||||
CheckVideo(ctx context.Context, in *VideoRequest, opts ...grpc.CallOption) (*ModerationResponse, error)
|
||||
}
|
||||
|
||||
type moderationServiceClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewModerationServiceClient(cc grpc.ClientConnInterface) ModerationServiceClient {
|
||||
return &moderationServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *moderationServiceClient) CheckImage(ctx context.Context, in *ImageRequest, opts ...grpc.CallOption) (*ModerationResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ModerationResponse)
|
||||
err := c.cc.Invoke(ctx, ModerationService_CheckImage_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *moderationServiceClient) CheckVideo(ctx context.Context, in *VideoRequest, opts ...grpc.CallOption) (*ModerationResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ModerationResponse)
|
||||
err := c.cc.Invoke(ctx, ModerationService_CheckVideo_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// ModerationServiceServer is the server API for ModerationService service.
|
||||
// All implementations must embed UnimplementedModerationServiceServer
|
||||
// for forward compatibility.
|
||||
type ModerationServiceServer interface {
|
||||
CheckImage(context.Context, *ImageRequest) (*ModerationResponse, error)
|
||||
CheckVideo(context.Context, *VideoRequest) (*ModerationResponse, error)
|
||||
mustEmbedUnimplementedModerationServiceServer()
|
||||
}
|
||||
|
||||
// UnimplementedModerationServiceServer must be embedded to have
|
||||
// forward compatible implementations.
|
||||
//
|
||||
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||
// pointer dereference when methods are called.
|
||||
type UnimplementedModerationServiceServer struct{}
|
||||
|
||||
func (UnimplementedModerationServiceServer) CheckImage(context.Context, *ImageRequest) (*ModerationResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CheckImage not implemented")
|
||||
}
|
||||
func (UnimplementedModerationServiceServer) CheckVideo(context.Context, *VideoRequest) (*ModerationResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CheckVideo not implemented")
|
||||
}
|
||||
func (UnimplementedModerationServiceServer) mustEmbedUnimplementedModerationServiceServer() {}
|
||||
func (UnimplementedModerationServiceServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeModerationServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to ModerationServiceServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeModerationServiceServer interface {
|
||||
mustEmbedUnimplementedModerationServiceServer()
|
||||
}
|
||||
|
||||
func RegisterModerationServiceServer(s grpc.ServiceRegistrar, srv ModerationServiceServer) {
|
||||
// If the following call pancis, it indicates UnimplementedModerationServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||
t.testEmbeddedByValue()
|
||||
}
|
||||
s.RegisterService(&ModerationService_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _ModerationService_CheckImage_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ImageRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ModerationServiceServer).CheckImage(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: ModerationService_CheckImage_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ModerationServiceServer).CheckImage(ctx, req.(*ImageRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _ModerationService_CheckVideo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(VideoRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ModerationServiceServer).CheckVideo(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: ModerationService_CheckVideo_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ModerationServiceServer).CheckVideo(ctx, req.(*VideoRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// ModerationService_ServiceDesc is the grpc.ServiceDesc for ModerationService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var ModerationService_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "moderation.ModerationService",
|
||||
HandlerType: (*ModerationServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "CheckImage",
|
||||
Handler: _ModerationService_CheckImage_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "CheckVideo",
|
||||
Handler: _ModerationService_CheckVideo_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "moderation.proto",
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user