tokenizer

This commit is contained in:
1iaan
2026-04-03 10:29:38 +08:00
parent de99cb2806
commit c1a895258f
70 changed files with 22320 additions and 239 deletions

1
keywords-filter/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
runtime

View File

@@ -0,0 +1,19 @@
# 编译阶段
FROM quay.io/0voice/golang:1.20 as stage0
RUN go env -w GOPROXY=https://proxy.golang.com.cn,https://goproxy.cn,direct
ADD ./ /src/keywords-filter
WORKDIR /src/keywords-filter
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o keywords-filter ./filter-server
FROM quay.io/0voice/alpine:3.18 as stage1
ADD ./grpc_health_probe-linux-amd64 /usr/bin/grpc_health_probe
RUN chmod +x /usr/bin/grpc_health_probe
MAINTAINER nick
WORKDIR /app/
ADD ./dev.config.yaml /app/config.yaml
ADD ./dict.txt /app/dict.txt
COPY --from=stage0 /src/keywords-filter/keywords-filter ./
# 指定入口程序
ENTRYPOINT ["./keywords-filter"]
# 指定容器的启动命令或者入口程序的参数
CMD ["--config=config.yaml","--dict=dict.txt"]

View File

@@ -0,0 +1,8 @@
server:
ip: 0.0.0.0
port: 50053
accessToken: "ang1chubdev1ozhome256487d22sapguuv1ozhom"
log:
# panic,fatal,errro,warn,info,debug,trace
level: "info"
logPath: "runtime/logs/app.log"

View File

@@ -0,0 +1,8 @@
server:
ip: 0.0.0.0
port: 50054
accessToken: "ang1chubdev1ozhome256487d22sapguuv1ozhom"
log:
# panic,fatal,errro,warn,info,debug,trace
level: "info"
logPath: "runtime/logs/app.log"

13992
keywords-filter/dict.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,38 @@
package interceptor
import (
"context"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
"keywords-filter/pkg/config"
"keywords-filter/pkg/zerror"
"strings"
)
func UnaryAuthInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) {
if info.FullMethod != "/grpc.health.v1.Health/Check" {
err = oauth2Valid(ctx)
if err != nil {
return nil, err
}
}
return handler(ctx, req)
}
func oauth2Valid(ctx context.Context) error {
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
return zerror.NewByMsg("元数据获取失败")
}
authorization := md["authorization"]
if len(authorization) < 1 {
return zerror.NewByMsg("元数据获取失败")
}
token := strings.TrimPrefix(authorization[0], "Bearer ")
cnf := config.GetConfig()
if token != cnf.Server.AccessToken {
return zerror.NewByMsg("鉴权失败")
}
return nil
}

View File

@@ -0,0 +1,55 @@
package main
import (
"flag"
"fmt"
"google.golang.org/grpc"
"google.golang.org/grpc/health"
"google.golang.org/grpc/health/grpc_health_v1"
"keywords-filter/filter-server/interceptor"
"keywords-filter/filter-server/server"
"keywords-filter/pkg/config"
"keywords-filter/pkg/filter"
"keywords-filter/pkg/log"
"keywords-filter/proto"
"net"
)
var (
configFile = flag.String("config", "dev.config.yaml", "")
dictFile = flag.String("dict", "dict.txt", "")
formatDict = flag.Bool("format", false, "")
)
func main() {
flag.Parse()
if *formatDict {
filter.OverwriteDict(*dictFile)
return
}
//初始化配置文件
config.InitConfig(*configFile)
cnf := config.GetConfig()
//初始化日志
log.SetLevel(cnf.Log.Level)
log.SetOutput(log.GetRotateWriter(cnf.Log.LogPath))
log.SetPrintCaller(true)
//初始话filter
filter.InitFilter(*dictFile)
lis, err := net.Listen("tcp", fmt.Sprintf("%s:%d", cnf.Server.IP, cnf.Server.Port))
if err != nil {
log.Fatal(err)
}
s := grpc.NewServer(grpc.UnaryInterceptor(interceptor.UnaryAuthInterceptor))
service := server.NewFilterService(filter.GetFilter())
proto.RegisterFilterServer(s, service)
healthCheckSrv := health.NewServer()
grpc_health_v1.RegisterHealthServer(s, healthCheckSrv)
if err = s.Serve(lis); err != nil {
log.Fatal(err)
}
}

View File

@@ -0,0 +1,32 @@
package server
import (
"context"
"keywords-filter/pkg/filter"
"keywords-filter/proto"
)
type filterService struct {
proto.UnimplementedFilterServer
filter filter.IFilter
}
func NewFilterService(filter filter.IFilter) proto.FilterServer {
return &filterService{
filter: filter,
}
}
func (s *filterService) Validate(_ context.Context, in *proto.FilterReq) (*proto.ValidateRes, error) {
ok, word := s.filter.Validate(in.Text)
return &proto.ValidateRes{
Ok: ok,
Keyword: word,
}, nil
}
func (s *filterService) FindAll(_ context.Context, in *proto.FilterReq) (*proto.FindAllRes, error) {
words := s.filter.FindAll(in.Text)
return &proto.FindAllRes{
Keywords: words,
}, nil
}

37
keywords-filter/go.mod Normal file
View File

@@ -0,0 +1,37 @@
module keywords-filter
go 1.20
require (
github.com/importcjj/sensitive v0.0.0-20200106142752-42d1c505be7b
github.com/sirupsen/logrus v1.9.3
github.com/spf13/viper v1.19.0
google.golang.org/grpc v1.62.1
google.golang.org/protobuf v1.34.2
gopkg.in/natefinch/lumberjack.v2 v2.2.1
)
require (
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/net v0.26.0 // indirect
golang.org/x/sys v0.21.0 // indirect
golang.org/x/text v0.16.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

86
keywords-filter/go.sum Normal file
View File

@@ -0,0 +1,86 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/importcjj/sensitive v0.0.0-20200106142752-42d1c505be7b h1:9hudrgWUhyfR4FRMOfL9KB1uYw48DUdHkkgr9ODOw7Y=
github.com/importcjj/sensitive v0.0.0-20200106142752-42d1c505be7b/go.mod h1:zLVdX6Ed2SvCbEamKmve16U0E03UkdJo4ls1TBfmc8Q=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 h1:1GBuWVLM/KMVUv1t1En5Gs+gFZCNd360GGb4sSxtrhU=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk=
google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

Binary file not shown.

View File

@@ -0,0 +1,192 @@
golang
defer
recover
sync
Protobuf
gin
grpc-gateway
OpenTelemetry
OTel
otel
k8s
Kubernetes
kubernetes
Docker
docker
Istio
istio
Prometheus
prometheus
cadvisor
cAdvisor
Elastic
Kibana
Grafana
apiserver
CI/CD
ci/cd
ArgoCD
argo
Argo
kaniko
Mesh
Volume
volume
promQL
PromQL
kafka
ingress
StorageClass
VolumeClaim
gitlab
openflow
dpdk
vpp
ovs
spdk
virtio
vhost
qemu
vSwitch
bridge
hugepage
nvme
dpvs
iperf3
rfc2544
ioengine
PCI
vxlan
gre
kni
Kernel
内核
KernelThread
内核线程
Virtual
memory
虚拟内存
内存屏障
内存管理
Scheduler
调度器
File
文件系统
Device
driver
设备驱动程序
Syscall
系统调用
Process
scheduling
进程调度
Page
页表
Swap
交换空间
Mount
Inode
挂载
索引节点
Block
块设备
Character
字符设备
IRQ
Kconfig
内核配置
Perf
Ftrace
内核跟踪工具
Valgrind
内存调试工具
System
系统定时器
DMA
伙伴系统
信号与槽
Signals
Slots
事件处理程序
Event
QML
多线程编程
Multithreading
Programming
QThread
QtQuick
模型
视图架构
Model/View
QObject
QWidget
QRegularExpression
QDesktopWidget
QNetworkAccessManager
QTcpServer
QTcpSocket
QUdpSocket
QMutex
SQLite/MySQL
MySQL编程
SQLite编程
OpenCV
OpenGL
Qt数据库编程
Qt网络编程
Linux
tcp
redis
mysql
网络
nginx
协程
io_uring
内存泄漏
bpf
ebpf
skynet
openresty
RocksDB
TiDB
ceph
etcd
fuse
p2p
http
mqtt
cuda
mutex
spinlock
hash
rbtree
btree
Makefile
git
wrk
Cuda
CUDA
D3D
d3d
ffmpeg
RTSP
WebRTC
PCM
RGB
YUv
MP4
FLV
TS
VLC
EasylCE
flvAnalyser
mp4box
audacity
Elecard
AAC
h264
SDL
AVFormat
AVCodec
AVPacket

View File

@@ -0,0 +1,42 @@
package config
import (
"github.com/spf13/viper"
"log"
)
type Config struct {
Server struct {
IP string
Port int
AccessToken string
}
Log struct {
Level string
LogPath string `mapstructure:"logPath"`
} `mapstructure:"log"`
}
var conf *Config
func InitConfig(filePath string, typ ...string) {
v := viper.New()
v.SetConfigFile(filePath)
if len(typ) > 0 {
v.SetConfigType(typ[0])
}
err := v.ReadInConfig()
if err != nil {
log.Fatal(err)
}
conf = &Config{}
err = v.Unmarshal(conf)
if err != nil {
log.Fatal(err)
}
}
func GetConfig() *Config {
return conf
}

View File

@@ -0,0 +1,98 @@
package filter
import (
"bufio"
"github.com/importcjj/sensitive"
"keywords-filter/pkg/log"
"os"
"regexp"
"strings"
)
type IFilter interface {
Validate(text string) (bool, string)
FindAll(text string) []string
}
type filter struct {
filter *sensitive.Filter
}
func (f *filter) Validate(text string) (bool, string) {
text = " " + strings.Trim(text, " ") + " "
ok, word := f.filter.Validate(text)
return ok, word
}
func (f *filter) FindAll(text string) []string {
text = " " + strings.Trim(text, " ") + " "
list := f.filter.FindAll(text)
for i := 0; i < len(list); i++ {
list[i] = strings.Trim(list[i], " ")
}
return list
}
var _filter *filter
func GetFilter() IFilter {
return _filter
}
func InitFilter(dictFilePath string) {
if dictFilePath == "" {
log.Fatal("请指定词库文件")
}
_, err := os.Stat(dictFilePath)
if os.IsNotExist(err) {
log.Fatal("词库文件不存在,请指定正确的词库文件")
}
f := sensitive.New()
f.UpdateNoisePattern("")
f.LoadWordDict(dictFilePath)
_filter = &filter{
filter: f,
}
}
func OverwriteDict(dictFilePath string) error {
file, err := os.Open(dictFilePath)
if err != nil {
log.Fatal(err)
return err
}
re := regexp.MustCompile(`\p{Han}+`)
newContent := ""
kwMp := make(map[string]struct{}, 0)
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
line = strings.Trim(line, " ")
//去重
if _, ok := kwMp[line]; ok {
continue
}
kwMp[line] = struct{}{}
match := re.FindString(line)
if match == "" {
newContent += " " + line + " \n"
} else {
newContent += line + "\n"
}
}
newContent = strings.Trim(newContent, "\n")
file.Close()
file, err = os.OpenFile(dictFilePath, os.O_TRUNC|os.O_CREATE|os.O_WRONLY, 0644)
defer file.Close()
if err != nil {
log.Fatal(err)
return err
}
_, err = file.WriteString(newContent)
if err != nil {
log.Fatal(err)
return err
}
return err
}

View File

@@ -0,0 +1,3 @@
# 日志框架
1. 可通过包调用日志打印,也可以通过对象调用日志打印
2. 可以自动切分日志文件

View File

@@ -0,0 +1,19 @@
package log
import "github.com/sirupsen/logrus"
import nativeLog "log"
type errorHook struct {
}
func (*errorHook) Levels() []logrus.Level {
return []logrus.Level{
logrus.PanicLevel,
logrus.FatalLevel,
logrus.ErrorLevel,
}
}
func (*errorHook) Fire(entry *logrus.Entry) error {
nativeLog.Println(entry.Message, entry.Data)
return nil
}

View File

@@ -0,0 +1,233 @@
package log
import (
"errors"
"fmt"
"github.com/sirupsen/logrus"
"io"
"runtime"
)
type ILogger interface {
SetLevel(lvl string)
SetOutput(writer io.Writer)
SetPrintCaller(bool)
SetCaller(caller func() (file string, line int, funcName string, err error))
Trace(args ...interface{})
Debug(args ...interface{})
Info(args ...interface{})
Warning(args ...interface{})
Error(args ...interface{})
Fatal(args ...interface{})
Panic(args ...interface{})
TraceF(format string, args ...interface{})
DebugF(format string, args ...interface{})
InfoF(format string, args ...interface{})
WarningF(format string, args ...interface{})
ErrorF(format string, args ...interface{})
FatalF(format string, args ...interface{})
PanicF(format string, args ...interface{})
WithFields(fields map[string]interface{}) ILogger
}
type Logger struct {
entry *logrus.Entry
// panic,fatal,error,warn,warning,info,debug,trace
level string
printCaller bool
caller func() (file string, line int, funcName string, err error)
}
// 设置日志打印级别
func (l *Logger) SetLevel(lvl string) {
if lvl == "" {
return
}
level, err := logrus.ParseLevel(lvl)
if err == nil {
l.level = lvl
l.entry.Logger.Level = level
}
}
// 设置日志输出位置
func (l *Logger) SetOutput(writer io.Writer) {
l.entry.Logger.SetOutput(writer)
}
// 设置是否打印调用信息
func (l *Logger) SetPrintCaller(printCaller bool) {
l.printCaller = printCaller
}
func (l *Logger) SetCaller(caller func() (file string, line int, funcName string, err error)) {
l.caller = caller
}
// 获取caller信息
func (l *Logger) getCallerInfo(level logrus.Level) map[string]interface{} {
mp := make(map[string]interface{})
if l.printCaller == true || level != logrus.InfoLevel {
file, line, funcName, err := l.caller()
if err == nil {
mp["file"] = fmt.Sprintf("%s:%d", file, line)
mp["func"] = funcName
}
}
return mp
}
func (l *Logger) log(level logrus.Level, args ...interface{}) {
l.entry.WithFields(l.getCallerInfo(level)).Log(level, args...)
}
func (l *Logger) logf(level logrus.Level, format string, args ...interface{}) {
l.entry.WithFields(l.getCallerInfo(level)).Logf(level, format, args...)
}
func (l *Logger) Trace(args ...interface{}) {
l.log(logrus.TraceLevel, args...)
}
func (l *Logger) Debug(args ...interface{}) {
l.log(logrus.DebugLevel, args...)
}
func (l *Logger) Info(args ...interface{}) {
l.log(logrus.InfoLevel, args...)
}
func (l *Logger) Warning(args ...interface{}) {
l.log(logrus.WarnLevel, args...)
}
func (l *Logger) Error(args ...interface{}) {
l.log(logrus.ErrorLevel, args...)
}
func (l *Logger) Fatal(args ...interface{}) {
l.log(logrus.FatalLevel, args...)
}
func (l *Logger) Panic(args ...interface{}) {
l.log(logrus.PanicLevel, args...)
}
func (l *Logger) TraceF(format string, args ...interface{}) {
l.logf(logrus.TraceLevel, format, args...)
}
func (l *Logger) DebugF(format string, args ...interface{}) {
l.logf(logrus.DebugLevel, format, args...)
}
func (l *Logger) InfoF(format string, args ...interface{}) {
l.logf(logrus.InfoLevel, format, args...)
}
func (l *Logger) WarningF(format string, args ...interface{}) {
l.logf(logrus.WarnLevel, format, args...)
}
func (l *Logger) ErrorF(format string, args ...interface{}) {
l.logf(logrus.ErrorLevel, format, args...)
}
func (l *Logger) FatalF(format string, args ...interface{}) {
l.logf(logrus.FatalLevel, format, args...)
}
func (l *Logger) PanicF(format string, args ...interface{}) {
l.logf(logrus.PanicLevel, format, args...)
}
func (l *Logger) WithFields(fields map[string]interface{}) ILogger {
entry := l.entry.WithFields(fields)
return &Logger{entry: entry, level: l.level, printCaller: l.printCaller, caller: l.caller}
}
var log *Logger
func NewLogger() ILogger {
return newLogger()
}
func newLogger() *Logger {
log := logrus.New()
log.SetLevel(logrus.InfoLevel)
log.AddHook(&errorHook{})
logger := &Logger{
entry: logrus.NewEntry(log),
caller: defaultCaller,
}
return logger
}
func init() {
log = newLogger()
}
// 设置日志打印级别
func SetLevel(lvl string) {
if lvl == "" {
return
}
level, err := logrus.ParseLevel(lvl)
if err == nil {
log.level = lvl
log.entry.Logger.Level = level
}
}
// 设置日志的输出位置
func SetOutput(writer io.Writer) {
log.entry.Logger.SetOutput(writer)
}
// 设置是否打印调用信息
func SetPrintCaller(printCaller bool) {
log.printCaller = printCaller
}
func SetCaller(caller func() (file string, line int, funcName string, err error)) {
log.caller = caller
}
func defaultCaller() (file string, line int, funcName string, err error) {
pc, f, l, ok := runtime.Caller(4)
if !ok {
err = errors.New("caller failure")
return
}
funcName = runtime.FuncForPC(pc).Name()
file, line = f, l
return
}
func Trace(args ...interface{}) {
log.log(logrus.TraceLevel, args...)
}
func Debug(args ...interface{}) {
log.log(logrus.DebugLevel, args...)
}
func Info(args ...interface{}) {
log.log(logrus.InfoLevel, args...)
}
func Warning(args ...interface{}) {
log.log(logrus.WarnLevel, args...)
}
func Error(args ...interface{}) {
log.log(logrus.ErrorLevel, args...)
}
func Fatal(args ...interface{}) {
log.log(logrus.FatalLevel, args...)
}
func Panic(args ...interface{}) {
log.log(logrus.PanicLevel, args...)
}
func TraceF(format string, args ...interface{}) {
log.logf(logrus.TraceLevel, format, args...)
}
func DebugF(format string, args ...interface{}) {
log.logf(logrus.DebugLevel, format, args...)
}
func InfoF(format string, args ...interface{}) {
log.logf(logrus.InfoLevel, format, args...)
}
func WarningF(format string, args ...interface{}) {
log.logf(logrus.WarnLevel, format, args...)
}
func ErrorF(format string, args ...interface{}) {
log.logf(logrus.ErrorLevel, format, args...)
}
func FatalF(format string, args ...interface{}) {
log.logf(logrus.FatalLevel, format, args...)
}
func PanicF(format string, args ...interface{}) {
log.logf(logrus.PanicLevel, format, args...)
}
func WithFields(fields map[string]interface{}) *Logger {
entry := log.entry.WithFields(fields)
return &Logger{entry: entry, level: log.level, printCaller: log.printCaller, caller: log.caller}
}

View File

@@ -0,0 +1,58 @@
package log
import (
"gopkg.in/natefinch/lumberjack.v2"
"io"
"sync"
)
type fileRotateWriter struct {
data map[string]io.Writer
sync.RWMutex
}
func (frw *fileRotateWriter) getWriter(logPath string) io.Writer {
frw.RLock()
defer frw.RUnlock()
w, ok := frw.data[logPath]
if !ok {
return nil
}
return w
}
func (frw *fileRotateWriter) setWriter(logPath string, w io.Writer) io.Writer {
frw.Lock()
defer frw.Unlock()
frw.data[logPath] = w
return w
}
var _fileRotateWriter *fileRotateWriter
func init() {
_fileRotateWriter = &fileRotateWriter{
data: map[string]io.Writer{},
}
}
func GetRotateWriter(logPath string) io.Writer {
if logPath == "" {
panic("日志文件路径不能为空")
}
writer := _fileRotateWriter.getWriter(logPath)
if writer != nil {
return writer
}
writer = &lumberjack.Logger{
//文件名
Filename: logPath,
//单个文件大小单位MB
MaxSize: 1,
//最多保留文件数
MaxBackups: 15,
//最长保留时间(天)
MaxAge: 7,
LocalTime: true,
}
return _fileRotateWriter.setWriter(logPath, writer)
}

View File

@@ -0,0 +1,14 @@
package zerror
type ZErrorCode string
func getErrMsg(errCode ZErrorCode) string {
msg, ok := errorMsgs[errCode]
if ok {
return msg
}
return ""
}
// 错误码与之对应的错误消息
var errorMsgs = map[ZErrorCode]string{}

View File

@@ -0,0 +1,101 @@
package zerror
import (
"errors"
"fmt"
)
type ZError struct {
ErrCode ZErrorCode `json:"err_code,omitempty"`
ErrMsg string `json:"err_msg,omitempty"`
errs []error
}
func (e *ZError) Error() string {
if e == nil {
return ""
}
if e.ErrMsg != "" {
return fmt.Sprintf("ErrCode:%s; ErrMsg:%s;", e.ErrCode, e.ErrMsg)
}
res := ""
if e.errs == nil || len(e.errs) == 0 {
return res
}
var first = true
for _, err := range e.errs {
if first {
res = err.Error()
first = false
} else {
res += ";" + err.Error()
}
}
return res
}
func (e *ZError) Errors() []error {
if e == nil {
return nil
}
return e.errs
}
func (e *ZError) Append(err error) {
if e == nil || err == nil {
return
}
ze, ok := err.(*ZError)
if ok {
e.errs = append(e.errs, ze.errs...)
} else {
e.errs = append(e.errs, err)
}
}
func NewByErr(err ...error) error {
res := &ZError{
errs: make([]error, 0),
}
for i, e := range err {
if e == nil {
continue
}
ze, ok := err[i].(*ZError)
if ok {
res.errs = append(res.errs, ze.errs...)
} else {
res.errs = append(res.errs, err[i])
}
}
if len(res.errs) > 0 {
return res
}
return nil
}
func NewByCode(errCode ZErrorCode, errMsg ...string) error {
msg := ""
if len(errMsg) > 0 {
msg = errMsg[0]
} else {
msg = getErrMsg(errCode)
}
return &ZError{
ErrCode: errCode,
ErrMsg: msg,
}
}
func NewByMsg(msg string) error {
err := errors.New(msg)
return NewByErr(err)
}
func Errors(err error) []error {
if err == nil {
return nil
}
ze, ok := err.(*ZError)
if !ok {
return []error{err}
}
//将一个空的[]error切片与ze.Errors()返回的错误切片合并在一起
//返回一个新切片
return append(([]error)(nil), ze.Errors()...)
}

View File

@@ -0,0 +1,294 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.28.1
// protoc v4.22.0
// source: proto/filter.proto
package proto
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
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 FilterReq struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Text string `protobuf:"bytes,1,opt,name=text,proto3" json:"text,omitempty"`
}
func (x *FilterReq) Reset() {
*x = FilterReq{}
if protoimpl.UnsafeEnabled {
mi := &file_proto_filter_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *FilterReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*FilterReq) ProtoMessage() {}
func (x *FilterReq) ProtoReflect() protoreflect.Message {
mi := &file_proto_filter_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use FilterReq.ProtoReflect.Descriptor instead.
func (*FilterReq) Descriptor() ([]byte, []int) {
return file_proto_filter_proto_rawDescGZIP(), []int{0}
}
func (x *FilterReq) GetText() string {
if x != nil {
return x.Text
}
return ""
}
type ValidateRes struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Ok bool `protobuf:"varint,1,opt,name=ok,proto3" json:"ok,omitempty"`
Keyword string `protobuf:"bytes,2,opt,name=keyword,proto3" json:"keyword,omitempty"`
}
func (x *ValidateRes) Reset() {
*x = ValidateRes{}
if protoimpl.UnsafeEnabled {
mi := &file_proto_filter_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ValidateRes) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ValidateRes) ProtoMessage() {}
func (x *ValidateRes) ProtoReflect() protoreflect.Message {
mi := &file_proto_filter_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ValidateRes.ProtoReflect.Descriptor instead.
func (*ValidateRes) Descriptor() ([]byte, []int) {
return file_proto_filter_proto_rawDescGZIP(), []int{1}
}
func (x *ValidateRes) GetOk() bool {
if x != nil {
return x.Ok
}
return false
}
func (x *ValidateRes) GetKeyword() string {
if x != nil {
return x.Keyword
}
return ""
}
type FindAllRes struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Keywords []string `protobuf:"bytes,1,rep,name=keywords,proto3" json:"keywords,omitempty"`
}
func (x *FindAllRes) Reset() {
*x = FindAllRes{}
if protoimpl.UnsafeEnabled {
mi := &file_proto_filter_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *FindAllRes) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*FindAllRes) ProtoMessage() {}
func (x *FindAllRes) ProtoReflect() protoreflect.Message {
mi := &file_proto_filter_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use FindAllRes.ProtoReflect.Descriptor instead.
func (*FindAllRes) Descriptor() ([]byte, []int) {
return file_proto_filter_proto_rawDescGZIP(), []int{2}
}
func (x *FindAllRes) GetKeywords() []string {
if x != nil {
return x.Keywords
}
return nil
}
var File_proto_filter_proto protoreflect.FileDescriptor
var file_proto_filter_proto_rawDesc = []byte{
0x0a, 0x12, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1a, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x5f, 0x66,
0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x7a, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x2e, 0x63, 0x6f, 0x6d,
0x22, 0x1f, 0x0a, 0x09, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x12, 0x12, 0x0a,
0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78,
0x74, 0x22, 0x37, 0x0a, 0x0b, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73,
0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x02, 0x6f, 0x6b,
0x12, 0x18, 0x0a, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x28, 0x0a, 0x0a, 0x46, 0x69,
0x6e, 0x64, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x77,
0x6f, 0x72, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x77,
0x6f, 0x72, 0x64, 0x73, 0x32, 0xbe, 0x01, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12,
0x5a, 0x0a, 0x08, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x12, 0x25, 0x2e, 0x6b, 0x65,
0x79, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x7a, 0x76,
0x6f, 0x69, 0x63, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52,
0x65, 0x71, 0x1a, 0x27, 0x2e, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x5f, 0x66, 0x69,
0x6c, 0x74, 0x65, 0x72, 0x2e, 0x7a, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2e,
0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x12, 0x58, 0x0a, 0x07, 0x46,
0x69, 0x6e, 0x64, 0x41, 0x6c, 0x6c, 0x12, 0x25, 0x2e, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64,
0x73, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x7a, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x2e,
0x63, 0x6f, 0x6d, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x26, 0x2e,
0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e,
0x7a, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x41,
0x6c, 0x6c, 0x52, 0x65, 0x73, 0x42, 0x17, 0x5a, 0x15, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64,
0x73, 0x2d, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_proto_filter_proto_rawDescOnce sync.Once
file_proto_filter_proto_rawDescData = file_proto_filter_proto_rawDesc
)
func file_proto_filter_proto_rawDescGZIP() []byte {
file_proto_filter_proto_rawDescOnce.Do(func() {
file_proto_filter_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_filter_proto_rawDescData)
})
return file_proto_filter_proto_rawDescData
}
var file_proto_filter_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
var file_proto_filter_proto_goTypes = []interface{}{
(*FilterReq)(nil), // 0: keywords_filter.zvoice.com.FilterReq
(*ValidateRes)(nil), // 1: keywords_filter.zvoice.com.ValidateRes
(*FindAllRes)(nil), // 2: keywords_filter.zvoice.com.FindAllRes
}
var file_proto_filter_proto_depIdxs = []int32{
0, // 0: keywords_filter.zvoice.com.Filter.Validate:input_type -> keywords_filter.zvoice.com.FilterReq
0, // 1: keywords_filter.zvoice.com.Filter.FindAll:input_type -> keywords_filter.zvoice.com.FilterReq
1, // 2: keywords_filter.zvoice.com.Filter.Validate:output_type -> keywords_filter.zvoice.com.ValidateRes
2, // 3: keywords_filter.zvoice.com.Filter.FindAll:output_type -> keywords_filter.zvoice.com.FindAllRes
2, // [2:4] is the sub-list for method output_type
0, // [0:2] 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
}
func init() { file_proto_filter_proto_init() }
func file_proto_filter_proto_init() {
if File_proto_filter_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_proto_filter_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*FilterReq); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_proto_filter_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ValidateRes); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_proto_filter_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*FindAllRes); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_proto_filter_proto_rawDesc,
NumEnums: 0,
NumMessages: 3,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_proto_filter_proto_goTypes,
DependencyIndexes: file_proto_filter_proto_depIdxs,
MessageInfos: file_proto_filter_proto_msgTypes,
}.Build()
File_proto_filter_proto = out.File
file_proto_filter_proto_rawDesc = nil
file_proto_filter_proto_goTypes = nil
file_proto_filter_proto_depIdxs = nil
}

View File

@@ -0,0 +1,20 @@
syntax = "proto3";
option go_package = "keywords-filter/proto";
package keywords_filter.zvoice.com;
message FilterReq {
string text = 1;
}
message ValidateRes {
bool ok = 1;
string keyword = 2;
}
message FindAllRes {
repeated string keywords = 1;
}
service Filter {
rpc Validate(FilterReq) returns (ValidateRes);
rpc FindAll(FilterReq) returns (FindAllRes);
}

View File

@@ -0,0 +1,141 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.2.0
// - protoc v4.22.0
// source: proto/filter.proto
package proto
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.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// FilterClient is the client API for Filter 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 FilterClient interface {
Validate(ctx context.Context, in *FilterReq, opts ...grpc.CallOption) (*ValidateRes, error)
FindAll(ctx context.Context, in *FilterReq, opts ...grpc.CallOption) (*FindAllRes, error)
}
type filterClient struct {
cc grpc.ClientConnInterface
}
func NewFilterClient(cc grpc.ClientConnInterface) FilterClient {
return &filterClient{cc}
}
func (c *filterClient) Validate(ctx context.Context, in *FilterReq, opts ...grpc.CallOption) (*ValidateRes, error) {
out := new(ValidateRes)
err := c.cc.Invoke(ctx, "/keywords_filter.zvoice.com.Filter/Validate", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *filterClient) FindAll(ctx context.Context, in *FilterReq, opts ...grpc.CallOption) (*FindAllRes, error) {
out := new(FindAllRes)
err := c.cc.Invoke(ctx, "/keywords_filter.zvoice.com.Filter/FindAll", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// FilterServer is the server API for Filter service.
// All implementations must embed UnimplementedFilterServer
// for forward compatibility
type FilterServer interface {
Validate(context.Context, *FilterReq) (*ValidateRes, error)
FindAll(context.Context, *FilterReq) (*FindAllRes, error)
mustEmbedUnimplementedFilterServer()
}
// UnimplementedFilterServer must be embedded to have forward compatible implementations.
type UnimplementedFilterServer struct {
}
func (UnimplementedFilterServer) Validate(context.Context, *FilterReq) (*ValidateRes, error) {
return nil, status.Errorf(codes.Unimplemented, "method Validate not implemented")
}
func (UnimplementedFilterServer) FindAll(context.Context, *FilterReq) (*FindAllRes, error) {
return nil, status.Errorf(codes.Unimplemented, "method FindAll not implemented")
}
func (UnimplementedFilterServer) mustEmbedUnimplementedFilterServer() {}
// UnsafeFilterServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to FilterServer will
// result in compilation errors.
type UnsafeFilterServer interface {
mustEmbedUnimplementedFilterServer()
}
func RegisterFilterServer(s grpc.ServiceRegistrar, srv FilterServer) {
s.RegisterService(&Filter_ServiceDesc, srv)
}
func _Filter_Validate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(FilterReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(FilterServer).Validate(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/keywords_filter.zvoice.com.Filter/Validate",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(FilterServer).Validate(ctx, req.(*FilterReq))
}
return interceptor(ctx, in, info, handler)
}
func _Filter_FindAll_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(FilterReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(FilterServer).FindAll(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/keywords_filter.zvoice.com.Filter/FindAll",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(FilterServer).FindAll(ctx, req.(*FilterReq))
}
return interceptor(ctx, in, info, handler)
}
// Filter_ServiceDesc is the grpc.ServiceDesc for Filter service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var Filter_ServiceDesc = grpc.ServiceDesc{
ServiceName: "keywords_filter.zvoice.com.Filter",
HandlerType: (*FilterServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Validate",
Handler: _Filter_Validate_Handler,
},
{
MethodName: "FindAll",
Handler: _Filter_FindAll_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "proto/filter.proto",
}