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,78 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"archive_test.go",
"dao_test.go",
"databus_test.go",
"figure_test.go",
"mysql_protect_test.go",
"mysql_report_test.go",
"mysql_test.go",
"notify_test.go",
"redis_test.go",
"search_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/dm/conf:go_default_library",
"//app/interface/main/dm/model:go_default_library",
"//library/log:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"archive.go",
"dao.go",
"databus.go",
"figure.go",
"mysql.go",
"mysql_protect.go",
"mysql_report.go",
"notify.go",
"redis.go",
"search.go",
],
importpath = "go-common/app/interface/main/dm/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/dm/conf:go_default_library",
"//app/interface/main/dm/model:go_default_library",
"//library/cache/redis:go_default_library",
"//library/database/elastic:go_default_library",
"//library/database/sql:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/queue/databus:go_default_library",
"//library/stat/prom:go_default_library",
"//library/sync/errgroup:go_default_library",
"//library/xstr: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,41 @@
package dao
import (
"context"
"fmt"
"net/url"
"go-common/app/interface/main/dm/model"
"go-common/library/log"
)
const (
_cidInfo = "/videoup/cid"
)
func (d *Dao) cidInfoURI() string {
return d.conf.Host.Archive + _cidInfo
}
// CidInfo 获取cid详细信息
func (d *Dao) CidInfo(c context.Context, cid int64) (info *model.CidInfo, err error) {
var (
res = &struct {
Code int `json:"code"`
Data *model.CidInfo `json:"data"`
}{}
params = url.Values{}
uri = d.cidInfoURI()
)
params.Set("cid", fmt.Sprint(cid))
if err = d.httpClient.Get(c, uri, "", params, &res); err != nil {
log.Error("d.httpClient.Get(%s,%v,%d)", uri, params, err)
return
}
if res.Code != 0 {
err = fmt.Errorf("code is:%d", res.Code)
log.Error("d.httpClient.Get(%s,%v,%v,%d)", uri, params, err, res.Code)
return
}
return res.Data, nil
}

View File

@@ -0,0 +1,16 @@
package dao
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestCidInfo(t *testing.T) {
Convey("test cid info", t, func() {
cidInfo, err := testDao.CidInfo(context.TODO(), 10109082)
So(err, ShouldBeNil)
So(cidInfo, ShouldNotBeNil)
})
}

View File

@@ -0,0 +1,94 @@
package dao
import (
"context"
"time"
"go-common/app/interface/main/dm/conf"
"go-common/library/cache/redis"
"go-common/library/database/elastic"
"go-common/library/database/sql"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/queue/databus"
"go-common/library/stat/prom"
)
var (
missedCount = prom.CacheMiss
cachedCount = prom.CacheHit
)
// Dao dao struct
type Dao struct {
conf *conf.Config
httpClient *bm.Client
// redis
redisDM *redis.Pool
redisDMIDExpire int32
redisLockExpire int32
redisIndexExpire int32
redisVideoExpire int32
// database
dmMetaReader *sql.DB // bilibili_dm_meta
biliDM *sql.DB // blibili_dm
dmWriter *sql.DB
// databus
databus *databus.Databus
// elastic
es *elastic.Elastic
}
// New new a dao and return.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
conf: c,
httpClient: bm.NewClient(c.HTTPClient),
// redis
redisDM: redis.NewPool(c.Redis.DM.Config),
redisDMIDExpire: int32(time.Duration(c.Redis.DM.DMIDExpire) / time.Second),
redisLockExpire: int32(time.Duration(c.Redis.DM.LockExpire) / time.Second),
redisIndexExpire: int32(time.Duration(c.Redis.DM.IndexExpire) / time.Second),
redisVideoExpire: int32(time.Duration(c.Redis.DM.VideoExpire) / time.Second),
// database
dmMetaReader: sql.NewMySQL(c.DB.DMMetaReader),
biliDM: sql.NewMySQL(c.DB.DM),
dmWriter: sql.NewMySQL(c.DB.DMWriter),
// databus
databus: databus.New(c.Databus),
// elastic
es: elastic.NewElastic(c.ES),
}
return
}
// PromCacheHit prom cache hit
func PromCacheHit(name string) {
cachedCount.Incr(name)
}
// PromCacheMiss prom cache hit
func PromCacheMiss(name string) {
missedCount.Incr(name)
}
// Ping ping dao status
func (d *Dao) Ping(c context.Context) (err error) {
// dm redis
rds := d.redisDM.Get(c)
defer rds.Close()
if _, err = rds.Do("SET", "ping", "pong"); err != nil {
log.Error("rds.Do(SET) error(%v)", err)
return
}
// database
if err = d.dmMetaReader.Ping(c); err != nil {
log.Error("dmMetaReader.Ping() error(%v)", err)
return
}
if err = d.biliDM.Ping(c); err != nil {
log.Error("biliDM.Ping() error(%v)", err)
return
}
return
}

View File

@@ -0,0 +1,32 @@
package dao
import (
"flag"
"os"
"testing"
"go-common/app/interface/main/dm/conf"
"go-common/library/log"
)
var testDao *Dao
func TestMain(m *testing.M) {
flag.Set("app_id", "main.community.dm")
flag.Set("conf_token", "4d343dc5d8c33460156baec8913eb64a")
flag.Set("tree_id", "2692")
flag.Set("conf_version", "docker-1")
flag.Set("deploy_env", "uat")
flag.Set("conf_host", "config.bilibili.co")
flag.Set("conf_path", "/tmp")
flag.Set("region", "sh")
flag.Set("zone", "sh001")
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
log.Init(conf.Conf.Xlog)
defer log.Close()
testDao = New(conf.Conf)
os.Exit(m.Run())
}

View File

@@ -0,0 +1,19 @@
package dao
import (
"context"
"go-common/app/interface/main/dm/model"
"go-common/library/log"
)
// SendAction send action to job.
func (d *Dao) SendAction(c context.Context, k string, act *model.ReportAction) (err error) {
if err = d.databus.Send(c, k, act); err != nil {
log.Error("actionPub.Send(data:%v) error(%v)", act, err)
} else {
log.Info("actionPub.Send(action:%v) success", act)
}
return
}

View File

@@ -0,0 +1,27 @@
package dao
import (
"context"
"fmt"
"testing"
"time"
"go-common/app/interface/main/dm/model"
. "github.com/smartystreets/goconvey/convey"
)
func TestSendAction(t *testing.T) {
var (
c = context.TODO()
act = &model.ReportAction{
Cid: int64(10106598),
Did: int64(719918177),
HideTime: time.Now().Unix() + 10,
}
)
Convey("", t, func() {
err := testDao.SendAction(c, fmt.Sprint(act.Cid), act)
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,46 @@
package dao
import (
"context"
"fmt"
"net/url"
"go-common/library/log"
)
const (
_codeFigureNotFound = 55001
_figureInfoURL = "/x/internal/figure/info"
)
func (d *Dao) figureInfoURI() string {
return d.conf.Host.API + _figureInfoURL
}
// FigureInfo .
func (d *Dao) FigureInfo(c context.Context, mid int64) (score int32, err error) {
var (
res = &struct {
Code int `json:"code"`
Data *struct {
Percentage int32 `json:"percentage"`
} `json:"data"`
}{}
params = url.Values{}
uri = d.figureInfoURI()
)
params.Set("mid", fmt.Sprint(mid))
if err = d.httpClient.Get(c, uri, "", params, &res); err != nil {
log.Error("d.httpClient.Get(%s,%v,%d)", uri, params, err)
return
}
if res.Code != 0 && res.Code != _codeFigureNotFound {
err = fmt.Errorf("code != 0 && code !=%d", _codeFigureNotFound)
log.Error("d.httpClient.Get(%s,%v,%v,%d)", uri, params, err, res.Code)
return
}
if res != nil && res.Data != nil {
score = res.Data.Percentage
}
return
}

View File

@@ -0,0 +1,35 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaofigureInfoURI(t *testing.T) {
convey.Convey("figureInfoURI", t, func(convCtx convey.C) {
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
p1 := testDao.figureInfoURI()
convCtx.Convey("Then p1 should not be nil.", func(convCtx convey.C) {
convCtx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoFigureInfo(t *testing.T) {
convey.Convey("FigureInfo", t, func(convCtx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
score, err := testDao.FigureInfo(c, mid)
convCtx.Convey("Then err should be nil.score should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(score, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,281 @@
package dao
import (
"context"
"fmt"
"sync"
"go-common/app/interface/main/dm/model"
"go-common/library/database/sql"
"go-common/library/log"
"go-common/library/sync/errgroup"
"go-common/library/xstr"
)
const (
_pagesize = 1000
_subjectSharding = 100
_indexSharding = 1000
_contentSharding = 1000
_subSQL = "SELECT id,type,oid,pid,mid,state,attr,acount,count,mcount,move_count,maxlimit,childpool,ctime,mtime FROM dm_subject_%02d WHERE type=? AND oid=?"
_idxSQL = "SELECT id,type,oid,mid,progress,state,pool,attr,ctime,mtime FROM dm_index_%03d WHERE id=? AND oid=? AND type=?"
_idxsByIDSQL = "SELECT id,type,oid,mid,progress,state,pool,attr,ctime,mtime FROM dm_index_%03d WHERE id IN(%s) AND oid=? AND type=?"
_contentSQL = "SELECT dmid,fontsize,color,mode,ip,plat,msg,ctime,mtime FROM dm_content_%03d WHERE dmid=?"
_contentsSQL = "SELECT dmid,fontsize,color,mode,ip,plat,msg,ctime,mtime FROM dm_content_%03d WHERE dmid IN(%s)"
_contentSpeSQL = "SELECT dmid,msg,ctime,mtime FROM dm_special_content WHERE dmid=?"
_contentsSpeSQL = "SELECT dmid,msg,ctime,mtime FROM dm_special_content WHERE dmid IN(%s)"
// dm transfer
_addTransferJob = "INSERT INTO dm_transfer_job SET from_cid=?,to_cid=?,mid=?,offset=?,state=?"
_selTransferJob = "SELECT id,from_cid,to_cid,mid,offset,state,ctime,mtime from dm_transfer_job WHERE from_cid=? AND to_cid=?"
_transferListSQL = "SELECT id,from_cid,state,ctime FROM dm_transfer_job where to_cid=?"
_uptTransferSQL = "UPDATE dm_transfer_job SET state=? WHERE id=?"
_selTransferID = "SELECT id,from_cid,to_cid,mid,offset,state,ctime,mtime from dm_transfer_job WHERE id=?"
//dm state update
_updateIdxStatSQL = "UPDATE dm_index_%03d SET state=? WHERE type=? AND oid=? AND id IN(%s)"
)
func (d *Dao) hitSubject(oid int64) int64 {
return oid % _subjectSharding
}
func (d *Dao) hitIndex(oid int64) int64 {
return oid % _indexSharding
}
func (d *Dao) hitContent(dmid int64) int64 {
return dmid % _contentSharding
}
// Subject get subject info from db.
func (d *Dao) Subject(c context.Context, tp int32, oid int64) (s *model.Subject, err error) {
s = &model.Subject{}
row := d.dmMetaReader.QueryRow(c, fmt.Sprintf(_subSQL, d.hitSubject(oid)), tp, oid)
if err = row.Scan(&s.ID, &s.Type, &s.Oid, &s.Pid, &s.Mid, &s.State, &s.Attr, &s.ACount, &s.Count, &s.MCount, &s.MoveCnt, &s.Maxlimit, &s.Childpool, &s.Ctime, &s.Mtime); err != nil {
if err == sql.ErrNoRows {
s = nil
err = nil
} else {
log.Error("row.Scan() error(%v)", err)
}
}
return
}
// Index get index by dmid
func (d *Dao) Index(c context.Context, tp int32, oid, dmid int64) (dm *model.DM, err error) {
dm = &model.DM{}
row := d.dmMetaReader.QueryRow(c, fmt.Sprintf(_idxSQL, d.hitIndex(oid)), dmid, oid, tp)
if err = row.Scan(&dm.ID, &dm.Type, &dm.Oid, &dm.Mid, &dm.Progress, &dm.State, &dm.Pool, &dm.Attr, &dm.Ctime, &dm.Mtime); err != nil {
if err == sql.ErrNoRows {
dm = nil
err = nil
} else {
log.Error("row.Scan() error(%v)", err)
}
}
return
}
// IndexsByID get dm index by dmids.
func (d *Dao) IndexsByID(c context.Context, tp int32, oid int64, dmids []int64) (res map[int64]*model.DM, special []int64, err error) {
rows, err := d.dmMetaReader.Query(c, fmt.Sprintf(_idxsByIDSQL, d.hitIndex(oid), xstr.JoinInts(dmids)), oid, tp)
if err != nil {
log.Error("db.Query() error(%v)", err)
return
}
defer rows.Close()
res = make(map[int64]*model.DM, len(dmids))
for rows.Next() {
dm := &model.DM{}
if err = rows.Scan(&dm.ID, &dm.Type, &dm.Oid, &dm.Mid, &dm.Progress, &dm.State, &dm.Pool, &dm.Attr, &dm.Ctime, &dm.Mtime); err != nil {
log.Error("row.Scan() error(%v)", err)
return
}
res[dm.ID] = dm
if dm.Pool == model.PoolSpecial {
special = append(special, dm.ID)
}
}
if err = rows.Err(); err != nil {
log.Error("rows.Err() error(%v)", err)
}
return
}
// Content dm content by dmid
func (d *Dao) Content(c context.Context, oid, dmid int64) (ct *model.Content, err error) {
ct = &model.Content{}
row := d.dmMetaReader.QueryRow(c, fmt.Sprintf(_contentSQL, d.hitContent(oid)), dmid)
if err = row.Scan(&ct.ID, &ct.FontSize, &ct.Color, &ct.Mode, &ct.IP, &ct.Plat, &ct.Msg, &ct.Ctime, &ct.Mtime); err != nil {
if err == sql.ErrNoRows {
ct = nil
err = nil
} else {
log.Error("row.Scan() error(%v)", err)
}
}
return
}
// Contents multi get dm content by dmids.
func (d *Dao) Contents(c context.Context, oid int64, dmids []int64) (res []*model.Content, err error) {
var (
wg errgroup.Group
lock sync.Mutex
)
pageNum := len(dmids) / _pagesize
if len(dmids)%_pagesize > 0 {
pageNum = pageNum + 1
}
for i := 0; i < pageNum; i++ {
start := i * _pagesize
end := (i + 1) * _pagesize
if end > len(dmids) {
end = len(dmids)
}
wg.Go(func() (err error) {
rows, err := d.dmMetaReader.Query(c, fmt.Sprintf(_contentsSQL, d.hitContent(oid), xstr.JoinInts(dmids[start:end])))
if err != nil {
log.Error("db.Query(%s) error(%v)", fmt.Sprintf(_contentsSQL, d.hitContent(oid), xstr.JoinInts(dmids)), err)
return
}
defer rows.Close()
for rows.Next() {
ct := &model.Content{}
if err = rows.Scan(&ct.ID, &ct.FontSize, &ct.Color, &ct.Mode, &ct.IP, &ct.Plat, &ct.Msg, &ct.Ctime, &ct.Mtime); err != nil {
log.Error("rows.Scan() error(%v)", err)
return
}
lock.Lock()
res = append(res, ct)
lock.Unlock()
}
err = rows.Err()
return
})
}
if err = wg.Wait(); err != nil {
log.Error("wg.Wait() error(%v)", err)
}
return
}
// ContentSpecial get special dm content by dmids.
func (d *Dao) ContentSpecial(c context.Context, dmid int64) (contentSpe *model.ContentSpecial, err error) {
contentSpe = &model.ContentSpecial{}
row := d.dmMetaReader.QueryRow(c, _contentSpeSQL, dmid)
if err = row.Scan(&contentSpe.ID, &contentSpe.Msg, &contentSpe.Ctime, &contentSpe.Mtime); err != nil {
if err == sql.ErrNoRows {
contentSpe = nil
err = nil
} else {
log.Error("rows.Scan() error(%v)", err)
}
}
return
}
// ContentsSpecial multi get special dm content by dmids.
func (d *Dao) ContentsSpecial(c context.Context, dmids []int64) (res map[int64]*model.ContentSpecial, err error) {
res = make(map[int64]*model.ContentSpecial, len(dmids))
rows, err := d.dmMetaReader.Query(c, fmt.Sprintf(_contentsSpeSQL, xstr.JoinInts(dmids)))
if err != nil {
log.Error("db.Query() error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
content := &model.ContentSpecial{}
if err = rows.Scan(&content.ID, &content.Msg, &content.Ctime, &content.Mtime); err != nil {
log.Error("rows.Scan() error(%v)", err)
return
}
res[content.ID] = content
}
if err = rows.Err(); err != nil {
log.Error("rows.Err() error(%v)", err)
}
return
}
// AddTransferJob add transfer job.
func (d *Dao) AddTransferJob(c context.Context, fromCid, toCid, mid int64, offset float64, state int8) (affect int64, err error) {
row, err := d.biliDM.Exec(c, _addTransferJob, fromCid, toCid, mid, offset, model.TransferJobStatInit)
if err != nil {
log.Error("d.biliDM.Exec(fromCid:%d,toCid:%d,mid:%d,offset:%v) error(%v)", fromCid, toCid, mid, offset, err)
}
return row.LastInsertId()
}
// CheckTransferJob check transfer job state.
func (d *Dao) CheckTransferJob(c context.Context, fromCid, toCid int64) (job *model.TransferJob, err error) {
job = new(model.TransferJob)
row := d.biliDM.QueryRow(c, _selTransferJob, fromCid, toCid)
if err = row.Scan(&job.ID, &job.FromCID, &job.ToCID, &job.MID, &job.Offset, &job.State, &job.Ctime, &job.Mtime); err != nil {
if err == sql.ErrNoRows {
job = nil
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// CheckTransferID check transfer job state by id
func (d *Dao) CheckTransferID(c context.Context, id int64) (job *model.TransferJob, err error) {
job = new(model.TransferJob)
row := d.biliDM.QueryRow(c, _selTransferID, id)
if err = row.Scan(&job.ID, &job.FromCID, &job.ToCID, &job.MID, &job.Offset, &job.State, &job.Ctime, &job.Mtime); err != nil {
if err == sql.ErrNoRows {
job = nil
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// TransferList cid 的转移历史
func (d *Dao) TransferList(c context.Context, cid int64) (l []*model.TransferHistory, err error) {
l = make([]*model.TransferHistory, 0)
rows, err := d.biliDM.Query(c, _transferListSQL, cid)
if err != nil {
log.Error("d.biliDM.Query(%s,%d) error(%v)", _transferListSQL, cid, err)
return
}
defer rows.Close()
for rows.Next() {
hs := new(model.TransferHistory)
if err = rows.Scan(&hs.ID, &hs.CID, &hs.State, &hs.CTime); err != nil {
log.Error("TransfrerList: rows.Scan() error(%v)", err)
return
}
l = append(l, hs)
}
if err = rows.Err(); err != nil {
log.Error("rows.Err() error(%v)", err)
}
return
}
// SetTransferState change transfer state
func (d *Dao) SetTransferState(c context.Context, id int64, state int8) (affect int64, err error) {
row, err := d.biliDM.Exec(c, _uptTransferSQL, state, id)
if err != nil {
log.Error("d.biliDM.Exec(%s,%d) error(%v)", _uptTransferSQL, id, err)
return
}
return row.RowsAffected()
}
// UpdateDMStat edit dm state
func (d *Dao) UpdateDMStat(c context.Context, tp int32, oid int64, state int32, dmids []int64) (affect int64, err error) {
res, err := d.dmWriter.Exec(c, fmt.Sprintf(_updateIdxStatSQL, d.hitIndex(oid), xstr.JoinInts(dmids)), state, tp, oid)
if err != nil {
log.Error("dmWriter.Exec(%s %d) error(%v)", _updateIdxStatSQL, oid, err)
return
}
return res.RowsAffected()
}

View File

@@ -0,0 +1,258 @@
package dao
import (
"context"
"fmt"
"sort"
"strings"
"time"
"go-common/app/interface/main/dm/model"
"go-common/library/database/sql"
"go-common/library/log"
"go-common/library/xstr"
)
const (
// dm protect apply
_addProtect = "INSERT INTO dm_protect_apply (cid, uid, apply_uid, aid, playtime, dmid, msg, status, ctime, mtime) VALUES %s"
_selProtect = "SELECT ctime FROM dm_protect_apply WHERE dmid=? ORDER BY id DESC"
_getPrttApply = "SELECT id,cid,apply_uid,aid,playtime,msg,ctime from dm_protect_apply where uid=? %s and status=-1"
_getProtectAids = "SELECT aid FROM dm_protect_apply WHERE uid=? GROUP BY aid"
_paStatus = "UPDATE dm_protect_apply SET status=%d WHERE uid=%d AND id IN (%s)"
_chgPaSwitch = "INSERT INTO dm_protect_up (uid, notice_switch) VALUES(?, ?) ON DUPLICATE KEY UPDATE notice_switch=?"
_getProtectByIDs = "SELECT cid,dmid FROM dm_protect_apply WHERE uid=%d AND id IN (%s)"
_paUsrStat = "SELECT aid,apply_uid,status,ctime from dm_protect_apply where ctime>?"
_paStatistics = "SELECT uid from dm_protect_apply where status=-1 GROUP BY uid"
_paNoticeSwitch = "SELECT uid FROM dm_protect_up WHERE uid IN (%s) AND notice_switch=0"
)
// AddProtectApply 添加保护弹幕申请
func (d *Dao) AddProtectApply(c context.Context, pas []*model.Pa) (affect int64, err error) {
var (
values, s string
)
for _, pa := range pas {
pa.Msg = strings.Replace(pa.Msg, `\`, `\\`, -1)
pa.Msg = strings.Replace(pa.Msg, `'`, `\'`, -1)
values += fmt.Sprintf(`(%d, %d, %d, %d, %f, %d, '%s', %d, '%s', '%s'),`, pa.CID, pa.UID, pa.ApplyUID, pa.AID, pa.Playtime, pa.DMID, pa.Msg, pa.Status, pa.Ctime.Format("2006-01-02 15:04:05"), pa.Mtime.Format("2006-01-02 15:04:05"))
}
if len(values) > 0 {
values = values[0:(len(values) - 1)]
}
s = fmt.Sprintf(_addProtect, values)
res, err := d.biliDM.Exec(c, s)
if err != nil {
log.Error("d.biliDM.Exec(%v) error(%v)", s, err)
return
}
affect, err = res.RowsAffected()
return
}
// ProtectApplyTime 根据dmid获取保护弹幕申请
func (d *Dao) ProtectApplyTime(c context.Context, dmid int64) (t time.Time, err error) {
row := d.biliDM.QueryRow(c, _selProtect, dmid)
if err = row.Scan(&t); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// ProtectApplies 保护弹幕申请列表
func (d *Dao) ProtectApplies(c context.Context, uid, aid int64, order string) (res []*model.Apply, err error) {
var (
query string
rows *sql.Rows
)
if aid > 0 {
query = fmt.Sprintf(_getPrttApply, "AND aid=?")
rows, err = d.biliDM.Query(c, query, uid, aid)
} else {
query = fmt.Sprintf(_getPrttApply, "")
rows, err = d.biliDM.Query(c, query, uid)
}
if err != nil {
log.Error("d.biliDM.Query(%s,%v,%v) error(%v)", query, uid, aid, err)
return
}
defer rows.Close()
for rows.Next() {
r := &model.Apply{}
t := time.Time{}
if err = rows.Scan(&r.ID, &r.CID, &r.ApplyUID, &r.AID, &r.Playtime, &r.Msg, &t); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
r.Ctime = t.Format("2006-01-02 15:04:05")
res = append(res, r)
}
if err = rows.Err(); err != nil {
log.Error("rows.Err() error(%v)", err)
return
}
if order == "playtime" {
sort.Sort(model.ApplySortPlaytime(res))
} else {
sort.Sort(model.ApplySortID(res))
}
return
}
// ProtectAids 被申请保护弹幕稿件列表
func (d *Dao) ProtectAids(c context.Context, uid int64) (res []int64, err error) {
rows, err := d.biliDM.Query(c, _getProtectAids, uid)
if err != nil {
log.Error("d.biliDM.Query(%s,%d) error(%v)", _getProtectAids, uid, err)
return
}
defer rows.Close()
for rows.Next() {
var aid int64
if err = rows.Scan(&aid); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
res = append(res, aid)
}
if err = rows.Err(); err != nil {
log.Error("rows.Err() error(%v)", err)
}
return
}
// UptPaStatus 修改保护弹幕状态
func (d *Dao) UptPaStatus(c context.Context, uid int64, ids string, status int) (affect int64, err error) {
s := fmt.Sprintf(_paStatus, status, uid, ids)
res, err := d.biliDM.Exec(c, s)
if err != nil {
log.Error("d.biliDM.Exec(%v) error(%v)", s, err)
}
affect, err = res.RowsAffected()
return
}
// ProtectApplyByIDs get protect apply by dmid
func (d *Dao) ProtectApplyByIDs(c context.Context, uid int64, ids string) (res map[int64][]int64, err error) {
res = make(map[int64][]int64, 10)
s := fmt.Sprintf(_getProtectByIDs, uid, ids)
rows, err := d.biliDM.Query(c, s)
if err != nil {
log.Error("d.biliDM.Query(%s) error(%v)", s, err)
return
}
defer rows.Close()
for rows.Next() {
var (
dmid int64
cid int64
)
if err = rows.Scan(&cid, &dmid); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
_, ok := res[cid]
if ok {
res[cid] = append(res[cid], dmid)
} else {
res[cid] = []int64{dmid}
}
}
if err = rows.Err(); err != nil {
log.Error("rows.Err() error(%v)", err)
}
return
}
// UptPaNoticeSwitch 设置申请保护弹幕站内通知开关
func (d *Dao) UptPaNoticeSwitch(c context.Context, uid int64, status int) (affect int64, err error) {
res, err := d.biliDM.Exec(c, _chgPaSwitch, uid, status, status)
if err != nil {
log.Error("d.biliDM.Exec(%s,%d,%d) error(%v)", _chgPaSwitch, status, uid, err)
}
affect, err = res.RowsAffected()
return
}
// PaNoticeClose 获取关闭申请保护弹幕站内通知
func (d *Dao) PaNoticeClose(c context.Context, uids []int64) (res map[int64]bool, err error) {
if len(uids) < 1 {
return
}
res = make(map[int64]bool, len(uids))
s := fmt.Sprintf(_paNoticeSwitch, xstr.JoinInts(uids))
rows, err := d.biliDM.Query(c, s)
if err != nil {
log.Error("d.biliDM.Query(%s) error(%v)", s, err)
return
}
defer rows.Close()
for rows.Next() {
var uid int64
if err = rows.Scan(&uid); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
res[uid] = true
}
if err = rows.Err(); err != nil {
log.Error("rows.Err() error(%v)", err)
}
return
}
// ProtectApplyStatistics 保护弹幕申请up统计
func (d *Dao) ProtectApplyStatistics(c context.Context) (res []int64, err error) {
rows, err := d.biliDM.Query(c, _paStatistics)
if err != nil {
log.Error("d.biliDM.Query(%s) error(%v)", _paStatistics, err)
return
}
defer rows.Close()
for rows.Next() {
var uid int64
if err = rows.Scan(&uid); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
res = append(res, uid)
}
if err = rows.Err(); err != nil {
log.Error("rows.Err() error(%v)", err)
}
return
}
// twoDayAgo22 两天前的22点
func twoDayAgo22() string {
yesterday := time.Now().Add(-48 * time.Hour)
year, month, day := yesterday.Date()
return time.Date(year, month, day, 0, 0, 0, 0, time.Local).Format("2006-01-02") + " 22:00:00"
}
// PaUsrStat 保护弹幕申请用户统计
func (d *Dao) PaUsrStat(c context.Context) (res []*model.ApplyUserStat, err error) {
rows, err := d.biliDM.Query(c, _paUsrStat, twoDayAgo22())
if err != nil {
log.Error("d.biliDM.Query(%s) error(%v)", _paUsrStat, err)
return
}
defer rows.Close()
for rows.Next() {
r := &model.ApplyUserStat{}
if err = rows.Scan(&r.Aid, &r.UID, &r.Status, &r.Ctime); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
res = append(res, r)
}
if err = rows.Err(); err != nil {
log.Error("rows.Err() error(%v)", err)
}
return
}

View File

@@ -0,0 +1,189 @@
package dao
import (
"context"
"go-common/app/interface/main/dm/model"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoAddProtectApply(t *testing.T) {
convey.Convey("AddProtectApply", t, func(convCtx convey.C) {
var (
c = context.Background()
pas = []*model.Pa{
{
ID: 123,
CID: 1,
UID: 1,
},
}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
affect, err := testDao.AddProtectApply(c, pas)
convCtx.Convey("Then err should be nil.affect should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(affect, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoProtectApplyTime(t *testing.T) {
convey.Convey("ProtectApplyTime", t, func(convCtx convey.C) {
var (
c = context.Background()
dmid = int64(0)
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
no, err := testDao.ProtectApplyTime(c, dmid)
convCtx.Convey("Then err should be nil.no should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(no, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoProtectApplies(t *testing.T) {
convey.Convey("ProtectApplies", t, func(convCtx convey.C) {
var (
c = context.Background()
uid = int64(123)
aid = int64(111)
order = ""
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
_, err := testDao.ProtectApplies(c, uid, aid, order)
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoProtectAids(t *testing.T) {
convey.Convey("ProtectAids", t, func(convCtx convey.C) {
var (
c = context.Background()
uid = int64(0)
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := testDao.ProtectAids(c, uid)
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoUptPaStatus(t *testing.T) {
convey.Convey("UptPaStatus", t, func(convCtx convey.C) {
var (
c = context.Background()
uid = int64(123)
ids = "123"
status = int(0)
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
affect, err := testDao.UptPaStatus(c, uid, ids, status)
convCtx.Convey("Then err should be nil.affect should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(affect, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoProtectApplyByIDs(t *testing.T) {
convey.Convey("ProtectApplyByIDs", t, func(convCtx convey.C) {
var (
c = context.Background()
uid = int64(123)
ids = "123"
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := testDao.ProtectApplyByIDs(c, uid, ids)
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoUptPaNoticeSwitch(t *testing.T) {
convey.Convey("UptPaNoticeSwitch", t, func(convCtx convey.C) {
var (
c = context.Background()
uid = int64(0)
status = int(0)
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
affect, err := testDao.UptPaNoticeSwitch(c, uid, status)
convCtx.Convey("Then err should be nil.affect should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(affect, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoPaNoticeClose(t *testing.T) {
convey.Convey("PaNoticeClose", t, func(convCtx convey.C) {
var (
c = context.Background()
uids = []int64{123}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := testDao.PaNoticeClose(c, uids)
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoProtectApplyStatistics(t *testing.T) {
convey.Convey("ProtectApplyStatistics", t, func(convCtx convey.C) {
var (
c = context.Background()
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := testDao.ProtectApplyStatistics(c)
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaotwoDayAgo22(t *testing.T) {
convey.Convey("twoDayAgo22", t, func(convCtx convey.C) {
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
p1 := twoDayAgo22()
convCtx.Convey("Then p1 should not be nil.", func(convCtx convey.C) {
convCtx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoPaUsrStat(t *testing.T) {
convey.Convey("PaUsrStat", t, func(convCtx convey.C) {
var (
c = context.Background()
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := testDao.PaUsrStat(c)
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,160 @@
package dao
import (
"context"
"fmt"
"go-common/app/interface/main/dm/model"
"go-common/library/database/sql"
"go-common/library/log"
)
const (
_rptSharding = 100
_rptUserSharding = 100
_rptLogSharding = 100
_insertRpt = "INSERT INTO dm_report_%d (cid,dmid,uid,reason,content,count,state,up_op,rp_time,score,ctime,mtime) VALUES(?,?,?,?,?,?,?,?,?,?,?,?)" +
" ON DUPLICATE KEY UPDATE uid=?,reason=?,state=?,content=?,count=count+1,rp_time=?,score=score+?"
_selectRpt = "SELECT id,cid,dmid,uid,reason,content,count,state,up_op,score,rp_time,ctime,mtime FROM dm_report_%d WHERE dmid=?"
_updateRptUPOp = "UPDATE dm_report_%d SET up_op=? WHERE dmid=?"
_updateRpt = "UPDATE dm_report_%d SET state=? WHERE dmid=?"
_insertUser = "INSERT IGNORE INTO dm_report_user_%d (dmid,uid,reason,state,content,ctime,mtime) VALUES(?,?,?,?,?,?,?)"
_selectRptLog = "SELECT id,dmid,adminid,reason,result,remark,elapsed,ctime,mtime FROM dm_report_admin_log_%d WHERE dmid=? ORDER BY mtime"
_insertRptLog = "INSERT INTO dm_report_admin_log_%d (dmid,adminid,reason,result,remark,elapsed) VALUES (?,?,?,?,?,?)"
_selectRptUser = "SELECT id,dmid,uid,reason,state,ctime,mtime FROM dm_report_user_%d WHERE dmid=? AND state=?"
_updateRptUserStat = "UPDATE dm_report_user_%d SET state=? WHERE dmid=? AND state!=?"
)
func rptTable(cid int64) int64 {
return cid % _rptSharding
}
func rptUserTable(dmid int64) int64 {
return dmid % _rptUserSharding
}
// RptLogTable return log table id by dmid
func RptLogTable(dmid int64) int64 {
return dmid % _rptLogSharding
}
// AddReport insert or update dm report.
func (d *Dao) AddReport(c context.Context, rpt *model.Report) (id int64, err error) {
res, err := d.biliDM.Exec(c, fmt.Sprintf(_insertRpt, rptTable(rpt.Cid)), rpt.Cid, rpt.Did, rpt.UID, rpt.Reason, rpt.Content, rpt.Count, rpt.State, rpt.UpOP, rpt.RpTime, rpt.Score, rpt.Ctime, rpt.Mtime, rpt.UID, rpt.Reason, rpt.State, rpt.Content, rpt.RpTime, rpt.Score)
if err != nil {
log.Error("d.AddReport(%v) error(%v)", rpt, err)
return
}
return res.LastInsertId()
}
// AddReportUser add dm report user.
func (d *Dao) AddReportUser(c context.Context, u *model.User) (id int64, err error) {
res, err := d.biliDM.Exec(c, fmt.Sprintf(_insertUser, rptUserTable(u.Did)), u.Did, u.UID, u.Reason, u.State, u.Content, u.Ctime, u.Mtime)
if err != nil {
log.Error("d.AddReportUser(%v) error(%v)", u, err)
return
}
return res.LastInsertId()
}
// ReportLog get report log of dmid.
func (d *Dao) ReportLog(c context.Context, dmid int64) (res []*model.RptLog, err error) {
rows, err := d.biliDM.Query(c, fmt.Sprintf(_selectRptLog, RptLogTable(dmid)), dmid)
if err != nil {
log.Error("d.ReportLog(dmid:%d) error(%v)", dmid, err)
return
}
defer rows.Close()
for rows.Next() {
r := &model.RptLog{}
if err = rows.Scan(&r.ID, &r.Did, &r.AdminID, &r.Reason, &r.Result, &r.Remark, &r.Elapsed, &r.Ctime, &r.Mtime); err != nil {
log.Error("rows.Scan() error(%v)", err)
return
}
res = append(res, r)
}
if err = rows.Err(); err != nil {
log.Error("rows.Err() error(%v)", err)
}
return
}
// Report dm report info by cid and dmid.
func (d *Dao) Report(c context.Context, cid, dmid int64) (rpt *model.Report, err error) {
rpt = &model.Report{}
row := d.biliDM.QueryRow(c, fmt.Sprintf(_selectRpt, rptTable(cid)), dmid)
err = row.Scan(&rpt.ID, &rpt.Cid, &rpt.Did, &rpt.UID, &rpt.Reason, &rpt.Content, &rpt.Count, &rpt.State, &rpt.UpOP, &rpt.Score, &rpt.RpTime, &rpt.Ctime, &rpt.Mtime)
if err != nil {
if err == sql.ErrNoRows {
rpt = nil
err = nil
} else {
log.Error("row.Scan() error(%v)", err)
}
}
return
}
// UpdateReportStat update report state
func (d *Dao) UpdateReportStat(c context.Context, cid, dmid int64, state int8) (affect int64, err error) {
sqlStr := fmt.Sprintf(_updateRpt, rptTable(cid))
res, err := d.biliDM.Exec(c, sqlStr, state, dmid)
if err != nil {
log.Error("d.UpdateReportStat(cid:%d, dmid:%d) error(%v)", cid, dmid, err)
return
}
return res.RowsAffected()
}
// UpdateReportUPOp update dm report state.
func (d *Dao) UpdateReportUPOp(c context.Context, cid, dmid int64, op int8) (affect int64, err error) {
res, err := d.biliDM.Exec(c, fmt.Sprintf(_updateRptUPOp, rptTable(cid)), op, dmid)
if err != nil {
log.Error("d.UpdateReportUPOp(cid:%d, dmid:%d) error(%v)", cid, dmid, err)
return
}
return res.RowsAffected()
}
// AddReportLog add report log.
func (d *Dao) AddReportLog(c context.Context, lg *model.RptLog) (err error) {
sqlStr := fmt.Sprintf(_insertRptLog, RptLogTable(lg.Did))
_, err = d.biliDM.Exec(c, sqlStr, lg.Did, lg.AdminID, lg.Reason, lg.Result, lg.Remark, lg.Elapsed)
if err != nil {
log.Error("d.AddReportLog(%v) error(%v)", lg, err)
}
return
}
// ReportUser return report use list of dmid.
func (d *Dao) ReportUser(c context.Context, dmid int64) (users []*model.User, err error) {
sqlStr := fmt.Sprintf(_selectRptUser, rptUserTable(dmid))
rows, err := d.biliDM.Query(c, sqlStr, dmid, model.NoticeUnsend)
if err != nil {
log.Error("d.ReportUser(query:%s, dmid:%d) error(%v)", sqlStr, dmid, err)
return
}
defer rows.Close()
for rows.Next() {
u := &model.User{}
if err = rows.Scan(&u.ID, &u.Did, &u.UID, &u.Reason, &u.State, &u.Ctime, &u.Mtime); err != nil {
log.Error("rows.Scan() error(%v)", err)
return
}
users = append(users, u)
}
if err = rows.Err(); err != nil {
log.Error("rows.Err() error(%v)", err)
}
return
}
// SetReportUserFinished set dmid state to be noticesend.
func (d *Dao) SetReportUserFinished(c context.Context, dmid int64) (err error) {
sqlStr := fmt.Sprintf(_updateRptUserStat, rptUserTable(dmid))
if _, err = d.biliDM.Exec(c, sqlStr, model.NoticeSend, dmid, model.NoticeSend); err != nil {
log.Error("d.SetReportUserFinished(sql:%s, dmid:%d) error(%v)", sqlStr, dmid, err)
}
return
}

View File

@@ -0,0 +1,198 @@
package dao
import (
"context"
"testing"
"go-common/app/interface/main/dm/model"
"github.com/smartystreets/goconvey/convey"
)
func TestDaorptTable(t *testing.T) {
convey.Convey("rptTable", t, func(convCtx convey.C) {
var (
cid = int64(0)
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
p1 := rptTable(cid)
convCtx.Convey("Then p1 should not be nil.", func(convCtx convey.C) {
convCtx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaorptUserTable(t *testing.T) {
convey.Convey("rptUserTable", t, func(convCtx convey.C) {
var (
dmid = int64(0)
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
p1 := rptUserTable(dmid)
convCtx.Convey("Then p1 should not be nil.", func(convCtx convey.C) {
convCtx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoRptLogTable(t *testing.T) {
convey.Convey("RptLogTable", t, func(convCtx convey.C) {
var (
dmid = int64(0)
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
p1 := RptLogTable(dmid)
convCtx.Convey("Then p1 should not be nil.", func(convCtx convey.C) {
convCtx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoAddReport(t *testing.T) {
convey.Convey("AddReport", t, func(convCtx convey.C) {
var (
c = context.Background()
rpt = &model.Report{}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
id, err := testDao.AddReport(c, rpt)
convCtx.Convey("Then err should be nil.id should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(id, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoAddReportUser(t *testing.T) {
convey.Convey("AddReportUser", t, func(convCtx convey.C) {
var (
c = context.Background()
u = &model.User{}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
id, err := testDao.AddReportUser(c, u)
convCtx.Convey("Then err should be nil.id should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(id, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoReportLog(t *testing.T) {
convey.Convey("ReportLog", t, func(convCtx convey.C) {
var (
c = context.Background()
dmid = int64(0)
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := testDao.ReportLog(c, dmid)
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoReport(t *testing.T) {
convey.Convey("Report", t, func(convCtx convey.C) {
var (
c = context.Background()
cid = int64(0)
dmid = int64(0)
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
rpt, err := testDao.Report(c, cid, dmid)
convCtx.Convey("Then err should be nil.rpt should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(rpt, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoUpdateReportStat(t *testing.T) {
convey.Convey("UpdateReportStat", t, func(convCtx convey.C) {
var (
c = context.Background()
cid = int64(0)
dmid = int64(0)
state = int8(0)
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
affect, err := testDao.UpdateReportStat(c, cid, dmid, state)
convCtx.Convey("Then err should be nil.affect should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(affect, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoUpdateReportUPOp(t *testing.T) {
convey.Convey("UpdateReportUPOp", t, func(convCtx convey.C) {
var (
c = context.Background()
cid = int64(0)
dmid = int64(0)
op = int8(0)
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
affect, err := testDao.UpdateReportUPOp(c, cid, dmid, op)
convCtx.Convey("Then err should be nil.affect should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(affect, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoAddReportLog(t *testing.T) {
convey.Convey("AddReportLog", t, func(convCtx convey.C) {
var (
c = context.Background()
lg = &model.RptLog{}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
err := testDao.AddReportLog(c, lg)
convCtx.Convey("Then err should be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoReportUser(t *testing.T) {
convey.Convey("ReportUser", t, func(convCtx convey.C) {
var (
c = context.Background()
dmid = int64(123)
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
_, err := testDao.ReportUser(c, dmid)
convCtx.Convey("Then err should be nil.users should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoSetReportUserFinished(t *testing.T) {
convey.Convey("SetReportUserFinished", t, func(convCtx convey.C) {
var (
c = context.Background()
dmid = int64(0)
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
err := testDao.SetReportUserFinished(c, dmid)
convCtx.Convey("Then err should be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,141 @@
package dao
import (
"context"
"testing"
"go-common/app/interface/main/dm/model"
)
func TestSubject(t *testing.T) {
var (
c = context.TODO()
tp int32 = 1
oid int64 = 1221
)
s, err := testDao.Subject(c, tp, oid)
if err != nil {
t.Error(err)
}
if s == nil {
t.Logf("oid:%d subject not exist", oid)
} else {
t.Logf("subject:%+v", s)
}
}
func TestIndex(t *testing.T) {
var (
c = context.TODO()
tp int32 = 1
oid int64 = 1221
dmid int64 = 719150137
)
dm, err := testDao.Index(c, tp, oid, dmid)
if err != nil {
t.Error(err)
}
if dm == nil {
t.Logf("dmid:%d not exist", dmid)
} else {
t.Logf("dm:%+v", dm)
}
}
func TestIndexsByID(t *testing.T) {
var (
c = context.TODO()
tp int32 = 1
oid int64 = 1221
dmids = []int64{719150137, 719150230, 719150141}
)
res, special, err := testDao.IndexsByID(c, tp, oid, dmids)
if err != nil {
t.Error(err)
}
for _, dm := range res {
t.Logf("dm:%+v", dm)
}
t.Logf("special:%+v", special)
}
func TestContent(t *testing.T) {
var (
c = context.TODO()
oid int64 = 1221
dmid int64 = 719150137
)
ct, err := testDao.Content(c, oid, dmid)
if err != nil {
t.Error(err)
}
if ct == nil {
t.Logf("content:%d not exist", dmid)
} else {
t.Logf("content:%+v", ct)
}
}
func TestContents(t *testing.T) {
var (
c = context.TODO()
oid int64 = 1221
dmids = []int64{719150137, 719150230, 719150141}
)
res, err := testDao.Contents(c, oid, dmids)
if err != nil {
t.Error(err)
}
for _, ct := range res {
t.Logf("content:%+v", ct)
}
}
func TestContentSpecial(t *testing.T) {
var (
c = context.TODO()
dmid int64 = 719150141
)
cs, err := testDao.ContentSpecial(c, dmid)
if err != nil {
t.Error(err)
}
t.Logf("content special:%+v", cs)
}
func TestContentsSpecial(t *testing.T) {
var (
c = context.TODO()
dmids = []int64{719150141, 719150141}
)
res, err := testDao.ContentsSpecial(c, dmids)
if err != nil {
t.Error(err)
}
for _, cs := range res {
t.Logf("content special:%+v", cs)
}
}
func TestCheckTransferJob(t *testing.T) {
var (
from, to int64 = 10108765, 10108763
)
job, err := testDao.CheckTransferJob(context.TODO(), from, to)
if err != nil {
t.Fatal(err)
}
t.Log(job)
}
func TestAddTransferJob(t *testing.T) {
var (
from, to, mid int64 = 10108765, 10108763, 27515615
offset = 1.00
state = model.TransferJobStatInit
)
_, err := testDao.AddTransferJob(context.TODO(), from, to, mid, offset, state)
if err != nil {
t.Fatal(err)
}
}

View File

@@ -0,0 +1,46 @@
package dao
import (
"context"
"errors"
"net/url"
"go-common/library/log"
"go-common/library/xstr"
)
const (
_notifyDataType = "4" // 消息类型1、回复我的2、@我3、收到的爱4、业务通知
_notifyURL = "/api/notify/send.user.notify.do"
_notifyMC = "1_8_2"
)
func (d *Dao) notifyURI() string {
return d.conf.Host.Message + _notifyURL
}
// SendNotify 发送站内信
func (d *Dao) SendNotify(c context.Context, title, content string, mids []int64) (err error) {
res := struct {
Code int `json:"code"`
Data struct {
TotalCount int
ErrorCount int
} `json:"data"`
}{}
params := url.Values{}
params.Set("mc", _notifyMC)
params.Set("title", title)
params.Set("data_type", _notifyDataType)
params.Set("context", content)
params.Set("mid_list", xstr.JoinInts(mids))
if err = d.httpClient.Post(c, d.notifyURI(), "", params, &res); err != nil {
log.Error("d.httpClient.Post(%s,%v,%d)", d.notifyURI(), params, err)
return
}
if res.Code != 0 {
err = errors.New("code != 0")
log.Error("d.httpClient.Post(%s,%v,%v,%d)", d.notifyURI(), params, err, res.Code)
}
return
}

View File

@@ -0,0 +1,36 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaonotifyURI(t *testing.T) {
convey.Convey("notifyURI", t, func(convCtx convey.C) {
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
p1 := testDao.notifyURI()
convCtx.Convey("Then p1 should not be nil.", func(convCtx convey.C) {
convCtx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoSendNotify(t *testing.T) {
convey.Convey("SendNotify", t, func(convCtx convey.C) {
var (
c = context.Background()
title = ""
content = ""
mids = []int64{1}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
err := testDao.SendNotify(c, title, content, mids)
convCtx.Convey("Then err should be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,264 @@
package dao
import (
"context"
"strconv"
"time"
"go-common/library/cache/redis"
"go-common/library/log"
)
const (
_rptCnt = "rc_"
_rptBrig = "rb_"
_prfxPaUsrCntKey = "pa_user_count_"
_prfxUdAccCntKey = "usr_dm_acc_cnt_"
_prfxRecallCntKey = "recall_cnt_"
_crontabRedisLock = "crontab_redis_lock"
_crontabRedisLockExpire = 2 * 3600
)
// tomorrowUnixTime 明天unix time
func tomorrowUnixTime() int64 {
tomorrow := time.Now().Add(24 * time.Hour)
year, month, day := tomorrow.Date()
return time.Date(year, month, day, 0, 0, 0, 0, time.Local).Unix()
}
// paUsrCntKey 用户申请保护弹幕计数 redis key
func keyProtectApplyCmt() string {
return _prfxPaUsrCntKey + time.Now().Format("20060102")
}
func keyRptCnt() string {
return _rptCnt + time.Now().Format("04")
}
func keyRptBrig(mid int64) string {
return _rptBrig + strconv.FormatInt(mid, 10)
}
func keyRecallCnt() string {
return _prfxRecallCntKey + time.Now().Format("20060102")
}
// UptUsrPaCnt 设置申请保护弹幕数
func (d *Dao) UptUsrPaCnt(c context.Context, uid int64, count int64) (err error) {
var (
key, expire = keyProtectApplyCmt(), tomorrowUnixTime()
conn = d.redisDM.Get(c)
)
defer conn.Close()
if err = conn.Send("ZINCRBY", key, count, uid); err != nil {
log.Error("conn.Send(ZADD,%s,%d,%d) error(%v)", key, count, uid, err)
return
}
if err = conn.Send("EXPIREAT", key, expire); err != nil {
log.Error("conn.Send(EXPIREAT key(%s) expire(%d)) error(%v)", key, expire, err)
return
}
if err = conn.Flush(); err != nil {
log.Error("conn.Flush error(%v)", err)
return
}
for i := 0; i < 2; i++ {
if _, err = conn.Receive(); err != nil {
log.Error("conn.Receive error(%v)", err)
return
}
}
return
}
// PaUsrCnt 保护弹幕申请计数
func (d *Dao) PaUsrCnt(c context.Context, uid int64) (cnt int, err error) {
var (
key = keyProtectApplyCmt()
conn = d.redisDM.Get(c)
)
defer conn.Close()
if cnt, err = redis.Int(conn.Do("ZSCORE", key, uid)); err != nil {
if err == redis.ErrNil {
err = nil
} else {
log.Error("conn.Do(ZSCORE, %s,%d) error(%v)", key, uid, err)
}
}
return
}
// UsrDMAccCnt 我的弹幕访问计数
func (d *Dao) UsrDMAccCnt(c context.Context, uid int64, t int64) (cnt int64, err error) {
var (
key = _prfxUdAccCntKey + strconv.FormatInt(uid, 10)
conn = d.redisDM.Get(c)
)
defer conn.Close()
if cnt, err = redis.Int64(conn.Do("INCRBY", key, t)); err != nil {
log.Error("conn.Do(INCRBY, %s,%d) error(%v)", key, t, err)
return
}
if cnt != t {
return
}
_, err = redis.Int(conn.Do("EXPIREAT", key, t+5))
if err != nil {
log.Error("conn.Do(EXPIREAT, %s,%d) error(%v)", key, t+5, err)
}
return
}
// RecallCnt 撤回弹幕计数
func (d *Dao) RecallCnt(c context.Context, uid int64) (cnt int, err error) {
var (
key = keyRecallCnt()
conn = d.redisDM.Get(c)
)
defer conn.Close()
if cnt, err = redis.Int(conn.Do("ZSCORE", key, uid)); err != nil {
if err == redis.ErrNil {
err = nil
} else {
log.Error("redis.Int(conn.Do(GET, %s,%d)) error(%v)", key, uid, err)
}
}
return
}
// UptRecallCnt 更新撤回弹幕计数
func (d *Dao) UptRecallCnt(c context.Context, uid int64) (err error) {
var (
key = keyRecallCnt()
conn = d.redisDM.Get(c)
)
defer conn.Close()
if err = conn.Send("ZINCRBY", key, 1, uid); err != nil {
log.Error("conn.Send(ZINCRBY, %s,%d) error(%v)", key, 1, err)
return
}
if err = conn.Send("EXPIRE", key, 3600*24); err != nil {
log.Error("conn.Send(EXPIRE, %s,%d) error(%v)", key, 3600*24, err)
return
}
if err = conn.Flush(); err != nil {
log.Error("conn.Flush() error(%v)", err)
return
}
for i := 0; i < 2; i++ {
if _, err = conn.Receive(); err != nil {
log.Error("conn.Receive() error(%v)", err)
return
}
}
return
}
// PaLock redis定时任务锁保证只有一个地方在执行定时任务
func (d *Dao) PaLock(c context.Context, key string) (incr int, err error) {
var (
conn = d.redisDM.Get(c)
r interface{}
)
key = _crontabRedisLock + key
defer conn.Close()
if err = conn.Send("INCRBY", key, 1); err != nil {
log.Error("conn.Send(INCRBY,%s) error(%v)", key, err)
return
}
if err = conn.Send("EXPIRE", key, _crontabRedisLockExpire); err != nil {
log.Error("conn.Send(EXPIRE key(%s) expire(%d)) error(%v)", key, _crontabRedisLockExpire, err)
return
}
if err = conn.Flush(); err != nil {
log.Error("conn.Flush error(%v)", err)
return
}
if r, err = conn.Receive(); err != nil {
log.Error("conn.Receive error(%v)", err)
return
}
if incr, err = redis.Int(r, err); err != nil {
log.Error("redis.Int error(%v)", err)
return
}
if _, err = conn.Receive(); err != nil {
log.Error("conn.Receive error(%v)", err)
}
return
}
// RptCnt 弹幕举报一分钟计数
func (d *Dao) RptCnt(c context.Context, uid int64) (n int, err error) {
var (
k = keyRptCnt()
conn = d.redisDM.Get(c)
)
if n, err = redis.Int(conn.Do("ZSCORE", k, uid)); err != nil {
if err == redis.ErrNil {
err = nil
} else {
log.Error("conn.Do(ZSCORE, %s,%d) error(%v)", k, uid, err)
}
}
conn.Close()
return
}
// UptRptCnt 更新一分钟的弹幕举报数
func (d *Dao) UptRptCnt(c context.Context, uid int64) (n int64, err error) {
var (
k = keyRptCnt()
conn = d.redisDM.Get(c)
)
defer conn.Close()
if err = conn.Send("ZINCRBY", k, 1, uid); err != nil {
log.Error("conn.Send(ZINCRBY, %s,%d) error(%v)", k, 1, err)
return
}
if err = conn.Send("EXPIRE", k, 60); err != nil {
log.Error("conn.Send(EXPIRE, %s,%d) error(%v)", k, 60, err)
return
}
if err = conn.Flush(); err != nil {
log.Error("conn.Flush() error(%v)", err)
return
}
for i := 0; i < 2; i++ {
if _, err = conn.Receive(); err != nil {
log.Error("conn.Receive() error(%v)", err)
return
}
}
return
}
// AddRptBrig 将用户禁闭30分钟不让举报
func (d *Dao) AddRptBrig(c context.Context, mid int64) (err error) {
var (
k = keyRptBrig(mid)
conn = d.redisDM.Get(c)
)
if _, err = conn.Do("SETEX", k, 1800, time.Now().Unix()); err != nil {
log.Error("conn.Do(SETEX, %s,%d) error(%v)", k, 1, err)
}
conn.Close()
return
}
// RptBrigTime 获得禁闭的开始时间
func (d *Dao) RptBrigTime(c context.Context, mid int64) (t int64, err error) {
var (
k = keyRptBrig(mid)
conn = d.redisDM.Get(c)
)
if t, err = redis.Int64(conn.Do("GET", k)); err != nil {
if err == redis.ErrNil {
err = nil
} else {
log.Error("conn.Do(GET, %s,%d) error(%v)", k, 1, err)
}
}
conn.Close()
return
}

View File

@@ -0,0 +1,59 @@
package dao
import (
"context"
"testing"
)
func TestUptUsrPaCnt(t *testing.T) {
err := testDao.UptUsrPaCnt(context.TODO(), 1234356789, 1)
if err != nil {
t.Fatal(err)
}
}
func TestPaUsrCnt(t *testing.T) {
cnt, err := testDao.PaUsrCnt(context.TODO(), 1234356789)
if err != nil {
t.Fatal(err)
}
if cnt == 0 {
t.Fatal("pa usr cnt err")
}
}
func TestUsrDMAccCnt(t *testing.T) {
n, err := testDao.UsrDMAccCnt(context.TODO(), 1234356789, 1)
if err != nil {
t.Fatal(err)
}
if n == 0 {
t.Fatal("usr dm acc cnt err")
}
}
func TestUptRecallCnt(t *testing.T) {
err := testDao.UptRecallCnt(context.TODO(), 1234356789)
if err != nil {
t.Fatal(err)
}
}
func TestRecallCnt(t *testing.T) {
n, err := testDao.RecallCnt(context.TODO(), 1234356789)
if err != nil {
t.Fatal(err)
}
if n == 0 {
t.Fatal("usr dm acc cnt err")
}
}
func TestPaLock(t *testing.T) {
incr, err := testDao.PaLock(context.TODO(), "go-test")
if err != nil {
t.Fatal(err)
}
if incr < 1 {
t.Fatal("PaLock err")
}
}

View File

@@ -0,0 +1,85 @@
package dao
import (
"context"
"fmt"
"strconv"
"time"
"go-common/app/interface/main/dm/model"
"go-common/library/database/elastic"
"go-common/library/log"
)
// return recent two years report search index.
func (d *Dao) rptSearchIndex() string {
year := time.Now().Year()
return fmt.Sprintf("dmreport_%d,dmreport_%d", year-1, year)
}
// SearchReportAid 根据mid获取用户的所有有举报弹幕的稿件
func (d *Dao) SearchReportAid(c context.Context, mid int64, upOp int8, states []int8, pn, ps int64) (aids []int64, err error) {
res := new(model.SearchReportAidResult)
order := []map[string]string{{"arc_aid": "desc"}}
req := d.es.NewRequest("dmreport").Fields("arc_aid").Index(d.rptSearchIndex())
req.WhereEq("arc_mid", mid).WhereEq("up_op", upOp).WhereIn("state", states).GroupBy(elastic.EnhancedModeGroupBy, "arc_aid", order)
req.Pn(int(pn)).Ps(int(ps))
if err = req.Scan(c, res); err != nil {
log.Error("search params(%s), err(%v)", req.Params(), err)
return
}
if values, ok := res.Result["group_by_arc_aid"]; ok {
for _, v := range values {
var aid int64
if aid, err = strconv.ParseInt(v.Key, 10, 64); err != nil {
log.Error("strconv.ParseInt(%s) error(%v)", v.Key, err)
return
}
aids = append(aids, aid)
}
}
return
}
// SearchReport 根据up主id,稿件id获取举报弹幕列表
func (d *Dao) SearchReport(c context.Context, mid, aid, pn, ps int64, upOp int8, states []int64) (res *model.SearchReportResult, err error) {
req := d.es.NewRequest("dmreport")
req.Fields("id", "dmid", "cid", "arc_aid", "arc_typeid", "dm_owner_uid", "dm_msg", "count", "content", "up_op", "state",
"uid", "rp_time", "reason", "dm_deleted", "arc_mid", "pool_id", "model", "score", "dm_ctime", "ctime", "mtime")
req.Index(d.rptSearchIndex())
if aid > 0 {
req.WhereEq("arc_aid", aid)
}
if mid > 0 {
req.WhereEq("arc_mid", mid)
}
if len(states) > 0 {
req.WhereIn("state", states)
}
req.WhereNot(elastic.NotTypeEq, "dm_owner_uid").WhereEq("dm_owner_uid", 0)
req.WhereEq("up_op", upOp)
req.Order("rp_time", "desc")
req.Pn(int(pn)).Ps(int(ps))
res = &model.SearchReportResult{}
if err = req.Scan(c, res); err != nil {
log.Error("req.Scan() search params(%s), err(%v)", req.Params(), err)
}
return
}
// UpdateSearchReport update report search index.
func (d *Dao) UpdateSearchReport(c context.Context, rpts []*model.UptSearchReport) (err error) {
up := d.es.NewUpdate("dmreport").Insert() // if data not exist insert,else update
for _, rpt := range rpts {
t, err1 := time.ParseInLocation("2006-01-02 15:04:05", rpt.Ctime, time.Local)
if err1 != nil {
log.Error("time.ParseInLocation(%s) error(%v)", rpt.Ctime, err1)
return err1
}
up.AddData(fmt.Sprintf("dmreport_%d", t.Year()), rpt)
}
if err = up.Do(c); err != nil {
log.Error("update.Do() error(%v)", err)
}
return
}

View File

@@ -0,0 +1,67 @@
package dao
import (
"context"
"testing"
"go-common/app/interface/main/dm/model"
. "github.com/smartystreets/goconvey/convey"
)
func TestRptSearchIndex(t *testing.T) {
Convey("", t, func() {
s := testDao.rptSearchIndex()
So(s, ShouldNotBeEmpty)
t.Log(s)
})
}
func TestSearchReport(t *testing.T) {
var (
c = context.TODO()
// mid, aid, pn, ps int64 = 432230, 9548327, 1, 20 //pre
mid, aid, pn, ps int64 = 27515615, 10100087, 1, 20
upOp int8 = 2
states = []int64{0, 2}
)
Convey("", t, func() {
res, err := testDao.SearchReport(c, mid, aid, pn, ps, upOp, states)
So(err, ShouldBeNil)
So(res, ShouldNotBeEmpty)
t.Logf("%+v", res.Page)
for _, v := range res.Result {
t.Logf("%+v", v)
}
})
}
func TestSearchReportAid(t *testing.T) {
var (
c = context.TODO()
mid, pn, ps int64 = 27515256, 1, 20
upOp int8
state = []int8{0, 2}
)
Convey("", t, func() {
aids, err := testDao.SearchReportAid(c, mid, upOp, state, pn, ps)
So(err, ShouldBeNil)
t.Logf("%+v", aids)
})
}
func TestUptSearchReport(t *testing.T) {
var (
c = context.TODO()
upt = &model.UptSearchReport{
DMid: 1958334770970627,
Upop: 0,
Ctime: "2018-07-06 09:20:57",
Mtime: "2018-07-27 19:20:50",
}
)
Convey("", t, func() {
err := testDao.UpdateSearchReport(c, []*model.UptSearchReport{upt})
So(err, ShouldBeNil)
})
}