Create & Init Project...

This commit is contained in:
2019-04-22 18:49:16 +08:00
commit fc4fa37393
25440 changed files with 4054998 additions and 0 deletions

View File

@ -0,0 +1,23 @@
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/service/live/live-dm/api/grpc:all-srcs",
"//app/service/live/live-dm/cmd:all-srcs",
"//app/service/live/live-dm/conf:all-srcs",
"//app/service/live/live-dm/dao:all-srcs",
"//app/service/live/live-dm/model:all-srcs",
"//app/service/live/live-dm/server/grpc:all-srcs",
"//app/service/live/live-dm/server/http:all-srcs",
"//app/service/live/live-dm/service:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,34 @@
# v1.0.0
1. 上线功能xxx
# v1.1.3
1. 添加保护
2. 接入礼物弹幕
#v1.1.4
1. databus 投递使用缓存队列
2. 房管接口由liverpc迁移至grpc
#v1.1.5
1. 短位号引起判断异常
#v1.1.6
1. 弹幕后台配置迁移
2. 去除弹幕广播http调用
#v1.1.7
1. 弹幕统计透传弹幕类型
#v1.1.8
1. 弹幕字 体大小限制
2. \ \n / 非法字符限制
#v1.1.10
1. 换行符号匹配
#v1.1.11
1. databus 投递消息类型
#1.1.12
1.2019拜年祭白名单
2.弹幕配置迁移

View File

@ -0,0 +1,6 @@
# Owner
yangbaibing
# Author
# Reviewer

View File

@ -0,0 +1,10 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- yangbaibing
labels:
- live
- service
- service/live/live-dm
options:
no_parent_owners: true

View File

@ -0,0 +1,12 @@
# live-dm-service
# 项目简介
1.
# 编译环境
# 依赖包
# 编译执行

View File

@ -0,0 +1,23 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/service/live/live-dm/api/grpc/v1:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,62 @@
load(
"@io_bazel_rules_go//proto:def.bzl",
"go_proto_library",
)
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
proto_library(
name = "v1_proto",
srcs = ["api.proto"],
tags = ["automanaged"],
deps = ["@gogo_special_proto//github.com/gogo/protobuf/gogoproto"],
)
go_proto_library(
name = "v1_go_proto",
compilers = ["@io_bazel_rules_go//proto:gogofast_grpc"],
importpath = "go-common/app/service/live/live-dm/api/grpc/v1",
proto = ":v1_proto",
tags = ["automanaged"],
deps = ["@com_github_gogo_protobuf//gogoproto:go_default_library"],
)
go_library(
name = "go_default_library",
srcs = [
"api.bm.go",
"client.go",
],
embed = [":v1_go_proto"],
importpath = "go-common/app/service/live/live-dm/api/grpc/v1",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/net/http/blademaster:go_default_library",
"//library/net/http/blademaster/binding:go_default_library",
"//library/net/rpc/warden:go_default_library",
"@com_github_gogo_protobuf//gogoproto:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
"@org_golang_google_grpc//:go_default_library",
"@org_golang_x_net//context:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,67 @@
// Code generated by protoc-gen-bm v0.1, DO NOT EDIT.
// source: api/grpc/v1/api.proto
/*
Package v1 is a generated blademaster stub package.
This code was generated with go-common/app/tool/bmgen/protoc-gen-bm v0.1.
It is generated from these files:
api/grpc/v1/api.proto
*/
package v1
import (
"context"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/binding"
)
// to suppressed 'imported but not used warning'
var _ *bm.Context
var _ context.Context
var _ binding.StructValidator
// ============
// DM Interface
// ============
type DM interface {
SendMsg(ctx context.Context, req *SendMsgReq) (resp *SendMsgResp, err error)
GetHistory(ctx context.Context, req *HistoryReq) (resp *HistoryResp, err error)
}
var v1DMSvc DM
// @params SendMsgReq
// @router GET /xlive/live-dm/v1/dM/SendMsg
// @response SendMsgResp
func dMSendMsg(c *bm.Context) {
p := new(SendMsgReq)
if err := c.BindWith(p, binding.Default(c.Request.Method, c.Request.Header.Get("Content-Type"))); err != nil {
return
}
resp, err := v1DMSvc.SendMsg(c, p)
c.JSON(resp, err)
}
// @params HistoryReq
// @router GET /xlive/live-dm/v1/dM/GetHistory
// @response HistoryResp
func dMGetHistory(c *bm.Context) {
p := new(HistoryReq)
if err := c.BindWith(p, binding.Default(c.Request.Method, c.Request.Header.Get("Content-Type"))); err != nil {
return
}
resp, err := v1DMSvc.GetHistory(c, p)
c.JSON(resp, err)
}
// RegisterV1DMService Register the blademaster route with middleware map
// midMap is the middleware map, the key is defined in proto
func RegisterV1DMService(e *bm.Engine, svc DM, midMap map[string]bm.HandlerFunc) {
v1DMSvc = svc
e.GET("/xlive/live-dm/v1/dM/SendMsg", dMSendMsg)
e.GET("/xlive/live-dm/v1/dM/GetHistory", dMGetHistory)
}

View File

@ -0,0 +1,65 @@
##
`GET http://api.live.bilibili.com/xlive/live-dm/v1/dM/SendMsg`
### 请求参数
```json
{
"uid": 0,
"roomid": 0,
"msg": "",
"rnd": "",
"ip": "",
"fontsize": 0,
"mode": 0,
"platform": "",
"msgtype": 0,
"bubble": 0,
"lancer": {
"buvid": "",
"userAgent": "",
"refer": "",
"cookie": "",
"build": 0
}
}
```
```json
{
"code": 0,
"message": "ok",
"data": {
"islimit": true,
"limitmsg": "",
"code": 0
}
}
```
##
`GET http://api.live.bilibili.com/xlive/live-dm/v1/dM/GetHistory`
### 请求参数
|参数名|必选|类型|描述|
|:---|:---|:---|:---|
|roomid|是|integer||
```json
{
"code": 0,
"message": "ok",
"data": {
"room": [
""
],
"admin": [
""
]
}
}
```

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,52 @@
syntax = "proto3";
package live.livedm.v1;
option go_package = "v1";
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
message SendMsgReq {
int64 uid = 1 [(gogoproto.moretags) = 'form:"uid" validate:"required"'];
int64 roomid = 2 [(gogoproto.moretags) = 'form:"roomid" validate:"required"'];
string msg = 3 [(gogoproto.moretags) = 'form:"msg" validate:"required"'];
string rnd = 4 [(gogoproto.moretags) = 'form:"rnd"'];
string ip = 5 [(gogoproto.moretags) = 'form:"ip"'];
int64 fontsize = 7 [(gogoproto.moretags) = 'form:"fontsize" validate:"gte=0"'];
int64 mode = 8 [(gogoproto.moretags) = 'form:"mode" validate:"gte=0"'];
string platform = 9 [(gogoproto.moretags) = 'form:"platform"'];
int64 msgtype = 10 [(gogoproto.moretags) = 'form:"msgtype" validate:"gte=0"'];
int64 bubble = 11 [(gogoproto.moretags) = 'form:"bubble"'];
lancer lancer = 12 [(gogoproto.moretags) = 'form:"lancer"'];
}
message lancer {
string buvid = 1 [(gogoproto.moretags) = 'form:"buvid"'];
string userAgent = 2 [(gogoproto.moretags) = 'form:"userAgent"'];
string refer = 3 [(gogoproto.moretags) = 'form:"refer"'];
string cookie = 4 [(gogoproto.moretags) = 'form:"cookie"'];
int64 build = 5 [(gogoproto.moretags) = 'form:"build"'];
}
message SendMsgResp {
bool isLimit = 1 [(gogoproto.jsontag) = "islimit"];
string limitMsg = 2 [(gogoproto.jsontag) = "limitmsg"];
int32 code = 3 [(gogoproto.jsontag) = "code"];
}
message HistoryReq {
int64 roomid = 1 [(gogoproto.moretags) = 'form:"roomid" validate:"required"'];
}
message HistoryResp{
repeated string room = 1 [(gogoproto.jsontag) = "room"];
repeated string admin = 2 [(gogoproto.jsontag) = "admin"];
}
message ErrMsg {
string message =1;
}
service DM {
rpc SendMsg(SendMsgReq) returns (SendMsgResp);
rpc GetHistory(HistoryReq) returns (HistoryResp);
}

View File

@ -0,0 +1,23 @@
package v1
import (
"context"
"go-common/library/net/rpc/warden"
"google.golang.org/grpc"
)
//AppID 弹幕服务discoverID
const AppID = "live.livedm"
//NewClient 弹幕服务client创建
func NewClient(cfg *warden.ClientConfig, opts ...grpc.DialOption) (DMClient, error) {
client := warden.NewClient(cfg, opts...)
conn, err := client.Dial(context.Background(), "discovery://default/"+AppID)
if err != nil {
return nil, err
}
return NewDMClient(conn), nil
}

View File

@ -0,0 +1 @@
# HTTP API文档

View File

@ -0,0 +1,27 @@
##
`GET http://api.live.bilibili.com/xlive/dm/v1/dM/SendMsg`
### 请求参数
|参数名|必选|类型|描述|
|:---|:---|:---|:---|
|uid|否|integer||
|roomid|否|integer||
|msg|否|string||
|rnd|否|integer||
|ip|否|string||
|fontsize|否|integer||
|mode|否|integer||
|platform|否|string||
|msgtype|否|integer||
```json
{
"code": 0,
"message": "ok",
"data": {
}
}
```

View File

@ -0,0 +1,45 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
)
go_binary(
name = "cmd",
embed = [":go_default_library"],
tags = ["automanaged"],
)
go_library(
name = "go_default_library",
srcs = ["main.go"],
data = ["test.toml"],
importpath = "go-common/app/service/live/live-dm/cmd",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/live/live-dm/conf:go_default_library",
"//app/service/live/live-dm/server/grpc:go_default_library",
"//app/service/live/live-dm/server/http:go_default_library",
"//app/service/live/live-dm/service:go_default_library",
"//library/ecode/tip:go_default_library",
"//library/log:go_default_library",
"//library/net/trace:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,49 @@
package main
import (
"flag"
"os"
"os/signal"
"syscall"
"time"
"go-common/app/service/live/live-dm/conf"
"go-common/app/service/live/live-dm/server/grpc"
"go-common/app/service/live/live-dm/server/http"
"go-common/app/service/live/live-dm/service"
ecode "go-common/library/ecode/tip"
"go-common/library/log"
"go-common/library/net/trace"
)
func main() {
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
log.Init(conf.Conf.Log)
defer log.Close()
log.Info("dm-service start")
trace.Init(conf.Conf.Tracer)
defer trace.Close()
ecode.Init(conf.Conf.Ecode)
svc := service.New(conf.Conf)
grpc.Init(conf.Conf)
http.Init(conf.Conf)
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
s := <-c
log.Info("get a signal %s", s.String())
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
svc.Close()
log.Info("dm-service exit")
time.Sleep(time.Second)
return
case syscall.SIGHUP:
default:
return
}
}
}

View File

@ -0,0 +1,118 @@
[HTTPClient]
key = "e7482d29be4a95b8"
secret = "9e803791cdef756e75faee68e12b7442"
dial = "100ms"
timeout = "5s"
keepAlive = "60s"
[HTTPClient.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[Redis]
name = "dm-service"
proto = "tcp"
addr = "172.18.33.171:6379"
idle = 10
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "1m"
[WhiteListRedis]
name = "dm-service"
proto = "tcp"
addr = "172.16.38.166:10028"
idle = 10
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "1m"
[BNJRoomList]
544641 = true
2233 = true
[BNDatabus]
key = "ec4c0820d525d67b"
secret = "e20f8f664bf10722efeb6aac0cc16011"
group = "LiveDanmuSend-LiveLive-P"
topic = "LiveDanmuSend-T"
action = "pub"
buffer = 128
name = "live-dm/databus"
proto = "tcp"
addr = "172.16.33.50:6205"
active = 1
idle = 1
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
[CacheDatabus]
Size = 1024
[LiveRPC.bannedService]
AppID = "live.bannedservice"
ConnTimeout = "50ms"
[LiveRPC.room]
AppID = "live.room"
ConnTimeout = "50ms"
[LiveRPC.liveUser]
AppID = "live.liveuser"
ConnTimeout = "50ms"
[LiveRPC.activity]
AppID = "live.activity"
ConnTimeout = "50ms"
[LiveRPC.avService]
AppID = "live.av"
ConnTimeout = "50ms"
[LiveRPC.fansMedal]
AppID = "live.fansmedal"
ConnTimeout = "50ms"
[LiveRPC.rc]
AppID = "live.rc"
ConnTimeout = "50ms"
[LiveRPC.rankdbService]
AppID = "live.rankdb"
ConnTimeout = "50ms"
[LiveRPC.userext]
AppID = "live.userext"
ConnTimeout = "50ms"
[LiveRPC.user]
AppID = "live.user"
ConnTimeout = "50ms"
[DmRules]
AreaLimit = false
RealName = false
PhoneLimit = true
AllUserLimit = false
LevelLimitStatus = false
LevelLimit = -1
MsgLength = 20
DmNum = 20
DMPercent = 25
[DmRules.Nixiang]
[DmRules.Color]
[Lancer.DMsend]
taskID = "000582"
proto = "tcp"
addr = "172.18.33.124:15140"
chanSize = 10240
[Lancer.DMErr]
taskID = "001409"
proto = "tcp"
addr = "172.18.33.124:15140"
chanSize = 10240

View File

@ -0,0 +1,44 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["conf.go"],
importpath = "go-common/app/service/live/live-dm/conf",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/cache/memcache:go_default_library",
"//library/cache/redis:go_default_library",
"//library/conf:go_default_library",
"//library/database/sql:go_default_library",
"//library/ecode/tip:go_default_library",
"//library/log:go_default_library",
"//library/log/infoc:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/http/blademaster/middleware/verify:go_default_library",
"//library/net/rpc/liverpc:go_default_library",
"//library/net/rpc/warden:go_default_library",
"//library/net/trace:go_default_library",
"//library/queue/databus:go_default_library",
"//vendor/github.com/BurntSushi/toml:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,133 @@
package conf
import (
"errors"
"flag"
"go-common/library/cache/memcache"
"go-common/library/cache/redis"
"go-common/library/conf"
"go-common/library/database/sql"
ecode "go-common/library/ecode/tip"
"go-common/library/log"
"go-common/library/log/infoc"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/verify"
"go-common/library/net/rpc/liverpc"
"go-common/library/net/rpc/warden"
"go-common/library/net/trace"
"go-common/library/queue/databus"
"github.com/BurntSushi/toml"
)
var (
confPath string
client *conf.Client
// Conf config
Conf = &Config{}
)
// Config .
type Config struct {
Log *log.Config
BM *bm.ServerConfig
Verify *verify.Config
Tracer *trace.Config
Redis *redis.Config
WhiteListRedis *redis.Config
Memcache *memcache.Config
MySQL *sql.Config
Ecode *ecode.Config
DmRules *dmRules
FilterClient *warden.ClientConfig
AccClient *warden.ClientConfig
XuserClent *warden.ClientConfig
LocationClient *warden.ClientConfig
SpyClient *warden.ClientConfig
BcastClient *warden.ClientConfig
UExpClient *warden.ClientConfig
IsAdminClient *warden.ClientConfig
HTTPClient *bm.ClientConfig
LiveRPC map[string]*liverpc.ClientConfig
BNDatabus *databus.Config
Lancer *lancer
CacheDatabus *cache
BNJRoomList map[string]bool
}
type cache struct {
Size int
}
type lancer struct {
DMErr *infoc.Config
DMSend *infoc.Config
}
type dmRules struct {
AllUserLimit bool
AreaLimit bool
LevelLimitStatus bool
LevelLimit int64
PhoneLimit bool
RealName bool
MsgLength int
DmNum int64
DmPercent int64
Nixiang map[string]bool
Color map[string]int64
DMwhitelist bool
DMwhiteListID string
}
func init() {
flag.StringVar(&confPath, "conf", "", "default config path")
}
// Init init conf
func Init() error {
if confPath != "" {
return local()
}
return remote()
}
func local() (err error) {
_, err = toml.DecodeFile(confPath, &Conf)
return
}
func remote() (err error) {
if client, err = conf.New(); err != nil {
return
}
if err = load(); err != nil {
return
}
go func() {
for range client.Event() {
log.Info("config reload")
if load() != nil {
log.Error("config reload error (%v)", err)
}
}
}()
return
}
func load() (err error) {
var (
s string
ok bool
tmpConf *Config
)
if s, ok = client.Toml2(); !ok {
return errors.New("load config center error")
}
if _, err = toml.Decode(s, &tmpConf); err != nil {
return errors.New("could not decode config")
}
*Conf = *tmpConf
return
}

View File

@ -0,0 +1,110 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"dao.go",
"data.go",
"getCheckInfo.go",
"getDMConf.go",
"gethistory.go",
"grpc.go",
"ipdb.go",
"liveRPC.go",
"ratelimit.go",
"send.go",
"white_list.go",
],
importpath = "go-common/app/service/live/live-dm/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/live/activity/api/liverpc:go_default_library",
"//app/service/live/activity/api/liverpc/v1:go_default_library",
"//app/service/live/av/api/liverpc:go_default_library",
"//app/service/live/banned_service/api/liverpc:go_default_library",
"//app/service/live/broadcast-proxy/api/v1:go_default_library",
"//app/service/live/fans_medal/api/liverpc:go_default_library",
"//app/service/live/fans_medal/api/liverpc/v2:go_default_library",
"//app/service/live/live-dm/conf:go_default_library",
"//app/service/live/live-dm/model:go_default_library",
"//app/service/live/live_user/api/liverpc:go_default_library",
"//app/service/live/live_user/api/liverpc/v1:go_default_library",
"//app/service/live/rankdb/api/liverpc:go_default_library",
"//app/service/live/rankdb/api/liverpc/v1:go_default_library",
"//app/service/live/rc/api/liverpc:go_default_library",
"//app/service/live/rc/api/liverpc/v1:go_default_library",
"//app/service/live/resource/sdk:go_default_library",
"//app/service/live/room/api/liverpc:go_default_library",
"//app/service/live/room/api/liverpc/v1:go_default_library",
"//app/service/live/room/api/liverpc/v2:go_default_library",
"//app/service/live/third_api/liveBroadcast:go_default_library",
"//app/service/live/user/api/liverpc:go_default_library",
"//app/service/live/user/api/liverpc/v3:go_default_library",
"//app/service/live/userext/api/liverpc:go_default_library",
"//app/service/live/userext/api/liverpc/v1:go_default_library",
"//app/service/live/xuser/api/grpc/v1:go_default_library",
"//app/service/main/account/api:go_default_library",
"//app/service/main/filter/api/grpc/v1:go_default_library",
"//app/service/main/location/api:go_default_library",
"//app/service/main/spy/api:go_default_library",
"//library/cache/redis:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/log/infoc:go_default_library",
"//library/net/rpc/liverpc:go_default_library",
"//library/net/rpc/warden:go_default_library",
"//library/queue/databus:go_default_library",
"//library/sync/pipeline/fanout:go_default_library",
"//vendor/github.com/ipipdotnet/ipdb-go:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
"@org_golang_google_grpc//:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_test(
name = "go_default_test",
srcs = [
"getCheckInfo_test.go",
"getDMConf_test.go",
"ratelimit_test.go",
"send_test.go",
"white_list_test.go",
],
embed = [":go_default_library"],
tags = ["automanaged"],
deps = [
"//app/service/live/activity/api/liverpc:go_default_library",
"//app/service/live/fans_medal/api/liverpc:go_default_library",
"//app/service/live/live-dm/conf:go_default_library",
"//app/service/live/live_user/api/liverpc:go_default_library",
"//app/service/live/rankdb/api/liverpc:go_default_library",
"//app/service/live/rc/api/liverpc:go_default_library",
"//app/service/live/room/api/liverpc:go_default_library",
"//app/service/live/userext/api/liverpc:go_default_library",
"//app/service/main/account/api:go_default_library",
"//app/service/main/filter/api/grpc/v1:go_default_library",
"//app/service/main/spy/api:go_default_library",
"//library/net/metadata:go_default_library",
],
)

View File

@ -0,0 +1,41 @@
package dao
import (
"context"
"go-common/app/service/live/live-dm/conf"
"go-common/library/cache/redis"
"go-common/library/sync/pipeline/fanout"
)
// Dao dao
type Dao struct {
c *conf.Config
redis *redis.Pool
whitelistredis *redis.Pool
Databus *fanout.Fanout
}
// New init mysql db
func New(c *conf.Config) (dao *Dao) {
dao = &Dao{
c: c,
redis: redis.NewPool(c.Redis),
whitelistredis: redis.NewPool(c.WhiteListRedis),
Databus: fanout.New("dmDatabus", fanout.Worker(1), fanout.Buffer(c.CacheDatabus.Size)),
}
return
}
// Close close the resource.
func (d *Dao) Close() {
d.redis.Close()
d.Databus.Close()
d.whitelistredis.Close()
}
// Ping dao ping
func (d *Dao) Ping(c context.Context) error {
// TODO: redis
return nil
}

View File

@ -0,0 +1,84 @@
package dao
import (
"encoding/json"
"go-common/app/service/live/live-dm/conf"
titansSdk "go-common/app/service/live/resource/sdk"
"go-common/library/log"
"go-common/library/log/infoc"
"go-common/library/queue/databus"
)
var (
//拜年祭投递databus
bndatabus *databus.Databus
//InfocDMSend 弹幕发送成功上报
InfocDMSend *infoc.Infoc
//InfocDMErr 弹幕发送失败上报
InfocDMErr *infoc.Infoc
)
//InitDatabus 初始化databus
func InitDatabus(c *conf.Config) {
bndatabus = databus.New(c.BNDatabus)
}
//InitLancer 初始化lancer上报
func InitLancer(c *conf.Config) {
InfocDMErr = infoc.New(c.Lancer.DMErr)
InfocDMSend = infoc.New(c.Lancer.DMSend)
}
//InitTitan 初始化kv配置
func InitTitan() {
conf := &titansSdk.Config{
TreeId: 72389,
Expire: 1,
}
titansSdk.Init(conf)
}
//LimitConf 弹幕限制配置
type LimitConf struct {
AreaLimit bool `json:"areaLimit"`
AllUserLimit bool `json:"AllUserLimit"`
LevelLimitStatus bool `json:"LevelLimitStatus"`
LevelLimit int64 `json:"LevelLimit"`
RealName bool `json:"RealName"`
PhoneLimit bool `json:"PhoneLimit"`
MsgLength int `json:"MsgLength"`
DmNum int64 `json:"DmNum"`
DMPercent int64 `json:"DMPercent"`
DMwhitelist bool `json:"DMwhitelist"`
DMwhitelistID string `json:"DMwhitelistID"`
}
//GetDMCheckConf 获取弹幕配置参数
func (l *LimitConf) GetDMCheckConf() {
cf, err := titansSdk.Get("dmLimit")
if err != nil {
log.Error("DM: get conf err:%+v", err)
return
}
conf := &LimitConf{}
err = json.Unmarshal([]byte(cf), conf)
if err != nil {
log.Error("DM: decode conf jsons err:%+v conf:%s", err, cf)
return
}
l.AreaLimit = conf.AreaLimit
l.AllUserLimit = conf.AllUserLimit
l.LevelLimitStatus = conf.LevelLimitStatus
l.LevelLimit = conf.LevelLimit
l.RealName = conf.RealName
l.PhoneLimit = conf.PhoneLimit
l.DmNum = conf.DmNum
l.DMwhitelist = conf.DMwhitelist
l.DMPercent = conf.DMPercent
l.MsgLength = conf.MsgLength
l.DMwhitelistID = conf.DMwhitelistID
}

View File

@ -0,0 +1,391 @@
package dao
import (
"context"
"strconv"
"sync"
fansMedalService "go-common/app/service/live/fans_medal/api/liverpc/v2"
"go-common/app/service/live/live-dm/conf"
liveUserService "go-common/app/service/live/live_user/api/liverpc/v1"
roomService "go-common/app/service/live/room/api/liverpc/v2"
userService "go-common/app/service/live/user/api/liverpc/v3"
userextService "go-common/app/service/live/userext/api/liverpc/v1"
xuserService "go-common/app/service/live/xuser/api/grpc/v1"
acctountService "go-common/app/service/main/account/api"
filterService "go-common/app/service/main/filter/api/grpc/v1"
spyService "go-common/app/service/main/spy/api"
"go-common/library/log"
"github.com/pkg/errors"
)
//UserInfo 用户等级,经验等信息
type UserInfo struct {
Vip int
Svip int
UserLever int64
UserScore int64
ULevelRank int64
ULevelColor int64
UnameColor string
RoomAdmin bool
PrivilegeType int
Bubble int64
MedalInfo *FansMedalInfo
lock sync.Mutex
}
//UserScore 用户真实分已经弹幕ai分
type UserScore struct {
UserScore int64
MsgAI int64
MsgLevel int64
lock sync.Mutex
}
//DMConf 弹幕配置
type DMConf struct {
Mode int64
Color int64
Length int64
}
//FansMedalInfo 粉丝勋章信息
type FansMedalInfo struct {
MedalID int64
RUID int64
RUName string
MedalLevel int64
MedalName string
AnchorName string
RoomID int64
MColor int64
SpecialMedal string
lock sync.Mutex
}
//RoomConf 播主房间配置信息
type RoomConf struct {
UID int64
RoomShield int64
RoomID int64
Anchor string
}
//UserBindInfo 用户手机,实名等信息
type UserBindInfo struct {
Identification int32
MobileVerify int32
Uname string
URank int32
// MobileVirtual int64 无虚拟号段信息
}
//Get 获取用户的弹幕配置信息
func (d *DMConf) Get(ctx context.Context, uid int64, roomid int64, c *conf.Config) error {
req := &userextService.DanmuConfGetAllReq{
Uid: uid,
Roomid: roomid,
}
resp, err := UserExtServiceClient.V1DanmuConf.GetAll(ctx, req)
if err != nil {
if errors.Cause(err) != context.Canceled {
log.Error("DM: userextService GetAll err: %v", err)
}
d.Color = 16777215
d.Mode = 1
d.Length = 20
return nil
}
if resp.Code != 0 {
log.Error("DM: userextService GetAll err code: %d", resp.Code)
d.Color = 16777215
d.Mode = 1
d.Length = 20
return nil
}
d.Color = resp.Data.Color
d.Mode = resp.Data.Mode
d.Length = resp.Data.Length
su := strconv.FormatInt(uid, 10)
if c.DmRules.Nixiang[su] {
d.Mode = 6
}
if c.DmRules.Color[su] != 0 {
d.Color = c.DmRules.Color[su]
}
return nil
}
// Get 获取用户等级,经验等信息
func (u *UserInfo) Get(ctx context.Context, uid int64) error {
req := &userService.UserGetUserLevelInfoReq{
Uid: uid,
}
resp, err := userClient.V3User.GetUserLevelInfo(ctx, req)
if err != nil {
if errors.Cause(err) != context.Canceled {
log.Error("DM: user err: %v", err)
}
u.lock.Lock()
u.UserLever = 0
u.UserScore = 0
u.ULevelColor = 16752445
u.lock.Unlock()
return nil
}
if resp.Code != 0 {
log.Error("DM: user GetUserLevelInfo err code: %d", resp.Code)
u.lock.Lock()
u.UserLever = 0
u.UserScore = 0
u.ULevelColor = 16752445
u.lock.Unlock()
return nil
}
u.lock.Lock()
u.UserLever = resp.Data.Level
u.UserScore = resp.Data.Exp
u.ULevelColor = resp.Data.Color
u.lock.Unlock()
return nil
}
//GetVipInfo 获取用户的老爷等级
func (u *UserInfo) GetVipInfo(ctx context.Context, uid int64) error {
req := &xuserService.UidReq{
Uid: uid,
}
resp, err := vipCli.Info(ctx, req)
if err != nil {
if errors.Cause(err) != context.Canceled {
log.Error("DM: xuserService get vip Info err: %v", err)
}
u.lock.Lock()
u.Vip = 0
u.Svip = 0
u.lock.Unlock()
return nil
}
u.lock.Lock()
u.Vip = resp.Info.Vip
u.Svip = resp.Info.Svip
u.lock.Unlock()
return nil
}
//GetPrivilegeType 获取大航海信息
func (u *UserInfo) GetPrivilegeType(ctx context.Context, uid int64, ruid int64) error {
req := &liveUserService.GuardGetByUidTargetIdReq{
Uid: uid,
TargetId: ruid,
IsLimitOne: 0,
}
resp, err := LiveUserServiceClient.V1Guard.GetByUidTargetId(ctx, req)
if err != nil {
if errors.Cause(err) != context.Canceled {
log.Error("DM: liveUserService GetByUidTargetId err: %v", err)
}
u.lock.Lock()
u.PrivilegeType = 0
u.lock.Unlock()
return nil
}
if resp.Code != 0 {
log.Error("DM: liveUserService GetByUidTargetId err code: %d", resp.Code)
u.lock.Lock()
u.PrivilegeType = 0
u.lock.Unlock()
return nil
}
var PrivilegeType int64
for _, val := range resp.Data {
i := val.PrivilegeType
if PrivilegeType == 0 {
PrivilegeType = i
}
if PrivilegeType != 0 && PrivilegeType > i {
PrivilegeType = i
}
}
u.lock.Lock()
u.PrivilegeType = int(PrivilegeType)
u.lock.Unlock()
return nil
}
//IsRoomAdmin 判断用户是否是房管
func (u *UserInfo) IsRoomAdmin(ctx context.Context, uid int64, roomid int64) error {
defer u.lock.Unlock()
if roomid == 59125 || roomid == 5440 {
u.lock.Lock()
u.RoomAdmin = false
return nil
}
req := &xuserService.RoomAdminIsAdminShortReq{
Uid: uid,
Roomid: roomid,
}
resp, err := isAdmin.IsAdminShort(ctx, req)
if err != nil {
log.Error("DM: xuser IsAdminShort err: %+v", err)
u.lock.Lock()
u.RoomAdmin = false
return nil
}
if resp.Result == 1 {
u.lock.Lock()
u.RoomAdmin = true
return nil
}
u.lock.Lock()
u.RoomAdmin = false
return nil
}
//GetFansMedal 获取主播的粉丝勋章信息
func (f *FansMedalInfo) GetFansMedal(ctx context.Context, uid int64) error {
req := &fansMedalService.HighQpsLiveWearedReq{
Uid: uid,
}
resq, err := FansMedalServiceClient.V2HighQps.LiveWeared(ctx, req)
if err != nil {
if errors.Cause(err) != context.Canceled {
log.Error("DM: fansMedalService LiveWeared err: %v", err)
}
f.RUID = 0
f.MedalLevel = 1
f.MedalName = ""
f.MColor = 0
return nil
}
if resq.Code != 0 {
log.Error("DM: fansMedalService LiveWeared err code: %d", resq.Code)
f.RUID = 0
f.MedalLevel = 1
f.MedalName = ""
f.MColor = 0
return nil
}
f.RUID = resq.Data.TargetId
f.MedalLevel = resq.Data.Level
f.MedalName = resq.Data.MedalName
f.MColor = resq.Data.MedalColor
return nil
}
//Get 获取主播房间配置信息s
func (r *RoomConf) Get(ctx context.Context, roomID int64) error {
req := &roomService.RoomGetByIdsReq{
Ids: []int64{roomID},
}
resp, err := RoomServiceClient.V2Room.GetByIds(ctx, req)
if err != nil {
if errors.Cause(err) != context.Canceled {
log.Error("DM: roomService GetByIds err: %v", err)
}
r.RoomID = roomID
r.UID = 0
r.RoomShield = 0
r.Anchor = ""
return nil
}
if resp.Code != 0 {
log.Error("DM: roomService GetByIds err code: %d", resp.Code)
r.RoomID = roomID
r.UID = 0
r.RoomShield = 0
r.Anchor = ""
return nil
}
if _, ok := resp.Data[roomID]; !ok {
log.Error("DM: roomService GetByIds error roomid:%d", roomID)
r.RoomID = roomID
r.UID = 0
r.RoomShield = 0
r.Anchor = ""
return nil
}
r.RoomID = resp.Data[roomID].Roomid
r.UID = resp.Data[roomID].Uid
r.RoomShield = resp.Data[roomID].RoomShield
r.Anchor = resp.Data[roomID].Uname
return nil
}
//Get 获取用户绑定信息,实名认知,绑定手机等信息
func (u *UserBindInfo) Get(ctx context.Context, uid int64) error {
req := &acctountService.MidReq{
Mid: uid,
}
resp, err := ac.Profile3(ctx, req)
if err != nil {
log.Error("DM: acctountService Profile3 err: %v", err)
u.Identification = 0
u.MobileVerify = 0
u.Uname = ""
u.URank = 0
return nil
}
u.Identification = resp.Profile.Identification
u.MobileVerify = resp.Profile.TelStatus
u.Uname = resp.Profile.Name
u.URank = resp.Profile.Rank
return nil
}
//GetUserScore 用户真实分
func (u *UserScore) GetUserScore(ctx context.Context, uid int64) error {
req := &spyService.InfoReq{
Mid: uid,
}
resp, err := SpyClient.Info(ctx, req)
if err != nil {
log.Error("DM: 获取用户真实分错误 err: %v", err)
u.lock.Lock()
u.UserScore = 0
u.lock.Unlock()
return nil
}
u.lock.Lock()
u.UserScore = int64(resp.Ui.Score)
u.lock.Unlock()
return nil
}
//GetMsgScore 获取弹幕AI分
func (u *UserScore) GetMsgScore(ctx context.Context, msg string) error {
req := &filterService.FilterReq{
Area: "live_danmu",
Message: msg,
}
resp, err := FilterClient.Filter(ctx, req)
if err != nil {
log.Error("DM: main filter err: %v", err)
u.lock.Lock()
u.MsgLevel = 0
u.MsgAI = 0
u.lock.Unlock()
return nil
}
u.lock.Lock()
u.MsgLevel = int64(resp.Level)
if resp.Ai == nil {
log.Error("DM: main filter err: miss ai scores")
u.MsgAI = 0
u.lock.Unlock()
return nil
}
if len(resp.Ai.Scores) == 0 {
u.MsgAI = 0
u.lock.Unlock()
return nil
}
u.MsgAI = int64(resp.Ai.Scores[0] * 10)
u.lock.Unlock()
return nil
}

View File

@ -0,0 +1,162 @@
package dao
import (
"context"
"flag"
"fmt"
"path/filepath"
"testing"
fansMedalService "go-common/app/service/live/fans_medal/api/liverpc"
"go-common/app/service/live/live-dm/conf"
liveUserService "go-common/app/service/live/live_user/api/liverpc"
roomService "go-common/app/service/live/room/api/liverpc"
userextService "go-common/app/service/live/userext/api/liverpc"
acctountService "go-common/app/service/main/account/api"
filterService "go-common/app/service/main/filter/api/grpc/v1"
spyService "go-common/app/service/main/spy/api"
)
func init() {
dir, _ := filepath.Abs("../cmd/test.toml")
flag.Set("conf", dir)
var err error
if err = conf.Init(); err != nil {
panic(err)
}
// InitAPI()
// InitGrpc(conf.Conf)
UserExtServiceClient = userextService.New(getConf("userext"))
LiveUserServiceClient = liveUserService.New(getConf("liveUser"))
FansMedalServiceClient = fansMedalService.New(getConf("fansMedal"))
RoomServiceClient = roomService.New(getConf("room"))
ac, err = acctountService.NewClient(conf.Conf.AccClient)
if err != nil {
panic(err)
}
vipCli, err = newVipService(conf.Conf.XuserClent)
if err != nil {
panic(err)
}
SpyClient, err = spyService.NewClient(conf.Conf.SpyClient)
if err != nil {
panic(err)
}
FilterClient, err = filterService.NewClient(conf.Conf.FilterClient)
if err != nil {
panic(err)
}
}
//group=qa01 DEPLOY_ENV=uat go test -run TestDMConf_Get
func TestDMConf_Get(t *testing.T) {
dc := &DMConf{}
if err := dc.Get(context.TODO(), 111, 222, conf.Conf); err != nil {
t.Error("获取弹幕配置失败", err)
}
if dc.Color == 0 && dc.Length == 0 && dc.Mode == 0 {
t.Error("获取弹幕配置失败, 返回值错误")
}
fmt.Println("##### Mode: ", dc.Mode)
fmt.Println("##### Color: ", dc.Color)
fmt.Println("##### Length: ", dc.Length)
}
//TODO 未测试
//group=fat1 DEPLOY_ENV=uat go test -run TestUserInfo_Get
func TestUserInfo_Get(t *testing.T) {
u := &UserInfo{}
if err := u.Get(context.TODO(), 110000232); err != nil {
t.Error(err)
}
if u.UserLever == 0 && u.UserScore == 0 {
t.Error("返回值错误")
}
fmt.Println("#### UserLever: ", u.UserLever)
fmt.Println("#### UserScore: ", u.UserScore)
fmt.Println("### Usercolor: ", u.ULevelColor)
}
//DEPLOY_ENV=uat go test -run TestUserInfo_GetVipInfo
func TestUserInfo_GetVipInfo(t *testing.T) {
u := &UserInfo{}
if err := u.GetVipInfo(context.TODO(), 2); err != nil {
t.Error("获取老爷失败: ", err)
}
fmt.Println("#### VIP: ", u.Vip)
fmt.Println("### SVIP: ", u.Svip)
}
//group=qa01 DEPLOY_ENV=uat go test -run TestUserInfo_GetPrivilegeType
func TestUserInfo_GetPrivilegeType(t *testing.T) {
u := &UserInfo{}
if err := u.GetPrivilegeType(context.TODO(), 10799340, 6810576); err != nil {
t.Error("返回值错误: ", err)
}
fmt.Println("PrivilegeType", u.PrivilegeType)
}
//group=qa01 DEPLOY_ENV=uat go test -run TestUserInfo_IsRoomAdmin
func TestUserInfo_IsRoomAdmin(t *testing.T) {
u := &UserInfo{}
if err := u.IsRoomAdmin(context.TODO(), 1877309, 5392); err != nil {
t.Error("返回值错误: ", err)
}
fmt.Println("IsRoomAdmin->", u.RoomAdmin)
}
//group=qa01 DEPLOY_ENV=uat go test -run TestUserInfo_GetFansMedal
func TestUserInfo_GetFansMedal(t *testing.T) {
m := &FansMedalInfo{}
if err := m.GetFansMedal(context.TODO(), 83940); err != nil {
t.Error("获取粉丝勋章失败: ", err)
}
fmt.Println("#####RUID: ", m.RUID)
fmt.Println("#####MedalLevel: ", m.MedalLevel)
fmt.Println("#####MedalName: ", m.MedalName)
fmt.Println("#####MColor: ", m.MColor)
}
//group=qa01 DEPLOY_ENV=uat go test -run TestRoomConf_Get
func TestRoomConf_Get(t *testing.T) {
r := &RoomConf{}
if err := r.Get(context.TODO(), 1016); err != nil {
t.Error("获取房间配置失败: ", err)
}
fmt.Println("RoomID->", r.RoomID)
fmt.Println("UID->", r.UID)
fmt.Println("RoomShield->", r.RoomShield)
fmt.Println("Anchor->", r.Anchor)
}
//group=qa01 DEPLOY_ENV=uat go test -run TestUserBindInfo_Get
func TestUserBindInfo_Get(t *testing.T) {
u := &UserBindInfo{}
if err := u.Get(context.TODO(), 222); err != nil {
t.Error("获取用户绑定信息失败: ", err)
}
fmt.Println("Identification->", u.Identification)
fmt.Println("MobileVerify->", u.MobileVerify)
fmt.Println("Uname->", u.Uname)
fmt.Println("URank->", u.URank)
}
//DEPLOY_ENV=uat go test -run TestGerUserScore
func TestGerUserScore(t *testing.T) {
u := &UserScore{}
if err := u.GetUserScore(context.TODO(), 111); err != nil {
t.Error("获取用户真实分失败:", err)
}
fmt.Println("###### UserScore:", u.UserScore)
}
//缺少souce值
//DEPLOY_ENV=uat go test -run TestGetMsgScore
func TestGetMsgScore(t *testing.T) {
u := &UserScore{}
if err := u.GetMsgScore(context.TODO(), "fuck"); err != nil {
t.Error("获取真实分失败:", err)
}
fmt.Println("MsgLeve->", u.MsgLevel)
fmt.Println("MsgAI=>", u.MsgAI)
}

View File

@ -0,0 +1,234 @@
package dao
import (
"context"
activityService "go-common/app/service/live/activity/api/liverpc/v1"
rankdbService "go-common/app/service/live/rankdb/api/liverpc/v1"
rcService "go-common/app/service/live/rc/api/liverpc/v1"
roomService "go-common/app/service/live/room/api/liverpc/v2"
userextService "go-common/app/service/live/userext/api/liverpc/v1"
acctountService "go-common/app/service/main/account/api"
"go-common/library/log"
"github.com/pkg/errors"
)
//CommentTitle 头衔信息
type CommentTitle struct {
OldTitle string `json:"oldtitle"`
Title string `json:"title"`
}
//GetUnameColor 获取用户的昵称颜色
func (u *UserInfo) GetUnameColor(ctx context.Context, uid int64, rid int64) error {
req := &userextService.ColorGetUnameColorReq{
Uid: uid,
RoomId: rid,
}
resq, err := UserExtServiceClient.V1Color.GetUnameColor(ctx, req)
if err != nil {
if errors.Cause(err) != context.Canceled {
log.Error("DM: UserExt GetUnameColor err: %v", err)
}
u.lock.Lock()
u.UnameColor = ""
u.lock.Unlock()
return nil
}
if resq.Code != 0 {
log.Error("DM: UserExt GetUnameColor errror code: %d", resq.Code)
u.lock.Lock()
u.UnameColor = ""
u.lock.Unlock()
return nil
}
u.lock.Lock()
u.UnameColor = resq.Data.UnameColor
u.lock.Unlock()
return nil
}
//GetSpeicalMedal 获取特殊勋章
func (f *FansMedalInfo) GetSpeicalMedal(ctx context.Context, uid int64, rid int64) error {
//更新special
req := &activityService.UnionFansGetSpecialMedalReq{
Uid: uid,
Ruid: rid,
}
resq, err := ActivityServiceClient.V1UnionFans.GetSpecialMedal(ctx, req)
if err != nil {
if errors.Cause(err) != context.Canceled {
log.Error("DM: GetSpecialMedal err: %v", err)
}
f.lock.Lock()
f.SpecialMedal = ""
f.lock.Unlock()
return nil
}
if resq.Code != 0 {
log.Error("DM: GetSpecialMedal err code: %d", resq.Code)
f.lock.Lock()
f.SpecialMedal = ""
f.lock.Unlock()
return nil
}
f.lock.Lock()
f.SpecialMedal = resq.Data.SpecialMedal
f.lock.Unlock()
return nil
}
//GetUserLevelRank 获取用户等级RANK
func (u *UserInfo) GetUserLevelRank(ctx context.Context, uid int64) error {
defer u.lock.Unlock()
req := &rankdbService.UserRankGetUserRankReq{
Uid: uid,
Type: "user_level",
}
resq, err := RankdbServiceClient.V1UserRank.GetUserRank(ctx, req)
if err != nil {
if errors.Cause(err) != context.Canceled {
log.Error("DM: GetUserRank err: %v", err)
}
u.lock.Lock()
u.ULevelRank = 1000000
return nil
}
if resq.Code != 0 {
log.Error("DM: GetUserRank error code: %d", resq.Code)
u.lock.Lock()
u.ULevelRank = 1000000
return nil
}
u.lock.Lock()
u.ULevelRank = resq.Data.Rank
return nil
}
//GetCommentTitle 获取头衔
func (c *CommentTitle) GetCommentTitle(ctx context.Context) error {
req := &rcService.UserTitleGetCommentTitleReq{}
resq, err := RcServiceClient.V1UserTitle.GetCommentTitle(ctx, req)
if err != nil {
if errors.Cause(err) != context.Canceled {
log.Error("DM: GetCommentTitle err: %v", err)
}
c.OldTitle = ""
c.Title = ""
return nil
}
if resq.Code != 0 {
log.Error("DM: GetCommentTitle error code: %d", resq.Code)
c.OldTitle = ""
c.Title = ""
return nil
}
if len(resq.Data) == 0 {
c.OldTitle = ""
c.Title = ""
return nil
}
c.OldTitle = resq.Data[0]
c.Title = resq.Data[1]
return nil
}
//GetMedalanchorName 获取勋章对应主播的昵称
func (f *FansMedalInfo) GetMedalanchorName(ctx context.Context, uid int64) error {
if uid == 0 {
f.RUName = ""
return nil
}
req := &acctountService.MidReq{
Mid: uid,
}
resp, err := ac.Profile3(ctx, req)
if err != nil {
log.Error("DM: acctountService Profile3 err: %v", err)
f.lock.Lock()
f.RUName = ""
f.lock.Unlock()
return nil
}
f.lock.Lock()
f.RUName = resp.Profile.Name
f.lock.Unlock()
return nil
}
//GetMedalRoomid 获取勋章对应主播的房间
func (f *FansMedalInfo) GetMedalRoomid(ctx context.Context, uid int64) error {
if uid == 0 {
f.lock.Lock()
f.RoomID = 0
f.lock.Unlock()
return nil
}
req := &roomService.RoomRoomIdByUidReq{
Uid: uid,
}
resp, err := RoomServiceClient.V2Room.RoomIdByUid(ctx, req)
if err != nil {
log.Error("DM: room RoomIdByUid err: %v", err)
f.lock.Lock()
f.RoomID = 0
f.lock.Unlock()
return nil
}
if resp.Code == 404 {
f.lock.Lock()
f.RoomID = 0
f.lock.Unlock()
return nil
}
if resp.Code != 0 {
log.Error("DM: room RoomIdByUid err code: %d", resp.Code)
f.lock.Lock()
f.RoomID = 0
f.lock.Unlock()
return nil
}
f.lock.Lock()
f.RoomID = resp.Data.RoomId
f.lock.Unlock()
return nil
}
//GetUserBubble 判断用户是否有气泡
func (u *UserInfo) GetUserBubble(ctx context.Context, uid int64, roomid int64, bubble int64, guardLevel int) error {
req := &userextService.BubbleGetBubbleReq{
Uid: uid,
RoomId: roomid,
BubbleId: bubble,
GuardLevel: int64(guardLevel),
}
defer u.lock.Unlock()
resp, err := UserExtServiceClient.V1Bubble.GetBubble(ctx, req)
if err != nil {
if errors.Cause(err) != context.Canceled {
log.Error("DM: userext Bubble check err: %v", err)
}
u.lock.Lock()
u.Bubble = bubble
return nil
}
if resp.Code != 0 {
log.Error("DM: userext Bubble check err code: %d", resp.Code)
u.lock.Lock()
u.Bubble = bubble
return nil
}
if resp.Data == nil {
log.Error("DM: userext Bubble check err not data")
u.lock.Lock()
u.Bubble = bubble
return nil
}
u.lock.Lock()
u.Bubble = resp.Data.Bubble
return nil
}

View File

@ -0,0 +1,153 @@
package dao
import (
"context"
"flag"
"fmt"
"path/filepath"
"testing"
activityService "go-common/app/service/live/activity/api/liverpc"
"go-common/app/service/live/live-dm/conf"
rankdbService "go-common/app/service/live/rankdb/api/liverpc"
rcService "go-common/app/service/live/rc/api/liverpc"
userextService "go-common/app/service/live/userext/api/liverpc"
acctountService "go-common/app/service/main/account/api"
"go-common/library/net/metadata"
)
func init() {
dir, _ := filepath.Abs("../cmd/test.toml")
flag.Set("conf", dir)
var err error
if err = conf.Init(); err != nil {
panic(err)
}
UserExtServiceClient = userextService.New(getConf("userext"))
ActivityServiceClient = activityService.New(getConf("activity"))
RankdbServiceClient = rankdbService.New(getConf("rankdbService"))
RcServiceClient = rcService.New(getConf("rc"))
ac, err = acctountService.NewClient(conf.Conf.AccClient)
if err != nil {
panic(err)
}
}
//group=qa01 DEPLOY_ENV=uat go test -run TestUserInfo_GetUnameColor
func TestUserInfo_GetUnameColor(t *testing.T) {
u := &UserInfo{}
if err := u.GetUnameColor(context.TODO(), 28272030, 10004); err != nil {
t.Error("获取用户昵称颜色失败: ", err)
}
fmt.Println("UnameColor->", u.UnameColor)
}
//group=qa01 DEPLOY_ENV=uat go test -run TestUserInfo_GetSpeicalMedal
func TestUserInfo_GetSpeicalMedal(t *testing.T) {
m := &FansMedalInfo{}
if err := m.GetSpeicalMedal(context.TODO(), 111, 222); err != nil {
t.Error("获取特殊勋章信息失败:", err)
}
fmt.Println("SpecialMedal->", m.SpecialMedal)
}
//group=qa01 DEPLOY_ENV=uat go test -run TestUserInfo_GetUserLevelRank
func TestUserInfo_GetUserLevelRank(t *testing.T) {
u := &UserInfo{}
if err := u.GetUserLevelRank(context.TODO(), 111); err != nil {
t.Error("获取用户等级RANK失败:", err)
}
fmt.Println("ULevelRank->", u.ULevelRank)
}
//group=qa01 DEPLOY_ENV=uat go test -run TestCommentTitle_GetCommentTitle
func TestCommentTitle_GetCommentTitle(t *testing.T) {
c := &CommentTitle{}
ctx1 := metadata.NewContext(context.TODO(), metadata.MD{})
if md, ok := metadata.FromContext(ctx1); ok {
md[metadata.Mid] = 5200
}
if err := c.GetCommentTitle(ctx1); err != nil {
t.Error("获取用户头衔失败:", err)
}
fmt.Println("OldTitle->", c.OldTitle)
fmt.Println("Title->", c.Title)
}
//group=qa01 DEPLOY_ENV=uat go test -run TestFansMedalInfo_GetMedalanchorName
func TestFansMedalInfo_GetMedalanchorName(t *testing.T) {
f := &FansMedalInfo{}
if err := f.GetMedalanchorName(context.TODO(), 222); err != nil {
t.Error("获取勋章对应主播昵称错误:", err)
}
fmt.Println("RUName->", f.RUName)
}
//group=fat1 DEPLOY_ENV=uat go test -run TestUserInof_GetUserBubble
func TestUserInof_GetUserBubble(t *testing.T) {
u := &UserInfo{}
if err := u.GetUserBubble(context.TODO(), 1, 1, 1, 1); err != nil {
t.Error("GetUserBubble调用失败")
}
if u.Bubble != 1 {
t.Error("判断气泡失败 uid 1 roomid 1 bubble 1: bubble: ", u.Bubble)
}
fmt.Println("Bubble1->", u.Bubble)
if err := u.GetUserBubble(context.TODO(), 1, 2, 1, 1); err != nil {
t.Error("GetUserBubble调用失败")
}
if u.Bubble != 0 {
t.Error("判断气泡失败 uid 1 roomid 2 bubble 1: bubble: ", u.Bubble)
}
fmt.Println("Bubble2->", u.Bubble)
}
// //group=qa01 DEPLOY_ENV=uat go test -run TestUserInfo_GetUserLevelColor
// func TestUserInfo_GetUserLevelColor(t *testing.T) {
// u := &UserInfo{}
// if err := u.GetUserLevelColor(52); err != nil {
// t.Error("返回值错误: ", err)
// }
// if u.ULevelColor != 16752445 {
// t.Error("51级以上颜色错误 16752445 ->", u.ULevelColor)
// }
// if err := u.GetUserLevelColor(42); err != nil {
// t.Error("返回值错误: ", err)
// }
// if u.ULevelColor != 16746162 {
// t.Error("51-41级颜色错误 16752445 ->", u.ULevelColor)
// }
// if err := u.GetUserLevelColor(32); err != nil {
// t.Error("返回值错误: ", err)
// }
// if u.ULevelColor != 10512625 {
// t.Error("41-31级颜色错误 10512625 ->", u.ULevelColor)
// }
// if err := u.GetUserLevelColor(22); err != nil {
// t.Error("返回值错误: ", err)
// }
// if u.ULevelColor != 5805790 {
// t.Error("31-21级颜色错误 16752445 ->", u.ULevelColor)
// }
// if err := u.GetUserLevelColor(12); err != nil {
// t.Error("返回值错误: ", err)
// }
// if u.ULevelColor != 6406234 {
// t.Error("21-11级颜色错误 16752445 ->", u.ULevelColor)
// }
// if err := u.GetUserLevelColor(2); err != nil {
// t.Error("返回值错误: ", err)
// }
// if u.ULevelColor != 9868950 {
// t.Error("0-11级颜色错误 16752445 ->", u.ULevelColor)
// }
// }

View File

@ -0,0 +1,51 @@
package dao
import (
"context"
"fmt"
"go-common/library/cache/redis"
"go-common/library/log"
)
//GetHistoryData 获取历史数据
func (d *Dao) GetHistoryData(ctx context.Context, roomid int64) (result map[string][]string, err error) {
var conn = d.redis.Get(ctx)
defer conn.Close()
var admkey = fmt.Sprintf("%s%d", _adminMsgHistoryCache, roomid)
var userkey = fmt.Sprintf("%s%d", _msgHistoryCache, roomid)
if err = conn.Send("LRANGE", admkey, 0, 9); err != nil {
log.Error("DM: LRANGE ADMIN KEY ROOMID %d ERR:%v", roomid, err)
}
if err = conn.Send("LRANGE", userkey, 0, 9); err != nil {
log.Error("DM: LRANGE USER KEY ROOMID %d ERR:%v", roomid, err)
}
if err = conn.Flush(); err != nil {
log.Error("DM: Flush KEY ROOMID %d ERR:%v", roomid, err)
return nil, err
}
var admin, user [][]byte
admin, err = redis.ByteSlices(conn.Receive())
if err != nil {
log.Error("DM: ByteSlices ADMIN KEY ROOMID %d ERR:%v", roomid, err)
return nil, err
}
user, err = redis.ByteSlices(conn.Receive())
if err != nil {
log.Error("DM: ByteSlices USER KEY ROOMID %d ERR:%v", roomid, err)
return nil, err
}
result = make(map[string][]string)
result["admin"] = make([]string, 0, 10)
result["room"] = make([]string, 0, 10)
for i := len(admin) - 1; i >= 0; i-- {
result["admin"] = append(result["admin"], string(admin[i]))
}
for i := len(user) - 1; i >= 0; i-- {
result["room"] = append(result["room"], string(user[i]))
}
return result, nil
}

View File

@ -0,0 +1,93 @@
package dao
import (
"context"
broadcasrtService "go-common/app/service/live/broadcast-proxy/api/v1"
"go-common/app/service/live/live-dm/conf"
xuserService "go-common/app/service/live/xuser/api/grpc/v1"
acctountService "go-common/app/service/main/account/api"
filterService "go-common/app/service/main/filter/api/grpc/v1"
locationService "go-common/app/service/main/location/api"
spyService "go-common/app/service/main/spy/api"
"go-common/library/net/rpc/warden"
"google.golang.org/grpc"
)
//LocationAppID location服务注册ID
const locationAppID = "location.service"
const vipAppID = "live.xuser"
var (
ac acctountService.AccountClient
vipCli xuserService.VipClient
//FilterClient 屏蔽词过滤
FilterClient filterService.FilterClient
//LcClient 地理区域信息
LcClient locationService.LocationClient
//SpyClient 用户真实分
SpyClient spyService.SpyClient
//BcastClient 弹幕推送
BcastClient *broadcasrtService.Client
//UserExp 用户等级
userExp *xuserService.Client
//isAdmin 房管
isAdmin xuserService.RoomAdminClient
)
//InitGrpc 初始化grpcclient
func InitGrpc(c *conf.Config) {
var err error
ac, err = acctountService.NewClient(c.AccClient)
if err != nil {
panic(err)
}
FilterClient, err = filterService.NewClient(c.FilterClient)
if err != nil {
panic(err)
}
LcClient, err = newLocationClient(c.LocationClient)
if err != nil {
panic(err)
}
vipCli, err = newVipService(c.XuserClent)
if err != nil {
panic(err)
}
SpyClient, err = spyService.NewClient(c.SpyClient)
if err != nil {
panic(err)
}
BcastClient, err = broadcasrtService.NewClient(c.BcastClient)
if err != nil {
panic(err)
}
userExp, err = xuserService.NewClient(c.UExpClient)
if err != nil {
panic(err)
}
isAdmin, err = xuserService.NewXuserRoomAdminClient(c.IsAdminClient)
if err != nil {
panic(err)
}
}
//创建Location服务client
func newLocationClient(cfg *warden.ClientConfig, opts ...grpc.DialOption) (locationService.LocationClient, error) {
client := warden.NewClient(cfg, opts...)
conn, err := client.Dial(context.Background(), "discovery://default/"+locationAppID)
if err != nil {
return nil, err
}
return locationService.NewLocationClient(conn), nil
}
func newVipService(cfg *warden.ClientConfig, opts ...grpc.DialOption) (xuserService.VipClient, error) {
client := warden.NewClient(cfg, opts...)
conn, err := client.Dial(context.Background(), "discovery://default/"+vipAppID)
if err != nil {
return nil, err
}
return xuserService.NewVipClient(conn), nil
}

View File

@ -0,0 +1,30 @@
package dao
import (
"github.com/ipipdotnet/ipdb-go"
)
const (
ip4dbaddr = "/data/conf/v4.ipdb"
ip6dbaddr = "/data/conf/v6.ipdb"
)
var (
//IP4db ip4地址库
IP4db *ipdb.City
//IP6db ip6地址库
IP6db *ipdb.City
)
//InitIPdb 初始化IPdb
func InitIPdb() {
var err error
IP4db, err = ipdb.NewCity(ip4dbaddr)
if err != nil {
panic(err)
}
IP6db, err = ipdb.NewCity(ip6dbaddr)
if err != nil {
panic(err)
}
}

View File

@ -0,0 +1,65 @@
package dao
import (
activityService "go-common/app/service/live/activity/api/liverpc"
avService "go-common/app/service/live/av/api/liverpc"
bannedService "go-common/app/service/live/banned_service/api/liverpc"
fansMedalService "go-common/app/service/live/fans_medal/api/liverpc"
"go-common/app/service/live/live-dm/conf"
liveUserService "go-common/app/service/live/live_user/api/liverpc"
rankdbService "go-common/app/service/live/rankdb/api/liverpc"
rcService "go-common/app/service/live/rc/api/liverpc"
roomService "go-common/app/service/live/room/api/liverpc"
liveBroadCast "go-common/app/service/live/third_api/liveBroadcast"
userService "go-common/app/service/live/user/api/liverpc"
userextService "go-common/app/service/live/userext/api/liverpc"
"go-common/library/net/rpc/liverpc"
)
var (
// BannedServiceClient liveRpc banner_service api
BannedServiceClient *bannedService.Client
// RoomServiceClient liveRpc room service api
RoomServiceClient *roomService.Client
// LiveUserServiceClient liveRpc liveUser service api
LiveUserServiceClient *liveUserService.Client
// AvServiceClient liveRpc av service api
AvServiceClient *avService.Client
//FansMedalServiceClient liverpc fansmedal service api
FansMedalServiceClient *fansMedalService.Client
//ActivityServiceClient liverpc activity service api
ActivityServiceClient *activityService.Client
//RcServiceClient liverpc rc service api
RcServiceClient *rcService.Client
//RankdbServiceClient liverpc rankdb service api
RankdbServiceClient *rankdbService.Client
//UserExtServiceClient liverpc userext service api
UserExtServiceClient *userextService.Client
//LiveBroadCastClient liverpc thirdApi
LiveBroadCastClient *liveBroadCast.Client
//UserClient liveRpc user api
userClient *userService.Client
)
//InitAPI init all service APIS
func InitAPI() {
BannedServiceClient = bannedService.New(getConf("banneDService"))
RoomServiceClient = roomService.New(getConf("room"))
LiveUserServiceClient = liveUserService.New(getConf("liveUser"))
AvServiceClient = avService.New(getConf("avService"))
FansMedalServiceClient = fansMedalService.New(getConf("fansMedal"))
ActivityServiceClient = activityService.New(getConf("activity"))
RcServiceClient = rcService.New(getConf("rc"))
RankdbServiceClient = rankdbService.New(getConf("rankdbService"))
UserExtServiceClient = userextService.New(getConf("userext"))
LiveBroadCastClient = liveBroadCast.New(conf.Conf.HTTPClient)
userClient = userService.New(getConf("user"))
}
func getConf(appName string) *liverpc.ClientConfig {
c := conf.Conf.LiveRPC
if c != nil {
return c[appName]
}
return nil
}

View File

@ -0,0 +1,111 @@
package dao
import (
"context"
"crypto/md5"
"fmt"
"strconv"
"time"
"go-common/library/cache/redis"
"go-common/library/ecode"
"go-common/library/log"
)
// LimitCheckInfo 频率限制检查参数
type LimitCheckInfo struct {
UID int64
RoomID int64
Msg string
MsgType int64
Dao *Dao
Conf *LimitConf
}
const (
_MaxGiftMsgNum = "r:m:stormmsgcount:"
_MAXMsgNum = "r:m:rmx:"
)
// LimitPerSec 每秒发言限制
func (l *LimitCheckInfo) LimitPerSec(ctx context.Context) error {
key := fmt.Sprintf("%d.%d", l.UID, time.Now().Unix())
var conn = l.Dao.redis.Get(ctx)
defer conn.Close()
ret, err := conn.Do("SET", key, 1, "EX", 1, "NX")
if err != nil {
log.Error("limitPerSec:conn.Do(SET EX NX) %s %d %v", key, 1, err)
return nil
}
if ret != nil {
return nil
}
return ecode.Error(0, "msg in 1s")
}
//LimitSameMsg 同一个用户同一房间5s 只能发送一条相同弹幕
func (l *LimitCheckInfo) LimitSameMsg(ctx context.Context) error {
key := fmt.Sprintf("%d.%s", l.RoomID, md5.Sum([]byte(strconv.FormatInt(l.UID, 10)+l.Msg)))
var conn = l.Dao.redis.Get(ctx)
defer conn.Close()
ret, err := conn.Do("SET", key, 1, "EX", 5, "NX")
if err != nil {
log.Error("DM LimitSameMsg conn.Do(SET, %s, 1, EX, 5, NX) error(%v)", key, err)
return nil
}
if ret != nil {
return nil
}
return ecode.Error(0, "msg repeat")
}
//LimitRoomPerSecond 单房间每秒只能发送制定条数弹幕
func (l *LimitCheckInfo) LimitRoomPerSecond(ctx context.Context) error {
maxNum := l.Conf.DmNum
percent := l.Conf.DMPercent
danNum := maxNum * percent / 100.0
giftNum := maxNum - danNum
msgKey := fmt.Sprintf("%s.%d.%d", _MAXMsgNum, l.RoomID, time.Now().Unix())
giftKey := fmt.Sprintf("%s.%d.%d", _MaxGiftMsgNum, l.RoomID, time.Now().Unix())
var conn = l.Dao.redis.Get(ctx)
defer conn.Close()
if l.MsgType != 0 {
//礼物弹幕
if count, err := redis.Int64(conn.Do("INCRBY", giftKey, 1)); err != nil {
log.Error("DMRateLimit: LimitRoomPerSecond INCRBY err: %v", err)
} else {
if count > giftNum {
return ecode.Error(0, "max limit")
}
}
if _, err := conn.Do("EXPIRE", giftKey, 2); err != nil {
log.Error("DMRateLimit: LimitRoomPerSecond EXPIRE err: %v", err)
}
return nil
}
//普通弹幕
var max = maxNum
if exit, err := redis.Bool(conn.Do("EXISTS", giftKey)); err != nil {
log.Error("DMRateLimit: LimitRoomPerSecond EXISTS gift err: %v", err)
} else {
if exit {
max = danNum
} else {
max = maxNum
}
}
if count, err := redis.Int64(conn.Do("INCRBY", msgKey, 1)); err != nil {
log.Error("DMRateLimit: LimitRoomPerSecond INCR err: %v", err)
} else {
if count > max {
return ecode.Error(0, "max limit")
}
}
if _, err := conn.Do("EXPIRE", msgKey, 2); err != nil {
log.Error("DMRateLimit: LimitRoomPerSecond EXPIRE err: %v", err)
}
return nil
}

View File

@ -0,0 +1,74 @@
package dao
import (
"context"
"flag"
"go-common/app/service/live/live-dm/conf"
"path/filepath"
"testing"
)
func init() {
dir, _ := filepath.Abs("../cmd/test.toml")
flag.Set("conf", dir)
var err error
if err = conf.Init(); err != nil {
panic(err)
}
InitAPI()
InitGrpc(conf.Conf)
}
//group=qa01 DEPLOY_ENV=uat go test -run TestLimitPerSec
func TestLimitPerSec(t *testing.T) {
l := LimitCheckInfo{
UID: 111,
RoomID: 222,
Msg: "6666",
Dao: New(conf.Conf),
MsgType: 0,
Conf: &LimitConf{
DmNum: 20,
DMPercent: 25,
},
}
if err := l.LimitPerSec(context.TODO()); err != nil {
t.Error("每秒限制错误:", err)
}
}
//group=qa01 DEPLOY_ENV=uat go test -run TestLimitSameMsg
func TestLimitSameMsg(t *testing.T) {
l := LimitCheckInfo{
UID: 111,
RoomID: 222,
Msg: "6666",
Dao: New(conf.Conf),
MsgType: 0,
Conf: &LimitConf{
DmNum: 20,
DMPercent: 25,
},
}
if err := l.LimitSameMsg(context.TODO()); err != nil {
t.Error("5秒相同发言错误:", err)
}
}
//group=qa01 DEPLOY_ENV=uat go test -run TestLimitRoomPerSecond
func TestLimitRoomPerSecond(t *testing.T) {
l := LimitCheckInfo{
UID: 111,
RoomID: 222,
Msg: "6666",
Dao: New(conf.Conf),
MsgType: 0,
Conf: &LimitConf{
DmNum: 20,
DMPercent: 25,
},
}
if err := l.LimitRoomPerSecond(context.TODO()); err != nil {
t.Error("每秒20弹幕错误:", err)
}
}

View File

@ -0,0 +1,144 @@
package dao
import (
"context"
"fmt"
"strconv"
broadcasrtService "go-common/app/service/live/broadcast-proxy/api/v1"
"go-common/app/service/live/live-dm/model"
roomService "go-common/app/service/live/room/api/liverpc/v1"
"go-common/library/cache/redis"
"go-common/library/log"
)
const (
_adminMsgHistoryCache = "cache:last10_roomadminmsg:"
_msgHistoryCache = "cache:last10_roommsg:"
)
//SaveHistory 弹幕历史存入redis
func (d *Dao) SaveHistory(ctx context.Context, hm string, adm bool, rid int64) {
var conn = d.redis.Get(ctx)
defer conn.Close()
if adm {
admKey := fmt.Sprintf("%s%d", _adminMsgHistoryCache, rid)
if err := conn.Send("LPUSH", admKey, hm); err != nil {
log.Error("DM: SaveHistory LPUSH err: %v", err)
}
if err := conn.Send("LLEN", admKey); err != nil {
log.Error("DM: SaveHistory LLEN err: %v", err)
return
}
if err := conn.Flush(); err != nil {
log.Error("DM: SaveHistory Flush err: %v", err)
return
}
if _, err := conn.Receive(); err != nil {
log.Error("DM: SaveHistory LPUSH err: %v", err)
}
count, err := redis.Int64(conn.Receive())
if err != nil {
log.Error("DM: SaveHistory LPUSH LLEN err: %v", err)
return
}
if count > 15 {
err := conn.Send("LTRIM", admKey, 0, 9)
if err != nil {
log.Error("DM: SaveHistory LTRIM err: %v", err)
}
}
if err := conn.Send("EXPIRE", admKey, 86400); err != nil {
log.Error("DM: SaveHistory EXPIRE err: %v", err)
}
if err := conn.Flush(); err != nil {
log.Error("DM: SaveHistory Flush err: %v", err)
}
}
userKey := fmt.Sprintf("%s%d", _msgHistoryCache, rid)
if err := conn.Send("LPUSH", userKey, hm); err != nil {
log.Error("DM: SaveHistory LPUSH err: %v", err)
}
if err := conn.Send("LLEN", userKey); err != nil {
log.Error("DM: SaveHistory LLEN err: %v", err)
return
}
if err := conn.Flush(); err != nil {
log.Error("DM: SaveHistory Flush err: %v", err)
return
}
if _, err := conn.Receive(); err != nil {
log.Error("DM: SaveHistory Receive LPUSH err: %v", err)
}
count, err := redis.Int64(conn.Receive())
if err != nil {
log.Error("DM: SaveHistory Int64 err: %v", err)
return
}
if count > 15 {
if err := conn.Send("LTRIM", userKey, 0, 9); err != nil {
log.Error("DM: SaveHistory LTRIM err: %v", err)
}
}
if err := conn.Send("EXPIRE", userKey, 86400); err != nil {
log.Error("DM: SaveHistory EXPIRE err: %v", err)
}
if err := conn.Flush(); err != nil {
log.Error("DM: SaveHistory Flush err: %v", err)
}
}
//IncrDMNum 弹幕条数
func IncrDMNum(ctx context.Context, rid int64, mode int64) {
req := &roomService.RoomIncrDanmuSendNumReq{
RoomId: rid,
Mode: mode,
}
resp, err := RoomServiceClient.V1Room.IncrDanmuSendNum(ctx, req)
if err != nil {
log.Error("DM: IncrDMNum err: %v", err)
return
}
if resp.Code != 0 {
log.Error("DM: IncrDMNum err code: %d", resp.Code)
return
}
}
//SendBroadCast 发送弹幕(http)
func SendBroadCast(ctx context.Context, sm string, rid int64) error {
err := LiveBroadCastClient.PushBroadcast(ctx, rid, 0, sm)
if err != nil {
log.Error("DM: SendBroadCast err: %v", err)
return err
}
return nil
}
//SendBroadCastGrpc 调用GRPC发送弹幕
func SendBroadCastGrpc(ctx context.Context, sm string, rid int64) error {
req := &broadcasrtService.RoomMessageRequest{
RoomId: int32(rid),
Message: sm,
}
_, err := BcastClient.DanmakuClient.RoomMessage(ctx, req)
if err != nil {
log.Error("DM: SendBroadCastGrpc err: %v", err)
return err
}
return nil
}
//SendBNDatabus 拜年祭制定房间投递到databus
func SendBNDatabus(ctx context.Context, uid int64, info *model.BNDatabus) {
uids := strconv.FormatInt(uid, 10)
if err := bndatabus.Send(ctx, uids, info); err != nil {
log.Error("[service.live-dm.v1.bndatabus] send error(%v), record(%v)", err, info)
}
}

View File

@ -0,0 +1,25 @@
package dao
import (
"context"
"flag"
"go-common/app/service/live/live-dm/conf"
"path/filepath"
"testing"
)
func init() {
dir, _ := filepath.Abs("../cmd/test.toml")
flag.Set("conf", dir)
var err error
if err = conf.Init(); err != nil {
panic(err)
}
InitAPI()
InitGrpc(conf.Conf)
}
//group=qa01 DEPLOY_ENV=uat go test -run TestIncrDMNum
func TestIncrDMNum(t *testing.T) {
IncrDMNum(context.TODO(), 5392, 2)
}

View File

@ -0,0 +1,22 @@
package dao
import (
"context"
"go-common/library/cache/redis"
"go-common/library/log"
)
//IsWhietListUID 通过UID判读是否是白名单用户
func (d *Dao) IsWhietListUID(ctx context.Context, key string) (isWhite bool) {
conn := d.whitelistredis.Get(ctx)
defer conn.Close()
var err error
isWhite, err = redis.Bool(conn.Do("EXISTS", key))
if err != nil {
log.Error("[DM] GetWhietListByUID redis err:%+v", err)
return true
}
return
}

View File

@ -0,0 +1,29 @@
package dao
import (
"context"
"flag"
"go-common/app/service/live/live-dm/conf"
"path/filepath"
"testing"
)
func init() {
dir, _ := filepath.Abs("../cmd/test.toml")
flag.Set("conf", dir)
var err error
if err = conf.Init(); err != nil {
panic(err)
}
}
// DEPLOY_ENV=uat go test -run TestIsWhietListUID
func TestIsWhietListUID(t *testing.T) {
dao := New(conf.Conf)
if isWhite := dao.IsWhietListUID(context.TODO(), "1111"); isWhite {
t.Error("白名单判断失败")
}
if isWhite := dao.IsWhietListUID(context.TODO(), "13269933"); !isWhite {
t.Error("白名单判断失败")
}
}

View File

@ -0,0 +1,28 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["model.go"],
importpath = "go-common/app/service/live/live-dm/model",
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,14 @@
package model
//BNDatabus 拜年祭投递消息
type BNDatabus struct {
Roomid int64 `json:"room_id"`
UID int64 `json:"uid"`
Uname string `json:"uname"`
UserLever int64 `json:"user_level"`
Color int64 `json:"color"`
Msg string `json:"content"`
Time int64 `json:"time"`
MsgID string `json:"msg_id"`
MsgType int64 `json:"msg_type"`
}

View File

@ -0,0 +1,35 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["server.go"],
importpath = "go-common/app/service/live/live-dm/server/grpc",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/live/live-dm/api/grpc/v1:go_default_library",
"//app/service/live/live-dm/conf:go_default_library",
"//app/service/live/live-dm/dao:go_default_library",
"//app/service/live/live-dm/service/v1:go_default_library",
"//library/net/rpc/warden:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,25 @@
package grpc
import (
dmg "go-common/app/service/live/live-dm/api/grpc/v1"
"go-common/app/service/live/live-dm/conf"
"go-common/app/service/live/live-dm/dao"
dms "go-common/app/service/live/live-dm/service/v1"
"go-common/library/net/rpc/warden"
)
//Init 弹幕grpc 初始化
func Init(c *conf.Config) {
dao.InitAPI()
dao.InitGrpc(c)
dao.InitIPdb()
dao.InitDatabus(c)
dao.InitLancer(c)
dao.InitTitan()
s := warden.NewServer(nil)
dmg.RegisterDMServer(s.Server(), dms.NewDMService(c))
_, err := s.Start()
if err != nil {
panic(err)
}
}

View File

@ -0,0 +1,35 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["http.go"],
importpath = "go-common/app/service/live/live-dm/server/http",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/live/live-dm/conf:go_default_library",
"//app/service/live/live-dm/service:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/http/blademaster/middleware/verify:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,53 @@
package http
import (
"net/http"
"go-common/app/service/live/live-dm/conf"
"go-common/app/service/live/live-dm/service"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/verify"
)
var (
srv *service.Service
vfy *verify.Verify
)
// Init init
func Init(c *conf.Config) {
srv = service.New(c)
vfy = verify.New(c.Verify)
engine := bm.DefaultServer(c.BM)
route(engine)
if err := engine.Start(); err != nil {
log.Error("bm Start error(%v)", err)
panic(err)
}
}
func route(e *bm.Engine) {
e.Ping(ping)
e.Register(register)
g := e.Group("/x/dm")
{
g.GET("/start", vfy.Verify, howToStart)
}
}
func ping(c *bm.Context) {
if err := srv.Ping(c); err != nil {
log.Error("ping error(%v)", err)
c.AbortWithStatus(http.StatusServiceUnavailable)
}
}
func register(c *bm.Context) {
c.JSON(map[string]interface{}{}, nil)
}
// example for http request handler
func howToStart(c *bm.Context) {
c.String(0, "Golang 大法好 !!!")
}

View File

@ -0,0 +1,35 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["service.go"],
importpath = "go-common/app/service/live/live-dm/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/live/live-dm/conf:go_default_library",
"//app/service/live/live-dm/dao:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/service/live/live-dm/service/v1:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,33 @@
package service
import (
"context"
"go-common/app/service/live/live-dm/conf"
"go-common/app/service/live/live-dm/dao"
)
// Service struct
type Service struct {
c *conf.Config
dao *dao.Dao
}
// New init
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
dao: dao.New(c),
}
return s
}
// Ping Service
func (s *Service) Ping(c context.Context) (err error) {
return s.dao.Ping(c)
}
// Close Service
func (s *Service) Close() {
s.dao.Close()
}

View File

@ -0,0 +1,72 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"dM.go",
"dmcheck.go",
"getCheckInfo.go",
"getDMConf.go",
"limit.go",
"send.go",
],
importpath = "go-common/app/service/live/live-dm/service/v1",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/live/av/api/liverpc/v1:go_default_library",
"//app/service/live/banned_service/api/liverpc/v1:go_default_library",
"//app/service/live/live-dm/api/grpc/v1:go_default_library",
"//app/service/live/live-dm/conf:go_default_library",
"//app/service/live/live-dm/dao:go_default_library",
"//app/service/live/live-dm/model:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/metadata:go_default_library",
"//library/sync/errgroup:go_default_library",
"//vendor/github.com/ipipdotnet/ipdb-go:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
"//vendor/github.com/satori/go.uuid:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_test(
name = "go_default_test",
srcs = [
"dm_test.go",
"dmcheck_test.go",
"getCheckInfo_test.go",
"getDMConf_test.go",
"limit_test.go",
"send_test.go",
],
embed = [":go_default_library"],
tags = ["automanaged"],
deps = [
"//app/service/live/live-dm/api/grpc/v1:go_default_library",
"//app/service/live/live-dm/conf:go_default_library",
"//app/service/live/live-dm/dao:go_default_library",
"//library/ecode:go_default_library",
"//library/net/metadata:go_default_library",
],
)

View File

@ -0,0 +1,201 @@
package v1
import (
"context"
"regexp"
"time"
v1pb "go-common/app/service/live/live-dm/api/grpc/v1"
"go-common/app/service/live/live-dm/conf"
"go-common/app/service/live/live-dm/dao"
"go-common/library/ecode"
"go-common/library/log"
)
// DMService struct
type DMService struct {
conf *conf.Config
// optionally add other properties here, such as dao
dao *dao.Dao
}
//SendMsg 发送弹幕逻辑参数
type SendMsg struct {
SendMsgReq *v1pb.SendMsgReq
Dmservice *DMService
SendMsgResp *v1pb.SendMsgResp
UserInfo *dao.UserInfo
RoomConf *dao.RoomConf
UserBindInfo *dao.UserBindInfo
DMconf *dao.DMConf
TitleConf *dao.CommentTitle
UserScore *dao.UserScore
LimitConf *dao.LimitConf
}
//
var (
reMsg = regexp.MustCompile(`#\s+#`)
msgMust = regexp.MustCompile(`(/n)|(\n)`)
)
//NewDMService init
func NewDMService(c *conf.Config) (s *DMService) {
s = &DMService{
conf: c,
dao: dao.New(c),
}
return s
}
// SendMsg implementation
func (s *DMService) SendMsg(ctx context.Context, req *v1pb.SendMsgReq) (resp *v1pb.SendMsgResp, err error) {
sdm := &SendMsg{
SendMsgReq: req,
Dmservice: s,
UserInfo: &dao.UserInfo{
MedalInfo: &dao.FansMedalInfo{},
},
RoomConf: &dao.RoomConf{},
UserBindInfo: &dao.UserBindInfo{},
TitleConf: &dao.CommentTitle{},
DMconf: &dao.DMConf{},
UserScore: &dao.UserScore{},
LimitConf: &dao.LimitConf{
AreaLimit: s.conf.DmRules.AreaLimit,
AllUserLimit: s.conf.DmRules.AllUserLimit,
LevelLimitStatus: s.conf.DmRules.LevelLimitStatus,
LevelLimit: s.conf.DmRules.LevelLimit,
RealName: s.conf.DmRules.RealName,
PhoneLimit: s.conf.DmRules.PhoneLimit,
MsgLength: s.conf.DmRules.MsgLength,
DMPercent: s.conf.DmRules.DmPercent,
DmNum: s.conf.DmRules.DmNum,
DMwhitelist: s.conf.DmRules.DMwhitelist,
DMwhitelistID: s.conf.DmRules.DMwhiteListID,
},
}
sdm.LimitConf.GetDMCheckConf()
resp = &v1pb.SendMsgResp{}
if req.GetLancer() == nil {
req.Lancer = &v1pb.Lancer{}
}
//限制字体大小为25
sdm.SendMsgReq.Fontsize = 25
//特殊字符处理
req.Msg = reMsg.ReplaceAllString(req.Msg, " ")
sdm.SendMsgReq.Msg = msgMust.ReplaceAllString(req.Msg, "")
// 发送弹幕的频率控制
if err = rateLimit(ctx, sdm); err != nil {
if perr, ok := err.(*ecode.Status); ok {
resp.Code = int32(perr.Code())
resp.LimitMsg = perr.Message()
resp.IsLimit = true
err = nil
log.Info("LIMITDM, reason: %s, [detail: uid:%d, roomid:%d, msg:%s]", perr.Message(), req.Uid, req.Roomid, req.Msg)
dao.InfocDMErr.Info(req.Roomid, req.Uid, req.Msg, perr.Message(),
time.Now().Unix(), req.Platform, req.Lancer.Build, req.Lancer.Buvid,
req.Lancer.UserAgent, req.Lancer.Refer)
return
}
log.Error("DM limit err:%+v", err)
}
// 获取弹幕禁言检查依赖数据
if err = getCheckMsg(ctx, sdm); err != nil {
if perr, ok := err.(*ecode.Status); ok {
resp.Code = int32(perr.Code())
resp.LimitMsg = perr.Message()
resp.IsLimit = false
err = nil
return
}
log.Error("DM get check message err:%+v", err)
dao.InfocDMErr.Info(req.Roomid, req.Uid, req.Msg, "弹幕禁言检查依赖获取失败",
time.Now().Unix(), req.Platform, req.Lancer.Build, req.Lancer.Buvid,
req.Lancer.UserAgent, req.Lancer.Refer)
}
// 弹幕禁言检查
if err = checkLegitimacy(ctx, sdm); err != nil {
if perr, ok := err.(*ecode.Status); ok {
resp.Code = int32(perr.Code())
resp.LimitMsg = perr.Message()
resp.IsLimit = true
err = nil
return
}
dao.InfocDMErr.Info(req.Roomid, req.Uid, req.Msg, "弹幕禁言检查失败",
time.Now().Unix(), req.Platform, req.Lancer.Build, req.Lancer.Buvid,
req.Lancer.UserAgent, req.Lancer.Refer)
return
}
// 获取弹幕发送依赖数据
if err = getDMconfig(ctx, sdm); err != nil {
if perr, ok := err.(*ecode.Status); ok {
resp.Code = int32(perr.Code())
resp.LimitMsg = perr.Message()
resp.IsLimit = false
err = nil
return
}
dao.InfocDMErr.Info(req.Roomid, req.Uid, req.Msg, "获取弹幕发送依赖数据失败",
time.Now().Unix(), req.Platform, req.Lancer.Build, req.Lancer.Buvid,
req.Lancer.UserAgent, req.Lancer.Refer)
return
}
// 发送弹幕
if err = send(ctx, sdm); err != nil {
if perr, ok := err.(*ecode.Status); ok {
resp.Code = int32(perr.Code())
resp.LimitMsg = perr.Message()
resp.IsLimit = false
err = nil
return
}
dao.InfocDMErr.Info(req.Roomid, req.Uid, req.Msg, "弹幕广播失败",
time.Now().Unix(), req.Platform, req.Lancer.Build, req.Lancer.Buvid,
req.Lancer.UserAgent, req.Lancer.Refer)
return
}
log.Info("LIMITDM, reason: %s, [detail: uid:%d, roomid:%d, msg:%s]", "弹幕发送成功", req.Uid, req.Roomid, req.Msg)
dao.InfocDMSend.Info(req.Roomid, req.Uid, req.Msg, req.Ip, time.Now().Unix(),
sdm.DMconf.Color, req.Mode, req.Platform, req.Lancer.Build,
req.Lancer.Buvid, req.Lancer.UserAgent, req.Lancer.Refer, req.Lancer.Cookie,
req.Msgtype)
return
}
// GetHistory implementation
func (s *DMService) GetHistory(ctx context.Context, req *v1pb.HistoryReq) (resp *v1pb.HistoryResp, err error) {
resp = &v1pb.HistoryResp{}
rest, err := s.dao.GetHistoryData(ctx, req.Roomid)
if err != nil {
return resp, err
}
resp.Admin = make([]string, 0, 10)
resp.Room = make([]string, 0, 10)
resp.Admin = append(resp.Admin, rest["admin"]...)
resp.Room = append(resp.Room, rest["room"]...)
return
}
func lancer(sdm *SendMsg, reason string) {
req := sdm.SendMsgReq
dao.InfocDMErr.Info(req.Roomid, req.Uid, req.Msg, reason,
time.Now().Unix(), req.Platform, req.Lancer.Build, req.Lancer.Buvid,
req.Lancer.UserAgent, req.Lancer.Refer)
}

View File

@ -0,0 +1,40 @@
package v1
import (
"context"
"flag"
v1pb "go-common/app/service/live/live-dm/api/grpc/v1"
"go-common/app/service/live/live-dm/conf"
"go-common/app/service/live/live-dm/dao"
"path/filepath"
"testing"
)
func init() {
dir, _ := filepath.Abs("../../cmd/test.toml")
flag.Set("conf", dir)
var err error
if err = conf.Init(); err != nil {
panic(err)
}
dao.InitAPI()
dao.InitGrpc(conf.Conf)
}
//group=qa01 DEPLOY_ENV=uat go test -run TestDMService_SendMsg
func TestDMService_SendMsg(t *testing.T) {
}
//group=qa01 DEPLOY_ENV=uat go test -run TestGetHistory
func TestGetHistory(t *testing.T) {
req := &v1pb.HistoryReq{
Roomid: 460828,
}
s := &DMService{
conf: conf.Conf,
dao: dao.New(conf.Conf),
}
s.GetHistory(context.TODO(), req)
}

View File

@ -0,0 +1,554 @@
package v1
import (
"context"
"fmt"
"strconv"
"time"
"github.com/ipipdotnet/ipdb-go"
avService "go-common/app/service/live/av/api/liverpc/v1"
bannedService "go-common/app/service/live/banned_service/api/liverpc/v1"
"go-common/app/service/live/live-dm/dao"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/net/metadata"
"go-common/library/sync/errgroup"
"github.com/pkg/errors"
)
//检查弹幕合法性
func checkLegitimacy(ctx context.Context, sdm *SendMsg) error {
g, ctx := errgroup.WithContext(ctx)
//防止竞态条件透传mid以及userip
if md, ok := metadata.FromContext(ctx); ok {
md[metadata.Mid] = sdm.SendMsgReq.Uid
md[metadata.RemoteIP] = sdm.SendMsgReq.Ip
}
//全局禁言检查
g.Go(func() error { return globalRestriction(ctx, sdm) })
//付费直播检查
g.Go(func() error { return paidRoomInspection(ctx, sdm) })
//弹幕长度检查
g.Go(func() error { return messageLenCheck(ctx, sdm) })
//房间配置禁言检查
g.Go(func() error { return roomInfoCheck(ctx, sdm) })
// 房间禁言名单
g.Go(func() error { return roomBluckList(ctx, sdm) })
// 主播过滤用户
g.Go(func() error { return anchorFilterUser(ctx, sdm) })
// 主播过滤内容
g.Go(func() error { return anchorFilterMsg(ctx, sdm) })
// 用户绑定信息判断是否禁言
g.Go(func() error { return authenticationAuthority(ctx, sdm) })
// 用户区域检查
if sdm.LimitConf.AreaLimit {
g.Go(func() error { return userAreaLive(sdm) })
}
//弹幕内容检查
g.Go(func() error { return messageCheck(ctx, sdm) })
// 调用真实接口判断,弹幕是否可以广播
g.Go(func() error { return canBroadCastMsg(ctx, sdm) })
//2019 拜年祭白名单
roomid := strconv.FormatInt(sdm.SendMsgReq.Roomid, 10)
if sdm.LimitConf.DMwhitelist && sdm.Dmservice.conf.BNJRoomList[roomid] {
g.Go(func() error { return dmWhiteList(ctx, sdm) })
}
return g.Wait()
}
//DMWhiteList 拜年祭白名单
func dmWhiteList(ctx context.Context, sdm *SendMsg) error {
if sdm.LimitConf.DMwhitelistID == "ID-0" {
log.Info("LIMITDM, reason: %s, [detail: uid:%d, roomid:%d, msg:%s]",
"非拜年祭白名单用户", sdm.SendMsgReq.Uid, sdm.SendMsgReq.Roomid,
sdm.SendMsgReq.Msg)
lancer(sdm, "非拜年祭白名单用户")
return ecode.Error(0, "w")
}
key := fmt.Sprintf("%s_%d", sdm.LimitConf.DMwhitelistID, sdm.SendMsgReq.Uid)
if isWhite := sdm.Dmservice.dao.IsWhietListUID(ctx, key); isWhite {
return nil
}
log.Info("LIMITDM, reason: %s, [detail: uid:%d, roomid:%d, msg:%s]",
"非拜年祭白名单用户", sdm.SendMsgReq.Uid, sdm.SendMsgReq.Roomid,
sdm.SendMsgReq.Msg)
lancer(sdm, "非拜年祭白名单用户")
return ecode.Error(0, "w")
}
//globalRestriction 全局禁言检查
func globalRestriction(ctx context.Context, sdm *SendMsg) error {
if sdm.LimitConf.AllUserLimit {
log.Info("LIMITDM, reason: %s, [detail: uid:%d, roomid:%d, msg:%s]",
"开启全局禁言", sdm.SendMsgReq.Uid, sdm.SendMsgReq.Roomid,
sdm.SendMsgReq.Msg)
lancer(sdm, "开启全局禁言")
return ecode.Error(0, "系统正在维护")
}
if sdm.UserInfo.UserLever <= sdm.LimitConf.LevelLimit && sdm.LimitConf.LevelLimitStatus {
log.Info("LIMITDM, reason: %s, [detail: uid:%d, roomid:%d, msg:%s, limitLevel:%d, userLever:%d]",
"全局等级禁言", sdm.SendMsgReq.Uid, sdm.SendMsgReq.Roomid,
sdm.SendMsgReq.Msg, sdm.LimitConf.LevelLimit, sdm.UserInfo.UserLever)
lancer(sdm, "开启全局等级禁言")
return ecode.Error(0, "系统正在维护")
}
//全站禁言
req := &bannedService.SiteBlockMngIsBlockUserReq{
Tuid: sdm.SendMsgReq.Uid,
}
resp, err := dao.BannedServiceClient.V1SiteBlockMng.IsBlockUser(ctx, req)
if err != nil {
if errors.Cause(err) != context.Canceled {
log.Error("DM: banned_service V1SiteBlockMng IsBlockUser err : %+v", err)
}
return nil
}
if resp.Code != 0 {
log.Error("DM: banned_service V1SiteBlockMng IsBlockUser err code: %d", resp.Code)
return nil
}
if resp.Data.IsBlock {
log.Info("LIMITDM, reason: %s, [detail: uid:%d, roomid:%d, msg:%s]",
"直播黑名单用户", sdm.SendMsgReq.Uid, sdm.SendMsgReq.Roomid,
sdm.SendMsgReq.Msg)
lancer(sdm, "直播黑名单用户")
return ecode.Error(0, "你被禁言啦")
}
return nil
}
//
//PaidRoomInspection 付费直播检查
func paidRoomInspection(ctx context.Context, sdm *SendMsg) error {
req := &avService.PayLiveLiveValidateReq{
RoomId: sdm.SendMsgReq.Roomid,
Platform: "grpc",
}
// if md, ok := metadata.FromContext(ctx); ok {
// md[metadata.Mid] = sdm.SendMsgReq.Uid
// md[metadata.RemoteIP] = sdm.SendMsgReq.Ip
// }
resp, err := dao.AvServiceClient.V1PayLive.LiveValidate(ctx, req)
if err != nil {
if errors.Cause(err) != context.Canceled {
log.Error("DM: V1PayLive err: %v", err)
}
return nil
}
if resp.Code == 5001 {
log.Info("LIMITDM, reason: %s, [detail: uid:%d, roomid:%d, msg:%s]",
"付费直播间", sdm.SendMsgReq.Uid, sdm.SendMsgReq.Roomid,
sdm.SendMsgReq.Msg)
lancer(sdm, "付费直播间")
return ecode.Error(-102, "非常抱歉,本场直播需要购票,即可参与互动")
} else if resp.Code == 5003 {
return nil
}
if resp.Code != 0 {
log.Error("DM: V1OayLive error code: %d", resp.Code)
lancer(sdm, "付费直播间")
return ecode.Error(-102, "非常抱歉,本场直播需要购票,即可参与互动")
}
if resp.Data.Permission != 1 {
log.Info("LIMITDM, reason: %s, [detail: uid:%d, roomid:%d, msg:%s]",
"付费直播间", sdm.SendMsgReq.Uid, sdm.SendMsgReq.Roomid,
sdm.SendMsgReq.Msg)
lancer(sdm, "付费直播间")
return ecode.Error(-102, "非常抱歉,本场直播需要购票,即可参与互动")
}
return nil
}
//MessageCheck 弹幕内容检查
func messageCheck(ctx context.Context, sdm *SendMsg) error {
//命中等级大于等于20
if sdm.UserScore.MsgLevel >= 20 {
log.Info("LIMITDM, reason: %s, [detail: uid:%d, roomid:%d, msg:%s]",
"弹幕内容非法", sdm.SendMsgReq.Uid, sdm.SendMsgReq.Roomid,
sdm.SendMsgReq.Msg)
lancer(sdm, "内容非法")
return ecode.Error(0, "内容非法")
}
return nil
}
//MessageLenCheck 弹幕长度检查
func messageLenCheck(ctx context.Context, sdm *SendMsg) error {
ml := len([]rune(sdm.SendMsgReq.Msg))
// 小于默认长度 允许发送
if ml < sdm.LimitConf.MsgLength {
return nil
}
// 弹幕长度
if ml <= int(sdm.DMconf.Length) {
return nil
}
log.Info("LIMITDM, reason: %s, [detail: uid:%d, roomid:%d, msg:%s, msgLength:%d, limitLength:%d]",
"超出限制长度", sdm.SendMsgReq.Uid, sdm.SendMsgReq.Roomid,
sdm.SendMsgReq.Msg, ml, sdm.DMconf.Length)
lancer(sdm, "超出限制长度")
return ecode.Error(-500, "超出限制长度")
}
//RoomInfoCheck 房间配置禁言检查
func roomInfoCheck(ctx context.Context, sdm *SendMsg) error {
if sdm.SendMsgReq.Uid == sdm.RoomConf.UID ||
sdm.UserInfo.RoomAdmin {
return nil
}
//查询房间禁言
req := &bannedService.SilentGetRoomSilentReq{
RoomId: sdm.SendMsgReq.Roomid,
}
resp, err := dao.BannedServiceClient.V1Silent.GetRoomSilent(ctx, req)
if err != nil {
if errors.Cause(err) != context.Canceled {
log.Error("DM: banned_service GetRoomSilent err: %v", err)
}
return nil
}
if resp.Code != 0 {
log.Error("DM: banned_service GetRoomSilent err code: %d", resp.Code)
return nil
}
switch resp.Data.Type {
case "level":
// 等级限制
if resp.Data.Level < sdm.UserInfo.UserLever {
return nil
}
// 老爷免疫
if sdm.UserInfo.Vip != 0 || sdm.UserInfo.Svip != 0 {
return nil
}
// 守护免疫
if sdm.UserInfo.PrivilegeType != 0 {
return nil
}
var errm string
if resp.Data.Second == -1 {
errm = "本场直播结束后解除~"
} else {
errm = strconv.FormatInt(resp.Data.Second/60, 10) + "分钟后解除~"
}
em := fmt.Sprintf("主播对UL %d以下开启了禁言%s", resp.Data.Level, errm)
log.Info("LIMITDM, reason: %s, [detail: uid:%d, roomid:%d, msg:%s]",
em, sdm.SendMsgReq.Uid, sdm.SendMsgReq.Roomid,
sdm.SendMsgReq.Msg)
lancer(sdm, "播主开启等级禁言")
return ecode.Error(-403, em)
case "medal":
var errm string
if resp.Data.Second == -1 {
errm = "本场直播结束后解除~"
} else {
errm = strconv.FormatInt(resp.Data.Second/60, 10) + "分钟后解除~"
}
em := fmt.Sprintf("主播对粉丝勋章%d以下开启了禁言%s", resp.Data.Level, errm)
//佩戴勋章不一致
if sdm.RoomConf.UID != sdm.UserInfo.MedalInfo.RUID {
log.Info("LIMITDM, reason: %s, [detail: uid:%d, roomid:%d, msg:%s]",
em, sdm.SendMsgReq.Uid, sdm.SendMsgReq.Roomid,
sdm.SendMsgReq.Msg)
lancer(sdm, "播主开启粉丝勋章限制")
return ecode.Error(-403, em)
}
// 勋章等级免疫
if resp.Data.Level < sdm.UserInfo.MedalInfo.MedalLevel {
return nil
}
// 守护免疫(等级限制)
pt := sdm.UserInfo.PrivilegeType
if pt >= 1 && pt <= 2 {
return nil
}
log.Info("LIMITDM, reason: %s, [detail: uid:%d, roomid:%d, msg:%s]",
em, sdm.SendMsgReq.Uid, sdm.SendMsgReq.Roomid,
sdm.SendMsgReq.Msg)
lancer(sdm, "播主开启粉丝勋章限制")
return ecode.Error(-403, em)
case "member":
//守护免疫(总督免疫)
if sdm.UserInfo.PrivilegeType == 1 {
return nil
}
var errm string
if resp.Data.Second == -1 {
errm = "本场直播结束后解除~"
} else {
errm = strconv.FormatInt(resp.Data.Second/60, 10) + "分钟后解除~"
}
em := fmt.Sprintf("主播对全体用户开启了禁言,%s", errm)
log.Info("LIMITDM, reason: %s, [detail: uid:%d, roomid:%d, msg:%s]",
em, sdm.SendMsgReq.Uid, sdm.SendMsgReq.Roomid,
sdm.SendMsgReq.Msg)
lancer(sdm, "播开启房间全体禁言")
return ecode.Error(-403, em)
}
return nil
}
//RoomBluckList 房间禁言名单
func roomBluckList(ctx context.Context, sdm *SendMsg) error {
req := &bannedService.SilentMngIsBlockUserReq{
Uid: sdm.SendMsgReq.Uid,
Roomid: sdm.SendMsgReq.Roomid,
Type: 1,
}
resp, err := dao.BannedServiceClient.V1SilentMng.IsBlockUser(ctx, req)
if err != nil {
if errors.Cause(err) != context.Canceled {
log.Error("DM: BannedService IsBlockUser err: %v", err)
}
return nil
}
if resp.Code != 0 {
log.Error("DM: BannedService IsBlockUser err code: %d", resp.Code)
return nil
}
if resp.Data.IsBlockUser {
if sdm.UserInfo.PrivilegeType == 1 {
return nil
}
tm := time.Unix(resp.Data.BlockEndTime, 0)
ms := "你在本房间被禁言至 " + tm.Format("2006-01-02 15:04:05")
log.Info("LIMITDM, reason: %s, [detail: uid:%d, roomid:%d, msg:%s]",
"主播禁言名单", sdm.SendMsgReq.Uid, sdm.SendMsgReq.Roomid,
sdm.SendMsgReq.Msg)
lancer(sdm, "播主禁言名单")
return ecode.Error(1003, ms)
}
return nil
}
//AnchorFilterUser 主播过滤用户
func anchorFilterUser(ctx context.Context, sdm *SendMsg) error {
if sdm.RoomConf.RoomShield != 1 {
return nil
}
req := &bannedService.ShieldMngIsShieldUserReq{
Uid: sdm.RoomConf.UID,
ShieldUid: sdm.SendMsgReq.Uid,
}
resp, err := dao.BannedServiceClient.V1ShieldMng.IsShieldUser(ctx, req)
if err != nil {
if errors.Cause(err) != context.Canceled {
log.Error("DM: BannedService IsShieldUser err: %v", err)
}
return nil
}
if resp.Code != 0 {
log.Error("DM: BannedService IsShieldUser err code: %d", resp.Code)
return nil
}
if resp.Data.IsShieldUser {
log.Info("LIMITDM, reason: %s, [detail: uid:%d, roomid:%d, msg:%s]",
"主播过滤用户", sdm.SendMsgReq.Uid, sdm.SendMsgReq.Roomid,
sdm.SendMsgReq.Msg)
lancer(sdm, "被播主过滤的用户")
return ecode.Error(0, "u")
}
return nil
}
//AnchorFilterMsg 主播过滤内容
func anchorFilterMsg(ctx context.Context, sdm *SendMsg) error {
if sdm.RoomConf.RoomShield != 1 {
return nil
}
req := &bannedService.ShieldIsShieldContentReq{
Uid: sdm.RoomConf.UID,
Content: sdm.SendMsgReq.Msg,
}
resp, err := dao.BannedServiceClient.V1Shield.IsShieldContent(ctx, req)
if err != nil {
if errors.Cause(err) != context.Canceled {
log.Error("DM: BannedService IsShieldContent err: %v", err)
}
return nil
}
if resp.Code != 0 {
log.Error("DM: BannedService IsShieldContent err code: %d", resp.Code)
return nil
}
if resp.Data.IsShieldContent {
log.Info("LIMITDM, reason: %s, [detail: uid:%d, roomid:%d, msg:%s]",
"主播过滤内容", sdm.SendMsgReq.Uid, sdm.SendMsgReq.Roomid,
sdm.SendMsgReq.Msg)
lancer(sdm, "被播主过滤的弹幕内容")
return ecode.Error(0, "k")
}
return nil
}
//CanBroadCastMsg 调用真实接口判断,弹幕是否可以广播
func canBroadCastMsg(ctx context.Context, sdm *SendMsg) error {
req := &bannedService.AdminSilentGetShieldRuleReq{
Roomid: sdm.SendMsgReq.Roomid,
}
resp, err := dao.BannedServiceClient.V1AdminSilent.GetShieldRule(ctx, req)
if err != nil {
if errors.Cause(err) != context.Canceled {
log.Error("DM: BannedService GetShieldRule err: %v", err)
}
return nil
}
if resp.Code != 0 {
log.Error("DM: BannedService GetShieldRule err code: %d", resp.Code)
return nil
}
if sdm.UserScore.UserScore >= resp.Data.RealScore &&
sdm.UserScore.MsgAI <= resp.Data.AiScore {
return nil
}
if sdm.UserScore.UserScore < resp.Data.RealScore {
log.Info("LIMITDM, reason: %s, [detail: uid:%d, roomid:%d, msg:%s, UserScore: %d, RealScore: %d]",
"用户真实分拦截", sdm.SendMsgReq.Uid, sdm.SendMsgReq.Roomid,
sdm.SendMsgReq.Msg, sdm.UserScore.UserScore, resp.Data.RealScore)
lancer(sdm, "用户真实分拦截")
}
if sdm.UserScore.MsgAI > resp.Data.AiScore {
log.Info("LIMITDM, reason: %s, [detail: uid:%d, roomid:%d, msg:%s MsgAI: %d, AiScore: %d]",
"弹幕AI分拦截", sdm.SendMsgReq.Uid, sdm.SendMsgReq.Roomid,
sdm.SendMsgReq.Msg, sdm.UserScore.MsgAI, resp.Data.AiScore)
lancer(sdm, "弹幕AI分拦截")
}
return ecode.Error(0, "fire")
}
//AuthenticationAuthority 用户绑定信息判断是否禁言
func authenticationAuthority(ctx context.Context, sdm *SendMsg) error {
if sdm.LimitConf.RealName {
if 1 != sdm.UserBindInfo.Identification {
log.Info("LIMITDM, reason: %s, [detail: uid:%d, roomid:%d, msg:%s]",
"未实名认证", sdm.SendMsgReq.Uid, sdm.SendMsgReq.Roomid,
sdm.SendMsgReq.Msg)
lancer(sdm, "未实名认证")
return ecode.Error(0, "实名认证才可以发言")
}
}
mvf := sdm.UserBindInfo.MobileVerify
if sdm.LimitConf.PhoneLimit {
if mvf != 1 {
log.Info("LIMITDM, reason: %s, [detail: uid:%d, roomid:%d, msg:%s]",
"未实绑定手机", sdm.SendMsgReq.Uid, sdm.SendMsgReq.Roomid,
sdm.SendMsgReq.Msg)
lancer(sdm, "未绑定手机")
return ecode.Error(1001, "根据国家实名制认证的相关要求,您需要绑定手机号,才能继续进行操作")
}
}
return nil
}
//UserArea 用户区域判断
// func userArea(ctx context.Context, sdm *SendMsg) error {
// var ip = strings.Split(sdm.SendMsgReq.Ip, ":")
// req := &locationService.InfoReq{
// Addr: ip[0],
// }
// resp, err := dao.LcClient.Info(ctx, req)
// if err != nil {
// log.Error("DM: 主站区域查询接口失败 ERR: %v ip:%s", err, sdm.SendMsgReq.Ip)
// return nil
// }
// if resp.Country == "中国" || resp.Country == "局域网" {
// return nil
// }
// log.Info("LIMITDM, reason: %s, [detail: uid:%d, roomid:%d, msg:%s, 用户IP:%s 用户区域:%s]",
// "用户所在区域无法发言", sdm.SendMsgReq.Uid, sdm.SendMsgReq.Roomid,
// sdm.SendMsgReq.Msg, sdm.SendMsgReq.Ip, resp.Country)
// return &errPb.Error{
// ErrCode: 0,
// ErrMessage: "你所在的地区暂无法发言",
// }
// }
//userAreaLive 用户区域判断
func userAreaLive(sdm *SendMsg) error {
var cityInfo *ipdb.CityInfo
var err error
for _, v := range sdm.SendMsgReq.Ip {
if string(v) == "." {
cityInfo, err = dao.IP4db.FindInfo(sdm.SendMsgReq.Ip, "CN")
break
} else if string(v) == ":" {
cityInfo, err = dao.IP6db.FindInfo(sdm.SendMsgReq.Ip, "CN")
break
}
}
if cityInfo == nil {
log.Error("DM: ip解析失败: %s", sdm.SendMsgReq.Ip)
return nil
}
if err != nil {
log.Error("IPdb errr:%+v", err)
return err
}
if cityInfo.CountryName == "中国" || cityInfo.CountryName == "局域网" {
return nil
}
log.Info("LIMITDM, reason: %s, [detail: uid:%d, roomid:%d, msg:%s, 用户IP:%s 用户区域:%s]",
"用户所在区域无法发言", sdm.SendMsgReq.Uid, sdm.SendMsgReq.Roomid,
sdm.SendMsgReq.Msg, sdm.SendMsgReq.Ip, cityInfo.CountryName)
lancer(sdm, "用户区域限制")
return ecode.Error(0, "你所在的地区暂无法发言")
}

View File

@ -0,0 +1,422 @@
package v1
import (
"context"
"fmt"
"testing"
v1pb "go-common/app/service/live/live-dm/api/grpc/v1"
"go-common/app/service/live/live-dm/conf"
"go-common/app/service/live/live-dm/dao"
"go-common/library/ecode"
"go-common/library/net/metadata"
)
//group=qa01 DEPLOY_ENV=uat go test -race -run TestCheckLegitimacy
func TestCheckLegitimacy(t *testing.T) {
s := &SendMsg{
SendMsgReq: &v1pb.SendMsgReq{
Uid: 1877309,
Roomid: 5392,
Ip: "115.239.211.112",
Msg: "6666",
Rnd: "1000",
Fontsize: 15,
Mode: 1,
Platform: "ios",
Msgtype: 0,
},
Dmservice: &DMService{
conf: conf.Conf,
},
UserInfo: &dao.UserInfo{
UserLever: 100,
MedalInfo: &dao.FansMedalInfo{},
},
RoomConf: &dao.RoomConf{
UID: 158807,
RoomID: 5392,
Anchor: "沢奇Sawaki",
},
UserBindInfo: &dao.UserBindInfo{
Uname: "Bili_111",
URank: 1000,
},
TitleConf: &dao.CommentTitle{},
DMconf: &dao.DMConf{
Mode: 6,
Color: 5555,
Length: 20,
},
UserScore: &dao.UserScore{
UserScore: 90,
},
}
if err := checkLegitimacy(context.TODO(), s); err != nil {
fmt.Print("####\n", err)
}
}
//group=qa01 DEPLOY_ENV=uat go test -run TestGlobalRestriction
func TestGlobalRestriction(t *testing.T) {
s := &SendMsg{
UserInfo: &dao.UserInfo{
UserLever: 1,
},
Dmservice: &DMService{
conf: conf.Conf,
},
}
if err := globalRestriction(context.TODO(), s); err != nil {
if err != ecode.DMUserLevel {
t.Error("全局禁言检查错误:", err)
}
}
s.Dmservice.conf.DmRules.LevelLimit = 10
s.UserInfo.UserLever = 5
if err := globalRestriction(context.TODO(), s); err != nil {
if err != ecode.DMUserLevel {
t.Error("全局等级禁言检查错误:", err)
}
}
s.Dmservice.conf.DmRules.AllUserLimit = true
if err := globalRestriction(context.TODO(), s); err != nil {
if err != ecode.DMallUser {
t.Error("全体禁言检查错误:", err)
}
}
}
//group=qa01 DEPLOY_ENV=uat go test -run TestPaidRoomInspection
func TestPaidRoomInspection(t *testing.T) {
ctx := metadata.NewContext(context.TODO(), metadata.MD{})
var s = &SendMsg{
UserInfo: &dao.UserInfo{
UserLever: 1,
},
SendMsgReq: &v1pb.SendMsgReq{
Uid: 111,
Roomid: 460460,
Ip: "115.239.211.112",
},
Dmservice: &DMService{
conf: conf.Conf,
},
}
if err := paidRoomInspection(ctx, s); err != nil {
if err != ecode.PayLive {
t.Error("付费检查失败")
}
}
s.SendMsgReq.Uid = 123
if err := paidRoomInspection(ctx, s); err != nil {
t.Error("付费检查失败")
}
}
//group=qa01 DEPLOY_ENV=uat go test -run TestDmcheck_MessageCheck
func TestDmcheck_MessageCheck(t *testing.T) {
s := &SendMsg{
UserScore: &dao.UserScore{
MsgLevel: 30,
},
SendMsgReq: &v1pb.SendMsgReq{},
}
if err := messageCheck(context.TODO(), s); err != nil {
if err != ecode.FilterLimit {
t.Error("弹幕内容检查失败 Level 30")
}
}
s.UserScore.MsgLevel = 10
if err := messageCheck(context.TODO(), s); err != nil {
t.Error("弹幕内容检查失败 Level 10")
}
}
//group=qa01 DEPLOY_ENV=uat go test -run TestDmcheck_MessageLenCheck
func TestDmcheck_MessageLenCheck(t *testing.T) {
s := &SendMsg{
SendMsgReq: &v1pb.SendMsgReq{
Msg: "6666",
},
DMconf: &dao.DMConf{Length: 30},
Dmservice: &DMService{
conf: conf.Conf,
},
}
if err := messageLenCheck(context.TODO(), s); err != nil {
t.Error("弹幕长度检查失败 msg:6666")
}
s.SendMsgReq.Msg = "666666666666666666666"
if err := messageLenCheck(context.TODO(), s); err != nil {
t.Error("弹幕长度检查失败 msglength:21")
}
s.SendMsgReq.Msg = "一一一一一一一一一一一一一一一一一一一一一"
s.DMconf.Length = 20
if err := messageLenCheck(context.TODO(), s); err != nil {
if err != ecode.MsgLengthLimit {
t.Error("弹幕长度检查失败 msglength:21个一")
}
}
s.SendMsgReq.Msg = "一一一一一一一一一一一一一一一一一一一一一"
s.DMconf.Length = 30
if err := messageLenCheck(context.TODO(), s); err != nil {
t.Error("弹幕长度检查失败 msglength:21个一 长度限制30")
}
}
//group=qa01 DEPLOY_ENV=uat go test -run TestDmcheck_RoomInfoCheck
func TestDmcheck_RoomInfoCheck(t *testing.T) {
s := &SendMsg{
SendMsgReq: &v1pb.SendMsgReq{
Msg: "6666",
Roomid: 460758,
Uid: 222,
},
DMconf: &dao.DMConf{
Length: 30,
},
Dmservice: &DMService{
conf: conf.Conf,
},
RoomConf: &dao.RoomConf{
UID: 111,
},
UserInfo: &dao.UserInfo{
RoomAdmin: false,
UserLever: 10,
},
}
if err := roomInfoCheck(context.TODO(), s); err != nil {
if err == ecode.RoomAllLimit && err == ecode.RoomMedalLimit &&
err == ecode.RoomLeverLimit {
t.Error("房间禁言检查错误")
}
}
s.UserInfo.PrivilegeType = 1
if err := roomInfoCheck(context.TODO(), s); err != nil {
t.Error("总督禁言检查错误")
}
s.UserInfo.PrivilegeType = 2
if err := roomInfoCheck(context.TODO(), s); err != nil {
if err == ecode.RoomAllLimit && err == ecode.RoomMedalLimit &&
err == ecode.RoomLeverLimit {
t.Error("房间禁言检查错误")
}
}
s.UserInfo.PrivilegeType = 0
s.UserInfo.UserLever = 6
if err := roomInfoCheck(context.TODO(), s); err != nil {
fmt.Print("11111", err)
if err == ecode.RoomAllLimit && err == ecode.RoomMedalLimit &&
err == ecode.RoomLeverLimit {
t.Error("房间禁言检查错误")
}
}
}
//group=qa01 DEPLOY_ENV=uat go test -run TestDmcheck_RoomBluckList
func TestDmcheck_RoomBluckList(t *testing.T) {
s := &SendMsg{
SendMsgReq: &v1pb.SendMsgReq{
Msg: "666",
Roomid: 460758,
Uid: 111,
},
DMconf: &dao.DMConf{
Length: 30,
},
Dmservice: &DMService{
conf: conf.Conf,
},
RoomConf: &dao.RoomConf{
UID: 110000298,
RoomShield: 1,
},
UserInfo: &dao.UserInfo{
RoomAdmin: false,
UserLever: 10,
},
}
if err := roomBluckList(context.TODO(), s); err != nil {
t.Error("房间黑名单检查错误", err)
}
}
//group=qa01 DEPLOY_ENV=uat go test -run TestDmcheck_AnchorFilterMsg
func TestDmcheck_AnchorFilterMsg(t *testing.T) {
s := &SendMsg{
SendMsgReq: &v1pb.SendMsgReq{
Msg: "666",
Roomid: 460758,
Uid: 222,
},
DMconf: &dao.DMConf{
Length: 30,
},
Dmservice: &DMService{
conf: conf.Conf,
},
RoomConf: &dao.RoomConf{
UID: 110000298,
RoomShield: 1,
},
UserInfo: &dao.UserInfo{
RoomAdmin: false,
UserLever: 10,
},
}
if err := anchorFilterMsg(context.TODO(), s); err != nil {
if err != ecode.ShieldContent {
t.Error("主播屏蔽过滤词失败")
}
}
}
//group=qa01 DEPLOY_ENV=uat go test -run TestDmcheck_AnchorFilterUser
func TestDmcheck_AnchorFilterUser(t *testing.T) {
s := &SendMsg{
SendMsgReq: &v1pb.SendMsgReq{
Msg: "666",
Roomid: 460758,
Uid: 222,
},
DMconf: &dao.DMConf{
Length: 30,
},
Dmservice: &DMService{
conf: conf.Conf,
},
RoomConf: &dao.RoomConf{
UID: 110000298,
RoomShield: 1,
},
UserInfo: &dao.UserInfo{
RoomAdmin: false,
UserLever: 10,
},
}
if err := anchorFilterUser(context.TODO(), s); err != nil {
if err != ecode.ShieldContent {
t.Error("主播屏蔽过滤用户失败")
}
}
}
//group=qa01 DEPLOY_ENV=uat go test -run TestDmcheck_CanBroadCastMsg
func TestDmcheck_CanBroadCastMsg(t *testing.T) {
s := &SendMsg{
SendMsgReq: &v1pb.SendMsgReq{
Msg: "666",
Roomid: 460758,
Uid: 222,
},
DMconf: &dao.DMConf{
Length: 30,
},
Dmservice: &DMService{
conf: conf.Conf,
},
RoomConf: &dao.RoomConf{
UID: 110000298,
RoomShield: 1,
},
UserInfo: &dao.UserInfo{
RoomAdmin: false,
UserLever: 10,
},
UserScore: &dao.UserScore{
UserScore: 10,
MsgAI: 0,
},
}
if err := canBroadCastMsg(context.TODO(), s); err != nil {
t.Error("真实分服务错误")
}
}
//group=qa01 DEPLOY_ENV=uat go test -run TestDmcheck_AuthenticationAuthority
func TestDmcheck_AuthenticationAuthority(t *testing.T) {
var s = &SendMsg{
UserInfo: &dao.UserInfo{
UserLever: 1,
},
UserBindInfo: &dao.UserBindInfo{
Identification: 0,
MobileVerify: 0,
},
SendMsgReq: &v1pb.SendMsgReq{
Uid: 111,
Roomid: 460460,
Ip: "115.239.211.112",
},
Dmservice: &DMService{
conf: conf.Conf,
},
}
if err := authenticationAuthority(context.TODO(), s); err != nil {
if err != ecode.RealName {
t.Error("实名认证检查失败")
}
}
s.UserBindInfo.Identification = 1
if err := authenticationAuthority(context.TODO(), s); err != nil {
if err != ecode.PhoneBind {
t.Error("手机绑定检查失败")
}
}
}
//group=qa01 DEPLOY_ENV=uat go test -run TestDmcheck_UserArea
// func TestDmcheck_UserArea(t *testing.T) {
// var s = &SendMsg{
// UserInfo: &dao.UserInfo{
// UserLever: 1,
// },
// SendMsgReq: &v1pb.SendMsgReq{
// Uid: 111,
// Roomid: 460460,
// Ip: "115.239.211.112",
// },
// Dmservice: &DMService{
// conf: conf.Conf,
// },
// }
// if err := userArea(context.TODO(), s); err != nil {
// t.Error("区域判断出错")
// }
// s.SendMsgReq.Ip = "198.11.179.19"
// if err := userArea(context.TODO(), s); err != nil {
// if err != ecode.CountryLimit {
// t.Error("区域判断出错 美国")
// }
// }
// }
//group=fat1 DEPLOY_ENV=uat go test -run TestDmcheck_userAreaLive
func TestDmcheck_userAreaLive(t *testing.T) {
dao.InitIPdb()
var s = &SendMsg{
UserInfo: &dao.UserInfo{
UserLever: 1,
},
SendMsgReq: &v1pb.SendMsgReq{
Uid: 111,
Roomid: 460460,
Ip: "115.239.211.112",
},
Dmservice: &DMService{
conf: conf.Conf,
},
}
err := userAreaLive(s)
if err != nil {
t.Error("#####", err)
}
}

View File

@ -0,0 +1,66 @@
package v1
import (
"context"
"go-common/library/sync/errgroup"
)
//getCheckMsg 获取弹幕检查信息
func getCheckMsg(ctx context.Context, sdm *SendMsg) error {
g, ctxn := errgroup.WithContext(ctx)
//获取弹幕配置
g.Go(func() error {
uid := sdm.SendMsgReq.Uid
roomid := sdm.SendMsgReq.Roomid
return sdm.DMconf.Get(ctxn, uid, roomid, sdm.Dmservice.conf)
})
//获取用户等级经验 TODO
g.Go(func() error {
return sdm.UserInfo.Get(ctxn, sdm.SendMsgReq.Uid)
})
//获取用户老爷等级
g.Go(func() error {
return sdm.UserInfo.GetVipInfo(ctxn, sdm.SendMsgReq.Uid)
})
//获取房间,大航海,房管信息
g.Go(func() error {
return getRoomConf(ctxn, sdm)
})
//获取用户绑定信息
g.Go(func() error {
return sdm.UserBindInfo.Get(ctxn, sdm.SendMsgReq.Uid)
})
//获取用户粉丝勋章信息
g.Go(func() error {
return sdm.UserInfo.MedalInfo.GetFansMedal(ctxn, sdm.SendMsgReq.Uid)
})
//获取弹幕真实分
g.Go(func() error {
return sdm.UserScore.GetMsgScore(ctxn, sdm.SendMsgReq.Msg)
})
//获取用户真实分
g.Go(func() error {
return sdm.UserScore.GetUserScore(ctx, sdm.SendMsgReq.Uid)
})
//获取房管信息
g.Go(func() error {
return sdm.UserInfo.IsRoomAdmin(ctx, sdm.SendMsgReq.Uid, sdm.SendMsgReq.Roomid)
})
return g.Wait()
}
//GetRoomConf 获取房间,大航海,房管信息
func getRoomConf(ctx context.Context, sdm *SendMsg) error {
if err := sdm.RoomConf.Get(ctx, sdm.SendMsgReq.Roomid); err != nil {
return err
}
//获取大航海信息
ruid := sdm.RoomConf.UID
return sdm.UserInfo.GetPrivilegeType(ctx, sdm.SendMsgReq.Uid, ruid)
}

View File

@ -0,0 +1,135 @@
package v1
import (
"context"
"encoding/json"
"fmt"
v1pb "go-common/app/service/live/live-dm/api/grpc/v1"
"go-common/app/service/live/live-dm/conf"
"go-common/app/service/live/live-dm/dao"
"testing"
)
//group=qa01 DEPLOY_ENV=uat go test -race -run TestGetCheckMsg
func TestGetCheckMsg(t *testing.T) {
s := &SendMsg{
SendMsgReq: &v1pb.SendMsgReq{
Uid: 111,
Roomid: 5392,
Ip: "115.239.211.112",
Msg: "6666",
Rnd: "1000",
Fontsize: 15,
Mode: 1,
Platform: "ios",
Msgtype: 0,
},
Dmservice: &DMService{
conf: conf.Conf,
},
UserInfo: &dao.UserInfo{
MedalInfo: &dao.FansMedalInfo{},
},
RoomConf: &dao.RoomConf{},
UserBindInfo: &dao.UserBindInfo{},
TitleConf: &dao.CommentTitle{},
DMconf: &dao.DMConf{},
UserScore: &dao.UserScore{},
}
if err := getCheckMsg(context.TODO(), s); err != nil {
t.Error("获取检查配置失败:", err)
}
j, _ := json.Marshal(s)
fmt.Print("####", string(j))
}
//group=qa01 DEPLOY_ENV=uat go test -race -run TestGetRoomConf
func TestGetRoomConf(t *testing.T) {
var s = &SendMsg{
UserInfo: &dao.UserInfo{
UserLever: 1,
},
UserBindInfo: &dao.UserBindInfo{
Identification: 0,
MobileVerify: 0,
},
SendMsgReq: &v1pb.SendMsgReq{
Uid: 1877309,
Roomid: 5392,
Ip: "115.239.211.112",
},
Dmservice: &DMService{
conf: conf.Conf,
},
RoomConf: &dao.RoomConf{
UID: 158807,
},
}
if err := getRoomConf(context.TODO(), s); err != nil {
t.Error("房间配置获取失败")
}
fmt.Printf("######%+v", s)
fmt.Printf("######%+v", s.UserInfo)
fmt.Printf("######%+v", s.RoomConf)
}
//group=qa01 DEPLOY_ENV=uat go test -run TestGetPrivilegeType
func TestGetPrivilegeType(t *testing.T) {
var s = &SendMsg{
UserInfo: &dao.UserInfo{
UserLever: 1,
},
UserBindInfo: &dao.UserBindInfo{
Identification: 0,
MobileVerify: 0,
},
SendMsgReq: &v1pb.SendMsgReq{
Uid: 1877309,
Roomid: 5392,
Ip: "115.239.211.112",
},
Dmservice: &DMService{
conf: conf.Conf,
},
RoomConf: &dao.RoomConf{
UID: 158807,
},
}
if err := s.UserInfo.GetPrivilegeType(context.TODO(), 1877309, 999); err != nil {
t.Error("大航海获取失败")
}
fmt.Printf("######%d", s.UserInfo.PrivilegeType)
}
//group=qa01 DEPLOY_ENV=uat go test -run TestIsRoomAdim111
func TestIsRoomAdim111(t *testing.T) {
var s = &SendMsg{
UserInfo: &dao.UserInfo{
UserLever: 1,
},
UserBindInfo: &dao.UserBindInfo{
Identification: 0,
MobileVerify: 0,
},
SendMsgReq: &v1pb.SendMsgReq{
Uid: 1877309,
Roomid: 5392,
Ip: "115.239.211.112",
},
Dmservice: &DMService{
conf: conf.Conf,
},
RoomConf: &dao.RoomConf{
UID: 158807,
},
}
s.UserInfo.IsRoomAdmin(context.TODO(), 110000654, 460874)
if !s.UserInfo.RoomAdmin {
t.Error("房管判断失败")
}
s.UserInfo.IsRoomAdmin(context.TODO(), 110000655, 460874)
if s.UserInfo.RoomAdmin {
t.Error("房管判断失败")
}
}

View File

@ -0,0 +1,47 @@
package v1
import (
"context"
"go-common/library/net/metadata"
"go-common/library/sync/errgroup"
)
func getDMconfig(ctx context.Context, sdm *SendMsg) error {
g, ctxn := errgroup.WithContext(ctx)
if md, ok := metadata.FromContext(ctxn); ok {
md[metadata.Mid] = sdm.SendMsgReq.Uid
}
//获取用户的昵称颜色
g.Go(func() error {
return sdm.UserInfo.GetUnameColor(ctxn, sdm.SendMsgReq.Uid, sdm.SendMsgReq.Roomid)
})
//获取特殊勋章
g.Go(func() error {
return sdm.UserInfo.MedalInfo.GetSpeicalMedal(ctxn, sdm.SendMsgReq.Uid, sdm.RoomConf.UID)
})
//获取用户等级RANK
g.Go(func() error {
return sdm.UserInfo.GetUserLevelRank(ctxn, sdm.SendMsgReq.Uid)
})
//获取用户头衔
g.Go(func() error {
return sdm.TitleConf.GetCommentTitle(ctxn)
})
//获取勋章对应主播的昵称
if sdm.UserInfo.MedalInfo.RUID != 0 {
g.Go(func() error {
return sdm.UserInfo.MedalInfo.GetMedalanchorName(ctxn, sdm.UserInfo.MedalInfo.RUID)
})
//获取勋章对应主播的房间号
g.Go(func() error {
return sdm.UserInfo.MedalInfo.GetMedalRoomid(ctxn, sdm.UserInfo.MedalInfo.RUID)
})
}
//获取用户气泡
g.Go(func() error {
return sdm.UserInfo.GetUserBubble(ctxn, sdm.SendMsgReq.Uid, sdm.SendMsgReq.Roomid, sdm.SendMsgReq.Bubble, sdm.UserInfo.PrivilegeType)
})
return g.Wait()
}

View File

@ -0,0 +1,59 @@
package v1
import (
"context"
"encoding/json"
"fmt"
v1pb "go-common/app/service/live/live-dm/api/grpc/v1"
"go-common/app/service/live/live-dm/conf"
"go-common/app/service/live/live-dm/dao"
"go-common/library/net/metadata"
"testing"
)
//group=qa01 DEPLOY_ENV=uat go test -race -run TestGetDMconfig
func TestGetDMconfig(t *testing.T) {
ctx := metadata.NewContext(context.TODO(), metadata.MD{})
s := &SendMsg{
SendMsgReq: &v1pb.SendMsgReq{
Uid: 520,
Roomid: 5392,
Ip: "115.239.211.112",
Msg: "6666",
Rnd: "1000",
Fontsize: 15,
Mode: 1,
Platform: "ios",
Msgtype: 0,
},
Dmservice: &DMService{
conf: conf.Conf,
},
UserInfo: &dao.UserInfo{
MedalInfo: &dao.FansMedalInfo{},
},
RoomConf: &dao.RoomConf{
UID: 158807,
RoomID: 5392,
Anchor: "沢奇Sawaki",
},
UserBindInfo: &dao.UserBindInfo{
Uname: "Bili_111",
URank: 1000,
},
TitleConf: &dao.CommentTitle{},
DMconf: &dao.DMConf{
Mode: 6,
Color: 5555,
Length: 20,
},
UserScore: &dao.UserScore{
UserScore: 90,
},
}
if err := getDMconfig(ctx, s); err != nil {
t.Error("获取弹幕配置失败", err)
}
j, _ := json.Marshal(s)
fmt.Print("####", string(j))
}

View File

@ -0,0 +1,30 @@
package v1
import (
"context"
"go-common/app/service/live/live-dm/dao"
"go-common/library/sync/errgroup"
)
func rateLimit(ctx context.Context, dm *SendMsg) error {
lc := &dao.LimitCheckInfo{
UID: dm.SendMsgReq.Uid,
RoomID: dm.SendMsgReq.Roomid,
Msg: dm.SendMsgReq.Msg,
MsgType: dm.SendMsgReq.Msgtype,
Dao: dm.Dmservice.dao,
Conf: dm.LimitConf,
}
g, ctx := errgroup.WithContext(ctx)
g.Go(func() error {
return lc.LimitPerSec(ctx)
})
g.Go(func() error {
return lc.LimitSameMsg(ctx)
})
g.Go(func() error {
return lc.LimitRoomPerSecond(ctx)
})
return g.Wait()
}

View File

@ -0,0 +1,9 @@
package v1
import (
"testing"
)
func TestRateLimit(t *testing.T) {
}

View File

@ -0,0 +1,238 @@
package v1
import (
"context"
"encoding/json"
"fmt"
"hash/crc32"
"strconv"
"time"
"go-common/app/service/live/live-dm/dao"
"go-common/app/service/live/live-dm/model"
"go-common/library/log"
"go-common/library/sync/errgroup"
uuid "github.com/satori/go.uuid"
)
//History 存档信息
type History struct {
Text string `json:"text"`
UID int64 `json:"uid"`
NickName string `json:"nickname"`
UnameColor string `json:"uname_color"`
TimeLine string `json:"timeline"`
Isadmin int32 `json:"isadmin"`
Vip int `json:"vip"`
SVip int `json:"svip"`
Medal []interface{} `json:"medal"`
Title []interface{} `json:"title"` //内容格式待定
UserLevel []interface{} `json:"user_level"`
Rank int32 `json:"rank"`
Teamid int64 `json:"teamid"`
RND string `json:"rnd"`
UserTitle string `json:"user_title"`
GuardLevel int `json:"guard_level"`
Bubble int64 `json:"bubble"`
}
//DatatoString 数据处理转换为json
func (h *History) DatatoString(s *SendMsg) string {
h.Text = s.SendMsgReq.Msg
h.NickName = s.UserBindInfo.Uname
h.UID = s.SendMsgReq.Uid
h.UnameColor = s.UserInfo.UnameColor
h.TimeLine = time.Unix(time.Now().Unix(), 0).Format("2006-01-02 15:04:05")
if s.UserInfo.RoomAdmin {
h.Isadmin = 1
} else {
h.Isadmin = 0
}
h.Vip = s.UserInfo.Vip
h.SVip = s.UserInfo.Svip
h.Rank = s.UserBindInfo.URank
h.Teamid = 0
h.RND = s.SendMsgReq.Rnd
h.UserTitle = s.TitleConf.Title
h.GuardLevel = s.UserInfo.PrivilegeType
h.Bubble = s.UserInfo.Bubble
md := make([]interface{}, 0, 6)
if s.UserInfo.MedalInfo.MedalName != "" {
md = append(md, s.UserInfo.MedalInfo.MedalLevel)
md = append(md, s.UserInfo.MedalInfo.MedalName)
md = append(md, s.UserInfo.MedalInfo.RUName) //TODO 获取主播get_weared_medal
md = append(md, s.UserInfo.MedalInfo.RoomID)
md = append(md, s.UserInfo.MedalInfo.MColor)
md = append(md, s.UserInfo.MedalInfo.SpecialMedal)
}
h.Medal = md
ul := make([]interface{}, 0, 4)
ul = append(ul, s.UserInfo.UserLever)
ul = append(ul, 0)
ul = append(ul, s.UserInfo.ULevelColor)
if s.UserInfo.ULevelRank > 50000 {
ul = append(ul, ">50000")
} else {
ul = append(ul, s.UserInfo.ULevelRank)
}
h.UserLevel = ul
tl := make([]interface{}, 0, 2)
tl = append(tl, s.TitleConf.OldTitle)
tl = append(tl, s.TitleConf.Title)
h.Title = tl
msg, _ := json.Marshal(h)
return string(msg)
}
//BroadCastMsg 广播信息
type BroadCastMsg struct {
CMD string `json:"cmd"`
Info []interface{} `json:"info"`
}
//DatatoString 数据处理转换为json
func (b *BroadCastMsg) DatatoString(s *SendMsg) string {
b.CMD = "DANMU_MSG"
b.Info = make([]interface{}, 0, 10)
//弹幕配置
dc := make([]interface{}, 0, 11)
dc = append(dc, 0)
dc = append(dc, s.SendMsgReq.Mode)
dc = append(dc, s.SendMsgReq.Fontsize)
dc = append(dc, s.DMconf.Color)
dc = append(dc, time.Now().Unix())
var rand int64
rand, _ = strconv.ParseInt(s.SendMsgReq.Rnd, 10, 64)
dc = append(dc, rand)
dc = append(dc, 0)
dc = append(dc, fmt.Sprintf("%08x", crc32.ChecksumIEEE([]byte(strconv.FormatInt(s.SendMsgReq.Uid, 10)))))
dc = append(dc, 0)
dc = append(dc, s.SendMsgReq.Msgtype)
dc = append(dc, s.UserInfo.Bubble)
//用户信息
userInfo := make([]interface{}, 0, 8)
userInfo = append(userInfo, s.SendMsgReq.Uid)
userInfo = append(userInfo, s.UserBindInfo.Uname)
var admin int
if s.UserInfo.RoomAdmin {
admin = 1
} else {
admin = 0
}
userInfo = append(userInfo, admin)
userInfo = append(userInfo, s.UserInfo.Vip)
userInfo = append(userInfo, s.UserInfo.Svip)
userInfo = append(userInfo, s.UserBindInfo.URank)
userInfo = append(userInfo, s.UserBindInfo.MobileVerify)
userInfo = append(userInfo, s.UserInfo.UnameColor)
//勋章配置
medalInfo := make([]interface{}, 0, 6)
if s.UserInfo.MedalInfo.MedalName != "" {
medalInfo = append(medalInfo, s.UserInfo.MedalInfo.MedalLevel)
medalInfo = append(medalInfo, s.UserInfo.MedalInfo.MedalName)
medalInfo = append(medalInfo, s.UserInfo.MedalInfo.RUName) // 主播名称
medalInfo = append(medalInfo, s.UserInfo.MedalInfo.RoomID)
medalInfo = append(medalInfo, s.UserInfo.MedalInfo.MColor)
medalInfo = append(medalInfo, s.UserInfo.MedalInfo.SpecialMedal)
}
//用户等级信息
ul := make([]interface{}, 0, 4)
ul = append(ul, s.UserInfo.UserLever)
ul = append(ul, 0)
ul = append(ul, s.UserInfo.ULevelColor)
if s.UserInfo.ULevelRank > 50000 {
ul = append(ul, ">50000")
} else {
ul = append(ul, s.UserInfo.ULevelRank)
}
//头衔
tl := make([]interface{}, 0, 2)
tl = append(tl, s.TitleConf.OldTitle)
tl = append(tl, s.TitleConf.Title)
//组合
b.Info = append(b.Info, dc)
b.Info = append(b.Info, s.SendMsgReq.Msg)
b.Info = append(b.Info, userInfo)
b.Info = append(b.Info, medalInfo)
b.Info = append(b.Info, ul)
b.Info = append(b.Info, tl)
b.Info = append(b.Info, 0)
b.Info = append(b.Info, s.UserInfo.PrivilegeType)
b.Info = append(b.Info, nil)
msg, _ := json.Marshal(b)
return string(msg)
}
func send(ctx context.Context, sdm *SendMsg) error {
g, ctx := errgroup.WithContext(ctx)
g.Go(func() error {
saveHistory(ctx, sdm)
return nil
})
g.Go(func() error {
incrDMNum(ctx, sdm)
return nil
})
g.Go(func() error {
return sendBroadCast(ctx, sdm)
})
//databus投递
err := sdm.Dmservice.dao.Databus.Do(context.Background(), func(c context.Context) {
sendDataBus(context.Background(), sdm)
})
if err != nil {
log.Error("DM: send databus save err: %+v", err)
}
return g.Wait()
}
func saveHistory(ctx context.Context, sdm *SendMsg) {
hm := &History{}
jhm := hm.DatatoString(sdm)
sdm.Dmservice.dao.SaveHistory(ctx, jhm, sdm.UserInfo.RoomAdmin, sdm.SendMsgReq.Roomid)
}
func incrDMNum(ctx context.Context, sdm *SendMsg) {
dao.IncrDMNum(ctx, sdm.SendMsgReq.Roomid, sdm.SendMsgReq.Msgtype)
}
func sendBroadCast(ctx context.Context, sdm *SendMsg) error {
bm := &BroadCastMsg{}
jbm := bm.DatatoString(sdm)
if err := dao.SendBroadCastGrpc(ctx, jbm, sdm.SendMsgReq.Roomid); err != nil {
// if err := dao.SendBroadCast(ctx, jbm, sdm.SendMsgReq.Roomid); err != nil {
lancer(sdm, "弹幕投递消息失败")
return nil
// }
// return nil
}
return nil
}
func sendDataBus(ctx context.Context, sdm *SendMsg) {
info := &model.BNDatabus{
Roomid: sdm.SendMsgReq.Roomid,
UID: sdm.SendMsgReq.Uid,
Uname: sdm.UserBindInfo.Uname,
UserLever: sdm.UserInfo.UserLever,
Color: sdm.DMconf.Color,
Msg: sdm.SendMsgReq.Msg,
Time: time.Now().Unix(),
MsgType: sdm.SendMsgReq.Msgtype,
MsgID: uuid.NewV4().String(),
}
dao.SendBNDatabus(ctx, sdm.SendMsgReq.Uid, info)
}

View File

@ -0,0 +1,144 @@
package v1
import (
"context"
v1pb "go-common/app/service/live/live-dm/api/grpc/v1"
"go-common/app/service/live/live-dm/conf"
"go-common/app/service/live/live-dm/dao"
"testing"
)
//group=qa01 DEPLOY_ENV=uat go test -run TestSaveHistory
func TestSaveHistory(t *testing.T) {
s := &SendMsg{
SendMsgReq: &v1pb.SendMsgReq{
Uid: 1877309,
Roomid: 5392,
Ip: "115.239.211.112",
Msg: "66666",
Rnd: "1000",
Fontsize: 15,
Mode: 0,
Platform: "ios",
Msgtype: 0,
},
Dmservice: &DMService{
conf: conf.Conf,
dao: dao.New(conf.Conf),
},
UserInfo: &dao.UserInfo{
ULevelColor: 9868950,
ULevelRank: 2,
MedalInfo: &dao.FansMedalInfo{},
RoomAdmin: false,
},
RoomConf: &dao.RoomConf{
UID: 158807,
RoomID: 5392,
Anchor: "沢奇Sawaki",
},
UserBindInfo: &dao.UserBindInfo{
Uname: "Bili_111",
URank: 1000,
},
TitleConf: &dao.CommentTitle{},
DMconf: &dao.DMConf{
Mode: 6,
Color: 5555,
Length: 20,
},
UserScore: &dao.UserScore{
UserScore: 90,
},
}
saveHistory(context.TODO(), s)
}
//group=qa01 DEPLOY_ENV=uat go test -run TestIncrDMNum
func TestIncrDMNum(t *testing.T) {
s := &SendMsg{
SendMsgReq: &v1pb.SendMsgReq{
Uid: 1877309,
Roomid: 5392,
Ip: "115.239.211.112",
Msg: "6666",
Rnd: "1000",
Fontsize: 15,
Mode: 1,
Platform: "ios",
Msgtype: 0,
},
Dmservice: &DMService{
conf: conf.Conf,
},
UserInfo: &dao.UserInfo{
ULevelColor: 9868950,
ULevelRank: 2,
MedalInfo: &dao.FansMedalInfo{},
},
RoomConf: &dao.RoomConf{
UID: 158807,
RoomID: 5392,
Anchor: "沢奇Sawaki",
},
UserBindInfo: &dao.UserBindInfo{
Uname: "Bili_111",
URank: 1000,
},
TitleConf: &dao.CommentTitle{},
DMconf: &dao.DMConf{
Mode: 6,
Color: 5555,
Length: 20,
},
UserScore: &dao.UserScore{
UserScore: 90,
},
}
incrDMNum(context.TODO(), s)
}
//group=qa01 DEPLOY_ENV=uat go test -run TestSendBroadCast
func TestSendBroadCast(t *testing.T) {
s := &SendMsg{
SendMsgReq: &v1pb.SendMsgReq{
Uid: 1877309,
Roomid: 5392,
Ip: "115.239.211.112",
Msg: "6666",
Rnd: "1000",
Fontsize: 15,
Mode: 1,
Platform: "ios",
Msgtype: 0,
},
Dmservice: &DMService{
conf: conf.Conf,
},
UserInfo: &dao.UserInfo{
ULevelColor: 9868950,
ULevelRank: 2,
MedalInfo: &dao.FansMedalInfo{},
},
RoomConf: &dao.RoomConf{
UID: 158807,
RoomID: 5392,
Anchor: "沢奇Sawaki",
},
UserBindInfo: &dao.UserBindInfo{
Uname: "Bili_111",
URank: 1000,
},
TitleConf: &dao.CommentTitle{},
DMconf: &dao.DMConf{
Mode: 6,
Color: 5555,
Length: 20,
},
UserScore: &dao.UserScore{
UserScore: 90,
},
}
sendBroadCast(context.TODO(), s)
}